mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
Auto merge of #12521 - Manishearth:safer-coord, r=bholley
Introduce safer layer of sugar for nsStyleUnion This routes (almost) all access to nsStyleUnion through a largely safe interface, CoordData. It also introduces a corresponding Rust enum, CoordDataValue, which can be used when interacting with CoordData LLVM should optimize the costs away in release mode. eddyb tested this a bit, and LLVM has no trouble threading matches together with inlining -- so all of the matches using enums here will have the same generated code as the old matches on the units. Some unresolved questions: Should I provide convenience methods like `set_coord`, `set_auto`, etc on CoordData? `.set_enum(CoordDataValue::Something)` should optimize down to the same thing, but the convenience methods look cleaner and won't load the optimizer as much. Also, we're converting immutable references to mutable ones, which can be used to cause unsafety using some acrobatics. Perhaps a trait-based approach is better? The issue is that in some places we only have a `&CoordData` (eg copy_from), but CoordData internally is `*mut`. It would be nice if CoordData could parametrize over its mutability, but Rust doesn't let us do that. The alternate approach is to make CoordData a trait (also CoordDataMut). The trait requires you to implement `get_union()` and `get_unit()`, and gives you the rest of the functions for free. `nsStyleCoord` would directly implement both traits. `nsStyleSides` would have `data_at(idx)` and `data_at_mut(idx)` methods which return a struct `SidesData` containing a reference to the Sides and the index, which itself implements the `CoordData` and `CoordDataMut` trait (we need two traits here because there will have to be two `SidesData` structs). I decided not to implement the traits approach first since it's pretty trivial to change this code to use traits, and the current design is more straightforward. Thoughts? r? @bholley cc @emilio @heycam <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12521) <!-- Reviewable:end -->
This commit is contained in:
commit
4a77cbdbb2
5 changed files with 461 additions and 352 deletions
|
@ -6,291 +6,117 @@
|
|||
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use gecko_bindings::structs::{nsStyleCoord, nsStyleUnion, nsStyleUnit};
|
||||
use gecko_bindings::structs::nsStyleCoord;
|
||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
|
||||
use std::cmp::max;
|
||||
use values::computed::Angle;
|
||||
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||
|
||||
|
||||
pub trait StyleCoordHelpers {
|
||||
fn copy_from(&mut self, other: &Self);
|
||||
fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T);
|
||||
|
||||
fn set_auto(&mut self);
|
||||
fn is_auto(&self) -> bool;
|
||||
|
||||
fn set_normal(&mut self);
|
||||
fn is_normal(&self) -> bool;
|
||||
|
||||
fn set_coord(&mut self, val: Au);
|
||||
fn is_coord(&self) -> bool;
|
||||
fn get_coord(&self) -> Au;
|
||||
|
||||
fn set_int(&mut self, val: i32);
|
||||
fn is_int(&self) -> bool;
|
||||
fn get_int(&self) -> i32;
|
||||
|
||||
fn set_enum(&mut self, val: i32);
|
||||
fn is_enum(&self) -> bool;
|
||||
fn get_enum(&self) -> i32;
|
||||
|
||||
fn set_percent(&mut self, val: f32);
|
||||
fn is_percent(&self) -> bool;
|
||||
fn get_percent(&self) -> f32;
|
||||
|
||||
fn set_factor(&mut self, val: f32);
|
||||
fn is_factor(&self) -> bool;
|
||||
fn get_factor(&self) -> f32;
|
||||
}
|
||||
|
||||
impl StyleCoordHelpers for nsStyleCoord {
|
||||
#[inline]
|
||||
fn copy_from(&mut self, other: &Self) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = other.mUnit;
|
||||
self.mValue = other.mValue;
|
||||
unsafe { self.addref_if_calc(); }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T) {
|
||||
val.to_gecko_style_coord(&mut self.mUnit, &mut self.mValue);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_auto(&mut self) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Auto;
|
||||
unsafe { *self.mValue.mInt.as_mut() = 0; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_auto(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Auto
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_normal(&mut self) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Normal;
|
||||
unsafe { *self.mValue.mInt.as_mut() = 0; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_normal(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Normal
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_coord(&mut self, val: Au) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Coord;
|
||||
unsafe { *self.mValue.mInt.as_mut() = val.0; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_coord(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Coord
|
||||
}
|
||||
#[inline]
|
||||
fn get_coord(&self) -> Au {
|
||||
debug_assert!(self.is_coord());
|
||||
Au(unsafe { *self.mValue.mInt.as_ref() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_int(&mut self, val: i32) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Integer;
|
||||
unsafe { *self.mValue.mInt.as_mut() = val; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_int(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Integer
|
||||
}
|
||||
#[inline]
|
||||
fn get_int(&self) -> i32 {
|
||||
debug_assert!(self.is_int());
|
||||
unsafe { *self.mValue.mInt.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_enum(&mut self, val: i32) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Enumerated;
|
||||
unsafe { *self.mValue.mInt.as_mut() = val; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_enum(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Enumerated
|
||||
}
|
||||
#[inline]
|
||||
fn get_enum(&self) -> i32 {
|
||||
debug_assert!(self.is_enum());
|
||||
unsafe { *self.mValue.mInt.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_percent(&mut self, val: f32) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Percent;
|
||||
unsafe { *self.mValue.mFloat.as_mut() = val; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_percent(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Percent
|
||||
}
|
||||
#[inline]
|
||||
fn get_percent(&self) -> f32 {
|
||||
debug_assert!(self.is_percent());
|
||||
unsafe { *self.mValue.mFloat.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_factor(&mut self, val: f32) {
|
||||
unsafe { self.mValue.reset(&mut self.mUnit) };
|
||||
self.mUnit = nsStyleUnit::eStyleUnit_Factor;
|
||||
unsafe { *self.mValue.mFloat.as_mut() = val; }
|
||||
}
|
||||
#[inline]
|
||||
fn is_factor(&self) -> bool {
|
||||
self.mUnit == nsStyleUnit::eStyleUnit_Factor
|
||||
}
|
||||
#[inline]
|
||||
fn get_factor(&self) -> f32 {
|
||||
debug_assert!(self.is_factor());
|
||||
unsafe { *self.mValue.mFloat.as_ref() }
|
||||
val.to_gecko_style_coord(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait GeckoStyleCoordConvertible : Sized {
|
||||
fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion);
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self>;
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T);
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentage {
|
||||
fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
|
||||
unsafe { union.reset(unit) };
|
||||
match *self {
|
||||
LengthOrPercentage::Length(au) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Coord;
|
||||
unsafe { *union.mInt.as_mut() = au.0; }
|
||||
},
|
||||
LengthOrPercentage::Percentage(p) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Percent;
|
||||
unsafe { *union.mFloat.as_mut() = p; }
|
||||
},
|
||||
LengthOrPercentage::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) },
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentage::Length(au) => CoordDataValue::Coord(au.0),
|
||||
LengthOrPercentage::Percentage(p) => CoordDataValue::Percent(p),
|
||||
LengthOrPercentage::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
|
||||
match *unit {
|
||||
nsStyleUnit::eStyleUnit_Coord
|
||||
=> Some(LengthOrPercentage::Length(Au(unsafe { *union.mInt.as_ref() }))),
|
||||
nsStyleUnit::eStyleUnit_Percent
|
||||
=> Some(LengthOrPercentage::Percentage(unsafe { *union.mFloat.as_ref() })),
|
||||
nsStyleUnit::eStyleUnit_Calc
|
||||
=> Some(LengthOrPercentage::Calc(unsafe { union.get_calc().into() })),
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord))),
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentage::Percentage(p)),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentage::Calc(calc.into())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
|
||||
fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
|
||||
unsafe { union.reset(unit) };
|
||||
match *self {
|
||||
LengthOrPercentageOrAuto::Length(au) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Coord;
|
||||
unsafe { *union.mInt.as_mut() = au.0; }
|
||||
},
|
||||
LengthOrPercentageOrAuto::Percentage(p) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Percent;
|
||||
unsafe { *union.mFloat.as_mut() = p; }
|
||||
},
|
||||
LengthOrPercentageOrAuto::Auto => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Auto;
|
||||
unsafe { *union.mInt.as_mut() = 0; }
|
||||
},
|
||||
LengthOrPercentageOrAuto::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) },
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentageOrAuto::Length(au) => CoordDataValue::Coord(au.0),
|
||||
LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p),
|
||||
LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
|
||||
LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
|
||||
match *unit {
|
||||
nsStyleUnit::eStyleUnit_Auto
|
||||
=> Some(LengthOrPercentageOrAuto::Auto),
|
||||
nsStyleUnit::eStyleUnit_Coord
|
||||
=> Some(LengthOrPercentageOrAuto::Length(Au(unsafe { *union.mInt.as_ref() }))),
|
||||
nsStyleUnit::eStyleUnit_Percent
|
||||
=> Some(LengthOrPercentageOrAuto::Percentage(unsafe { *union.mFloat.as_ref() })),
|
||||
nsStyleUnit::eStyleUnit_Calc
|
||||
=> Some(LengthOrPercentageOrAuto::Calc(unsafe { union.get_calc().into() })),
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrAuto::Length(Au(coord))),
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrAuto::Percentage(p)),
|
||||
CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrAuto::Calc(calc.into())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
|
||||
fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
|
||||
unsafe { union.reset(unit) };
|
||||
match *self {
|
||||
LengthOrPercentageOrNone::Length(au) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Coord;
|
||||
unsafe { *union.mInt.as_mut() = au.0; }
|
||||
},
|
||||
LengthOrPercentageOrNone::Percentage(p) => {
|
||||
*unit = nsStyleUnit::eStyleUnit_Percent;
|
||||
unsafe { *union.mFloat.as_mut() = p; }
|
||||
},
|
||||
LengthOrPercentageOrNone::None => {
|
||||
*unit = nsStyleUnit::eStyleUnit_None;
|
||||
unsafe { *union.mInt.as_mut() = 0; }
|
||||
},
|
||||
LengthOrPercentageOrNone::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) },
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentageOrNone::Length(au) => CoordDataValue::Coord(au.0),
|
||||
LengthOrPercentageOrNone::Percentage(p) => CoordDataValue::Percent(p),
|
||||
LengthOrPercentageOrNone::None => CoordDataValue::None,
|
||||
LengthOrPercentageOrNone::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
|
||||
match *unit {
|
||||
nsStyleUnit::eStyleUnit_None
|
||||
=> Some(LengthOrPercentageOrNone::None),
|
||||
nsStyleUnit::eStyleUnit_Coord
|
||||
=> Some(LengthOrPercentageOrNone::Length(Au(unsafe { *union.mInt.as_ref() }))),
|
||||
nsStyleUnit::eStyleUnit_Percent
|
||||
=> Some(LengthOrPercentageOrNone::Percentage(unsafe { *union.mFloat.as_ref() })),
|
||||
nsStyleUnit::eStyleUnit_Calc
|
||||
=> Some(LengthOrPercentageOrNone::Calc(unsafe { union.get_calc().into() })),
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrNone::Length(Au(coord))),
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrNone::Percentage(p)),
|
||||
CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrNone::Calc(calc.into())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> {
|
||||
fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) {
|
||||
unsafe { union.reset(unit) };
|
||||
fn to_gecko_style_coord<U: CoordDataMut>(&self, coord: &mut U) {
|
||||
if let Some(ref me) = *self {
|
||||
me.to_gecko_style_coord(unit, union);
|
||||
me.to_gecko_style_coord(coord);
|
||||
} else {
|
||||
*unit = nsStyleUnit::eStyleUnit_None;
|
||||
unsafe { *union.mInt.as_mut() = 0; }
|
||||
coord.set_value(CoordDataValue::None);
|
||||
}
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
|
||||
Some(T::from_gecko_style_coord(unit, union))
|
||||
fn from_gecko_style_coord<U: CoordData>(coord: &U) -> Option<Self> {
|
||||
Some(T::from_gecko_style_coord(coord))
|
||||
}
|
||||
}
|
||||
|
||||
impl GeckoStyleCoordConvertible for Angle {
|
||||
fn to_gecko_style_coord(&self,
|
||||
unit: &mut nsStyleUnit,
|
||||
union: &mut nsStyleUnion) {
|
||||
unsafe { union.reset(unit) };
|
||||
*unit = nsStyleUnit::eStyleUnit_Radian;
|
||||
unsafe { *union.mFloat.as_mut() = self.radians() };
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
coord.set_value(CoordDataValue::Radian(self.radians()))
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord(unit: &nsStyleUnit, union: &nsStyleUnion) -> Option<Self> {
|
||||
if *unit == nsStyleUnit::eStyleUnit_Radian {
|
||||
Some(Angle::from_radians(unsafe { *union.mFloat.as_ref() }))
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
if let CoordDataValue::Radian(r) = coord.as_value() {
|
||||
Some(Angle::from_radians(r))
|
||||
// XXXManishearth should this handle Degree too?
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use gecko_bindings::bindings::{Gecko_FontFamilyList_AppendGeneric, Gecko_FontFam
|
|||
use gecko_bindings::bindings::{Gecko_FontFamilyList_Clear, Gecko_InitializeImageLayer};
|
||||
use gecko_bindings::bindings;
|
||||
use gecko_bindings::structs;
|
||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
|
||||
use gecko_glue::ArcHelpers;
|
||||
use gecko_values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
|
||||
use gecko_values::convert_rgba_to_nscolor;
|
||||
|
@ -325,67 +326,67 @@ def set_gecko_property(ffi_name, expr):
|
|||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="impl_split_style_coord(ident, unit_ffi_name, union_ffi_name, need_clone=False)">
|
||||
<%def name="impl_split_style_coord(ident, gecko_ffi_name, index, need_clone=False)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
v.to_gecko_style_coord(&mut self.gecko.${unit_ffi_name},
|
||||
&mut self.gecko.${union_ffi_name});
|
||||
v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${index}));
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.${union_ffi_name}.reset(&mut self.gecko.${unit_ffi_name}) };
|
||||
self.gecko.${unit_ffi_name} = other.gecko.${unit_ffi_name};
|
||||
self.gecko.${union_ffi_name} = other.gecko.${union_ffi_name};
|
||||
unsafe { self.gecko.${union_ffi_name}.addref_if_calc(&self.gecko.${unit_ffi_name}) };
|
||||
self.gecko.${gecko_ffi_name}.data_at_mut(${index}).copy_from(&other.gecko.${gecko_ffi_name}.data_at(${index}));
|
||||
}
|
||||
% if need_clone:
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use properties::longhands::${ident}::computed_value::T;
|
||||
T::from_gecko_style_coord(&self.gecko.${unit_ffi_name},
|
||||
&self.gecko.${union_ffi_name})
|
||||
T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}.data_at(${index}))
|
||||
.expect("clone for ${ident} failed")
|
||||
}
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="impl_style_coord(ident, gecko_ffi_name, need_clone=False)">
|
||||
${impl_split_style_coord(ident,
|
||||
"%s.mUnit" % gecko_ffi_name,
|
||||
"%s.mValue" % gecko_ffi_name,
|
||||
need_clone=need_clone)}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_corner_style_coord(ident, x_unit_ffi_name, x_union_ffi_name, \
|
||||
y_unit_ffi_name, y_union_ffi_name, need_clone=False)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
v.0.width.to_gecko_style_coord(&mut self.gecko.${x_unit_ffi_name},
|
||||
&mut self.gecko.${x_union_ffi_name});
|
||||
v.0.height.to_gecko_style_coord(&mut self.gecko.${y_unit_ffi_name},
|
||||
&mut self.gecko.${y_union_ffi_name});
|
||||
v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name});
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
unsafe { self.gecko.${x_union_ffi_name}.reset(&mut self.gecko.${x_unit_ffi_name}) };
|
||||
unsafe { self.gecko.${y_union_ffi_name}.reset(&mut self.gecko.${y_unit_ffi_name}) };
|
||||
self.gecko.${x_unit_ffi_name} = other.gecko.${x_unit_ffi_name};
|
||||
self.gecko.${x_union_ffi_name} = other.gecko.${x_union_ffi_name};
|
||||
self.gecko.${y_unit_ffi_name} = other.gecko.${y_unit_ffi_name};
|
||||
self.gecko.${y_union_ffi_name} = other.gecko.${y_union_ffi_name};
|
||||
unsafe { self.gecko.${x_union_ffi_name}.addref_if_calc(&self.gecko.${x_unit_ffi_name}) };
|
||||
unsafe { self.gecko.${y_union_ffi_name}.addref_if_calc(&self.gecko.${y_unit_ffi_name}) };
|
||||
self.gecko.${gecko_ffi_name}.copy_from(&other.gecko.${gecko_ffi_name});
|
||||
}
|
||||
% if need_clone:
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use properties::longhands::${ident}::computed_value::T;
|
||||
T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name})
|
||||
.expect("clone for ${ident} failed")
|
||||
}
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index, need_clone=False)">
|
||||
#[allow(non_snake_case)]
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
v.0.width.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
|
||||
v.0.height.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
|
||||
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
|
||||
self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
|
||||
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
|
||||
}
|
||||
% if need_clone:
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use properties::longhands::${ident}::computed_value::T;
|
||||
use euclid::Size2D;
|
||||
let width = GeckoStyleCoordConvertible::from_gecko_style_coord(&self.gecko.${x_unit_ffi_name},
|
||||
&self.gecko.${x_union_ffi_name})
|
||||
let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
|
||||
&self.gecko.${gecko_ffi_name}.data_at(${x_index}))
|
||||
.expect("Failed to clone ${ident}");
|
||||
let height = GeckoStyleCoordConvertible::from_gecko_style_coord(&self.gecko.${y_unit_ffi_name},
|
||||
&self.gecko.${y_union_ffi_name})
|
||||
let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
|
||||
&self.gecko.${gecko_ffi_name}.data_at(${y_index}))
|
||||
.expect("Failed to clone ${ident}");
|
||||
T(Size2D::new(width, height))
|
||||
}
|
||||
|
@ -602,10 +603,9 @@ fn static_assert() {
|
|||
|
||||
% for corner in CORNERS:
|
||||
<% impl_corner_style_coord("border_%s_radius" % corner.ident,
|
||||
"mBorderRadius.mUnits[%s]" % corner.x_index,
|
||||
"mBorderRadius.mValues[%s]" % corner.x_index,
|
||||
"mBorderRadius.mUnits[%s]" % corner.y_index,
|
||||
"mBorderRadius.mValues[%s]" % corner.y_index,
|
||||
"mBorderRadius",
|
||||
corner.x_index,
|
||||
corner.y_index,
|
||||
need_clone=True) %>
|
||||
% endfor
|
||||
</%self:impl_trait>
|
||||
|
@ -616,8 +616,8 @@ fn static_assert() {
|
|||
|
||||
% for side in SIDES:
|
||||
<% impl_split_style_coord("margin_%s" % side.ident,
|
||||
"mMargin.mUnits[%s]" % side.index,
|
||||
"mMargin.mValues[%s]" % side.index,
|
||||
"mMargin",
|
||||
side.index,
|
||||
need_clone=True) %>
|
||||
% endfor
|
||||
</%self:impl_trait>
|
||||
|
@ -628,8 +628,8 @@ fn static_assert() {
|
|||
|
||||
% for side in SIDES:
|
||||
<% impl_split_style_coord("padding_%s" % side.ident,
|
||||
"mPadding.mUnits[%s]" % side.index,
|
||||
"mPadding.mValues[%s]" % side.index,
|
||||
"mPadding",
|
||||
side.index,
|
||||
need_clone=True) %>
|
||||
% endfor
|
||||
</%self:impl_trait>
|
||||
|
@ -640,16 +640,16 @@ fn static_assert() {
|
|||
|
||||
% for side in SIDES:
|
||||
<% impl_split_style_coord("%s" % side.ident,
|
||||
"mOffset.mUnits[%s]" % side.index,
|
||||
"mOffset.mValues[%s]" % side.index,
|
||||
"mOffset",
|
||||
side.index,
|
||||
need_clone=True) %>
|
||||
% endfor
|
||||
|
||||
pub fn set_z_index(&mut self, v: longhands::z_index::computed_value::T) {
|
||||
use properties::longhands::z_index::computed_value::T;
|
||||
match v {
|
||||
T::Auto => self.gecko.mZIndex.set_auto(),
|
||||
T::Number(n) => self.gecko.mZIndex.set_int(n),
|
||||
T::Auto => self.gecko.mZIndex.set_value(CoordDataValue::Auto),
|
||||
T::Number(n) => self.gecko.mZIndex.set_value(CoordDataValue::Integer(n)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -664,13 +664,14 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_z_index(&self) -> longhands::z_index::computed_value::T {
|
||||
use properties::longhands::z_index::computed_value::T;
|
||||
|
||||
if self.gecko.mZIndex.is_auto() {
|
||||
return T::Auto;
|
||||
return match self.gecko.mZIndex.as_value() {
|
||||
CoordDataValue::Auto => T::Auto,
|
||||
CoordDataValue::Integer(n) => T::Number(n),
|
||||
_ => {
|
||||
debug_assert!(false);
|
||||
T::Number(0)
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(self.gecko.mZIndex.is_int());
|
||||
T::Number(self.gecko.mZIndex.get_int())
|
||||
}
|
||||
|
||||
pub fn set_box_sizing(&mut self, v: longhands::box_sizing::computed_value::T) {
|
||||
|
@ -702,10 +703,9 @@ fn static_assert() {
|
|||
|
||||
% for corner in CORNERS:
|
||||
<% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
|
||||
"mOutlineRadius.mUnits[%s]" % corner.x_index,
|
||||
"mOutlineRadius.mValues[%s]" % corner.x_index,
|
||||
"mOutlineRadius.mUnits[%s]" % corner.y_index,
|
||||
"mOutlineRadius.mValues[%s]" % corner.y_index) %>
|
||||
"mOutlineRadius",
|
||||
corner.x_index,
|
||||
corner.y_index) %>
|
||||
% endfor
|
||||
|
||||
pub fn outline_has_nonzero_width(&self) -> bool {
|
||||
|
@ -826,7 +826,8 @@ fn static_assert() {
|
|||
match v {
|
||||
% for value in keyword.values_for('gecko'):
|
||||
T::${to_rust_ident(value)} =>
|
||||
self.gecko.mVerticalAlign.set_enum(structs::${keyword.gecko_constant(value)} as i32),
|
||||
self.gecko.mVerticalAlign.set_value(
|
||||
CoordDataValue::Enumerated(structs::${keyword.gecko_constant(value)})),
|
||||
% endfor
|
||||
T::LengthOrPercentage(v) => self.gecko.mVerticalAlign.set(v),
|
||||
}
|
||||
|
@ -836,19 +837,16 @@ fn static_assert() {
|
|||
use properties::longhands::vertical_align::computed_value::T;
|
||||
use values::computed::LengthOrPercentage;
|
||||
|
||||
if self.gecko.mVerticalAlign.is_enum() {
|
||||
match self.gecko.mVerticalAlign.get_enum() as u32 {
|
||||
% for value in keyword.values_for('gecko'):
|
||||
structs::${keyword.gecko_constant(value)}
|
||||
=> T::${to_rust_ident(value)},
|
||||
% endfor
|
||||
_ => panic!("Unexpected enum variant for vertical-align"),
|
||||
}
|
||||
} else {
|
||||
let v = LengthOrPercentage::from_gecko_style_coord(&self.gecko.mVerticalAlign.mUnit,
|
||||
&self.gecko.mVerticalAlign.mValue)
|
||||
.expect("Expected length or percentage for vertical-align");
|
||||
T::LengthOrPercentage(v)
|
||||
match self.gecko.mVerticalAlign.as_value() {
|
||||
% for value in keyword.values_for('gecko'):
|
||||
CoordDataValue::Enumerated(structs::${keyword.gecko_constant(value)}) => T::${to_rust_ident(value)},
|
||||
% endfor
|
||||
CoordDataValue::Enumerated(_) => panic!("Unexpected enum variant for vertical-align"),
|
||||
_ => {
|
||||
let v = LengthOrPercentage::from_gecko_style_coord(&self.gecko.mVerticalAlign)
|
||||
.expect("Expected length or percentage for vertical-align");
|
||||
T::LengthOrPercentage(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1132,29 +1130,29 @@ fn static_assert() {
|
|||
pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
|
||||
use properties::longhands::line_height::computed_value::T;
|
||||
// FIXME: Align binary representations and ditch |match| for cast + static_asserts
|
||||
match v {
|
||||
T::Normal => self.gecko.mLineHeight.set_normal(),
|
||||
T::Length(val) => self.gecko.mLineHeight.set_coord(val),
|
||||
T::Number(val) => self.gecko.mLineHeight.set_factor(val),
|
||||
let en = match v {
|
||||
T::Normal => CoordDataValue::Normal,
|
||||
T::Length(val) => CoordDataValue::Coord(val.0),
|
||||
T::Number(val) => CoordDataValue::Factor(val),
|
||||
T::MozBlockHeight =>
|
||||
self.gecko.mLineHeight.set_enum(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT as i32),
|
||||
}
|
||||
CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
|
||||
};
|
||||
self.gecko.mLineHeight.set_value(en);
|
||||
}
|
||||
|
||||
pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
|
||||
use properties::longhands::line_height::computed_value::T;
|
||||
if self.gecko.mLineHeight.is_normal() {
|
||||
return T::Normal;
|
||||
return match self.gecko.mLineHeight.as_value() {
|
||||
CoordDataValue::Normal => T::Normal,
|
||||
CoordDataValue::Coord(coord) => T::Length(Au(coord)),
|
||||
CoordDataValue::Factor(n) => T::Number(n),
|
||||
CoordDataValue::Enumerated(val) if val == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT =>
|
||||
T::MozBlockHeight,
|
||||
_ => {
|
||||
debug_assert!(false);
|
||||
T::MozBlockHeight
|
||||
}
|
||||
}
|
||||
if self.gecko.mLineHeight.is_coord() {
|
||||
return T::Length(self.gecko.mLineHeight.get_coord());
|
||||
}
|
||||
if self.gecko.mLineHeight.is_factor() {
|
||||
return T::Number(self.gecko.mLineHeight.get_factor());
|
||||
}
|
||||
|
||||
debug_assert!(self.gecko.mLineHeight.get_enum() == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT as i32);
|
||||
T::MozBlockHeight
|
||||
}
|
||||
|
||||
<%call expr="impl_coord_copy('line_height', 'mLineHeight')"></%call>
|
||||
|
@ -1283,8 +1281,8 @@ fn static_assert() {
|
|||
|
||||
pub fn set_column_width(&mut self, v: longhands::column_width::computed_value::T) {
|
||||
match v.0 {
|
||||
Some(au) => self.gecko.mColumnWidth.set_coord(au),
|
||||
None => self.gecko.mColumnWidth.set_auto(),
|
||||
Some(au) => self.gecko.mColumnWidth.set_value(CoordDataValue::Coord(au.0)),
|
||||
None => self.gecko.mColumnWidth.set_value(CoordDataValue::Auto),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue