diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 6a008a09b9f..26159c5681c 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -10,49 +10,15 @@ #![allow(unsafe_code)] -use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko_bindings::bindings; -use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue, Matrix4x4Components}; +use crate::gecko_bindings::structs::{self, Matrix4x4Components}; use crate::gecko_bindings::structs::{nsStyleImage, nsresult}; use crate::stylesheets::RulesMutateError; use crate::values::computed::transform::Matrix3D; use crate::values::computed::url::ComputedImageUrl; -use crate::values::computed::{Gradient, Image, LengthPercentage}; -use crate::values::computed::{Length, Percentage, TextAlign}; +use crate::values::computed::{Gradient, Image, TextAlign}; use crate::values::generics::image::GenericImage; use crate::values::generics::rect::Rect; -use crate::Zero; -use app_units::Au; -use style_traits::values::specified::AllowedNumericType; - -impl From for nsStyleCoord_CalcValue { - fn from(other: LengthPercentage) -> nsStyleCoord_CalcValue { - debug_assert!( - other.was_calc || !other.has_percentage || other.unclamped_length() == Length::zero() - ); - nsStyleCoord_CalcValue { - mLength: other.unclamped_length().to_i32_au(), - mPercent: other.percentage(), - mHasPercent: other.has_percentage, - } - } -} - -impl From for LengthPercentage { - fn from(other: nsStyleCoord_CalcValue) -> LengthPercentage { - let percentage = if other.mHasPercent { - Some(Percentage(other.mPercent)) - } else { - None - }; - Self::with_clamping_mode( - Au(other.mLength).into(), - percentage, - AllowedNumericType::All, - /* was_calc = */ true, - ) - } -} impl nsStyleImage { /// Set a given Servo `Image` value into this `nsStyleImage`. @@ -296,31 +262,6 @@ impl From for nsresult { } } -impl Rect -where - T: GeckoStyleCoordConvertible, -{ - /// Convert this generic Rect to given Gecko fields. - pub fn to_gecko_rect(&self, sides: &mut crate::gecko_bindings::structs::nsStyleSides) { - self.0.to_gecko_style_coord(&mut sides.data_at_mut(0)); - self.1.to_gecko_style_coord(&mut sides.data_at_mut(1)); - self.2.to_gecko_style_coord(&mut sides.data_at_mut(2)); - self.3.to_gecko_style_coord(&mut sides.data_at_mut(3)); - } - - /// Convert from given Gecko data to generic Rect. - pub fn from_gecko_rect( - sides: &crate::gecko_bindings::structs::nsStyleSides, - ) -> Option> { - Some(Rect::new( - T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(2)).expect("coord[2] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(3)).expect("coord[3] cound not convert"), - )) - } -} - impl TextAlign { /// Obtain a specified value from a Gecko keyword value /// diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index c5a096bdff1..f0c998f8f08 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -7,165 +7,15 @@ //! Different kind of helpers to interact with Gecko values. use crate::counter_style::{Symbol, Symbols}; -use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr}; -use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; -use crate::values::computed::{Length, LengthPercentage}; -use crate::values::computed::{Number, NumberOrPercentage, Percentage}; -use crate::values::generics::length::LengthPercentageOrAuto; -use crate::values::generics::{CounterStyleOrNone, NonNegative}; +use crate::gecko_bindings::structs::CounterStylePtr; +use crate::values::generics::CounterStyleOrNone; use crate::values::Either; -use crate::{Atom, Zero}; +use crate::Atom; use app_units::Au; use cssparser::RGBA; use nsstring::{nsACString, nsCStr}; use std::cmp::max; -/// A trait that defines an interface to convert from and to `nsStyleCoord`s. -/// -/// TODO(emilio): Almost everything that is in this file should be somehow -/// switched to cbindgen. -pub trait GeckoStyleCoordConvertible: Sized { - /// Convert this to a `nsStyleCoord`. - fn to_gecko_style_coord(&self, coord: &mut T); - /// Given a `nsStyleCoord`, try to get a value of this type.. - fn from_gecko_style_coord(coord: &T) -> Option; -} - -impl nsStyleCoord { - #[inline] - /// Set this `nsStyleCoord` value to `val`. - pub fn set(&mut self, val: T) { - val.to_gecko_style_coord(self); - } -} - -impl GeckoStyleCoordConvertible for NonNegative -where - Inner: GeckoStyleCoordConvertible, -{ - fn to_gecko_style_coord(&self, coord: &mut T) { - self.0.to_gecko_style_coord(coord) - } - - fn from_gecko_style_coord(coord: &T) -> Option { - Some(NonNegative(Inner::from_gecko_style_coord(coord)?)) - } -} - -impl GeckoStyleCoordConvertible for Number { - fn to_gecko_style_coord(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Factor(*self)); - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Factor(f) => Some(f), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for Percentage { - fn to_gecko_style_coord(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Percent(self.0)); - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Percent(p) => Some(Percentage(p)), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for NumberOrPercentage { - fn to_gecko_style_coord(&self, coord: &mut T) { - match *self { - NumberOrPercentage::Number(ref n) => n.to_gecko_style_coord(coord), - NumberOrPercentage::Percentage(ref p) => p.to_gecko_style_coord(coord), - } - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Factor(f) => Some(NumberOrPercentage::Number(f)), - CoordDataValue::Percent(p) => Some(NumberOrPercentage::Percentage(Percentage(p))), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for LengthPercentage { - fn to_gecko_style_coord(&self, coord: &mut T) { - if self.was_calc { - return coord.set_value(CoordDataValue::Calc((*self).into())); - } - debug_assert!(!self.has_percentage || self.unclamped_length() == Length::zero()); - if self.has_percentage { - return coord.set_value(CoordDataValue::Percent(self.percentage())); - } - coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au())) - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Coord(coord) => Some(LengthPercentage::new(Au(coord).into(), None)), - CoordDataValue::Percent(p) => { - Some(LengthPercentage::new(Au(0).into(), Some(Percentage(p)))) - }, - CoordDataValue::Calc(calc) => Some(calc.into()), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for Length { - fn to_gecko_style_coord(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Coord(self.to_i32_au())); - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Coord(coord) => Some(Au(coord).into()), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for LengthPercentageOrAuto -where - LengthPercentage: GeckoStyleCoordConvertible, -{ - fn to_gecko_style_coord(&self, coord: &mut T) { - match *self { - LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto), - LengthPercentageOrAuto::LengthPercentage(ref lp) => lp.to_gecko_style_coord(coord), - } - } - - fn from_gecko_style_coord(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::Auto => Some(LengthPercentageOrAuto::Auto), - _ => LengthPercentage::from_gecko_style_coord(coord) - .map(LengthPercentageOrAuto::LengthPercentage), - } - } -} - -impl GeckoStyleCoordConvertible for Option { - fn to_gecko_style_coord(&self, coord: &mut U) { - if let Some(ref me) = *self { - me.to_gecko_style_coord(coord); - } else { - coord.set_value(CoordDataValue::None); - } - } - - fn from_gecko_style_coord(coord: &U) -> Option { - Some(T::from_gecko_style_coord(coord)) - } -} - /// Convert a given RGBA value to `nscolor`. pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 { ((rgba.alpha as u32) << 24) | diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs index 338236c175a..00faf63ba66 100644 --- a/components/style/gecko_bindings/sugar/mod.rs +++ b/components/style/gecko_bindings/sugar/mod.rs @@ -7,7 +7,6 @@ mod ns_com_ptr; mod ns_compatibility; mod ns_style_auto_array; -pub mod ns_style_coord; mod ns_t_array; pub mod origin_flags; pub mod ownership; diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs deleted file mode 100644 index 7c6612f35ef..00000000000 --- a/components/style/gecko_bindings/sugar/ns_style_coord.rs +++ /dev/null @@ -1,369 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -//! Rust helpers for Gecko's `nsStyleCoord`. - -use crate::gecko_bindings::bindings; -use crate::gecko_bindings::structs::nsStyleSides; -use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue}; -use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord}; -use std::mem; - -impl nsStyleCoord { - #[inline] - /// Get a `null` nsStyleCoord. - pub fn null() -> Self { - // Can't construct directly because it has private fields - let mut coord: Self = unsafe { mem::zeroed() }; - coord.leaky_set_null(); - coord - } -} - -unsafe impl CoordData for nsStyleCoord { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { *self.get_mUnit() } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { *self.get_mValue() } - } -} - -unsafe impl CoordDataMut for nsStyleCoord { - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) { - let unit = self.get_mUnit_mut() as *mut _; - let value = self.get_mValue_mut() as *mut _; - (&mut *unit, &mut *value) - } -} - -impl nsStyleCoord_CalcValue { - /// Create an "empty" CalcValue (whose value is `0`). - pub fn new() -> Self { - nsStyleCoord_CalcValue { - mLength: 0, - mPercent: 0.0, - mHasPercent: false, - } - } -} - -impl PartialEq for nsStyleCoord_CalcValue { - fn eq(&self, other: &Self) -> bool { - self.mLength == other.mLength && - self.mPercent == other.mPercent && - self.mHasPercent == other.mHasPercent - } -} - -impl nsStyleSides { - /// Immutably get the `nsStyleCoord`-like object representing the side at - /// index `index`. - #[inline] - pub fn data_at(&self, index: usize) -> SidesData { - SidesData { - sides: self, - index: index, - } - } - - /// Mutably get the `nsStyleCoord`-like object representing the side at - /// index `index`. - #[inline] - pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut { - SidesDataMut { - sides: self, - index: index, - } - } -} - -/// A `nsStyleCoord`-like object on top of an immutable reference to -/// `nsStyleSides`. -pub struct SidesData<'a> { - sides: &'a nsStyleSides, - index: usize, -} - -/// A `nsStyleCoord`-like object on top of an mutable reference to -/// `nsStyleSides`. -pub struct SidesDataMut<'a> { - sides: &'a mut nsStyleSides, - index: usize, -} - -unsafe impl<'a> CoordData for SidesData<'a> { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { self.sides.get_mUnits()[self.index] } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { self.sides.get_mValues()[self.index] } - } -} -unsafe impl<'a> CoordData for SidesDataMut<'a> { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { self.sides.get_mUnits()[self.index] } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { self.sides.get_mValues()[self.index] } - } -} -unsafe impl<'a> CoordDataMut for SidesDataMut<'a> { - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) { - let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _; - let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _; - (&mut *unit, &mut *value) - } -} - -/// Enum representing the tagged union that is CoordData. -/// -/// In release mode this should never actually exist in the code, and will be -/// optimized out by threading matches and inlining. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum CoordDataValue { - /// eStyleUnit_Null - Null, - /// eStyleUnit_Normal - Normal, - /// eStyleUnit_Auto - Auto, - /// eStyleUnit_None - None, - /// eStyleUnit_Percent - Percent(f32), - /// eStyleUnit_Factor - Factor(f32), - /// eStyleUnit_Degree - Degree(f32), - /// eStyleUnit_FlexFraction - FlexFraction(f32), - /// eStyleUnit_Coord - Coord(nscoord), - /// eStyleUnit_Integer - Integer(i32), - /// eStyleUnit_Enumerated - Enumerated(u32), - /// eStyleUnit_Calc - Calc(nsStyleCoord_CalcValue), -} - -/// A trait to abstract on top of a mutable `nsStyleCoord`-like object. -pub unsafe trait CoordDataMut: CoordData { - /// Get mutably the unit and the union. - /// - /// This is unsafe since it's possible to modify the unit without changing - /// the union. - /// - /// NB: This can't be two methods since we can't mutably borrow twice - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion); - - /// Clean up any resources used by the union. - /// - /// Currently, this only happens if the nsStyleUnit is a Calc. - #[inline] - fn reset(&mut self) { - unsafe { - if self.unit() == nsStyleUnit::eStyleUnit_Calc { - let (unit, union) = self.values_mut(); - bindings::Gecko_ResetStyleCoord(unit, union); - } - } - } - - #[inline] - /// Copies the unit and value from another `CoordData` type. - fn copy_from(&mut self, other: &T) { - unsafe { - self.reset(); - self.copy_from_unchecked(other); - self.addref_if_calc(); - } - } - - #[inline] - /// Moves the unit and value from another `CoordData` type. - fn move_from(&mut self, other: T) { - unsafe { - self.reset(); - self.copy_from_unchecked(&other); - } - } - - #[inline] - /// Copies the unit and value from another `CoordData` type without checking - /// the type of the value (so refcounted values like calc may leak). - unsafe fn copy_from_unchecked(&mut self, other: &T) { - let (unit, union) = self.values_mut(); - *unit = other.unit(); - *union = other.union(); - } - - /// Useful for initializing uninits, given that `set_value` may segfault on - /// uninits. - fn leaky_set_null(&mut self) { - use crate::gecko_bindings::structs::nsStyleUnit::*; - unsafe { - let (unit, union) = self.values_mut(); - *unit = eStyleUnit_Null; - *union.mInt.as_mut() = 0; - } - } - - #[inline(always)] - /// Sets the inner value. - fn set_value(&mut self, value: CoordDataValue) { - use self::CoordDataValue::*; - use crate::gecko_bindings::structs::nsStyleUnit::*; - self.reset(); - unsafe { - let (unit, union) = self.values_mut(); - match value { - Null => { - *unit = eStyleUnit_Null; - *union.mInt.as_mut() = 0; - }, - Normal => { - *unit = eStyleUnit_Normal; - *union.mInt.as_mut() = 0; - }, - Auto => { - *unit = eStyleUnit_Auto; - *union.mInt.as_mut() = 0; - }, - None => { - *unit = eStyleUnit_None; - *union.mInt.as_mut() = 0; - }, - Percent(f) => { - *unit = eStyleUnit_Percent; - *union.mFloat.as_mut() = f; - }, - Factor(f) => { - *unit = eStyleUnit_Factor; - *union.mFloat.as_mut() = f; - }, - Degree(f) => { - *unit = eStyleUnit_Degree; - *union.mFloat.as_mut() = f; - }, - FlexFraction(f) => { - *unit = eStyleUnit_FlexFraction; - *union.mFloat.as_mut() = f; - }, - Coord(coord) => { - *unit = eStyleUnit_Coord; - *union.mInt.as_mut() = coord; - }, - Integer(i) => { - *unit = eStyleUnit_Integer; - *union.mInt.as_mut() = i; - }, - Enumerated(i) => { - *unit = eStyleUnit_Enumerated; - *union.mInt.as_mut() = i as i32; - }, - Calc(calc) => { - // Gecko_SetStyleCoordCalcValue changes the unit internally - bindings::Gecko_SetStyleCoordCalcValue(unit, union, calc); - }, - } - } - } - - #[inline] - /// Gets the `Calc` value mutably, asserts in debug builds if the unit is - /// not `Calc`. - unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - &mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc) - } - - #[inline] - /// Does what it promises, if the unit is `calc`, it bumps the reference - /// count _of the calc expression_. - fn addref_if_calc(&mut self) { - unsafe { - if self.unit() == nsStyleUnit::eStyleUnit_Calc { - bindings::Gecko_AddRefCalcArbitraryThread(self.as_calc_mut()); - } - } - } -} -/// A trait to abstract on top of a `nsStyleCoord`-like object. -pub unsafe trait CoordData { - /// Get the unit of this object. - fn unit(&self) -> nsStyleUnit; - /// Get the `nsStyleUnion` for this object. - fn union(&self) -> nsStyleUnion; - - #[inline(always)] - /// Get the appropriate value for this object. - fn as_value(&self) -> CoordDataValue { - use self::CoordDataValue::*; - use crate::gecko_bindings::structs::nsStyleUnit::*; - unsafe { - match self.unit() { - eStyleUnit_Null => Null, - eStyleUnit_Normal => Normal, - eStyleUnit_Auto => Auto, - eStyleUnit_None => None, - eStyleUnit_Percent => Percent(self.get_float()), - eStyleUnit_Factor => Factor(self.get_float()), - eStyleUnit_Degree => Degree(self.get_float()), - eStyleUnit_FlexFraction => FlexFraction(self.get_float()), - eStyleUnit_Coord => Coord(self.get_integer()), - eStyleUnit_Integer => Integer(self.get_integer()), - eStyleUnit_Enumerated => Enumerated(self.get_integer() as u32), - eStyleUnit_Calc => Calc(self.get_calc_value()), - } - } - } - - #[inline] - /// Pretend inner value is a float; obtain it. - unsafe fn get_float(&self) -> f32 { - use crate::gecko_bindings::structs::nsStyleUnit::*; - debug_assert!( - self.unit() == eStyleUnit_Percent || - self.unit() == eStyleUnit_Factor || - self.unit() == eStyleUnit_Degree || - self.unit() == eStyleUnit_FlexFraction - ); - *self.union().mFloat.as_ref() - } - - #[inline] - /// Pretend inner value is an int; obtain it. - unsafe fn get_integer(&self) -> i32 { - use crate::gecko_bindings::structs::nsStyleUnit::*; - debug_assert!( - self.unit() == eStyleUnit_Coord || - self.unit() == eStyleUnit_Integer || - self.unit() == eStyleUnit_Enumerated - ); - *self.union().mInt.as_ref() - } - - #[inline] - /// Pretend inner value is a calc; obtain it. - /// Ensure that the unit is Calc before calling this. - unsafe fn get_calc_value(&self) -> nsStyleCoord_CalcValue { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - (*self.as_calc())._base - } - - #[inline] - /// Pretend the inner value is a calc expression, and obtain it. - unsafe fn as_calc(&self) -> &nsStyleCoord_Calc { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - &*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc) - } -}