avm1: Correct `TextFormat` properties coercion
This commit is contained in:
parent
068e7acc6f
commit
10b7c69719
|
@ -88,8 +88,7 @@ fn set_size<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.size = match value {
|
text_format.size = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -233,7 +232,7 @@ fn set_align<'gc>(
|
||||||
"center" => Some(swf::TextAlign::Center),
|
"center" => Some(swf::TextAlign::Center),
|
||||||
"right" => Some(swf::TextAlign::Right),
|
"right" => Some(swf::TextAlign::Right),
|
||||||
"justify" => Some(swf::TextAlign::Justify),
|
"justify" => Some(swf::TextAlign::Justify),
|
||||||
_ => None,
|
_ => return Ok(()),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -256,8 +255,7 @@ fn set_left_margin<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.left_margin = match value {
|
text_format.left_margin = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?.max(0.0)).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -279,8 +277,7 @@ fn set_right_margin<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.right_margin = match value {
|
text_format.right_margin = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?.max(0.0)).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -299,8 +296,7 @@ fn set_indent<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.indent = match value {
|
text_format.indent = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -319,8 +315,7 @@ fn set_leading<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.leading = match value {
|
text_format.leading = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -342,8 +337,7 @@ fn set_block_indent<'gc>(
|
||||||
) -> Result<(), Error<'gc>> {
|
) -> Result<(), Error<'gc>> {
|
||||||
text_format.block_indent = match value {
|
text_format.block_indent = match value {
|
||||||
Value::Undefined | Value::Null => None,
|
Value::Undefined | Value::Null => None,
|
||||||
// TODO: round up
|
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -376,8 +370,7 @@ fn set_tab_stops<'gc>(
|
||||||
let tab_stops: Result<Vec<_>, Error<'gc>> = (0..length)
|
let tab_stops: Result<Vec<_>, Error<'gc>> = (0..length)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let element = object.get_element(activation, i);
|
let element = object.get_element(activation, i);
|
||||||
// TODO: round up
|
Ok(round_to_i32(element.coerce_to_f64(activation)?).into())
|
||||||
Ok(element.coerce_to_i32(activation)?.into())
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Some(tab_stops?)
|
Some(tab_stops?)
|
||||||
|
@ -551,3 +544,23 @@ pub fn create_proto<'gc>(
|
||||||
define_properties_on(PROTO_DECLS, gc_context, object, fn_proto);
|
define_properties_on(PROTO_DECLS, gc_context, object, fn_proto);
|
||||||
text_format.into()
|
text_format.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implements the IEEE-754 "Round to nearest, ties to even" rounding rule.
|
||||||
|
/// (e.g., both 1.5 and 2.5 will round to 2).
|
||||||
|
/// This is the rounding method used by Flash for the above coercions.
|
||||||
|
/// Although this is easy to do on most architectures, Rust provides no standard
|
||||||
|
/// way to round in this manner (`f64::round` always rounds away from zero).
|
||||||
|
/// For more info and the below code snippet, see: https://github.com/rust-lang/rust/issues/55107
|
||||||
|
/// This also clamps out-of-range values and NaN to `i32::MIN`.
|
||||||
|
/// TODO: Investigate using SSE/wasm intrinsics for this.
|
||||||
|
fn round_to_i32(x: f64) -> i32 {
|
||||||
|
let k = 1.0 / f64::EPSILON;
|
||||||
|
let a = x.abs();
|
||||||
|
let out = if a < k { ((a + k) - k).copysign(x) } else { x };
|
||||||
|
// Values outside of i32 range get clamped to i32::MIN.
|
||||||
|
if out.is_finite() && out >= i32::MIN.into() && out <= i32::MAX.into() {
|
||||||
|
out as i32
|
||||||
|
} else {
|
||||||
|
i32::MIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -324,6 +324,7 @@ swf_tests! {
|
||||||
(textfield_background_color, "avm1/textfield_background_color", 1),
|
(textfield_background_color, "avm1/textfield_background_color", 1),
|
||||||
(textfield_border_color, "avm1/textfield_border_color", 1),
|
(textfield_border_color, "avm1/textfield_border_color", 1),
|
||||||
(textfield_variable, "avm1/textfield_variable", 8),
|
(textfield_variable, "avm1/textfield_variable", 8),
|
||||||
|
(text_format, "avm1/text_format", 1),
|
||||||
(error, "avm1/error", 1),
|
(error, "avm1/error", 1),
|
||||||
(color_transform, "avm1/color_transform", 1),
|
(color_transform, "avm1/color_transform", 1),
|
||||||
(with, "avm1/with", 1),
|
(with, "avm1/with", 1),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue