mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Sync Servo / Gecko image-orientation rounding; pass as enum.
Make Servo's rounding of image-orientation values agree with Gecko's, and pass orientations directly as an enum instead of as angles. Depends on a Gecko change to be subsequently landed in m-c.
This commit is contained in:
parent
8e14d93602
commit
c6a7f10182
4 changed files with 85 additions and 29 deletions
|
@ -900,7 +900,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_SetImageOrientation(aVisibility: *mut nsStyleVisibility,
|
pub fn Gecko_SetImageOrientation(aVisibility: *mut nsStyleVisibility,
|
||||||
aRadians: f64, aFlip: bool);
|
aOrientation: u8, aFlip: bool);
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_SetImageOrientationAsFromImage(aVisibility:
|
pub fn Gecko_SetImageOrientationAsFromImage(aVisibility:
|
||||||
|
|
|
@ -3851,9 +3851,9 @@ fn static_assert() {
|
||||||
bindings::Gecko_SetImageOrientationAsFromImage(&mut self.gecko);
|
bindings::Gecko_SetImageOrientationAsFromImage(&mut self.gecko);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
T::AngleWithFlipped(ref angle, flipped) => {
|
T::AngleWithFlipped(ref orientation, flipped) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_SetImageOrientation(&mut self.gecko, angle.radians() as f64, flipped);
|
bindings::Gecko_SetImageOrientation(&mut self.gecko, *orientation as u8, flipped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,8 @@ ${helpers.single_keyword("image-rendering",
|
||||||
|
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
use std::f32::consts::PI;
|
use std::f64::consts::PI;
|
||||||
use values::CSSFloat;
|
const TWO_PI: f64 = 2.0 * PI;
|
||||||
const TWO_PI: CSSFloat = 2.0 * PI;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
@ -99,31 +98,77 @@ ${helpers.single_keyword("image-rendering",
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use values::computed::Angle;
|
use std::fmt;
|
||||||
|
use style_traits::ToCss;
|
||||||
|
use values::specified::Angle;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum Orientation {
|
||||||
|
Angle0 = 0,
|
||||||
|
Angle90,
|
||||||
|
Angle180,
|
||||||
|
Angle270,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Orientation {
|
||||||
|
pub fn angle(&self) -> Angle {
|
||||||
|
match *self {
|
||||||
|
Orientation::Angle0 => Angle::from_degrees(0.0, false),
|
||||||
|
Orientation::Angle90 => Angle::from_degrees(90.0, false),
|
||||||
|
Orientation::Angle180 => Angle::from_degrees(180.0, false),
|
||||||
|
Orientation::Angle270 => Angle::from_degrees(270.0, false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Orientation {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
// Should agree with Angle::to_css.
|
||||||
|
match *self {
|
||||||
|
Orientation::Angle0 => dest.write_str("0deg"),
|
||||||
|
Orientation::Angle90 => dest.write_str("90deg"),
|
||||||
|
Orientation::Angle180 => dest.write_str("180deg"),
|
||||||
|
Orientation::Angle270 => dest.write_str("270deg"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum T {
|
pub enum T {
|
||||||
FromImage,
|
FromImage,
|
||||||
AngleWithFlipped(Angle, bool),
|
AngleWithFlipped(Orientation, bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use self::computed_value::Orientation;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T::AngleWithFlipped(computed::Angle::zero(), false)
|
computed_value::T::AngleWithFlipped(Orientation::Angle0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to CSS Content Module Level 3:
|
// According to CSS Content Module Level 3:
|
||||||
// The computed value of the property is calculated by rounding the specified angle
|
// The computed value of the property is calculated by rounding the specified angle
|
||||||
// to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
|
// to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
|
||||||
|
// This mirrors the Gecko implementation in
|
||||||
|
// nsStyleImageOrientation::CreateAsAngleAndFlip.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn normalize_angle(angle: &computed::Angle) -> computed::Angle {
|
fn orientation_of_angle(angle: &computed::Angle) -> Orientation {
|
||||||
let radians = angle.radians();
|
// Note that `angle` can be negative.
|
||||||
let rounded_quarter_turns = (4.0 * radians / TWO_PI).round();
|
let mut rounded_angle = angle.radians64() % TWO_PI;
|
||||||
let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0;
|
if rounded_angle < 0.0 {
|
||||||
let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI;
|
// This computation introduces rounding error. Gecko previously
|
||||||
computed::Angle::from_radians(normalized_radians)
|
// didn't handle the negative case correctly; by branching we can
|
||||||
|
// match Gecko's behavior when it was correct.
|
||||||
|
rounded_angle = rounded_angle + TWO_PI;
|
||||||
|
}
|
||||||
|
if rounded_angle < 0.25 * PI { Orientation::Angle0 }
|
||||||
|
else if rounded_angle < 0.75 * PI { Orientation::Angle90 }
|
||||||
|
else if rounded_angle < 1.25 * PI { Orientation::Angle180 }
|
||||||
|
else if rounded_angle < 1.75 * PI { Orientation::Angle270 }
|
||||||
|
else { Orientation::Angle0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -133,11 +178,11 @@ ${helpers.single_keyword("image-rendering",
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
if let Some(ref angle) = self.angle {
|
if let Some(ref angle) = self.angle {
|
||||||
let angle = angle.to_computed_value(context);
|
let angle = angle.to_computed_value(context);
|
||||||
let normalized_angle = normalize_angle(&angle);
|
let orientation = orientation_of_angle(&angle);
|
||||||
computed_value::T::AngleWithFlipped(normalized_angle, self.flipped)
|
computed_value::T::AngleWithFlipped(orientation, self.flipped)
|
||||||
} else {
|
} else {
|
||||||
if self.flipped {
|
if self.flipped {
|
||||||
computed_value::T::AngleWithFlipped(computed::Angle::zero(), true)
|
computed_value::T::AngleWithFlipped(Orientation::Angle0, true)
|
||||||
} else {
|
} else {
|
||||||
computed_value::T::FromImage
|
computed_value::T::FromImage
|
||||||
}
|
}
|
||||||
|
@ -148,9 +193,9 @@ ${helpers.single_keyword("image-rendering",
|
||||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||||
match *computed {
|
match *computed {
|
||||||
computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
|
computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
|
||||||
computed_value::T::AngleWithFlipped(ref angle, flipped) => {
|
computed_value::T::AngleWithFlipped(ref orientation, flipped) => {
|
||||||
SpecifiedValue {
|
SpecifiedValue {
|
||||||
angle: Some(Angle::from_computed_value(angle)),
|
angle: Some(orientation.angle()),
|
||||||
flipped: flipped,
|
flipped: flipped,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ use media_queries::Device;
|
||||||
use properties;
|
use properties;
|
||||||
use properties::{ComputedValues, StyleBuilder};
|
use properties::{ComputedValues, StyleBuilder};
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::f32::consts::PI;
|
use std::f64;
|
||||||
|
use std::f64::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use super::{CSSFloat, CSSInteger, RGBA};
|
use super::{CSSFloat, CSSInteger, RGBA};
|
||||||
|
@ -313,17 +314,27 @@ impl Angle {
|
||||||
/// Return the amount of radians this angle represents.
|
/// Return the amount of radians this angle represents.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn radians(&self) -> CSSFloat {
|
pub fn radians(&self) -> CSSFloat {
|
||||||
const RAD_PER_DEG: CSSFloat = PI / 180.0;
|
self.radians64().min(f32::MAX as f64).max(f32::MIN as f64) as f32
|
||||||
const RAD_PER_GRAD: CSSFloat = PI / 200.0;
|
}
|
||||||
const RAD_PER_TURN: CSSFloat = PI * 2.0;
|
|
||||||
|
/// Return the amount of radians this angle represents as a 64-bit float.
|
||||||
|
/// Gecko stores angles as singles, but does this computation using doubles.
|
||||||
|
/// See nsCSSValue::GetAngleValueInRadians.
|
||||||
|
/// This is significant enough to mess up rounding to the nearest
|
||||||
|
/// quarter-turn for 225 degrees, for example.
|
||||||
|
#[inline]
|
||||||
|
pub fn radians64(&self) -> f64 {
|
||||||
|
const RAD_PER_DEG: f64 = PI / 180.0;
|
||||||
|
const RAD_PER_GRAD: f64 = PI / 200.0;
|
||||||
|
const RAD_PER_TURN: f64 = PI * 2.0;
|
||||||
|
|
||||||
let radians = match *self {
|
let radians = match *self {
|
||||||
Angle::Degree(val) => val * RAD_PER_DEG,
|
Angle::Degree(val) => val as f64 * RAD_PER_DEG,
|
||||||
Angle::Gradian(val) => val * RAD_PER_GRAD,
|
Angle::Gradian(val) => val as f64 * RAD_PER_GRAD,
|
||||||
Angle::Turn(val) => val * RAD_PER_TURN,
|
Angle::Turn(val) => val as f64 * RAD_PER_TURN,
|
||||||
Angle::Radian(val) => val,
|
Angle::Radian(val) => val as f64,
|
||||||
};
|
};
|
||||||
radians.min(f32::MAX).max(f32::MIN)
|
radians.min(f64::MAX).max(f64::MIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an angle that represents a rotation of zero radians.
|
/// Returns an angle that represents a rotation of zero radians.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue