diff --git a/components/style/gecko_conversions.rs b/components/style/gecko_conversions.rs new file mode 100644 index 00000000000..95ab9eb8b00 --- /dev/null +++ b/components/style/gecko_conversions.rs @@ -0,0 +1,36 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +//! This module contains conversion helpers between Servo and Gecko types +//! Ideally, it would be in geckolib itself, but coherence +//! forces us to keep the traits and implementations here + +use app_units::Au; +use gecko_bindings::structs::nsStyleCoord_CalcValue; +use values::computed::CalcLengthOrPercentage; + +impl From for nsStyleCoord_CalcValue { + fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue { + let has_percentage = other.percentage.is_some(); + nsStyleCoord_CalcValue { + mLength: other.length.map_or(0, |l| l.0), + mPercent: other.percentage.unwrap_or(0.0), + mHasPercent: has_percentage, + } + } +} + +impl From for CalcLengthOrPercentage { + fn from(other: nsStyleCoord_CalcValue) -> CalcLengthOrPercentage { + let percentage = if other.mHasPercent { + Some(other.mPercent) + } else { + None + }; + CalcLengthOrPercentage { + length: Some(Au(other.mLength)), + percentage: percentage, + } + } +} diff --git a/components/style/lib.rs b/components/style/lib.rs index 813a24af14e..f90368f4ca8 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -81,6 +81,8 @@ pub mod dom; pub mod element_state; pub mod error_reporting; pub mod font_face; +#[cfg(feature = "gecko")] +pub mod gecko_conversions; pub mod keyframes; pub mod logical_geometry; pub mod matching; diff --git a/ports/geckolib/gecko_bindings/bindings.rs b/ports/geckolib/gecko_bindings/bindings.rs index 1d5a6c10b94..550d5c8cc8e 100644 --- a/ports/geckolib/gecko_bindings/bindings.rs +++ b/ports/geckolib/gecko_bindings/bindings.rs @@ -123,6 +123,16 @@ unsafe impl Sync for nsStyleImageLayers {} impl HeapSizeOf for nsStyleImageLayers { fn heap_size_of_children(&self) -> usize { 0 } } use structs::nsStyleImageLayers_Layer as Layer; use structs::nsStyleImageLayers_LayerType as LayerType; +use structs::nsStyleUnit; +unsafe impl Send for nsStyleUnit {} +unsafe impl Sync for nsStyleUnit {} +impl HeapSizeOf for nsStyleUnit { fn heap_size_of_children(&self) -> usize { 0 } } +use structs::nsStyleUnion; +unsafe impl Send for nsStyleUnion {} +unsafe impl Sync for nsStyleUnion {} +impl HeapSizeOf for nsStyleUnion { fn heap_size_of_children(&self) -> usize { 0 } } +use structs::nsStyleCoord_CalcValue as CalcValue; +use structs::nsStyleCoord_Calc as Calc; use structs::SheetParsingMode; use structs::nsMainThreadPtrHandle; use structs::nsMainThreadPtrHolder; @@ -255,6 +265,13 @@ extern "C" { len: usize); pub fn Gecko_InitializeImageLayer(layer: *mut Layer, layer_type: LayerType); + pub fn Gecko_ResetStyleCoord(unit: *mut nsStyleUnit, + value: *mut nsStyleUnion); + pub fn Gecko_SetStyleCoordCalcValue(unit: *mut nsStyleUnit, + value: *mut nsStyleUnion, + calc: CalcValue); + pub fn Gecko_AddRefCalcArbitraryThread(aPtr: *mut Calc); + pub fn Gecko_ReleaseCalcArbitraryThread(aPtr: *mut Calc); pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8, length: u32, parsing_mode: SheetParsingMode, base: *mut ThreadSafeURIHolder, diff --git a/ports/geckolib/gecko_bindings/structs_debug.rs b/ports/geckolib/gecko_bindings/structs_debug.rs index 90598bb0893..e0763c1bb9c 100644 --- a/ports/geckolib/gecko_bindings/structs_debug.rs +++ b/ports/geckolib/gecko_bindings/structs_debug.rs @@ -4885,12 +4885,11 @@ fn bindgen_test_layout_nsStyleCoord_CalcValue() { #[derive(Debug)] pub struct nsStyleCoord_Calc { pub _base: nsStyleCoord_CalcValue, - pub mRefCnt: nsAutoRefCnt, - pub _mOwningThread: nsAutoOwningThread, + pub mRefCnt: ThreadSafeAutoRefCnt, } #[test] fn bindgen_test_layout_nsStyleCoord_Calc() { - assert_eq!(::std::mem::size_of::() , 32usize); + assert_eq!(::std::mem::size_of::() , 24usize); assert_eq!(::std::mem::align_of::() , 8usize); } #[repr(u32)] diff --git a/ports/geckolib/gecko_bindings/structs_release.rs b/ports/geckolib/gecko_bindings/structs_release.rs index a2da2f94d32..16d904662fa 100644 --- a/ports/geckolib/gecko_bindings/structs_release.rs +++ b/ports/geckolib/gecko_bindings/structs_release.rs @@ -4864,12 +4864,11 @@ fn bindgen_test_layout_nsStyleCoord_CalcValue() { #[derive(Debug)] pub struct nsStyleCoord_Calc { pub _base: nsStyleCoord_CalcValue, - pub mRefCnt: nsAutoRefCnt, - pub _mOwningThread: nsAutoOwningThread, + pub mRefCnt: ThreadSafeAutoRefCnt, } #[test] fn bindgen_test_layout_nsStyleCoord_Calc() { - assert_eq!(::std::mem::size_of::() , 32usize); + assert_eq!(::std::mem::size_of::() , 24usize); assert_eq!(::std::mem::align_of::() , 8usize); } #[repr(u32)] diff --git a/ports/geckolib/gecko_bindings/sugar/mod.rs b/ports/geckolib/gecko_bindings/sugar/mod.rs index 9c1e4637249..fa995c3f963 100644 --- a/ports/geckolib/gecko_bindings/sugar/mod.rs +++ b/ports/geckolib/gecko_bindings/sugar/mod.rs @@ -3,4 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ mod ns_style_auto_array; +mod ns_style_coord; mod ns_t_array; diff --git a/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs b/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs new file mode 100644 index 00000000000..ef03f4d7b41 --- /dev/null +++ b/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs @@ -0,0 +1,54 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +use bindings::{Gecko_ResetStyleCoord, Gecko_SetStyleCoordCalcValue, Gecko_AddRefCalcArbitraryThread}; +use std::mem::transmute; +use structs::{nsStyleCoord_CalcValue, nsStyleCoord_Calc, nsStyleUnit, nsStyleUnion, nsStyleCoord}; + +// Functions here are unsafe because it is possible to use the wrong nsStyleUnit +// FIXME we should be pairing up nsStyleUnion and nsStyleUnit somehow +// nsStyleCoord is one way to do it, but there are other structs using pairs +// of union and unit too + +impl nsStyleUnion { + /// Clean up any resources used by an nsStyleUnit + /// Currently, this only happens if the nsStyleUnit + /// is a Calc + pub unsafe fn reset(&mut self, unit: &mut nsStyleUnit) { + if *unit == nsStyleUnit::eStyleUnit_Calc { + Gecko_ResetStyleCoord(unit, self); + } + } + + /// Set internal value to a calc() value + /// reset() the union before calling this + pub unsafe fn set_calc_value(&mut self, unit: &mut nsStyleUnit, v: nsStyleCoord_CalcValue) { + // Calc should have been cleaned up + debug_assert!(*unit != nsStyleUnit::eStyleUnit_Calc); + Gecko_SetStyleCoordCalcValue(unit, self, v); + } + + pub unsafe fn get_calc(&self) -> nsStyleCoord_CalcValue { + (*self.as_calc())._base + } + + pub unsafe fn addref_if_calc(&mut self, unit: &nsStyleUnit) { + if *unit == nsStyleUnit::eStyleUnit_Calc { + Gecko_AddRefCalcArbitraryThread(self.as_calc_mut()); + } + } + + unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc { + transmute(*self.mPointer.as_mut() as *mut nsStyleCoord_Calc) + } + unsafe fn as_calc(&self) -> &nsStyleCoord_Calc { + transmute(*self.mPointer.as_ref() as *const nsStyleCoord_Calc) + } +} + +impl nsStyleCoord { + pub unsafe fn addref_if_calc(&mut self) { + self.mValue.addref_if_calc(&self.mUnit); + } +} diff --git a/ports/geckolib/gecko_bindings/tools/regen.py b/ports/geckolib/gecko_bindings/tools/regen.py index d2cf66a0f54..4c3d4e5ac9c 100755 --- a/ports/geckolib/gecko_bindings/tools/regen.py +++ b/ports/geckolib/gecko_bindings/tools/regen.py @@ -121,6 +121,8 @@ COMPILATION_TARGETS = { "nsStyleEffects", "nsStyleImage", "nsStyleGradient", "nsStyleCoord", "nsStyleGradientStop", "nsStyleImageLayers", "nsStyleImageLayers::Layer", "nsStyleImageLayers::LayerType", + "nsStyleUnit", "nsStyleUnion", "nsStyleCoord::CalcValue", + "nsStyleCoord::Calc", "SheetParsingMode", "nsMainThreadPtrHandle", "nsMainThreadPtrHolder", "nscolor", "nsFont", "FontFamilyList", diff --git a/ports/geckolib/properties.mako.rs b/ports/geckolib/properties.mako.rs index 0228c471e66..e2332cce1f8 100644 --- a/ports/geckolib/properties.mako.rs +++ b/ports/geckolib/properties.mako.rs @@ -35,7 +35,7 @@ use style::properties::{CascadePropertyFn, ServoComputedValues, ComputedValues}; use style::properties::longhands; use style::properties::style_struct_traits::*; use values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba}; -use values::{convert_rgba_to_nscolor, debug_assert_unit_is_safe_to_copy}; +use values::convert_rgba_to_nscolor; use values::round_border_to_device_pixels; #[derive(Clone, Debug)] @@ -317,9 +317,10 @@ def set_gecko_property(ffi_name, expr): &mut self.gecko.${union_ffi_name}); } fn copy_${ident}_from(&mut self, other: &Self) { - debug_assert_unit_is_safe_to_copy(self.gecko.${unit_ffi_name}); + 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}) }; } % if need_clone: fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { @@ -347,12 +348,14 @@ ${impl_split_style_coord(ident, &mut self.gecko.${y_union_ffi_name}); } fn copy_${ident}_from(&mut self, other: &Self) { - debug_assert_unit_is_safe_to_copy(self.gecko.${x_unit_ffi_name}); - debug_assert_unit_is_safe_to_copy(self.gecko.${y_unit_ffi_name}); + 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}) }; } % if need_clone: fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { @@ -627,7 +630,10 @@ fn static_assert() { } fn copy_z_index_from(&mut self, other: &Self) { - debug_assert_unit_is_safe_to_copy(self.gecko.mZIndex.mUnit); + use gecko_bindings::structs::nsStyleUnit; + // z-index is never a calc(). If it were, we'd be leaking here, so + // assert that it isn't. + debug_assert!(self.gecko.mZIndex.mUnit != nsStyleUnit::eStyleUnit_Calc); self.gecko.mZIndex.mUnit = other.gecko.mZIndex.mUnit; self.gecko.mZIndex.mValue = other.gecko.mZIndex.mValue; } diff --git a/ports/geckolib/values.rs b/ports/geckolib/values.rs index ee24be7565c..b44d78c084e 100644 --- a/ports/geckolib/values.rs +++ b/ports/geckolib/values.rs @@ -43,10 +43,10 @@ pub trait StyleCoordHelpers { impl StyleCoordHelpers for nsStyleCoord { #[inline] fn copy_from(&mut self, other: &Self) { - debug_assert_unit_is_safe_to_copy(self.mUnit); - debug_assert_unit_is_safe_to_copy(other.mUnit); + unsafe { self.mValue.reset(&mut self.mUnit) }; self.mUnit = other.mUnit; self.mValue = other.mValue; + unsafe { self.addref_if_calc(); } } #[inline] @@ -56,6 +56,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -66,6 +67,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -76,6 +78,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -91,6 +94,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -106,6 +110,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -121,6 +126,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -136,6 +142,7 @@ impl StyleCoordHelpers for nsStyleCoord { #[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; } } @@ -157,6 +164,7 @@ pub trait GeckoStyleCoordConvertible : Sized { 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; @@ -166,7 +174,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentage { *unit = nsStyleUnit::eStyleUnit_Percent; unsafe { *union.mFloat.as_mut() = p; } }, - LengthOrPercentage::Calc(_) => unimplemented!(), + LengthOrPercentage::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) }, }; } @@ -177,7 +185,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentage { nsStyleUnit::eStyleUnit_Percent => Some(LengthOrPercentage::Percentage(unsafe { *union.mFloat.as_ref() })), nsStyleUnit::eStyleUnit_Calc - => unimplemented!(), + => Some(LengthOrPercentage::Calc(unsafe { union.get_calc().into() })), _ => None, } } @@ -185,6 +193,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentage { 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; @@ -198,7 +207,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto { *unit = nsStyleUnit::eStyleUnit_Auto; unsafe { *union.mInt.as_mut() = 0; } }, - LengthOrPercentageOrAuto::Calc(_) => unimplemented!(), + LengthOrPercentageOrAuto::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) }, }; } @@ -211,7 +220,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto { nsStyleUnit::eStyleUnit_Percent => Some(LengthOrPercentageOrAuto::Percentage(unsafe { *union.mFloat.as_ref() })), nsStyleUnit::eStyleUnit_Calc - => unimplemented!(), + => Some(LengthOrPercentageOrAuto::Calc(unsafe { union.get_calc().into() })), _ => None, } } @@ -219,6 +228,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto { 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; @@ -232,7 +242,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone { *unit = nsStyleUnit::eStyleUnit_None; unsafe { *union.mInt.as_mut() = 0; } }, - LengthOrPercentageOrNone::Calc(_) => unimplemented!(), + LengthOrPercentageOrNone::Calc(calc) => unsafe { union.set_calc_value(unit, calc.into()) }, }; } @@ -245,7 +255,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone { nsStyleUnit::eStyleUnit_Percent => Some(LengthOrPercentageOrNone::Percentage(unsafe { *union.mFloat.as_ref() })), nsStyleUnit::eStyleUnit_Calc - => unimplemented!(), + => Some(LengthOrPercentageOrNone::Calc(unsafe { union.get_calc().into() })), _ => None, } } @@ -253,6 +263,7 @@ impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone { impl GeckoStyleCoordConvertible for Option { fn to_gecko_style_coord(&self, unit: &mut nsStyleUnit, union: &mut nsStyleUnion) { + unsafe { union.reset(unit) }; if let Some(ref me) = *self { me.to_gecko_style_coord(unit, union); } else { @@ -270,6 +281,7 @@ 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() }; } @@ -310,7 +322,3 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au { max(au_per_device_px, Au(width.0 / au_per_device_px.0 * au_per_device_px.0)) } } - -pub fn debug_assert_unit_is_safe_to_copy(unit: nsStyleUnit) { - debug_assert!(unit != nsStyleUnit::eStyleUnit_Calc, "stylo: Can't yet handle refcounted Calc"); -}