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>> {
|
||||
text_format.size = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -233,7 +232,7 @@ fn set_align<'gc>(
|
|||
"center" => Some(swf::TextAlign::Center),
|
||||
"right" => Some(swf::TextAlign::Right),
|
||||
"justify" => Some(swf::TextAlign::Justify),
|
||||
_ => None,
|
||||
_ => return Ok(()),
|
||||
},
|
||||
};
|
||||
Ok(())
|
||||
|
@ -256,8 +255,7 @@ fn set_left_margin<'gc>(
|
|||
) -> Result<(), Error<'gc>> {
|
||||
text_format.left_margin = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?.max(0.0)).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -279,8 +277,7 @@ fn set_right_margin<'gc>(
|
|||
) -> Result<(), Error<'gc>> {
|
||||
text_format.right_margin = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?.max(0.0)).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -299,8 +296,7 @@ fn set_indent<'gc>(
|
|||
) -> Result<(), Error<'gc>> {
|
||||
text_format.indent = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -319,8 +315,7 @@ fn set_leading<'gc>(
|
|||
) -> Result<(), Error<'gc>> {
|
||||
text_format.leading = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -342,8 +337,7 @@ fn set_block_indent<'gc>(
|
|||
) -> Result<(), Error<'gc>> {
|
||||
text_format.block_indent = match value {
|
||||
Value::Undefined | Value::Null => None,
|
||||
// TODO: round up
|
||||
value => Some(value.coerce_to_i32(activation)?.into()),
|
||||
value => Some(round_to_i32(value.coerce_to_f64(activation)?).into()),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -376,8 +370,7 @@ fn set_tab_stops<'gc>(
|
|||
let tab_stops: Result<Vec<_>, Error<'gc>> = (0..length)
|
||||
.map(|i| {
|
||||
let element = object.get_element(activation, i);
|
||||
// TODO: round up
|
||||
Ok(element.coerce_to_i32(activation)?.into())
|
||||
Ok(round_to_i32(element.coerce_to_f64(activation)?).into())
|
||||
})
|
||||
.collect();
|
||||
Some(tab_stops?)
|
||||
|
@ -551,3 +544,23 @@ pub fn create_proto<'gc>(
|
|||
define_properties_on(PROTO_DECLS, gc_context, object, fn_proto);
|
||||
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_border_color, "avm1/textfield_border_color", 1),
|
||||
(textfield_variable, "avm1/textfield_variable", 8),
|
||||
(text_format, "avm1/text_format", 1),
|
||||
(error, "avm1/error", 1),
|
||||
(color_transform, "avm1/color_transform", 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