render: Improve performance of round_to_i32

This patch improves performance of matrix::round_to_i32()
by using f32::round_ties_even(), which has been stable
since 1.77.0, instead of a custom algorithm.
This commit is contained in:
Kamil Jarosz 2024-05-08 13:36:45 +02:00 committed by Adrian Wielgosik
parent 6ad4bc4999
commit b99bdadb8f
1 changed files with 3 additions and 8 deletions

View File

@ -1,5 +1,7 @@
use swf::{Fixed16, Point, PointDelta, Rectangle, Twips};
/// TODO: Consider using portable SIMD when it's stable (https://doc.rust-lang.org/std/simd/index.html).
/// The transformation matrix used by Flash display objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Matrix {
@ -286,18 +288,11 @@ impl From<Matrix> for swf::Matrix {
/// 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 transforms.
/// Although this is easy to do on most architectures, Rust provides no standard
/// way to round in this manner (`f32::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(f: f32) -> i32 {
if f.is_finite() {
let a = f.abs();
if f < 2_147_483_648.0_f32 {
let k = 1.0 / f32::EPSILON;
let out = if a < k { ((a + k) - k).copysign(f) } else { f };
out as i32
f.round_ties_even() as i32
} else {
// Out-of-range clamps to MIN.
i32::MIN