Add a bunch of necessary fixes to default text formatting and HTML format extraction.

This also replaces the `edittext_html_defaults` test with a more robust test that checks the default format and global format of SWF-based, text, and HTML test vectors.
This commit is contained in:
David Wendt 2020-06-13 18:45:54 -04:00
parent 4f3d4c82fb
commit 8628261dc8
9 changed files with 257 additions and 46 deletions

View File

@ -174,7 +174,7 @@ impl<'gc> EditText<'gc> {
},
font_id: None,
font_class_name: None,
height: Some(Twips::from_pixels(height)),
height: Some(Twips::from_pixels(12.0)),
color: Some(swf::Color {
r: 0,
g: 0,

View File

@ -142,26 +142,30 @@ impl TextFormat {
let font_class = et
.font_class_name
.clone()
.or_else(|| font.map(|font| font.descriptor().class().to_string()));
.or_else(|| font.map(|font| font.descriptor().class().to_string()))
.unwrap_or_else(|| "Times New Roman".to_string());
let align = et.layout.clone().map(|l| l.align);
let left_margin = et.layout.clone().map(|l| l.left_margin.to_pixels());
let right_margin = et.layout.clone().map(|l| l.right_margin.to_pixels());
let indent = et.layout.clone().map(|l| l.indent.to_pixels());
let leading = et.layout.map(|l| l.leading.to_pixels());
// TODO: Text fields that don't specify a font are assumed to be 12px
// Times New Roman non-bold, non-italic. This will need to be revised
// when we start supporting device fonts.
Self {
font: font_class,
font: Some(font_class),
size: et.height.map(|h| h.to_pixels()),
color: et.color,
align,
bold: font.map(|font| font.descriptor().bold()),
italic: font.map(|font| font.descriptor().italic()),
underline: None, // TODO: What is this by default? False?
bold: Some(font.map(|font| font.descriptor().bold()).unwrap_or(false)),
italic: Some(font.map(|font| font.descriptor().italic()).unwrap_or(false)),
underline: Some(false),
left_margin,
right_margin,
indent,
block_indent: Some(0.0), // TODO: This isn't specified by the tag itself
kerning: Some(true), // TODO: this isn't specified by the tag itself
kerning: Some(false),
leading,
letter_spacing: Some(0.0), // TODO: This isn't specified by the tag itself
tab_stops: Some(vec![]), // TODO: Are there default tab stops?
@ -259,6 +263,21 @@ impl TextFormat {
}
}
}
if let Some(letter_spacing) =
node.attribute_value(&XMLName::from_str("letterSpacing"))
{
tf.letter_spacing = letter_spacing.parse().ok();
}
tf.kerning = match node
.attribute_value(&XMLName::from_str("kerning"))
.as_deref()
{
Some("1") => Some(true),
Some("0") => Some(false),
_ => tf.kerning,
}
}
Some(name) if name == XMLName::from_str("b") => {
tf.bold = Some(true);
@ -1143,6 +1162,7 @@ impl FormatSpans {
/// presentational markup and CSS stylesheets.
pub fn lower_from_html<'gc>(&mut self, tree: XMLDocument<'gc>) {
let mut format_stack = vec![self.default_format.clone()];
let mut last_successful_format = None;
self.text = "".to_string();
self.spans = vec![];
@ -1167,9 +1187,15 @@ impl FormatSpans {
&node.node_value().unwrap(),
format_stack.last(),
);
last_successful_format = format_stack.last().cloned();
}
Step::Out(node) if node.tag_name().unwrap().node_name().as_str() == "p" => {
self.replace_text(self.text.len(), self.text.len(), "\n", format_stack.last());
self.replace_text(
self.text.len(),
self.text.len(),
"\n",
last_successful_format.as_ref(),
);
format_stack.pop();
}
Step::Out(_) => {

View File

@ -198,7 +198,7 @@ swf_tests! {
(as1_constructor_v7, "avm1/as1_constructor_v7", 1),
(issue_710, "avm1/issue_710", 1),
(edittext_font_size, "avm1/edittext_font_size", 1),
(edittext_html_defaults, "avm1/edittext_html_defaults", 1),
(edittext_default_format, "avm1/edittext_default_format", 1),
(edittext_leading, "avm1/edittext_leading", 1),
#[ignore] (edittext_newlines, "avm1/edittext_newlines", 1),
}

View File

@ -0,0 +1,222 @@
//Global text format parameters of a SWF-derived text field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Noto Sans
//tf.indent
0
//tf.italic
false
//tf.kerning
true
//tf.leading
2
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url
//Default text format parameters of a SWF-derived text field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Noto Sans
//tf.indent
0
//tf.italic
false
//tf.kerning
false
//tf.leading
2
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url
//Global text format parameters of a dynamic text field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Times New Roman
//tf.indent
0
//tf.italic
false
//tf.kerning
false
//tf.leading
0
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url
//Default text format parameters of a dynamic text field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Times New Roman
//tf.indent
0
//tf.italic
false
//tf.kerning
false
//tf.leading
0
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url
//Global text format parameters of a dynamic HTML field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Times New Roman
//tf.indent
0
//tf.italic
false
//tf.kerning
false
//tf.leading
0
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url
//Default text format parameters of a dynamic HTML field
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Times New Roman
//tf.indent
0
//tf.italic
false
//tf.kerning
false
//tf.leading
0
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url

Binary file not shown.

Binary file not shown.

View File

@ -1,37 +0,0 @@
//Text format parameters of Noto Sans text field with HTML:
//tf.align
left
//tf.blockIndent
0
//tf.bold
false
//tf.bullet
false
//tf.color
0
//tf.font
Noto Sans
//tf.indent
0
//tf.italic
false
//tf.kerning
true
//tf.leading
2
//tf.leftMargin
0
//tf.letterSpacing
0
//tf.rightMargin
0
//tf.size
12
//tf.tabStops.join(',')
//tf.target
//tf.underline
false
//tf.url