handle font cascading on body (+button & li font support)
This commit is contained in:
@@ -144,7 +144,7 @@ func get_element_styles_with_inheritance(element: HTMLElement, event: String = "
|
|||||||
# Inherit certain properties from parent elements
|
# Inherit certain properties from parent elements
|
||||||
var inheritable_properties = ["width", "height", "font-size", "color", "font-family"]
|
var inheritable_properties = ["width", "height", "font-size", "color", "font-family"]
|
||||||
var parent_element = element.parent
|
var parent_element = element.parent
|
||||||
while parent_element and parent_element.tag_name != "body":
|
while parent_element:
|
||||||
var parent_styles = get_element_styles_internal(parent_element, event)
|
var parent_styles = get_element_styles_internal(parent_element, event)
|
||||||
for property in inheritable_properties:
|
for property in inheritable_properties:
|
||||||
# Only inherit if child doesn't already have this property
|
# Only inherit if child doesn't already have this property
|
||||||
|
|||||||
@@ -92,92 +92,100 @@ static func apply_element_styles(node: Control, element: HTMLParser.HTMLElement,
|
|||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
static func apply_styles_to_label(label: RichTextLabel, styles: Dictionary, element: HTMLParser.HTMLElement, parser, text_override: String = "") -> void:
|
static func apply_styles_to_label(label: Control, styles: Dictionary, element: HTMLParser.HTMLElement, parser, text_override: String = "") -> void:
|
||||||
var text = text_override if text_override != "" else (element.get_preserved_text() if element.tag_name == "pre" else element.get_bbcode_formatted_text(parser))
|
if label is Button:
|
||||||
|
apply_font_to_button(label, styles)
|
||||||
|
return
|
||||||
|
|
||||||
var font_size = 24 # default
|
if not label is RichTextLabel:
|
||||||
|
return
|
||||||
|
|
||||||
if styles.has("font-family"):
|
var text = text_override if text_override != "" else (element.get_preserved_text() if element.tag_name == "pre" else element.get_bbcode_formatted_text(parser))
|
||||||
var font_family = styles["font-family"]
|
|
||||||
var font_resource = FontManager.get_font(font_family)
|
|
||||||
|
|
||||||
# set a sans-serif fallback first
|
var font_size = 24 # default
|
||||||
if font_family not in ["sans-serif", "serif", "monospace"]:
|
|
||||||
if not FontManager.loaded_fonts.has(font_family):
|
|
||||||
# Font not loaded yet, use sans-serif as fallback
|
|
||||||
var fallback_font = FontManager.get_font("sans-serif")
|
|
||||||
apply_font_to_label(label, fallback_font)
|
|
||||||
|
|
||||||
if font_resource:
|
if styles.has("font-family"):
|
||||||
apply_font_to_label(label, font_resource)
|
var font_family = styles["font-family"]
|
||||||
|
var font_resource = FontManager.get_font(font_family)
|
||||||
|
|
||||||
# Apply font size
|
# set a sans-serif fallback first
|
||||||
if styles.has("font-size"):
|
if font_family not in ["sans-serif", "serif", "monospace"]:
|
||||||
font_size = int(styles["font-size"])
|
if not FontManager.loaded_fonts.has(font_family):
|
||||||
# Apply color
|
# Font not loaded yet, use sans-serif as fallback
|
||||||
var color_tag = ""
|
var fallback_font = FontManager.get_font("sans-serif")
|
||||||
if styles.has("color"):
|
apply_font_to_label(label, fallback_font)
|
||||||
var color = styles["color"] as Color
|
|
||||||
|
|
||||||
if color == Color.BLACK and StyleManager.body_text_color != Color.BLACK:
|
if font_resource:
|
||||||
color = StyleManager.body_text_color
|
apply_font_to_label(label, font_resource)
|
||||||
|
|
||||||
|
# Apply font size
|
||||||
|
if styles.has("font-size"):
|
||||||
|
font_size = int(styles["font-size"])
|
||||||
|
# Apply color
|
||||||
|
var color_tag = ""
|
||||||
|
if styles.has("color"):
|
||||||
|
var color = styles["color"] as Color
|
||||||
|
|
||||||
|
if color == Color.BLACK and StyleManager.body_text_color != Color.BLACK:
|
||||||
|
color = StyleManager.body_text_color
|
||||||
color_tag = "[color=#%s]" % color.to_html(false)
|
color_tag = "[color=#%s]" % color.to_html(false)
|
||||||
else:
|
else:
|
||||||
if StyleManager.body_text_color != Color.BLACK:
|
if StyleManager.body_text_color != Color.BLACK:
|
||||||
color_tag = "[color=#%s]" % StyleManager.body_text_color.to_html(false)
|
color_tag = "[color=#%s]" % StyleManager.body_text_color.to_html(false)
|
||||||
# Apply bold
|
|
||||||
var bold_open = ""
|
|
||||||
var bold_close = ""
|
|
||||||
if styles.has("font-bold") and styles["font-bold"]:
|
|
||||||
bold_open = "[b]"
|
|
||||||
bold_close = "[/b]"
|
|
||||||
# Apply italic
|
|
||||||
var italic_open = ""
|
|
||||||
var italic_close = ""
|
|
||||||
if styles.has("font-italic") and styles["font-italic"]:
|
|
||||||
italic_open = "[i]"
|
|
||||||
italic_close = "[/i]"
|
|
||||||
# Apply underline
|
|
||||||
var underline_open = ""
|
|
||||||
var underline_close = ""
|
|
||||||
if styles.has("underline") and styles["underline"]:
|
|
||||||
underline_open = "[u]"
|
|
||||||
underline_close = "[/u]"
|
|
||||||
# Apply monospace font
|
|
||||||
var mono_open = ""
|
|
||||||
var mono_close = ""
|
|
||||||
if styles.has("font-mono") and styles["font-mono"]:
|
|
||||||
# If font-family is already monospace, just use BBCode for styling
|
|
||||||
if not (styles.has("font-family") and styles["font-family"] == "monospace"):
|
|
||||||
mono_open = "[code]"
|
|
||||||
mono_close = "[/code]"
|
|
||||||
if styles.has("text-align"):
|
|
||||||
match styles["text-align"]:
|
|
||||||
"left":
|
|
||||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
|
||||||
"center":
|
|
||||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
||||||
"right":
|
|
||||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
|
||||||
"justify":
|
|
||||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_FILL
|
|
||||||
# Construct final text
|
|
||||||
var styled_text = "[font_size=%d]%s%s%s%s%s%s%s%s%s%s%s[/font_size]" % [
|
|
||||||
font_size,
|
|
||||||
color_tag,
|
|
||||||
bold_open,
|
|
||||||
italic_open,
|
|
||||||
underline_open,
|
|
||||||
mono_open,
|
|
||||||
text,
|
|
||||||
mono_close,
|
|
||||||
underline_close,
|
|
||||||
italic_close,
|
|
||||||
bold_close,
|
|
||||||
"[/color]" if color_tag.length() > 0 else "",
|
|
||||||
]
|
|
||||||
|
|
||||||
label.text = styled_text
|
# Apply bold
|
||||||
|
var bold_open = ""
|
||||||
|
var bold_close = ""
|
||||||
|
if styles.has("font-bold") and styles["font-bold"]:
|
||||||
|
bold_open = "[b]"
|
||||||
|
bold_close = "[/b]"
|
||||||
|
# Apply italic
|
||||||
|
var italic_open = ""
|
||||||
|
var italic_close = ""
|
||||||
|
if styles.has("font-italic") and styles["font-italic"]:
|
||||||
|
italic_open = "[i]"
|
||||||
|
italic_close = "[/i]"
|
||||||
|
# Apply underline
|
||||||
|
var underline_open = ""
|
||||||
|
var underline_close = ""
|
||||||
|
if styles.has("underline") and styles["underline"]:
|
||||||
|
underline_open = "[u]"
|
||||||
|
underline_close = "[/u]"
|
||||||
|
# Apply monospace font
|
||||||
|
var mono_open = ""
|
||||||
|
var mono_close = ""
|
||||||
|
if styles.has("font-mono") and styles["font-mono"]:
|
||||||
|
# If font-family is already monospace, just use BBCode for styling
|
||||||
|
if not (styles.has("font-family") and styles["font-family"] == "monospace"):
|
||||||
|
mono_open = "[code]"
|
||||||
|
mono_close = "[/code]"
|
||||||
|
if styles.has("text-align"):
|
||||||
|
match styles["text-align"]:
|
||||||
|
"left":
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||||
|
"center":
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
"right":
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||||
|
"justify":
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_FILL
|
||||||
|
# Construct final text
|
||||||
|
var styled_text = "[font_size=%d]%s%s%s%s%s%s%s%s%s%s%s[/font_size]" % [
|
||||||
|
font_size,
|
||||||
|
color_tag,
|
||||||
|
bold_open,
|
||||||
|
italic_open,
|
||||||
|
underline_open,
|
||||||
|
mono_open,
|
||||||
|
text,
|
||||||
|
mono_close,
|
||||||
|
underline_close,
|
||||||
|
italic_close,
|
||||||
|
bold_close,
|
||||||
|
"[/color]" if color_tag.length() > 0 else "",
|
||||||
|
]
|
||||||
|
|
||||||
|
label.text = styled_text
|
||||||
|
|
||||||
static func apply_flex_container_properties(node: FlexContainer, styles: Dictionary) -> void:
|
static func apply_flex_container_properties(node: FlexContainer, styles: Dictionary) -> void:
|
||||||
FlexUtils.apply_flex_container_properties(node, styles)
|
FlexUtils.apply_flex_container_properties(node, styles)
|
||||||
@@ -249,3 +257,17 @@ static func apply_font_to_label(label: RichTextLabel, font_resource: Font) -> vo
|
|||||||
label.add_theme_font_override("bold_font", font_resource)
|
label.add_theme_font_override("bold_font", font_resource)
|
||||||
label.add_theme_font_override("italics_font", font_resource)
|
label.add_theme_font_override("italics_font", font_resource)
|
||||||
label.add_theme_font_override("bold_italics_font", font_resource)
|
label.add_theme_font_override("bold_italics_font", font_resource)
|
||||||
|
|
||||||
|
static func apply_font_to_button(button: Button, styles: Dictionary) -> void:
|
||||||
|
if styles.has("font-family"):
|
||||||
|
var font_family = styles["font-family"]
|
||||||
|
var font_resource = FontManager.get_font(font_family)
|
||||||
|
|
||||||
|
# Set fallback first for FOUT prevention
|
||||||
|
if font_family not in ["sans-serif", "serif", "monospace"]:
|
||||||
|
if not FontManager.loaded_fonts.has(font_family):
|
||||||
|
var fallback_font = FontManager.get_font("sans-serif")
|
||||||
|
button.add_theme_font_override("font", fallback_font)
|
||||||
|
|
||||||
|
if font_resource:
|
||||||
|
button.add_theme_font_override("font", font_resource)
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ func apply_button_styles(element: HTMLParser.HTMLElement, parser: HTMLParser, na
|
|||||||
if not element or not parser:
|
if not element or not parser:
|
||||||
return
|
return
|
||||||
|
|
||||||
var styles = parser.get_element_styles_internal(element, "")
|
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||||
var hover_styles = parser.get_element_styles_internal(element, "hover")
|
var hover_styles = parser.get_element_styles_with_inheritance(element, "hover", [])
|
||||||
var active_styles = parser.get_element_styles_internal(element, "active")
|
var active_styles = parser.get_element_styles_with_inheritance(element, "active", [])
|
||||||
var button_node = $ButtonNode
|
var button_node = $ButtonNode
|
||||||
|
|
||||||
# Apply text color with state-dependent colors
|
# Apply text color with state-dependent colors
|
||||||
|
|||||||
@@ -3,4 +3,6 @@ extends Control
|
|||||||
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
func init(element: HTMLParser.HTMLElement, parser: HTMLParser = null) -> void:
|
||||||
# This is mainly for cases where <li> appears outside of <ul>/<ol>
|
# This is mainly for cases where <li> appears outside of <ul>/<ol>
|
||||||
var label: RichTextLabel = $RichTextLabel
|
var label: RichTextLabel = $RichTextLabel
|
||||||
label.text = "[font_size=24]%s[/font_size]" % element.get_bbcode_formatted_text(parser)
|
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||||
|
|
||||||
|
StyleManager.apply_styles_to_label(label, styles, element, parser)
|
||||||
@@ -55,7 +55,9 @@ func create_li_node(element: HTMLParser.HTMLElement, list_type: String, index: i
|
|||||||
marker_label.theme = BROWSER_TEXT
|
marker_label.theme = BROWSER_TEXT
|
||||||
|
|
||||||
var marker_text = get_marker_for_type(list_type, index)
|
var marker_text = get_marker_for_type(list_type, index)
|
||||||
StyleManager.apply_styles_to_label(marker_label, {}, null, null, marker_text)
|
|
||||||
|
var marker_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||||
|
StyleManager.apply_styles_to_label(marker_label, marker_styles, element, parser, marker_text)
|
||||||
|
|
||||||
# Create content
|
# Create content
|
||||||
var content_label = RichTextLabel.new()
|
var content_label = RichTextLabel.new()
|
||||||
@@ -66,7 +68,9 @@ func create_li_node(element: HTMLParser.HTMLElement, list_type: String, index: i
|
|||||||
content_label.theme = BROWSER_TEXT
|
content_label.theme = BROWSER_TEXT
|
||||||
|
|
||||||
var content_text = element.get_bbcode_formatted_text(parser)
|
var content_text = element.get_bbcode_formatted_text(parser)
|
||||||
StyleManager.apply_styles_to_label(content_label, {}, null, null, content_text)
|
|
||||||
|
var content_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||||
|
StyleManager.apply_styles_to_label(content_label, content_styles, element, parser, content_text)
|
||||||
|
|
||||||
li_container.add_theme_constant_override("separation", 0)
|
li_container.add_theme_constant_override("separation", 0)
|
||||||
li_container.add_child(marker_label)
|
li_container.add_child(marker_label)
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ func create_li_node(element: HTMLParser.HTMLElement, list_type: String, marker_w
|
|||||||
bullet_label.theme = BROWSER_TEXT
|
bullet_label.theme = BROWSER_TEXT
|
||||||
|
|
||||||
var bullet_text = get_bullet_for_type(list_type)
|
var bullet_text = get_bullet_for_type(list_type)
|
||||||
StyleManager.apply_styles_to_label(bullet_label, {}, null, null, bullet_text)
|
|
||||||
|
var bullet_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||||
|
StyleManager.apply_styles_to_label(bullet_label, bullet_styles, element, parser, bullet_text)
|
||||||
|
|
||||||
# Create content
|
# Create content
|
||||||
var content_label = RichTextLabel.new()
|
var content_label = RichTextLabel.new()
|
||||||
@@ -60,7 +62,9 @@ func create_li_node(element: HTMLParser.HTMLElement, list_type: String, marker_w
|
|||||||
content_label.theme = BROWSER_TEXT
|
content_label.theme = BROWSER_TEXT
|
||||||
content_label.scroll_active = false
|
content_label.scroll_active = false
|
||||||
var content_text = element.get_bbcode_formatted_text(parser)
|
var content_text = element.get_bbcode_formatted_text(parser)
|
||||||
StyleManager.apply_styles_to_label(content_label, {}, null, null, content_text)
|
|
||||||
|
var content_styles = parser.get_element_styles_with_inheritance(element, "", []) if parser else {}
|
||||||
|
StyleManager.apply_styles_to_label(content_label, content_styles, element, parser, content_text)
|
||||||
|
|
||||||
li_container.add_theme_constant_override("separation", 0)
|
li_container.add_theme_constant_override("separation", 0)
|
||||||
li_container.add_child(bullet_label)
|
li_container.add_child(bullet_label)
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
|||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
func register_font_dependent_element(label: RichTextLabel, styles: Dictionary, element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
|
func register_font_dependent_element(label: Control, styles: Dictionary, element: HTMLParser.HTMLElement, parser: HTMLParser) -> void:
|
||||||
font_dependent_elements.append({
|
font_dependent_elements.append({
|
||||||
"label": label,
|
"label": label,
|
||||||
"styles": styles,
|
"styles": styles,
|
||||||
|
|||||||
Reference in New Issue
Block a user