diff options
47 files changed, 994 insertions, 432 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 7bba2ce0e53..747543dd7fc 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -41,7 +41,7 @@ use std::ops::{Deref, DerefMut}; use std::sync::Arc; use style::computed_values::{border_style, cursor, filter, image_rendering, mix_blend_mode}; use style::computed_values::{pointer_events}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style_traits::cursor::Cursor; use text::TextRun; use text::glyph::CharIndex; diff --git a/components/layout/block.rs b/components/layout/block.rs index 19bb6e71ce2..06f41861425 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -60,7 +60,7 @@ use style::computed_values::{border_collapse, box_sizing, display, float, overfl use style::computed_values::{position, text_align, transform_style}; use style::context::StyleContext; use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use util::geometry::MAX_RECT; diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 25988b7eb11..aedbeaf04f6 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -45,7 +45,7 @@ use std::sync::atomic::Ordering; use style::computed_values::content::ContentItem; use style::computed_values::{caption_side, display, empty_cells, float, list_style_position}; use style::computed_values::{position}; -use style::properties::{self, ComputedValues}; +use style::properties::{self, ComputedValues, TComputedValues}; use table::TableFlow; use table_caption::TableCaptionFlow; use table_cell::TableCellFlow; diff --git a/components/layout/context.rs b/components/layout/context.rs index 2775e6e791c..7b6fa3e4691 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -26,13 +26,14 @@ use std::rc::Rc; use std::sync::{Arc, Mutex, RwLock}; use style::context::{LocalStyleContext, StyleContext}; use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; +use style::properties::ComputedValues; use style::selector_impl::ServoSelectorImpl; use style::servo::SharedStyleContext; use url::Url; use util::opts; struct LocalLayoutContext { - style_context: LocalStyleContext, + style_context: LocalStyleContext<ComputedValues>, font_context: RefCell<FontContext>, } @@ -107,12 +108,12 @@ pub struct LayoutContext<'a> { cached_local_layout_context: Rc<LocalLayoutContext>, } -impl<'a> StyleContext<'a, ServoSelectorImpl> for LayoutContext<'a> { +impl<'a> StyleContext<'a, ServoSelectorImpl, ComputedValues> for LayoutContext<'a> { fn shared_context(&self) -> &'a SharedStyleContext { &self.shared.style_context } - fn local_context(&self) -> &LocalStyleContext { + fn local_context(&self) -> &LocalStyleContext<ComputedValues> { &self.cached_local_layout_context.style_context } } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 4d62d221a5e..d20186cf0f9 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -51,7 +51,7 @@ use style::computed_values::{border_style, image_rendering, overflow_x, position use style::computed_values::{transform, transform_style, visibility}; use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use style::properties::style_structs::Border; -use style::properties::{self, ComputedValues}; +use style::properties::{self, ComputedValues, TComputedValues}; use style::values::RGBA; use style::values::computed; use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto, LinearGradient}; diff --git a/components/layout/flex.rs b/components/layout/flex.rs index b53bb697c49..dbc01b58178 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -28,8 +28,8 @@ use std::cmp::max; use std::sync::Arc; use style::computed_values::{flex_direction, float}; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; use style::properties::style_structs; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::LengthOrPercentageOrAuto; // A mode describes which logical axis a flex axis is parallel with. diff --git a/components/layout/flow.rs b/components/layout/flow.rs index b61540dfb3b..dc434ce03f2 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -50,7 +50,7 @@ use std::{fmt, mem, raw}; use style::computed_values::{clear, display, empty_cells, float, position, overflow_x, text_align}; use style::dom::TRestyleDamage; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; -use style::properties::{self, ComputedValues}; +use style::properties::{self, ComputedValues, TComputedValues}; use style::values::computed::LengthOrPercentageOrAuto; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow}; use table_caption::TableCaptionFlow; diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 8c1c54fd282..227b492b038 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -41,7 +41,7 @@ use style::computed_values::{overflow_x, position, text_decoration, transform_st use style::computed_values::{white_space, word_break, z_index}; use style::dom::TRestyleDamage; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::computed::{LengthOrPercentageOrNone}; use text; diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index b0284c62d7e..7af9c4349d2 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use style::computed_values::content::ContentItem; use style::computed_values::{display, list_style_type}; use style::dom::TRestyleDamage; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use text::TextRunScanner; use wrapper::PseudoElementType; diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index d909192c0d3..8daf3cdd14f 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -7,7 +7,7 @@ use std::fmt; use std::sync::Arc; use style::computed_values::float; use style::dom::TRestyleDamage; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; bitflags! { #[doc = "Individual layout actions that may be necessary after restyling."] @@ -53,6 +53,7 @@ bitflags! { } impl TRestyleDamage for RestyleDamage { + type ConcreteComputedValues = ComputedValues; fn compute(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage { compute_damage(old, new) } /// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed. diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 8784728d808..175295c6f09 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -30,7 +30,7 @@ use std::{fmt, isize, mem}; use style::computed_values::{display, overflow_x, position, text_align, text_justify}; use style::computed_values::{text_overflow, vertical_align, white_space}; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::LengthOrPercentage; use text; use unicode_bidi; diff --git a/components/layout/layout_thread.rs b/components/layout/layout_thread.rs index cbad465b4f8..646defb49e4 100644 --- a/components/layout/layout_thread.rs +++ b/components/layout/layout_thread.rs @@ -72,6 +72,7 @@ use style::error_reporting::ParseErrorReporter; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaType}; use style::parallel::WorkQueueData; +use style::properties::TComputedValues; use style::selector_impl::ServoSelectorImpl; use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS; use style::servo::{SharedStyleContext, Stylesheet, Stylist}; diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 6c8817ec1da..e64faa96758 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -23,7 +23,7 @@ use inline::InlineMetrics; use std::sync::Arc; use style::computed_values::{list_style_type, position}; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use text; /// A block with the CSS `display` property equal to `list-item`. diff --git a/components/layout/model.rs b/components/layout/model.rs index 057bb46fa52..6312bf3d30b 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -13,7 +13,7 @@ use std::cmp::{max, min}; use std::fmt; use style::computed_values::transform::ComputedMatrix; use style::logical_geometry::LogicalMargin; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::{BorderRadiusSize, LengthOrPercentageOrAuto}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrNone}; diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 4b7ac7d8814..b7e89fecf6c 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -21,7 +21,7 @@ use std::fmt; use std::sync::Arc; use style::context::StyleContext; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use util::print_tree::PrintTree; diff --git a/components/layout/query.rs b/components/layout/query.rs index 9d1b9ed1db3..e05564f1aca 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -27,6 +27,7 @@ use std::sync::{Arc, Mutex}; use string_cache::Atom; use style::computed_values; use style::logical_geometry::{WritingMode, BlockFlowDirection, InlineBaseDirection}; +use style::properties::TComputedValues; use style::properties::longhands::{display, position}; use style::properties::style_structs; use style::selector_impl::PseudoElement; diff --git a/components/layout/table.rs b/components/layout/table.rs index 0c8d8865a8d..bd6b6bee6ed 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -25,7 +25,7 @@ use std::fmt; use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing, table_layout}; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::CSSFloat; use style::values::computed::LengthOrPercentageOrAuto; use table_row::{TableRowFlow}; diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index e1706fc53cd..20ca8d8a8dc 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -17,7 +17,7 @@ use gfx::display_list::{StackingContext, StackingContextId}; use std::fmt; use std::sync::Arc; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use util::print_tree::PrintTree; /// A table formatting context. diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index ea16a5b5a59..508d201f6fd 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -21,7 +21,7 @@ use std::fmt; use std::sync::Arc; use style::computed_values::{border_collapse, border_top_style}; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use table::InternalTable; use table_row::{CollapsedBorder, CollapsedBorderProvenance}; use util::print_tree::PrintTree; diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 32d2c693131..762e3526cf6 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -18,7 +18,7 @@ use std::cmp::max; use std::fmt; use std::sync::Arc; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::LengthOrPercentageOrAuto; /// A table formatting context. diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 45e8bca12ec..64a2e71beed 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -25,7 +25,7 @@ use std::iter::{Enumerate, IntoIterator, Peekable}; use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing, border_top_style}; use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::computed::LengthOrPercentageOrAuto; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt}; use table_cell::{CollapsedBordersForCell, TableCellFlow}; diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 44da4878119..a43d6f6ebbc 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -21,7 +21,7 @@ use std::iter::{IntoIterator, Iterator, Peekable}; use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing}; use style::logical_geometry::{LogicalSize, WritingMode}; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, TableLikeFlow}; use table_row; use util::print_tree::PrintTree; diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index a8e16812efd..e543f981127 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -31,7 +31,7 @@ use std::ops::Add; use std::sync::Arc; use style::computed_values::{border_collapse, table_layout}; use style::logical_geometry::LogicalSize; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::values::CSSFloat; use style::values::computed::LengthOrPercentageOrAuto; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; diff --git a/components/layout/text.rs b/components/layout/text.rs index 2a9e99d18d3..0969bc4e43e 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -23,8 +23,8 @@ use std::sync::Arc; use style::computed_values::{line_height, text_orientation, text_rendering, text_transform}; use style::computed_values::{white_space}; use style::logical_geometry::{LogicalSize, WritingMode}; -use style::properties::ComputedValues; use style::properties::style_structs::Font as FontStyle; +use style::properties::{ComputedValues, TComputedValues}; use unicode_bidi::{is_rtl, process_text}; use unicode_script::{get_script, Script}; use util::linked_list::split_off_head; diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 30ca65f6e39..094bc40a4a0 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -66,7 +66,7 @@ use style::computed_values::content::ContentItem; use style::computed_values::{content, display}; use style::dom::{TDocument, TElement, TNode, UnsafeNode}; use style::element_state::*; -use style::properties::ComputedValues; +use style::properties::{ComputedValues, TComputedValues}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; use style::restyle_hints::ElementSnapshot; use style::selector_impl::{NonTSPseudoClass, PseudoElement, ServoSelectorImpl}; @@ -131,6 +131,7 @@ impl<'ln> ServoLayoutNode<'ln> { } impl<'ln> TNode for ServoLayoutNode<'ln> { + type ConcreteComputedValues = ComputedValues; type ConcreteElement = ServoLayoutElement<'ln>; type ConcreteDocument = ServoLayoutDocument<'ln>; type ConcreteRestyleDamage = RestyleDamage; diff --git a/components/style/animation.rs b/components/style/animation.rs index b152be5fcc3..e7663093cd5 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -7,7 +7,6 @@ use bezier::Bezier; use cssparser::{Color, RGBA}; use dom::{OpaqueNode, TRestyleDamage}; use euclid::point::Point2D; -use properties::ComputedValues; use properties::longhands::background_position::computed_value::T as BackgroundPosition; use properties::longhands::border_spacing::computed_value::T as BorderSpacing; use properties::longhands::clip::computed_value::ClipRect; @@ -25,6 +24,8 @@ use properties::longhands::transition_timing_function::computed_value::{Transiti use properties::longhands::vertical_align::computed_value::T as VerticalAlign; use properties::longhands::visibility::computed_value::T as Visibility; use properties::longhands::z_index::computed_value::T as ZIndex; +use properties::style_struct_traits::TAnimation; +use properties::{ComputedValues, TComputedValues}; use std::cmp::Ordering; use std::iter::repeat; use std::sync::mpsc::Sender; @@ -73,7 +74,7 @@ impl PropertyAnimation { -> Vec<PropertyAnimation> { let mut result = Vec::new(); let transition_property = - new_style.get_animation().transition_property.0[transition_index]; + new_style.as_servo().get_animation().transition_property.0[transition_index]; if transition_property != TransitionProperty::All { if let Some(property_animation) = PropertyAnimation::from_transition_property(transition_property, @@ -929,22 +930,22 @@ impl<T> GetMod for Vec<T> { /// Inserts transitions into the queue of running animations as applicable for the given style /// difference. This is called from the layout worker threads. Returns true if any animations were /// kicked off and false otherwise. -pub fn start_transitions_if_applicable(new_animations_sender: &Mutex<Sender<Animation>>, - node: OpaqueNode, - old_style: &ComputedValues, - new_style: &mut ComputedValues) - -> bool { +pub fn start_transitions_if_applicable<C: TComputedValues>(new_animations_sender: &Mutex<Sender<Animation>>, + node: OpaqueNode, + old_style: &C, + new_style: &mut C) + -> bool { let mut had_animations = false; - for i in 0..new_style.get_animation().transition_property.0.len() { + for i in 0..new_style.get_animation().transition_count() { // Create any property animations, if applicable. - let property_animations = PropertyAnimation::from_transition(i, old_style, new_style); + let property_animations = PropertyAnimation::from_transition(i, old_style.as_servo(), new_style.as_servo_mut()); for property_animation in property_animations { // Set the property to the initial value. - property_animation.update(new_style, 0.0); + property_animation.update(new_style.as_servo_mut(), 0.0); // Kick off the animation. let now = time::precise_time_s(); - let animation_style = new_style.get_animation(); + let animation_style = new_style.as_servo().get_animation(); let start_time = now + (animation_style.transition_delay.0.get_mod(i).seconds() as f64); new_animations_sender.lock().unwrap().send(Animation { @@ -964,9 +965,10 @@ pub fn start_transitions_if_applicable(new_animations_sender: &Mutex<Sender<Anim /// Updates a single animation and associated style based on the current time. If `damage` is /// provided, inserts the appropriate restyle damage. -pub fn update_style_for_animation<ConcreteRestyleDamage: TRestyleDamage>(animation: &Animation, - style: &mut Arc<ComputedValues>, - damage: Option<&mut ConcreteRestyleDamage>) { +pub fn update_style_for_animation<C: TComputedValues, + Damage: TRestyleDamage<ConcreteComputedValues=C>>(animation: &Animation, + style: &mut Arc<C>, + damage: Option<&mut Damage>) { let now = time::precise_time_s(); let mut progress = (now - animation.start_time) / animation.duration(); if progress > 1.0 { @@ -977,9 +979,9 @@ pub fn update_style_for_animation<ConcreteRestyleDamage: TRestyleDamage>(animati } let mut new_style = (*style).clone(); - animation.property_animation.update(&mut *Arc::make_mut(&mut new_style), progress); + animation.property_animation.update(Arc::make_mut(&mut new_style).as_servo_mut(), progress); if let Some(damage) = damage { - *damage = *damage | ConcreteRestyleDamage::compute(Some(style), &new_style); + *damage = *damage | Damage::compute(Some(style), &new_style); } *style = new_style diff --git a/components/style/context.rs b/components/style/context.rs index 6e4edfd1b52..ef19bc2561e 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -8,6 +8,7 @@ use dom::OpaqueNode; use error_reporting::ParseErrorReporter; use euclid::Size2D; use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; +use properties::TComputedValues; use selector_impl::SelectorImplExt; use selector_matching::Stylist; use std::cell::RefCell; @@ -54,15 +55,15 @@ pub struct SharedStyleContext<Impl: SelectorImplExt> { pub error_reporter: Box<ParseErrorReporter + Sync>, } -pub struct LocalStyleContext { - pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache>, - pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>, +pub struct LocalStyleContext<C: TComputedValues> { + pub applicable_declarations_cache: RefCell<ApplicableDeclarationsCache<C>>, + pub style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache<C>>, } -pub trait StyleContext<'a, Impl: SelectorImplExt> { +pub trait StyleContext<'a, Impl: SelectorImplExt, C: TComputedValues> { fn shared_context(&self) -> &'a SharedStyleContext<Impl>; - fn local_context(&self) -> &LocalStyleContext; + fn local_context(&self) -> &LocalStyleContext<C>; } /// Why we're doing reflow. diff --git a/components/style/data.rs b/components/style/data.rs index ffe12908cba..6bc6916a564 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -2,26 +2,28 @@ * 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 properties::ComputedValues; +use properties::TComputedValues; use selectors::parser::SelectorImpl; use std::collections::HashMap; use std::hash::BuildHasherDefault; use std::sync::Arc; use std::sync::atomic::AtomicIsize; -pub struct PrivateStyleData<Impl: SelectorImpl> { +pub struct PrivateStyleData<Impl: SelectorImpl, ConcreteComputedValues: TComputedValues> { /// The results of CSS styling for this node. - pub style: Option<Arc<ComputedValues>>, + pub style: Option<Arc<ConcreteComputedValues>>, /// The results of CSS styling for each pseudo-element (if any). - pub per_pseudo: HashMap<Impl::PseudoElement, Arc<ComputedValues>, BuildHasherDefault<::fnv::FnvHasher>>, + pub per_pseudo: HashMap<Impl::PseudoElement, Arc<ConcreteComputedValues>, + BuildHasherDefault<::fnv::FnvHasher>>, /// Information needed during parallel traversals. pub parallel: DomParallelInfo, } -impl<Impl: SelectorImpl> PrivateStyleData<Impl> { - pub fn new() -> PrivateStyleData<Impl> { +impl<Impl, ConcreteComputedValues> PrivateStyleData<Impl, ConcreteComputedValues> + where Impl: SelectorImpl, ConcreteComputedValues: TComputedValues { + pub fn new() -> PrivateStyleData<Impl, ConcreteComputedValues> { PrivateStyleData { style: None, per_pseudo: HashMap::with_hasher(Default::default()), diff --git a/components/style/dom.rs b/components/style/dom.rs index 37859736dbe..861cec599a2 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -6,7 +6,7 @@ use data::PrivateStyleData; use element_state::ElementState; -use properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock}; +use properties::{PropertyDeclaration, PropertyDeclarationBlock, TComputedValues}; use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint}; use selector_impl::ElementExt; use selectors::Element; @@ -43,14 +43,16 @@ impl OpaqueNode { } pub trait TRestyleDamage : BitOr<Output=Self> + Copy { - fn compute(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -> Self; + type ConcreteComputedValues: TComputedValues; + fn compute(old: Option<&Arc<Self::ConcreteComputedValues>>, new: &Self::ConcreteComputedValues) -> Self; fn rebuild_and_reflow() -> Self; } pub trait TNode : Sized + Copy + Clone { type ConcreteElement: TElement<ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>; type ConcreteDocument: TDocument<ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>; - type ConcreteRestyleDamage: TRestyleDamage; + type ConcreteRestyleDamage: TRestyleDamage<ConcreteComputedValues = Self::ConcreteComputedValues>; + type ConcreteComputedValues: TComputedValues; fn to_unsafe(&self) -> UnsafeNode; unsafe fn from_unsafe(n: &UnsafeNode) -> Self; @@ -135,17 +137,20 @@ pub trait TNode : Sized + Copy + Clone { /// Borrows the PrivateStyleData without checks. #[inline(always)] unsafe fn borrow_data_unchecked(&self) - -> Option<*const PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>; + -> Option<*const PrivateStyleData<<Self::ConcreteElement as Element>::Impl, + Self::ConcreteComputedValues>>; /// Borrows the PrivateStyleData immutably. Fails on a conflicting borrow. #[inline(always)] fn borrow_data(&self) - -> Option<Ref<PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>>; + -> Option<Ref<PrivateStyleData<<Self::ConcreteElement as Element>::Impl, + Self::ConcreteComputedValues>>>; /// Borrows the PrivateStyleData mutably. Fails on a conflicting borrow. #[inline(always)] fn mutate_data(&self) - -> Option<RefMut<PrivateStyleData<<Self::ConcreteElement as Element>::Impl>>>; + -> Option<RefMut<PrivateStyleData<<Self::ConcreteElement as Element>::Impl, + Self::ConcreteComputedValues>>>; /// Get the description of how to account for recent style changes. fn restyle_damage(self) -> Self::ConcreteRestyleDamage; @@ -166,7 +171,7 @@ pub trait TNode : Sized + Copy + Clone { /// Returns the style results for the given node. If CSS selector matching /// has not yet been performed, fails. - fn style(&self) -> Ref<Arc<ComputedValues>> { + fn style(&self) -> Ref<Arc<Self::ConcreteComputedValues>> { Ref::map(self.borrow_data().unwrap(), |data| data.style.as_ref().unwrap()) } diff --git a/components/style/lib.rs b/components/style/lib.rs index a696b882d43..951a32cd3ce 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -50,7 +50,7 @@ pub mod animation; pub mod attr; pub mod bezier; pub mod context; -mod custom_properties; +pub mod custom_properties; pub mod data; pub mod dom; pub mod element_state; diff --git a/components/style/matching.rs b/components/style/matching.rs index 1c158505e97..025e229e57c 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -8,8 +8,8 @@ use animation::{self, Animation}; use context::SharedStyleContext; use data::PrivateStyleData; use dom::{TElement, TNode, TRestyleDamage}; -use properties::{ComputedValues, PropertyDeclaration, cascade}; -use selector_impl::SelectorImplExt; +use properties::{PropertyDeclaration, TComputedValues, cascade}; +use selector_impl::{ElementExt, SelectorImplExt}; use selector_matching::{DeclarationBlock, Stylist}; use selectors::Element; use selectors::bloom::BloomFilter; @@ -151,25 +151,25 @@ impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> { static APPLICABLE_DECLARATIONS_CACHE_SIZE: usize = 32; -pub struct ApplicableDeclarationsCache { - cache: SimpleHashCache<ApplicableDeclarationsCacheEntry, Arc<ComputedValues>>, +pub struct ApplicableDeclarationsCache<C: TComputedValues> { + cache: SimpleHashCache<ApplicableDeclarationsCacheEntry, Arc<C>>, } -impl ApplicableDeclarationsCache { - pub fn new() -> ApplicableDeclarationsCache { +impl<C: TComputedValues> ApplicableDeclarationsCache<C> { + pub fn new() -> Self { ApplicableDeclarationsCache { cache: SimpleHashCache::new(APPLICABLE_DECLARATIONS_CACHE_SIZE), } } - pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> { + pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<C>> { match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) { None => None, Some(ref values) => Some((*values).clone()), } } - pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) { + pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<C>) { self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style) } @@ -179,14 +179,14 @@ impl ApplicableDeclarationsCache { } /// An LRU cache of the last few nodes seen, so that we can aggressively try to reuse their styles. -pub struct StyleSharingCandidateCache { - cache: LRUCache<StyleSharingCandidate, ()>, +pub struct StyleSharingCandidateCache<C: TComputedValues> { + cache: LRUCache<StyleSharingCandidate<C>, ()>, } #[derive(Clone)] -pub struct StyleSharingCandidate { - pub style: Arc<ComputedValues>, - pub parent_style: Arc<ComputedValues>, +pub struct StyleSharingCandidate<C: TComputedValues> { + pub style: Arc<C>, + pub parent_style: Arc<C>, pub local_name: Atom, // FIXME(pcwalton): Should be a list of atoms instead. pub class: Option<String>, @@ -195,8 +195,8 @@ pub struct StyleSharingCandidate { pub link: bool, } -impl PartialEq for StyleSharingCandidate { - fn eq(&self, other: &StyleSharingCandidate) -> bool { +impl<C: TComputedValues> PartialEq for StyleSharingCandidate<C> { + fn eq(&self, other: &Self) -> bool { arc_ptr_eq(&self.style, &other.style) && arc_ptr_eq(&self.parent_style, &other.parent_style) && self.local_name == other.local_name && @@ -207,12 +207,12 @@ impl PartialEq for StyleSharingCandidate { } } -impl StyleSharingCandidate { +impl<C: TComputedValues> StyleSharingCandidate<C> { /// Attempts to create a style sharing candidate from this node. Returns /// the style sharing candidate or `None` if this node is ineligible for /// style sharing. #[allow(unsafe_code)] - fn new<E: TElement>(element: &E) -> Option<StyleSharingCandidate> { + fn new<N: TNode<ConcreteComputedValues=C>>(element: &N::ConcreteElement) -> Option<Self> { let parent_element = match element.parent_element() { None => return None, Some(parent_element) => parent_element, @@ -254,7 +254,7 @@ impl StyleSharingCandidate { link: element.is_link(), namespace: (*element.get_namespace()).clone(), common_style_affecting_attributes: - create_common_style_affecting_attributes_from_element::<E>(&element) + create_common_style_affecting_attributes_from_element::<N::ConcreteElement>(&element) }) } @@ -332,19 +332,19 @@ impl StyleSharingCandidate { static STYLE_SHARING_CANDIDATE_CACHE_SIZE: usize = 40; -impl StyleSharingCandidateCache { - pub fn new() -> StyleSharingCandidateCache { +impl<C: TComputedValues> StyleSharingCandidateCache<C> { + pub fn new() -> Self { StyleSharingCandidateCache { cache: LRUCache::new(STYLE_SHARING_CANDIDATE_CACHE_SIZE), } } - pub fn iter(&self) -> Iter<(StyleSharingCandidate, ())> { + pub fn iter(&self) -> Iter<(StyleSharingCandidate<C>, ())> { self.cache.iter() } - pub fn insert_if_possible<E: TElement>(&mut self, element: &E) { - match StyleSharingCandidate::new(element) { + pub fn insert_if_possible<N: TNode<ConcreteComputedValues=C>>(&mut self, element: &N::ConcreteElement) { + match StyleSharingCandidate::new::<N>(element) { None => {} Some(candidate) => self.cache.insert(candidate, ()) } @@ -368,15 +368,15 @@ trait PrivateMatchMethods: TNode where <Self::ConcreteElement as Element>::Impl: SelectorImplExt { fn cascade_node_pseudo_element(&self, context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>, - parent_style: Option<&Arc<ComputedValues>>, + parent_style: Option<&Arc<Self::ConcreteComputedValues>>, applicable_declarations: &[DeclarationBlock], - mut style: Option<&mut Arc<ComputedValues>>, + mut style: Option<&mut Arc<Self::ConcreteComputedValues>>, applicable_declarations_cache: - &mut ApplicableDeclarationsCache, + &mut ApplicableDeclarationsCache<Self::ConcreteComputedValues>, new_animations_sender: &Mutex<Sender<Animation>>, shareable: bool, animate_properties: bool) - -> (Self::ConcreteRestyleDamage, Arc<ComputedValues>) { + -> (Self::ConcreteRestyleDamage, Arc<Self::ConcreteComputedValues>) { let mut cacheable = true; if animate_properties { cacheable = !self.update_animations_for_cascade(context, &mut style) && cacheable; @@ -416,10 +416,11 @@ trait PrivateMatchMethods: TNode if animate_properties { if let Some(ref style) = style { let animations_started = - animation::start_transitions_if_applicable(new_animations_sender, - self.opaque(), - &**style, - &mut this_style); + animation::start_transitions_if_applicable::<Self::ConcreteComputedValues>( + new_animations_sender, + self.opaque(), + &**style, + &mut this_style); cacheable = cacheable && !animations_started } } @@ -440,7 +441,7 @@ trait PrivateMatchMethods: TNode fn update_animations_for_cascade(&self, context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>, - style: &mut Option<&mut Arc<ComputedValues>>) + style: &mut Option<&mut Arc<Self::ConcreteComputedValues>>) -> bool { let style = match *style { None => return false, @@ -456,7 +457,7 @@ trait PrivateMatchMethods: TNode had_animations_to_expire = animations_to_expire.is_some(); if let Some(ref animations) = animations_to_expire { for animation in *animations { - animation.property_animation.update(&mut *Arc::make_mut(style), 1.0); + animation.property_animation.update(Arc::make_mut(style).as_servo_mut(), 1.0); } } } @@ -474,7 +475,8 @@ trait PrivateMatchMethods: TNode if had_running_animations { let mut all_running_animations = context.running_animations.write().unwrap(); for running_animation in all_running_animations.get(&this_opaque).unwrap() { - animation::update_style_for_animation::<Self::ConcreteRestyleDamage>(running_animation, style, None); + animation::update_style_for_animation::<Self::ConcreteComputedValues, + Self::ConcreteRestyleDamage>(running_animation, style, None); } all_running_animations.remove(&this_opaque); } @@ -489,14 +491,15 @@ impl<N: TNode> PrivateMatchMethods for N trait PrivateElementMatchMethods: TElement { fn share_style_with_candidate_if_possible(&self, parent_node: Option<Self::ConcreteNode>, - candidate: &StyleSharingCandidate) - -> Option<Arc<ComputedValues>> { + candidate: &StyleSharingCandidate<<Self::ConcreteNode as + TNode>::ConcreteComputedValues>) + -> Option<Arc<<Self::ConcreteNode as TNode>::ConcreteComputedValues>> { let parent_node = match parent_node { Some(ref parent_node) if parent_node.as_element().is_some() => parent_node, Some(_) | None => return None, }; - let parent_data: Option<&PrivateStyleData<_>> = unsafe { + let parent_data: Option<&PrivateStyleData<_, _>> = unsafe { parent_node.borrow_data_unchecked().map(|d| &*d) }; @@ -550,7 +553,8 @@ pub trait ElementMatchMethods : TElement /// guarantee that at the type system level yet. unsafe fn share_style_if_possible(&self, style_sharing_candidate_cache: - &mut StyleSharingCandidateCache, + &mut StyleSharingCandidateCache<<Self::ConcreteNode as + TNode>::ConcreteComputedValues>, parent: Option<Self::ConcreteNode>) -> StyleSharingResult<<Self::ConcreteNode as TNode>::ConcreteRestyleDamage> { if opts::get().disable_share_style_cache { @@ -639,7 +643,8 @@ pub trait MatchMethods : TNode { context: &SharedStyleContext<<Self::ConcreteElement as Element>::Impl>, parent: Option<Self>, applicable_declarations: &ApplicableDeclarations<<Self::ConcreteElement as Element>::Impl>, - applicable_declarations_cache: &mut ApplicableDeclarationsCache, + applicable_declarations_cache: + &mut ApplicableDeclarationsCache<Self::ConcreteComputedValues>, new_animations_sender: &Mutex<Sender<Animation>>) where <Self::ConcreteElement as Element>::Impl: SelectorImplExt { // Get our parent's style. This must be unsafe so that we don't touch the parent's diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index a7cd97743cc..7c0189f599e 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -10,9 +10,7 @@ use std::ascii::AsciiExt; use std::collections::HashSet; -use std::default::Default; use std::fmt; -use std::hash::{Hash, Hasher}; use std::intrinsics; use std::mem; use std::sync::Arc; @@ -24,7 +22,6 @@ use error_reporting::ParseErrorReporter; use url::Url; use euclid::SideOffsets2D; use euclid::size::Size2D; -use fnv::FnvHasher; use string_cache::Atom; use computed_values; use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode}; @@ -32,7 +29,7 @@ use parser::{ParserContext, log_css_error}; use selectors::matching::DeclarationBlock; use stylesheets::Origin; use values::AuExtensionMethods; -use values::computed::{self, ToComputedValue}; +use values::computed::{self, TContext, ToComputedValue}; use values::specified::BorderStyle; use self::property_bit_field::PropertyBitField; @@ -142,17 +139,20 @@ pub mod longhands { use error_reporting::ParseErrorReporter; use properties::longhands; use properties::property_bit_field::PropertyBitField; - use properties::{ComputedValues, PropertyDeclaration}; + use properties::{ComputedValues, PropertyDeclaration, TComputedValues}; + use properties::style_struct_traits::T${THIS_STYLE_STRUCT.name}; + use properties::style_structs; use std::collections::HashMap; use std::sync::Arc; - use values::computed::ToComputedValue; + use values::computed::{TContext, ToComputedValue}; use values::{computed, specified}; use string_cache::Atom; ${caller.body()} #[allow(unused_variables)] - pub fn cascade_property(declaration: &PropertyDeclaration, - inherited_style: &ComputedValues, - context: &mut computed::Context, + pub fn cascade_property<C: TComputedValues>( + declaration: &PropertyDeclaration, + inherited_style: &C, + context: &mut computed::Context<C>, seen: &mut PropertyBitField, cacheable: &mut bool, error_reporter: &mut Box<ParseErrorReporter + Send>) { @@ -167,31 +167,39 @@ pub mod longhands { return } seen.set_${property.ident}(); - let computed_value = ::properties::substitute_variables_${property.ident}( - declared_value, &context.style.custom_properties, |value| match *value { - DeclaredValue::Value(ref specified_value) => { - specified_value.to_computed_value(&context) - } - DeclaredValue::WithVariables { .. } => unreachable!(), - DeclaredValue::Initial => get_initial_value(), - DeclaredValue::Inherit => { - // This is a bit slow, but this is rare so it shouldn't - // matter. - // - // FIXME: is it still? - *cacheable = false; - inherited_style.${THIS_STYLE_STRUCT.ident} - .${property.ident} - .clone() - } - }, error_reporter - ); - Arc::make_mut(&mut context.style.${THIS_STYLE_STRUCT.ident}).${property.ident} = - computed_value; + { + let custom_props = context.style().custom_properties(); + ::properties::substitute_variables_${property.ident}( + declared_value, &custom_props, |value| match *value { + DeclaredValue::Value(ref specified_value) => { + let computed = specified_value.to_computed_value(context); + context.mutate_style().mutate_${THIS_STYLE_STRUCT.name.lower()}() + .set_${property.ident}(computed); + } + DeclaredValue::WithVariables { .. } => unreachable!(), + DeclaredValue::Initial => { + // We assume that it's faster to use copy_*_from rather than + // set_*(get_initial_value()); + let initial_struct = C::initial_values().get_${THIS_STYLE_STRUCT.name.lower()}(); + context.mutate_style().mutate_${THIS_STYLE_STRUCT.name.lower()}() + .copy_${property.ident}_from(initial_struct); + }, + DeclaredValue::Inherit => { + // This is a bit slow, but this is rare so it shouldn't + // matter. + // + // FIXME: is it still? + *cacheable = false; + let inherited_struct = inherited_style.get_${THIS_STYLE_STRUCT.name.lower()}(); + context.mutate_style().mutate_${THIS_STYLE_STRUCT.name.lower()}() + .copy_${property.ident}_from(inherited_struct); + } + }, error_reporter + ); + } % if custom_cascade: - cascade_property_custom(&computed_value, - declaration, + cascade_property_custom(declaration, inherited_style, context, seen, @@ -334,7 +342,6 @@ pub mod longhands { use app_units::Au; use cssparser::ToCss; use std::fmt; - use values::computed::Context; impl ToCss for SpecifiedValue { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -361,7 +368,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { self.0.to_computed_value(context) } } @@ -399,7 +406,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; impl ToCss for SpecifiedValue { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -421,7 +427,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { self.0.to_computed_value(context) } } @@ -453,6 +459,7 @@ pub mod longhands { %> pub use self::computed_value::T as SpecifiedValue; use values::computed::{Context, ComputedValueAsSpecified}; + use properties::style_struct_traits::TInheritedText; pub mod computed_value { #[allow(non_camel_case_types)] @@ -498,31 +505,27 @@ pub mod longhands { impl ComputedValueAsSpecified for SpecifiedValue {} - fn cascade_property_custom(_computed_value: &computed_value::T, + fn cascade_property_custom<C: TComputedValues>( _declaration: &PropertyDeclaration, - _inherited_style: &ComputedValues, - context: &mut computed::Context, + _inherited_style: &C, + context: &mut computed::Context<C>, _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut Box<ParseErrorReporter + Send>) { - Arc::make_mut(&mut context.style.box_)._servo_display_for_hypothetical_box = - longhands::_servo_display_for_hypothetical_box::derive_from_display(&context); - Arc::make_mut(&mut context.style.inheritedtext)._servo_text_decorations_in_effect = - longhands::_servo_text_decorations_in_effect::derive_from_display(&context); + longhands::_servo_display_for_hypothetical_box::derive_from_display(context); + longhands::_servo_text_decorations_in_effect::derive_from_display(context); } </%self:longhand> ${single_keyword("position", "static absolute relative fixed")} <%self:single_keyword_computed name="float" values="none left right"> - use values::computed::Context; - impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { - let positioned = matches!(context.style.box_.position, + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { + let positioned = matches!(context.style().get_box().clone_position(), longhands::position::SpecifiedValue::absolute | longhands::position::SpecifiedValue::fixed); if positioned { @@ -546,9 +549,9 @@ pub mod longhands { } #[inline] - pub fn derive_from_display(context: &computed::Context) - -> computed_value::T { - context.style.box_.display + pub fn derive_from_display<Cx: TContext>(context: &mut Cx) { + let d = context.style().get_box().clone_display(); + context.mutate_style().mutate_box().set__servo_display_for_hypothetical_box(d); } </%self:longhand> @@ -636,7 +639,6 @@ pub mod longhands { use std::fmt; use values::AuExtensionMethods; use values::CSSFloat; - use values::computed::Context; #[derive(Debug, Clone, PartialEq, Copy, HeapSizeOf)] pub enum SpecifiedValue { @@ -699,7 +701,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Normal => computed_value::T::Normal, SpecifiedValue::Number(value) => computed_value::T::Number(value), @@ -729,7 +731,6 @@ pub mod longhands { <%self:longhand name="vertical-align"> use cssparser::ToCss; use std::fmt; - use values::computed::Context; <% vertical_align_keywords = ( "baseline sub super top text-top middle bottom text-bottom".split()) %> @@ -797,7 +798,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { % for keyword in vertical_align_keywords: SpecifiedValue::${to_rust_ident(keyword)} => { @@ -823,7 +824,6 @@ pub mod longhands { // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. <%self:longhand name="overflow-y"> use super::overflow_x; - use values::computed::Context; use cssparser::ToCss; use std::fmt; @@ -845,7 +845,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T(self.0.to_computed_value(context)) } } @@ -1052,7 +1052,6 @@ pub mod longhands { use cssparser::{ToCss, Token}; use std::fmt; use url::Url; - use values::computed::Context; use values::LocalToCss; #[derive(Debug, Clone, PartialEq, Eq, HeapSizeOf)] @@ -1093,7 +1092,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T { match *self { SpecifiedValue::None => computed_value::T(None), SpecifiedValue::Url(ref url) => computed_value::T(Some(url.clone())), @@ -1272,7 +1271,6 @@ pub mod longhands { <%self:longhand name="background-image"> use cssparser::ToCss; use std::fmt; - use values::computed::Context; use values::specified::Image; use values::LocalToCss; @@ -1320,7 +1318,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue(None) => computed_value::T(None), SpecifiedValue(Some(ref image)) => @@ -1334,7 +1332,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; pub mod computed_value { use values::computed::LengthOrPercentage; @@ -1419,7 +1416,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T { horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), @@ -1456,7 +1453,6 @@ pub mod longhands { use cssparser::{ToCss, Token}; use std::ascii::AsciiExt; use std::fmt; - use values::computed::Context; pub mod computed_value { use values::computed::LengthOrPercentageOrAuto; @@ -1529,7 +1525,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &computed::Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Explicit(ref size) => { computed_value::T::Explicit(computed_value::ExplicitSize { @@ -1593,14 +1589,13 @@ pub mod longhands { <%self:raw_longhand name="color"> use cssparser::{Color, RGBA}; - use values::computed::Context; use values::specified::{CSSColor, CSSRGBA}; impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T { self.parsed } } @@ -1747,7 +1742,6 @@ pub mod longhands { <%self:longhand name="font-weight"> use cssparser::ToCss; use std::fmt; - use values::computed::Context; #[derive(Debug, Clone, PartialEq, Eq, Copy, HeapSizeOf)] pub enum SpecifiedValue { @@ -1831,12 +1825,12 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { % for weight in range(100, 901, 100): SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight}, % endfor - SpecifiedValue::Bolder => match context.inherited_style.font.font_weight { + SpecifiedValue::Bolder => match context.inherited_style().get_font().clone_font_weight() { computed_value::T::Weight100 => computed_value::T::Weight400, computed_value::T::Weight200 => computed_value::T::Weight400, computed_value::T::Weight300 => computed_value::T::Weight400, @@ -1847,7 +1841,7 @@ pub mod longhands { computed_value::T::Weight800 => computed_value::T::Weight900, computed_value::T::Weight900 => computed_value::T::Weight900, }, - SpecifiedValue::Lighter => match context.inherited_style.font.font_weight { + SpecifiedValue::Lighter => match context.inherited_style().get_font().clone_font_weight() { computed_value::T::Weight100 => computed_value::T::Weight100, computed_value::T::Weight200 => computed_value::T::Weight100, computed_value::T::Weight300 => computed_value::T::Weight100, @@ -1868,7 +1862,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::FONT_MEDIUM_PX; - use values::computed::Context; use values::specified::{LengthOrPercentage, Length, Percentage}; impl ToCss for SpecifiedValue { @@ -1891,24 +1884,25 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match self.0 { LengthOrPercentage::Length(Length::FontRelative(value)) => { - value.to_computed_value(context.inherited_style.font.font_size, - context.style.root_font_size) + value.to_computed_value(context.inherited_style().get_font().clone_font_size(), + context.style().root_font_size()) } LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => { - value.to_computed_value(context.inherited_style.font.font_size) + value.to_computed_value(context.inherited_style().get_font().clone_font_size()) } LengthOrPercentage::Length(l) => { - l.to_computed_value(&context) + l.to_computed_value(context) } LengthOrPercentage::Percentage(Percentage(value)) => { - context.inherited_style.font.font_size.scale_by(value) + context.inherited_style().get_font().clone_font_size().scale_by(value) } LengthOrPercentage::Calc(calc) => { - let calc = calc.to_computed_value(&context); - calc.length() + context.inherited_style.font.font_size.scale_by(calc.percentage()) + let calc = calc.to_computed_value(context); + calc.length() + context.inherited_style().get_font().clone_font_size() + .scale_by(calc.percentage()) } } } @@ -1992,7 +1986,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub enum SpecifiedValue { @@ -2033,7 +2026,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Normal => computed_value::T(None), SpecifiedValue::Specified(l) => @@ -2055,7 +2048,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub enum SpecifiedValue { @@ -2096,7 +2088,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Normal => computed_value::T(None), SpecifiedValue::Specified(l) => @@ -2136,6 +2128,7 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::computed::ComputedValueAsSpecified; + use properties::style_struct_traits::TInheritedText; impl ComputedValueAsSpecified for SpecifiedValue {} @@ -2207,16 +2200,14 @@ pub mod longhands { if !empty { Ok(result) } else { Err(()) } } - fn cascade_property_custom(_computed_value: &computed_value::T, + fn cascade_property_custom<C: TComputedValues>( _declaration: &PropertyDeclaration, - _inherited_style: &ComputedValues, - context: &mut computed::Context, + _inherited_style: &C, + context: &mut computed::Context<C>, _seen: &mut PropertyBitField, _cacheable: &mut bool, _error_reporter: &mut Box<ParseErrorReporter + Send>) { - Arc::make_mut(&mut context.style.inheritedtext)._servo_text_decorations_in_effect = - longhands::_servo_text_decorations_in_effect::derive_from_text_decoration( - &context); + longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context); } </%self:longhand> @@ -2228,6 +2219,7 @@ pub mod longhands { use std::fmt; use values::computed::ComputedValueAsSpecified; + use properties::style_struct_traits::{TBox, TColor, TText}; impl ComputedValueAsSpecified for SpecifiedValue {} @@ -2258,20 +2250,20 @@ pub mod longhands { } } - fn maybe(flag: bool, context: &computed::Context) -> Option<RGBA> { + fn maybe<Cx: TContext>(flag: bool, context: &Cx) -> Option<RGBA> { if flag { - Some(context.style.color.color) + Some(context.style().get_color().clone_color()) } else { None } } - fn derive(context: &computed::Context) -> computed_value::T { + fn derive<Cx: TContext>(context: &Cx) -> computed_value::T { // Start with no declarations if this is a block; otherwise, start with the // declarations in effect and add in the text decorations that this inline specifies. - let mut result = match context.style.box_.display { + let mut result = match context.style().get_box().clone_display() { super::display::computed_value::T::inline => { - context.inherited_style.inheritedtext._servo_text_decorations_in_effect + context.inherited_style().get_inheritedtext().clone__servo_text_decorations_in_effect() } _ => { SpecifiedValue { @@ -2283,27 +2275,28 @@ pub mod longhands { }; if result.underline.is_none() { - result.underline = maybe(context.style.text.text_decoration.underline, context) + result.underline = maybe(context.style().get_text().has_underline(), context) } if result.overline.is_none() { - result.overline = maybe(context.style.text.text_decoration.overline, context) + result.overline = maybe(context.style().get_text().has_overline(), context) } if result.line_through.is_none() { - result.line_through = maybe(context.style.text.text_decoration.line_through, context) + result.line_through = maybe(context.style().get_text().has_line_through(), context) } + result } #[inline] - pub fn derive_from_text_decoration(context: &computed::Context) - -> computed_value::T { - derive(context) + pub fn derive_from_text_decoration<Cx: TContext>(context: &mut Cx) { + let derived = derive(context); + context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived); } #[inline] - pub fn derive_from_display(context: &computed::Context) - -> computed_value::T { - derive(context) + pub fn derive_from_display<Cx: TContext>(context: &mut Cx) { + let derived = derive(context); + context.mutate_style().mutate_inheritedtext().set__servo_text_decorations_in_effect(derived); } </%self:longhand> @@ -2365,7 +2358,6 @@ pub mod longhands { <%self:longhand name="border-spacing"> use app_units::Au; use values::AuExtensionMethods; - use values::computed::Context; use cssparser::ToCss; use std::fmt; @@ -2414,7 +2406,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T { horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), @@ -2529,7 +2521,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub enum SpecifiedValue { @@ -2570,7 +2561,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Auto => computed_value::T(None), SpecifiedValue::Specified(l) => @@ -2591,7 +2582,6 @@ pub mod longhands { <%self:longhand name="column-count" experimental="True"> use cssparser::ToCss; use std::fmt; - use values::computed::Context; #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub enum SpecifiedValue { @@ -2631,7 +2621,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Auto => computed_value::T(None), SpecifiedValue::Specified(count) => @@ -2658,7 +2648,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub enum SpecifiedValue { @@ -2699,7 +2688,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { match *self { SpecifiedValue::Normal => computed_value::T(None), SpecifiedValue::Specified(l) => @@ -2724,7 +2713,6 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; use values::CSSFloat; - use values::computed::Context; impl ToCss for SpecifiedValue { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -2747,7 +2735,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T { if self.0 < 0.0 { 0.0 } else if self.0 > 1.0 { @@ -2766,7 +2754,6 @@ pub mod longhands { use cssparser::{self, ToCss}; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct SpecifiedValue(Vec<SpecifiedBoxShadow>); @@ -2890,12 +2877,12 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T(self.0.iter().map(|value| compute_one_box_shadow(value, context)).collect()) } } - pub fn compute_one_box_shadow(value: &SpecifiedBoxShadow, context: &computed::Context) + pub fn compute_one_box_shadow<Cx: TContext>(value: &SpecifiedBoxShadow, context: &Cx) -> computed_value::BoxShadow { computed_value::BoxShadow { offset_x: value.offset_x.to_computed_value(context), @@ -2978,8 +2965,6 @@ pub mod longhands { // NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2. - use values::computed::Context; - pub mod computed_value { use app_units::Au; @@ -3083,7 +3068,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T(self.0.map(|value| computed_value::ClipRect { top: value.top.to_computed_value(context), right: value.right.map(|right| right.to_computed_value(context)), @@ -3130,7 +3115,6 @@ pub mod longhands { use cssparser::{self, ToCss}; use std::fmt; use values::AuExtensionMethods; - use values::computed::Context; #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct SpecifiedValue(Vec<SpecifiedTextShadow>); @@ -3289,7 +3273,7 @@ pub mod longhands { impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; - fn to_computed_value(&self, context: &computed::Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T(self.0.iter().map(|value| { computed_value::TextShadow { offset_x: value.offset_x.to_computed_value(context), @@ -3518,7 +3502,7 @@ pub mod longhands { impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; - fn to_computed_value(&self, context: &computed::Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T{ filters: self.0.iter().map(|value| { match *value { SpecifiedFilter::Blur(factor) => @@ -3540,7 +3524,6 @@ pub mod longhands { <%self:longhand name="transform"> use app_units::Au; use values::CSSFloat; - use values::computed::Context; use cssparser::ToCss; use std::fmt; @@ -3957,7 +3940,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { if self.0.is_empty() { return computed_value::T(None) } @@ -4083,7 +4066,6 @@ pub mod longhands { <%self:longhand name="transform-origin"> use app_units::Au; use values::AuExtensionMethods; - use values::computed::Context; use values::specified::{Length, LengthOrPercentage, Percentage}; use cssparser::ToCss; @@ -4149,7 +4131,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T { horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), @@ -4164,7 +4146,6 @@ pub mod longhands { "computed::LengthOrNone::None")} <%self:longhand name="perspective-origin"> - use values::computed::Context; use values::specified::{LengthOrPercentage, Percentage}; use cssparser::ToCss; @@ -4225,7 +4206,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> computed_value::T { computed_value::T { horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), @@ -4240,7 +4221,6 @@ pub mod longhands { saturation color luminosity""")} <%self:longhand name="image-rendering"> - use values::computed::Context; pub mod computed_value { use cssparser::ToCss; @@ -4289,7 +4269,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T { *self } } @@ -4307,7 +4287,7 @@ pub mod longhands { pub mod computed_value { use cssparser::ToCss; use std::fmt; - use values::computed::{Context, ToComputedValue}; + use values::computed::{TContext, ToComputedValue}; pub use values::computed::Time as SingleComputedValue; @@ -4318,7 +4298,7 @@ pub mod longhands { type ComputedValue = T; #[inline] - fn to_computed_value(&self, _: &Context) -> T { + fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> T { (*self).clone() } } @@ -4363,7 +4343,6 @@ pub mod longhands { // TODO(pcwalton): Multiple transitions. <%self:longhand name="transition-timing-function"> use self::computed_value::{StartEnd, TransitionTimingFunction}; - use values::computed::Context; use euclid::point::Point2D; @@ -4487,7 +4466,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T { (*self).clone() } } @@ -4560,7 +4539,6 @@ pub mod longhands { // TODO(pcwalton): Lots more properties. <%self:longhand name="transition-property"> use self::computed_value::TransitionProperty; - use values::computed::Context; pub use self::computed_value::SingleComputedValue as SingleSpecifiedValue; pub use self::computed_value::T as SpecifiedValue; @@ -4807,7 +4785,7 @@ pub mod longhands { type ComputedValue = computed_value::T; #[inline] - fn to_computed_value(&self, _: &Context) -> computed_value::T { + fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> computed_value::T { (*self).clone() } } @@ -5587,13 +5565,12 @@ mod property_bit_field { % for property in LONGHANDS: % if property.derived_from is None: #[allow(non_snake_case)] - fn substitute_variables_${property.ident}<F, R>( + fn substitute_variables_${property.ident}<F>( value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, f: F, error_reporter: &mut Box<ParseErrorReporter + Send>) - -> R - where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) -> R + where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { if let DeclaredValue::WithVariables { ref css, first_token_type, ref base_url, from_shorthand @@ -5604,15 +5581,15 @@ mod property_bit_field { from_shorthand, custom_properties, f, - error_reporter) + error_reporter); } else { - f(value) + f(value); } } #[allow(non_snake_case)] #[inline(never)] - fn substitute_variables_${property.ident}_slow<F, R>( + fn substitute_variables_${property.ident}_slow<F>( css: &String, first_token_type: TokenSerializationType, base_url: &Url, @@ -5620,9 +5597,7 @@ mod property_bit_field { custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, f: F, error_reporter: &mut Box<ParseErrorReporter + Send>) - -> R - where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) - -> R { + where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) { f(& ::custom_properties::substitute(css, first_token_type, custom_properties) .and_then(|css| { @@ -5656,7 +5631,7 @@ mod property_bit_field { // Invalid at computed-value time. DeclaredValue::${"Inherit" if property.style_struct.inherited else "Initial"} ) - ) + ); } % endif % endfor @@ -6087,8 +6062,58 @@ impl PropertyDeclaration { } } +pub mod style_struct_traits { + use super::longhands; + + % for style_struct in STYLE_STRUCTS: + pub trait T${style_struct.name}: Clone + PartialEq { + % for longhand in style_struct.longhands: + #[allow(non_snake_case)] + fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T); + #[allow(non_snake_case)] + fn copy_${longhand.ident}_from(&mut self, other: &Self); + % endfor + % if style_struct.name == "Animation": + fn transition_count(&self) -> usize; + % elif style_struct.name == "Border": + % for side in ["top", "right", "bottom", "left"]: + fn border_${side}_is_none_or_hidden_and_has_nonzero_width(&self) -> bool; + % endfor + % elif style_struct.name == "Box": + fn clone_display(&self) -> longhands::display::computed_value::T; + fn clone_position(&self) -> longhands::position::computed_value::T; + fn is_floated(&self) -> bool; + fn overflow_x_is_visible(&self) -> bool; + fn overflow_y_is_visible(&self) -> bool; + % elif style_struct.name == "Color": + fn clone_color(&self) -> longhands::color::computed_value::T; + % elif style_struct.name == "Font": + fn clone_font_size(&self) -> longhands::font_size::computed_value::T; + fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T; + fn compute_font_hash(&mut self); + % elif style_struct.name == "InheritedBox": + fn clone_direction(&self) -> longhands::direction::computed_value::T; + fn clone_writing_mode(&self) -> longhands::writing_mode::computed_value::T; + fn clone_text_orientation(&self) -> longhands::text_orientation::computed_value::T; + % elif style_struct.name == "InheritedText": + #[allow(non_snake_case)] + fn clone__servo_text_decorations_in_effect(&self) -> + longhands::_servo_text_decorations_in_effect::computed_value::T; + % elif style_struct.name == "Outline": + fn outline_is_none_or_hidden_and_has_nonzero_width(&self) -> bool; + % elif style_struct.name == "Text": + fn has_underline(&self) -> bool; + fn has_overline(&self) -> bool; + fn has_line_through(&self) -> bool; + % endif + } + % endfor +} + pub mod style_structs { + use fnv::FnvHasher; use super::longhands; + use std::hash::{Hash, Hasher}; % for style_struct in STYLE_STRUCTS: % if style_struct.name == "Font": @@ -6116,7 +6141,132 @@ pub mod style_structs { } % endif + impl super::style_struct_traits::T${style_struct.name} for ${style_struct.name} { + % for longhand in style_struct.longhands: + fn set_${longhand.ident}(&mut self, v: longhands::${longhand.ident}::computed_value::T) { + self.${longhand.ident} = v; + } + fn copy_${longhand.ident}_from(&mut self, other: &Self) { + self.${longhand.ident} = other.${longhand.ident}.clone(); + } + % endfor + % if style_struct.name == "Animation": + fn transition_count(&self) -> usize { + self.transition_property.0.len() + } + % elif style_struct.name == "Border": + % for side in ["top", "right", "bottom", "left"]: + fn border_${side}_is_none_or_hidden_and_has_nonzero_width(&self) -> bool { + self.border_${side}_style.none_or_hidden() && + self.border_${side}_width != ::app_units::Au(0) + } + % endfor + % elif style_struct.name == "Box": + fn clone_display(&self) -> longhands::display::computed_value::T { + self.display.clone() + } + fn clone_position(&self) -> longhands::position::computed_value::T { + self.position.clone() + } + fn is_floated(&self) -> bool { + self.float != longhands::float::SpecifiedValue::none + } + fn overflow_x_is_visible(&self) -> bool { + self.overflow_x == longhands::overflow_x::computed_value::T::visible + } + fn overflow_y_is_visible(&self) -> bool { + self.overflow_y.0 == longhands::overflow_x::computed_value::T::visible + } + % elif style_struct.name == "Color": + fn clone_color(&self) -> longhands::color::computed_value::T { + self.color.clone() + } + % elif style_struct.name == "Font": + fn clone_font_size(&self) -> longhands::font_size::computed_value::T { + self.font_size.clone() + } + fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T { + self.font_weight.clone() + } + fn compute_font_hash(&mut self) { + // Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`. + let mut hasher: FnvHasher = Default::default(); + hasher.write_u16(self.font_weight as u16); + self.font_stretch.hash(&mut hasher); + self.font_family.hash(&mut hasher); + self.hash = hasher.finish() + } + % elif style_struct.name == "InheritedBox": + fn clone_direction(&self) -> longhands::direction::computed_value::T { + self.direction.clone() + } + fn clone_writing_mode(&self) -> longhands::writing_mode::computed_value::T { + self.writing_mode.clone() + } + fn clone_text_orientation(&self) -> longhands::text_orientation::computed_value::T { + self.text_orientation.clone() + } + % elif style_struct.name == "InheritedText": + fn clone__servo_text_decorations_in_effect(&self) -> + longhands::_servo_text_decorations_in_effect::computed_value::T { + self._servo_text_decorations_in_effect.clone() + } + % elif style_struct.name == "Outline": + fn outline_is_none_or_hidden_and_has_nonzero_width(&self) -> bool { + self.outline_style.none_or_hidden() && self.outline_width != ::app_units::Au(0) + } + % elif style_struct.name == "Text": + fn has_underline(&self) -> bool { + self.text_decoration.underline + } + fn has_overline(&self) -> bool { + self.text_decoration.overline + } + fn has_line_through(&self) -> bool { + self.text_decoration.line_through + } + % endif + } + + % endfor +} + +pub trait TComputedValues : Clone + Send + Sync + 'static { + % for style_struct in STYLE_STRUCTS: + type Concrete${style_struct.name}: style_struct_traits::T${style_struct.name}; + % endfor + + // Temporary bailout case for stuff we haven't made work with the trait + // yet - panics for non-Servo implementations. + // + // Used only for animations. Don't use it in other places. + fn as_servo<'a>(&'a self) -> &'a ComputedValues; + fn as_servo_mut<'a>(&'a mut self) -> &'a mut ComputedValues; + + fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, + shareable: bool, + writing_mode: WritingMode, + root_font_size: Au, + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: Arc<Self::Concrete${style_struct.name}>, + % endfor + ) -> Self; + + fn initial_values() -> &'static Self; + + fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F); + + % for style_struct in STYLE_STRUCTS: + fn clone_${style_struct.name.lower()}(&self) -> Arc<Self::Concrete${style_struct.name}>; + fn get_${style_struct.name.lower()}<'a>(&'a self) -> &'a Self::Concrete${style_struct.name}; + fn mutate_${style_struct.name.lower()}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.name}; % endfor + + fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>>; + fn root_font_size(&self) -> Au; + fn set_root_font_size(&mut self, size: Au); + fn set_writing_mode(&mut self, mode: WritingMode); + fn is_multicol(&self) -> bool; } #[derive(Clone, HeapSizeOf)] @@ -6130,6 +6280,71 @@ pub struct ComputedValues { pub root_font_size: Au, } +impl TComputedValues for ComputedValues { + % for style_struct in STYLE_STRUCTS: + type Concrete${style_struct.name} = style_structs::${style_struct.name}; + % endfor + + fn as_servo<'a>(&'a self) -> &'a ComputedValues { self } + fn as_servo_mut<'a>(&'a mut self) -> &'a mut ComputedValues { self } + + fn new(custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, + shareable: bool, + writing_mode: WritingMode, + root_font_size: Au, + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: Arc<style_structs::${style_struct.name}>, + % endfor + ) -> Self { + ComputedValues { + custom_properties: custom_properties, + shareable: shareable, + writing_mode: writing_mode, + root_font_size: root_font_size, + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: ${style_struct.ident}, + % endfor + } + } + + fn initial_values() -> &'static Self { &*INITIAL_SERVO_VALUES } + + fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(f: F) { + CASCADE_PROPERTY.with(|x| f(x)); + } + + % for style_struct in STYLE_STRUCTS: + #[inline] + fn clone_${style_struct.name.lower()}(&self) -> Arc<Self::Concrete${style_struct.name}> { + self.${style_struct.ident}.clone() + } + #[inline] + fn get_${style_struct.name.lower()}<'a>(&'a self) -> &'a Self::Concrete${style_struct.name} { + &self.${style_struct.ident} + } + #[inline] + fn mutate_${style_struct.name.lower()}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.name} { + Arc::make_mut(&mut self.${style_struct.ident}) + } + % endfor + + // Cloning the Arc here is fine because it only happens in the case where we have custom + // properties, and those are both rare and expensive. + fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> { + self.custom_properties.as_ref().map(|x| x.clone()) + } + + fn root_font_size(&self) -> Au { self.root_font_size } + fn set_root_font_size(&mut self, size: Au) { self.root_font_size = size } + fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; } + + #[inline] + fn is_multicol(&self) -> bool { + let style = self.get_column(); + style.column_count.0.is_some() || style.column_width.0.is_some() + } +} + impl ComputedValues { /// Resolves the currentColor keyword. /// Any color value form computed values (except for the 'color' property itself) @@ -6231,12 +6446,6 @@ impl ComputedValues { } #[inline] - pub fn is_multicol(&self) -> bool { - let style = self.get_column(); - style.column_count.0.is_some() || style.column_width.0.is_some() - } - - #[inline] pub fn get_font_arc(&self) -> Arc<style_structs::Font> { self.font.clone() } @@ -6301,19 +6510,6 @@ impl ComputedValues { false } - % for style_struct in STYLE_STRUCTS: - #[inline] - pub fn get_${style_struct.name.lower()} - <'a>(&'a self) -> &'a style_structs::${style_struct.name} { - &*self.${style_struct.ident} - } - #[inline] - pub fn mutate_${style_struct.name.lower()} - <'a>(&'a mut self) -> &'a mut style_structs::${style_struct.name} { - &mut *Arc::make_mut(&mut self.${style_struct.ident}) - } - % endfor - pub fn computed_value_to_string(&self, name: &str) -> Result<String, ()> { match name { % for style_struct in STYLE_STRUCTS: @@ -6333,16 +6529,16 @@ impl ComputedValues { /// Return a WritingMode bitflags from the relevant CSS properties. -pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode { +pub fn get_writing_mode<S: style_struct_traits::TInheritedBox>(inheritedbox_style: &S) -> WritingMode { use logical_geometry; let mut flags = WritingMode::empty(); - match inheritedbox_style.direction { + match inheritedbox_style.clone_direction() { computed_values::direction::T::ltr => {}, computed_values::direction::T::rtl => { flags.insert(logical_geometry::FLAG_RTL); }, } - match inheritedbox_style.writing_mode { + match inheritedbox_style.clone_writing_mode() { computed_values::writing_mode::T::horizontal_tb => {}, computed_values::writing_mode::T::vertical_rl => { flags.insert(logical_geometry::FLAG_VERTICAL); @@ -6352,7 +6548,7 @@ pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> Wri flags.insert(logical_geometry::FLAG_VERTICAL_LR); }, } - match inheritedbox_style.text_orientation { + match inheritedbox_style.clone_text_orientation() { computed_values::text_orientation::T::sideways_right => {}, computed_values::text_orientation::T::sideways_left => { flags.insert(logical_geometry::FLAG_VERTICAL_LR); @@ -6369,7 +6565,7 @@ pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> Wri /// The initial values for all style structs as defined by the specification. lazy_static! { - pub static ref INITIAL_VALUES: ComputedValues = ComputedValues { + pub static ref INITIAL_SERVO_VALUES: ComputedValues = ComputedValues { % for style_struct in STYLE_STRUCTS: ${style_struct.ident}: Arc::new(style_structs::${style_struct.name} { % for longhand in style_struct.longhands: @@ -6389,35 +6585,34 @@ lazy_static! { /// Fast path for the function below. Only computes new inherited styles. -#[allow(unused_mut)] -fn cascade_with_cached_declarations( +#[allow(unused_mut, unused_imports)] +fn cascade_with_cached_declarations<C: TComputedValues>( viewport_size: Size2D<Au>, applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>], shareable: bool, - parent_style: &ComputedValues, - cached_style: &ComputedValues, + parent_style: &C, + cached_style: &C, custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>, mut error_reporter: Box<ParseErrorReporter + Send>) - -> ComputedValues { + -> C { let mut context = computed::Context { is_root_element: false, viewport_size: viewport_size, inherited_style: parent_style, - style: ComputedValues { + style: C::new( + custom_properties, + shareable, + WritingMode::empty(), + parent_style.root_font_size(), % for style_struct in STYLE_STRUCTS: - ${style_struct.ident}: - % if style_struct.inherited: - parent_style - % else: - cached_style - % endif - .${style_struct.ident}.clone(), + % if style_struct.inherited: + parent_style + % else: + cached_style + % endif + .clone_${style_struct.name.lower()}(), % endfor - custom_properties: custom_properties, - shareable: shareable, - writing_mode: WritingMode::empty(), - root_font_size: parent_style.root_font_size, - }, + ), }; let mut seen = PropertyBitField::new(); // Declaration blocks are stored in increasing precedence order, @@ -6432,42 +6627,47 @@ fn cascade_with_cached_declarations( PropertyDeclaration::${property.camel_case}(ref ${'_' if not style_struct.inherited else ''}declared_value) => { + use properties::style_struct_traits::T${style_struct.name}; % if style_struct.inherited: if seen.get_${property.ident}() { continue } seen.set_${property.ident}(); - let computed_value = + let custom_props = context.style().custom_properties(); substitute_variables_${property.ident}( - declared_value, &context.style.custom_properties, + declared_value, &custom_props, |value| match *value { DeclaredValue::Value(ref specified_value) - => specified_value.to_computed_value(&context), + => { + let computed = specified_value.to_computed_value(&context); + context.mutate_style().mutate_${style_struct.name.lower()}() + .set_${property.ident}(computed); + }, DeclaredValue::Initial - => longhands::${property.ident}::get_initial_value(), + => { + // FIXME(bholley): We may want set_X_to_initial_value() here. + let initial = longhands::${property.ident}::get_initial_value(); + context.mutate_style().mutate_${style_struct.name.lower()}() + .set_${property.ident}(initial); + }, DeclaredValue::Inherit => { // This is a bit slow, but this is rare so it shouldn't // matter. // // FIXME: is it still? - parent_style.${style_struct.ident} - .${property.ident} - .clone() + let inherited_struct = parent_style.get_${style_struct.ident}(); + context.mutate_style().mutate_${style_struct.name.lower()}() + .copy_${property.ident}_from(inherited_struct); } DeclaredValue::WithVariables { .. } => unreachable!() }, &mut error_reporter ); - Arc::make_mut(&mut context.style.${style_struct.ident}) - .${property.ident} = computed_value; % endif % if property.name in DERIVED_LONGHANDS: % for derived in DERIVED_LONGHANDS[property.name]: - Arc::make_mut(&mut context.style.${derived.style_struct.ident}) - .${derived.ident} = longhands::${derived.ident} - ::derive_from_${property.ident}( - &context); + ::derive_from_${property.ident}(&mut context); % endfor % endif } @@ -6485,23 +6685,25 @@ fn cascade_with_cached_declarations( if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || seen.get_font_family() { - compute_font_hash(&mut *Arc::make_mut(&mut context.style.font)) + use properties::style_struct_traits::TFont; + context.mutate_style().mutate_font().compute_font_hash(); } context.style } -type CascadePropertyFn = extern "Rust" fn(declaration: &PropertyDeclaration, - inherited_style: &ComputedValues, - context: &mut computed::Context, - seen: &mut PropertyBitField, - cacheable: &mut bool, - error_reporter: &mut Box<ParseErrorReporter + Send>); +pub type CascadePropertyFn<C: TComputedValues> = + extern "Rust" fn(declaration: &PropertyDeclaration, + inherited_style: &C, + context: &mut computed::Context<C>, + seen: &mut PropertyBitField, + cacheable: &mut bool, + error_reporter: &mut Box<ParseErrorReporter + Send>); // This is a thread-local rather than a lazy static to avoid atomic operations when cascading // properties. -thread_local!(static CASCADE_PROPERTY: Vec<Option<CascadePropertyFn>> = { - let mut result: Vec<Option<CascadePropertyFn>> = Vec::new(); +thread_local!(static CASCADE_PROPERTY: Vec<Option<CascadePropertyFn<ComputedValues>>> = { + let mut result: Vec<Option<CascadePropertyFn<ComputedValues>>> = Vec::new(); % for style_struct in STYLE_STRUCTS: % for property in style_struct.longhands: let discriminant; @@ -6537,19 +6739,22 @@ thread_local!(static CASCADE_PROPERTY: Vec<Option<CascadePropertyFn>> = { /// this is ignored. /// /// Returns the computed values and a boolean indicating whether the result is cacheable. -pub fn cascade(viewport_size: Size2D<Au>, +pub fn cascade<C: TComputedValues>( + viewport_size: Size2D<Au>, applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>], shareable: bool, - parent_style: Option< &ComputedValues >, - cached_style: Option< &ComputedValues >, + parent_style: Option< &C >, + cached_style: Option< &C >, mut error_reporter: Box<ParseErrorReporter + Send>) - -> (ComputedValues, bool) { - let initial_values = &*INITIAL_VALUES; + -> (C, bool) { + use properties::style_struct_traits::{TBorder, TBox, TColor, TFont, TOutline}; + let initial_values = C::initial_values(); let (is_root_element, inherited_style) = match parent_style { Some(parent_style) => (false, parent_style), None => (true, initial_values), }; + let inherited_custom_properties = inherited_style.custom_properties(); let mut custom_properties = None; let mut seen_custom = HashSet::new(); for sub_list in applicable_declarations.iter().rev() { @@ -6558,7 +6763,7 @@ pub fn cascade(viewport_size: Size2D<Au>, match *declaration { PropertyDeclaration::Custom(ref name, ref value) => { ::custom_properties::cascade( - &mut custom_properties, &inherited_style.custom_properties, + &mut custom_properties, &inherited_custom_properties, &mut seen_custom, name, value) } _ => {} @@ -6566,7 +6771,7 @@ pub fn cascade(viewport_size: Size2D<Au>, } } let custom_properties = ::custom_properties::finish_cascade( - custom_properties, &inherited_style.custom_properties); + custom_properties, &inherited_custom_properties); if let (Some(cached_style), Some(parent_style)) = (cached_style, parent_style) { let style = cascade_with_cached_declarations(viewport_size, @@ -6583,21 +6788,20 @@ pub fn cascade(viewport_size: Size2D<Au>, is_root_element: is_root_element, viewport_size: viewport_size, inherited_style: inherited_style, - style: ComputedValues { + style: C::new( + custom_properties, + shareable, + WritingMode::empty(), + inherited_style.root_font_size(), % for style_struct in STYLE_STRUCTS: - ${style_struct.ident}: - % if style_struct.inherited: - inherited_style - % else: - initial_values - % endif - .${style_struct.ident}.clone(), + % if style_struct.inherited: + inherited_style + % else: + initial_values + % endif + .clone_${style_struct.name.lower()}(), % endfor - custom_properties: custom_properties, - shareable: shareable, - writing_mode: WritingMode::empty(), - root_font_size: inherited_style.root_font_size, - }, + ), }; // Set computed values, overwriting earlier declarations for the same property. @@ -6609,7 +6813,7 @@ pub fn cascade(viewport_size: Size2D<Au>, // We could (and used to) use a pattern match here, but that bloats this function to over 100K // of compiled code! To improve i-cache behavior, we outline the individual functions and use // virtual dispatch instead. - CASCADE_PROPERTY.with(|cascade_property| { + C::do_cascade_property(|cascade_property| { % for category_to_cascade_now in ["early", "other"]: for sub_list in applicable_declarations.iter().rev() { // Declarations are already stored in reverse order. @@ -6655,14 +6859,14 @@ pub fn cascade(viewport_size: Size2D<Au>, let mut style = context.style; - let positioned = matches!(style.box_.position, + let positioned = matches!(style.get_box().clone_position(), longhands::position::SpecifiedValue::absolute | longhands::position::SpecifiedValue::fixed); - let floated = style.box_.float != longhands::float::SpecifiedValue::none; + let floated = style.get_box().is_floated(); if positioned || floated || is_root_element { use computed_values::display::T; - let specified_display = style.box_.display; + let specified_display = style.get_box().clone_display(); let computed_display = match specified_display { T::inline_table => { Some(T::table) @@ -6677,26 +6881,26 @@ pub fn cascade(viewport_size: Size2D<Au>, _ => None }; if let Some(computed_display) = computed_display { - let box_ = Arc::make_mut(&mut style.box_); - box_.display = computed_display; - box_._servo_display_for_hypothetical_box = if is_root_element { + let box_ = style.mutate_box(); + box_.set_display(computed_display); + box_.set__servo_display_for_hypothetical_box(if is_root_element { computed_display } else { specified_display - }; + }); } } { use computed_values::overflow_x::T as overflow; use computed_values::overflow_y; - match (style.box_.overflow_x, style.box_.overflow_y.0) { - (overflow::visible, overflow::visible) => {} - (overflow::visible, _) => { - Arc::make_mut(&mut style.box_).overflow_x = overflow::auto + match (style.get_box().overflow_x_is_visible(), style.get_box().overflow_y_is_visible()) { + (true, true) => {} + (true, _) => { + style.mutate_box().set_overflow_x(overflow::auto); } - (_, overflow::visible) => { - Arc::make_mut(&mut style.box_).overflow_y = overflow_y::T(overflow::auto) + (_, true) => { + style.mutate_box().set_overflow_y(overflow_y::T(overflow::auto)); } _ => {} } @@ -6705,27 +6909,29 @@ pub fn cascade(viewport_size: Size2D<Au>, // The initial value of border-*-width may be changed at computed value time. % for side in ["top", "right", "bottom", "left"]: // Like calling to_computed_value, which wouldn't type check. - if style.border.border_${side}_style.none_or_hidden() && - style.border.border_${side}_width != Au(0) { - Arc::make_mut(&mut style.border).border_${side}_width = Au(0); + if style.get_border().border_${side}_is_none_or_hidden_and_has_nonzero_width() { + style.mutate_border().set_border_${side}_width(Au(0)); } % endfor // The initial value of outline width may be changed at computed value time. - if style.outline.outline_style.none_or_hidden() && style.outline.outline_width != Au(0) { - Arc::make_mut(&mut style.outline).outline_width = Au(0); + if style.get_outline().outline_is_none_or_hidden_and_has_nonzero_width() { + style.mutate_outline().set_outline_width(Au(0)); } if is_root_element { - style.root_font_size = style.font.font_size; + let s = style.get_font().clone_font_size(); + style.set_root_font_size(s); } if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || seen.get_font_family() { - compute_font_hash(&mut *Arc::make_mut(&mut style.font)) + use properties::style_struct_traits::TFont; + style.mutate_font().compute_font_hash(); } - style.writing_mode = get_writing_mode(&*style.inheritedbox); + let mode = get_writing_mode(style.get_inheritedbox()); + style.set_writing_mode(mode); (style, cacheable) } @@ -6930,12 +7136,3 @@ macro_rules! longhand_properties_idents { } } } - -/// Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`. -fn compute_font_hash(font: &mut style_structs::Font) { - let mut hasher: FnvHasher = Default::default(); - hasher.write_u16(font.font_weight as u16); - font.font_stretch.hash(&mut hasher); - font.font_family.hash(&mut hasher); - font.hash = hasher.finish() -} diff --git a/components/style/servo.rs b/components/style/servo.rs index 56aef8f6210..10867d4eaf8 100644 --- a/components/style/servo.rs +++ b/components/style/servo.rs @@ -3,13 +3,14 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use context; use data; +use properties::ComputedValues; use selector_impl::ServoSelectorImpl; use selector_matching; use stylesheets; /// Concrete types for servo Style implementation pub type Stylesheet = stylesheets::Stylesheet<ServoSelectorImpl>; -pub type PrivateStyleData = data::PrivateStyleData<ServoSelectorImpl>; +pub type PrivateStyleData = data::PrivateStyleData<ServoSelectorImpl, ComputedValues>; pub type Stylist = selector_matching::Stylist<ServoSelectorImpl>; pub type StylistWrapper = context::StylistWrapper<ServoSelectorImpl>; pub type SharedStyleContext = context::SharedStyleContext<ServoSelectorImpl>; diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 79759cf26b9..f39347e83ab 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -123,7 +123,7 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C, root: OpaqueNode, node: N) where N: TNode, - C: StyleContext<'a, <N::ConcreteElement as Element>::Impl>, + C: StyleContext<'a, <N::ConcreteElement as Element>::Impl, N::ConcreteComputedValues>, <N::ConcreteElement as Element>::Impl: SelectorImplExt + 'a { // Initialize layout data. // @@ -195,7 +195,7 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C, // Add ourselves to the LRU cache. if let Some(element) = shareable_element { - style_sharing_candidate_cache.insert_if_possible(&element); + style_sharing_candidate_cache.insert_if_possible::<'ln, N>(&element); } } StyleSharingResult::StyleWasShared(index, damage) => { diff --git a/components/style/values.rs b/components/style/values.rs index b35a2ca0766..69cd83309fc 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -100,6 +100,7 @@ pub mod specified { use std::ops::Mul; use style_traits::values::specified::AllowedNumericType; use super::AuExtensionMethods; + use super::computed::{TContext, ToComputedValue}; use super::{CSSFloat, FONT_MEDIUM_PX}; use url::Url; @@ -1418,11 +1419,11 @@ pub mod specified { } } - impl super::computed::ToComputedValue for Time { + impl ToComputedValue for Time { type ComputedValue = Time; #[inline] - fn to_computed_value(&self, _: &super::computed::Context) -> Time { + fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> Time { *self } } @@ -1437,7 +1438,8 @@ pub mod specified { pub mod computed { use app_units::Au; use euclid::size::Size2D; - use properties::ComputedValues; + use properties::TComputedValues; + use properties::style_struct_traits::TFont; use std::fmt; use super::AuExtensionMethods; use super::specified::AngleOrCorner; @@ -1446,21 +1448,39 @@ pub mod computed { pub use cssparser::Color as CSSColor; pub use super::specified::{Angle, BorderStyle, Time}; - pub struct Context<'a> { + pub trait TContext { + type ConcreteComputedValues: TComputedValues; + fn is_root_element(&self) -> bool; + fn viewport_size(&self) -> Size2D<Au>; + fn inherited_style(&self) -> &Self::ConcreteComputedValues; + fn style(&self) -> &Self::ConcreteComputedValues; + fn mutate_style(&mut self) -> &mut Self::ConcreteComputedValues; + } + + pub struct Context<'a, C: TComputedValues> { pub is_root_element: bool, pub viewport_size: Size2D<Au>, - pub inherited_style: &'a ComputedValues, + pub inherited_style: &'a C, /// Values access through this need to be in the properties "computed early": /// color, text-decoration, font-size, display, position, float, border-*-style, outline-style - pub style: ComputedValues, + pub style: C, + } + + impl<'a, C: TComputedValues> TContext for Context<'a, C> { + type ConcreteComputedValues = C; + fn is_root_element(&self) -> bool { self.is_root_element } + fn viewport_size(&self) -> Size2D<Au> { self.viewport_size } + fn inherited_style(&self) -> &C { &self.inherited_style } + fn style(&self) -> &C { &self.style } + fn mutate_style(&mut self) -> &mut C { &mut self.style } } pub trait ToComputedValue { type ComputedValue; #[inline] - fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue; + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> Self::ComputedValue; } pub trait ComputedValueAsSpecified {} @@ -1469,7 +1489,7 @@ pub mod computed { type ComputedValue = T; #[inline] - fn to_computed_value(&self, _context: &Context) -> T { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> T { self.clone() } } @@ -1478,7 +1498,7 @@ pub mod computed { type ComputedValue = CSSColor; #[inline] - fn to_computed_value(&self, _context: &Context) -> CSSColor { + fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> CSSColor { self.parsed } } @@ -1489,17 +1509,17 @@ pub mod computed { type ComputedValue = Au; #[inline] - fn to_computed_value(&self, context: &Context) -> Au { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> Au { match *self { specified::Length::Absolute(length) => length, specified::Length::Calc(calc) => calc.to_computed_value(context).length(), specified::Length::FontRelative(length) => - length.to_computed_value(context.style.get_font().font_size, - context.style.root_font_size), + length.to_computed_value(context.style().get_font().clone_font_size(), + context.style().root_font_size()), specified::Length::ViewportPercentage(length) => - length.to_computed_value(context.viewport_size), + length.to_computed_value(context.viewport_size()), specified::Length::ServoCharacterWidth(length) => - length.to_computed_value(context.style.get_font().font_size) + length.to_computed_value(context.style().get_font().clone_font_size()) } } } @@ -1583,7 +1603,7 @@ pub mod computed { impl ToComputedValue for specified::CalcLengthOrPercentage { type ComputedValue = CalcLengthOrPercentage; - fn to_computed_value(&self, context: &Context) -> CalcLengthOrPercentage { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> CalcLengthOrPercentage { let mut length = None; if let Some(absolute) = self.absolute { @@ -1593,13 +1613,13 @@ pub mod computed { for val in &[self.vw, self.vh, self.vmin, self.vmax] { if let Some(val) = *val { length = Some(length.unwrap_or(Au(0)) + - val.to_computed_value(context.viewport_size)); + val.to_computed_value(context.viewport_size())); } } for val in &[self.ch, self.em, self.ex, self.rem] { if let Some(val) = *val { length = Some(length.unwrap_or(Au(0)) + val.to_computed_value( - context.style.get_font().font_size, context.style.root_font_size)); + context.style().get_font().clone_font_size(), context.style().root_font_size())); } } @@ -1621,7 +1641,7 @@ pub mod computed { type ComputedValue = BorderRadiusSize; #[inline] - fn to_computed_value(&self, context: &Context) -> BorderRadiusSize { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> BorderRadiusSize { let specified::BorderRadiusSize(s) = *self; let w = s.width.to_computed_value(context); let h = s.height.to_computed_value(context); @@ -1664,7 +1684,7 @@ pub mod computed { impl ToComputedValue for specified::LengthOrPercentage { type ComputedValue = LengthOrPercentage; - fn to_computed_value(&self, context: &Context) -> LengthOrPercentage { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentage { match *self { specified::LengthOrPercentage::Length(value) => { LengthOrPercentage::Length(value.to_computed_value(context)) @@ -1712,7 +1732,7 @@ pub mod computed { type ComputedValue = LengthOrPercentageOrAuto; #[inline] - fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentageOrAuto { match *self { specified::LengthOrPercentageOrAuto::Length(value) => { LengthOrPercentageOrAuto::Length(value.to_computed_value(context)) @@ -1764,7 +1784,7 @@ pub mod computed { type ComputedValue = LengthOrPercentageOrNone; #[inline] - fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrPercentageOrNone { match *self { specified::LengthOrPercentageOrNone::Length(value) => { LengthOrPercentageOrNone::Length(value.to_computed_value(context)) @@ -1812,7 +1832,7 @@ pub mod computed { type ComputedValue = LengthOrNone; #[inline] - fn to_computed_value(&self, context: &Context) -> LengthOrNone { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LengthOrNone { match *self { specified::LengthOrNone::Length(specified::Length::Calc(calc)) => { LengthOrNone::Length(calc.to_computed_value(context).length()) @@ -1840,7 +1860,7 @@ pub mod computed { type ComputedValue = Image; #[inline] - fn to_computed_value(&self, context: &Context) -> Image { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> Image { match *self { specified::Image::Url(ref url) => Image::Url(url.clone()), specified::Image::LinearGradient(ref linear_gradient) => { @@ -1936,7 +1956,7 @@ pub mod computed { type ComputedValue = LinearGradient; #[inline] - fn to_computed_value(&self, context: &Context) -> LinearGradient { + fn to_computed_value<Cx: TContext>(&self, context: &Cx) -> LinearGradient { let specified::LinearGradient { angle_or_corner, ref stops diff --git a/components/style/viewport.rs b/components/style/viewport.rs index 53c6d5bcbc2..f2da78088e4 100644 --- a/components/style/viewport.rs +++ b/components/style/viewport.rs @@ -8,7 +8,7 @@ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; use parser::{ParserContext, log_css_error}; -use properties::INITIAL_VALUES; +use properties::{ComputedValues, TComputedValues}; use std::ascii::AsciiExt; use std::collections::hash_map::{Entry, HashMap}; use std::fmt; @@ -594,8 +594,8 @@ impl MaybeNew for ViewportConstraints { let context = Context { is_root_element: false, viewport_size: initial_viewport, - inherited_style: &*INITIAL_VALUES, - style: INITIAL_VALUES.clone(), + inherited_style: ComputedValues::initial_values(), + style: ComputedValues::initial_values().clone(), }; // DEVICE-ADAPT § 9.3 Resolving 'extend-to-zoom' diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml index c8d5dcabcea..cd9031ee98e 100644 --- a/ports/geckolib/Cargo.toml +++ b/ports/geckolib/Cargo.toml @@ -3,6 +3,8 @@ name = "geckoservo" version = "0.0.1" authors = ["The Servo Project Developers"] +build = "build.rs" + [lib] name = "geckoservo" path = "lib.rs" diff --git a/ports/geckolib/bindings.rs b/ports/geckolib/bindings.rs index ba761f17d78..545e30d00f7 100644 --- a/ports/geckolib/bindings.rs +++ b/ports/geckolib/bindings.rs @@ -28,6 +28,7 @@ pub type intptr_t = int64_t; pub type uintptr_t = uint64_t; pub type intmax_t = ::libc::c_long; pub type uintmax_t = ::libc::c_ulong; +pub enum nsIAtom { } pub enum nsINode { } pub type RawGeckoNode = nsINode; pub enum Element { } @@ -35,6 +36,7 @@ pub type RawGeckoElement = Element; pub enum nsIDocument { } pub type RawGeckoDocument = nsIDocument; pub enum ServoNodeData { } +pub enum ServoComputedValues { } pub enum RawServoStyleSheet { } pub enum RawServoStyleSet { } extern "C" { @@ -72,7 +74,8 @@ extern "C" { pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t, length: uint32_t) -> *mut RawServoStyleSheet; - pub fn Servo_ReleaseStylesheet(sheet: *mut RawServoStyleSheet); + pub fn Servo_AddRefStyleSheet(sheet: *mut RawServoStyleSheet); + pub fn Servo_ReleaseStyleSheet(sheet: *mut RawServoStyleSheet); pub fn Servo_AppendStyleSheet(sheet: *mut RawServoStyleSheet, set: *mut RawServoStyleSet); pub fn Servo_PrependStyleSheet(sheet: *mut RawServoStyleSheet, @@ -82,6 +85,12 @@ extern "C" { pub fn Servo_StyleSheetHasRules(sheet: *mut RawServoStyleSheet) -> bool; pub fn Servo_InitStyleSet() -> *mut RawServoStyleSet; pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet); + pub fn Servo_GetComputedValues(element: *mut RawGeckoElement) + -> *mut ServoComputedValues; + pub fn Servo_GetComputedValuesForAnonymousBox(pseudoTag: *mut nsIAtom) + -> *mut ServoComputedValues; + pub fn Servo_AddRefComputedValues(arg1: *mut ServoComputedValues); + pub fn Servo_ReleaseComputedValues(arg1: *mut ServoComputedValues); pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement, ns: *const uint8_t, name: *const uint8_t, length: *mut uint32_t) diff --git a/ports/geckolib/build.rs b/ports/geckolib/build.rs new file mode 100644 index 00000000000..0cb930b072b --- /dev/null +++ b/ports/geckolib/build.rs @@ -0,0 +1,80 @@ +/* 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 std::env; +use std::fs::File; +use std::io::Write; +use std::path::Path; +use std::process::{Command, Stdio, exit}; + +#[cfg(windows)] +fn find_python() -> String { + if Command::new("python27.exe").arg("--version").output().is_ok() { + return "python27.exe".to_owned(); + } + + if Command::new("python.exe").arg("--version").output().is_ok() { + return "python.exe".to_owned(); + } + + panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var"); +} + +#[cfg(not(windows))] +fn find_python() -> String { + if Command::new("python2.7").arg("--version").output().unwrap().status.success() { + "python2.7" + } else { + "python" + }.to_owned() +} + +fn main() { + let python = match env::var("PYTHON") { + Ok(python_path) => python_path, + Err(_) => find_python(), + }; + + // Mako refuses to load templates outside the scope of the current working directory, + // so we need to run it from the top source directory. + let geckolib_dir = Path::new(file!()).parent().unwrap(); + let top_dir = geckolib_dir.join("..").join(".."); + + let style_template = Path::new("components/style/properties.mako.rs"); + let geckolib_template = Path::new("ports/geckolib/properties.mako.rs"); + let mako = Path::new("components/style/Mako-0.9.1.zip"); + + let result = Command::new(python) + .current_dir(top_dir) + .env("PYTHONPATH", &mako) + .env("STYLE_TEMPLATE", &style_template) + .env("GECKOLIB_TEMPLATE", &geckolib_template) + .arg("-c") + .arg(r#" +import json +import os +import sys +from mako.template import Template +from mako import exceptions +try: + style_template = Template(filename=os.environ['STYLE_TEMPLATE'], input_encoding='utf8') + style_template.render() + + geckolib_template = Template(filename=os.environ['GECKOLIB_TEMPLATE'], input_encoding='utf8') + output = geckolib_template.render(STYLE_STRUCTS = style_template.module.STYLE_STRUCTS, + LONGHANDS = style_template.module.LONGHANDS) + print(output.encode('utf8')) +except: + sys.stderr.write(exceptions.text_error_template().render().encode('utf8')) + sys.exit(1) +"#) + .stderr(Stdio::inherit()) + .output() + .unwrap(); + if !result.status.success() { + exit(1) + } + let out = env::var("OUT_DIR").unwrap(); + File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap(); +} diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 510e39cc041..56c8d9e146c 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -5,24 +5,28 @@ #![allow(unsafe_code)] use app_units::Au; -use bindings::RawGeckoDocument; -use bindings::{ServoNodeData, RawServoStyleSet, RawServoStyleSheet, uint8_t, uint32_t}; +use bindings::{RawGeckoDocument, RawGeckoElement}; +use bindings::{RawServoStyleSet, RawServoStyleSheet, ServoComputedValues, ServoNodeData}; +use bindings::{nsIAtom, uint8_t, uint32_t}; use data::PerDocumentStyleData; use euclid::Size2D; +use properties::GeckoComputedValues; use selector_impl::{SharedStyleContext, Stylesheet}; +use std::marker::PhantomData; use std::mem::{forget, transmute}; +use std::ptr; use std::slice; use std::str::from_utf8_unchecked; use std::sync::{Arc, Mutex}; use style::context::{ReflowGoal, StylistWrapper}; -use style::dom::{TDocument, TNode}; +use style::dom::{TDocument, TElement, TNode}; use style::error_reporting::StdoutErrorReporter; use style::parallel; use style::stylesheets::Origin; use traversal::RecalcStyleOnly; use url::Url; use util::arc_ptr_eq; -use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData}; +use wrapper::{GeckoDocument, GeckoElement, GeckoNode, NonOpaqueStyleData}; /* * For Gecko->Servo function calls, we need to redeclare the same signature that was declared in @@ -82,23 +86,39 @@ pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t, } } -fn with_arc_stylesheet<F, Output>(raw: *mut RawServoStyleSheet, cb: F) -> Output - where F: FnOnce(&Arc<Stylesheet>) -> Output { - let owned = unsafe { consume_arc_stylesheet(raw) }; - let result = cb(&owned); - forget(owned); - result +struct ArcHelpers<GeckoType, ServoType> { + phantom1: PhantomData<GeckoType>, + phantom2: PhantomData<ServoType>, } -unsafe fn consume_arc_stylesheet(raw: *mut RawServoStyleSheet) -> Arc<Stylesheet> { - transmute(raw) +impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> { + fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output + where F: FnOnce(&Arc<ServoType>) -> Output { + let owned = unsafe { Self::into(raw) }; + let result = cb(&owned); + forget(owned); + result + } + + unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> { + transmute(ptr) + } + + unsafe fn addref(ptr: *mut GeckoType) { + Self::with(ptr, |arc| forget(arc.clone())); + } + + unsafe fn release(ptr: *mut GeckoType) { + let _ = Self::into(ptr); + } } #[no_mangle] pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut RawServoStyleSheet, raw_data: *mut RawServoStyleSet) { + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data); - with_arc_stylesheet(raw_sheet, |sheet| { + Helpers::with(raw_sheet, |sheet| { data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet)); data.stylesheets.push(sheet.clone()); data.stylesheets_changed = true; @@ -108,8 +128,9 @@ pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut RawServoStyleSheet, #[no_mangle] pub extern "C" fn Servo_PrependStyleSheet(raw_sheet: *mut RawServoStyleSheet, raw_data: *mut RawServoStyleSet) { + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data); - with_arc_stylesheet(raw_sheet, |sheet| { + Helpers::with(raw_sheet, |sheet| { data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet)); data.stylesheets.insert(0, sheet.clone()); data.stylesheets_changed = true; @@ -119,8 +140,9 @@ pub extern "C" fn Servo_PrependStyleSheet(raw_sheet: *mut RawServoStyleSheet, #[no_mangle] pub extern "C" fn Servo_RemoveStyleSheet(raw_sheet: *mut RawServoStyleSheet, raw_data: *mut RawServoStyleSet) { + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data); - with_arc_stylesheet(raw_sheet, |sheet| { + Helpers::with(raw_sheet, |sheet| { data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet)); data.stylesheets_changed = true; }); @@ -128,15 +150,46 @@ pub extern "C" fn Servo_RemoveStyleSheet(raw_sheet: *mut RawServoStyleSheet, #[no_mangle] pub extern "C" fn Servo_StyleSheetHasRules(raw_sheet: *mut RawServoStyleSheet) -> bool { - with_arc_stylesheet(raw_sheet, |sheet| !sheet.rules.is_empty()) + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; + Helpers::with(raw_sheet, |sheet| !sheet.rules.is_empty()) } +#[no_mangle] +pub extern "C" fn Servo_AddRefStyleSheet(sheet: *mut RawServoStyleSheet) -> () { + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; + unsafe { Helpers::addref(sheet) }; +} #[no_mangle] -pub extern "C" fn Servo_ReleaseStylesheet(sheet: *mut RawServoStyleSheet) -> () { - unsafe { - let _ = consume_arc_stylesheet(sheet); - } +pub extern "C" fn Servo_ReleaseStyleSheet(sheet: *mut RawServoStyleSheet) -> () { + type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>; + unsafe { Helpers::release(sheet) }; +} + +#[no_mangle] +pub extern "C" fn Servo_GetComputedValues(element: *mut RawGeckoElement) + -> *mut ServoComputedValues { + let node = unsafe { GeckoElement::from_raw(element).as_node() }; + let arc_cv = node.borrow_data().map(|data| data.style.clone()); + arc_cv.map_or(ptr::null_mut(), |arc| unsafe { transmute(arc) }) +} + +#[no_mangle] +pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(_: *mut nsIAtom) + -> *mut ServoComputedValues { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn Servo_AddRefComputedValues(ptr: *mut ServoComputedValues) -> () { + type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>; + unsafe { Helpers::addref(ptr) }; +} + +#[no_mangle] +pub extern "C" fn Servo_ReleaseComputedValues(ptr: *mut ServoComputedValues) -> () { + type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>; + unsafe { Helpers::release(ptr) }; } #[no_mangle] @@ -145,7 +198,6 @@ pub extern "C" fn Servo_InitStyleSet() -> *mut RawServoStyleSet { Box::into_raw(data) as *mut RawServoStyleSet } - #[no_mangle] pub extern "C" fn Servo_DropStyleSet(data: *mut RawServoStyleSet) -> () { unsafe { diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index dfb9bb06ea3..e28bf611a5c 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -40,3 +40,10 @@ pub mod glue; mod selector_impl; mod traversal; mod wrapper; + +// Generated from the properties.mako.rs template by build.rs +#[macro_use] +#[allow(unsafe_code)] +pub mod properties { + include!(concat!(env!("OUT_DIR"), "/properties.rs")); +} diff --git a/ports/geckolib/properties.mako.rs b/ports/geckolib/properties.mako.rs new file mode 100644 index 00000000000..4d2010dcecd --- /dev/null +++ b/ports/geckolib/properties.mako.rs @@ -0,0 +1,168 @@ +/* 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 app_units::Au; +use std::sync::Arc; +use style::custom_properties::ComputedValuesMap; +use style::logical_geometry::WritingMode; +use style::properties::{CascadePropertyFn, ComputedValues, TComputedValues}; +use style::properties::longhands; +use style::properties::style_struct_traits::*; + +#[derive(Clone)] +pub struct GeckoComputedValues { + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: Arc<Gecko${style_struct.name}>, + % endfor + + custom_properties: Option<Arc<ComputedValuesMap>>, + shareable: bool, + pub writing_mode: WritingMode, + pub root_font_size: Au, +} + +impl TComputedValues for GeckoComputedValues { +% for style_struct in STYLE_STRUCTS: + type Concrete${style_struct.name} = Gecko${style_struct.name}; +% endfor + + // These will go away, and we will never implement them. + fn as_servo<'a>(&'a self) -> &'a ComputedValues { unimplemented!() } + fn as_servo_mut<'a>(&'a mut self) -> &'a mut ComputedValues { unimplemented!() } + + fn new(custom_properties: Option<Arc<ComputedValuesMap>>, + shareable: bool, + writing_mode: WritingMode, + root_font_size: Au, + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: Arc<Gecko${style_struct.name}>, + % endfor + ) -> Self { + GeckoComputedValues { + custom_properties: custom_properties, + shareable: shareable, + writing_mode: writing_mode, + root_font_size: root_font_size, + % for style_struct in STYLE_STRUCTS: + ${style_struct.ident}: ${style_struct.ident}, + % endfor + } + } + + fn initial_values() -> &'static Self { unimplemented!() } + + fn do_cascade_property<F: FnOnce(&Vec<Option<CascadePropertyFn<Self>>>)>(_: F) { + unimplemented!() + } + + % for style_struct in STYLE_STRUCTS: + #[inline] + fn clone_${style_struct.name.lower()}(&self) -> Arc<Self::Concrete${style_struct.name}> { + self.${style_struct.ident}.clone() + } + #[inline] + fn get_${style_struct.name.lower()}<'a>(&'a self) -> &'a Self::Concrete${style_struct.name} { + &self.${style_struct.ident} + } + #[inline] + fn mutate_${style_struct.name.lower()}<'a>(&'a mut self) -> &'a mut Self::Concrete${style_struct.name} { + Arc::make_mut(&mut self.${style_struct.ident}) + } + % endfor + + fn custom_properties(&self) -> Option<Arc<ComputedValuesMap>> { self.custom_properties.as_ref().map(|x| x.clone())} + fn root_font_size(&self) -> Au { self.root_font_size } + fn set_root_font_size(&mut self, s: Au) { self.root_font_size = s; } + fn set_writing_mode(&mut self, mode: WritingMode) { self.writing_mode = mode; } + + #[inline] + fn is_multicol(&self) -> bool { unimplemented!() } +} + +% for style_struct in STYLE_STRUCTS: +#[derive(PartialEq, Clone, HeapSizeOf, Debug)] +pub struct Gecko${style_struct.name}; +impl T${style_struct.name} for Gecko${style_struct.name} { + % for longhand in style_struct.longhands: + fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) { + unimplemented!() + } + fn copy_${longhand.ident}_from(&mut self, _: &Self) { + unimplemented!() + } + % endfor + % if style_struct.name == "Animation": + fn transition_count(&self) -> usize { + unimplemented!() + } + % elif style_struct.name == "Border": + % for side in ["top", "right", "bottom", "left"]: + fn border_${side}_is_none_or_hidden_and_has_nonzero_width(&self) -> bool { + unimplemented!() + } + % endfor + % elif style_struct.name == "Box": + fn clone_display(&self) -> longhands::display::computed_value::T { + unimplemented!() + } + fn clone_position(&self) -> longhands::position::computed_value::T { + unimplemented!() + } + fn is_floated(&self) -> bool { + unimplemented!() + } + fn overflow_x_is_visible(&self) -> bool { + unimplemented!() + } + fn overflow_y_is_visible(&self) -> bool { + unimplemented!() + } + % elif style_struct.name == "Color": + fn clone_color(&self) -> longhands::color::computed_value::T { + unimplemented!() + } + % elif style_struct.name == "Font": + fn clone_font_size(&self) -> longhands::font_size::computed_value::T { + unimplemented!() + } + fn clone_font_weight(&self) -> longhands::font_weight::computed_value::T { + unimplemented!() + } + fn compute_font_hash(&mut self) { + unimplemented!() + } + % elif style_struct.name == "InheritedBox": + fn clone_direction(&self) -> longhands::direction::computed_value::T { + unimplemented!() + } + fn clone_writing_mode(&self) -> longhands::writing_mode::computed_value::T { + unimplemented!() + } + fn clone_text_orientation(&self) -> longhands::text_orientation::computed_value::T { + unimplemented!() + } + % elif style_struct.name == "InheritedText": + fn clone__servo_text_decorations_in_effect(&self) -> + longhands::_servo_text_decorations_in_effect::computed_value::T { + unimplemented!() + } + % elif style_struct.name == "Outline": + fn outline_is_none_or_hidden_and_has_nonzero_width(&self) -> bool { + unimplemented!() + } + % elif style_struct.name == "Text": + fn has_underline(&self) -> bool { + unimplemented!() + } + fn has_overline(&self) -> bool { + unimplemented!() + } + fn has_line_through(&self) -> bool { + unimplemented!() + } + % endif + +} + +% endfor diff --git a/ports/geckolib/selector_impl.rs b/ports/geckolib/selector_impl.rs index 45ded949052..0bd84ab9782 100644 --- a/ports/geckolib/selector_impl.rs +++ b/ports/geckolib/selector_impl.rs @@ -2,19 +2,16 @@ * 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 properties::GeckoComputedValues; use selectors::parser::{ParserContext, SelectorImpl}; -use std::process; use style; use style::element_state::ElementState; -use style::error_reporting::StdoutErrorReporter; use style::selector_impl::SelectorImplExt; -use style::stylesheets::Origin; -use url::Url; pub type Stylist = style::selector_matching::Stylist<GeckoSelectorImpl>; pub type Stylesheet = style::stylesheets::Stylesheet<GeckoSelectorImpl>; pub type SharedStyleContext = style::context::SharedStyleContext<GeckoSelectorImpl>; -pub type PrivateStyleData = style::data::PrivateStyleData<GeckoSelectorImpl>; +pub type PrivateStyleData = style::data::PrivateStyleData<GeckoSelectorImpl, GeckoComputedValues>; pub struct GeckoSelectorImpl; diff --git a/ports/geckolib/traversal.rs b/ports/geckolib/traversal.rs index b1cfbd1fbbd..33fc1fd322e 100644 --- a/ports/geckolib/traversal.rs +++ b/ports/geckolib/traversal.rs @@ -2,20 +2,23 @@ * 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 properties::GeckoComputedValues; use selector_impl::{GeckoSelectorImpl, SharedStyleContext}; use std::cell::RefCell; use std::mem; use std::rc::Rc; use style::context::{LocalStyleContext, StyleContext}; -use style::dom::{OpaqueNode, TNode}; +use style::dom::OpaqueNode; use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; use style::traversal::{DomTraversalContext, recalc_style_at}; +use wrapper::GeckoNode; -thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalStyleContext>>> = RefCell::new(None)); +thread_local!(static LOCAL_CONTEXT_KEY: + RefCell<Option<Rc<LocalStyleContext<GeckoComputedValues>>>> = RefCell::new(None)); // Keep this implementation in sync with the one in components/layout/context.rs. fn create_or_get_local_context(shared: &SharedStyleContext) - -> Rc<LocalStyleContext> { + -> Rc<LocalStyleContext<GeckoComputedValues>> { LOCAL_CONTEXT_KEY.with(|r| { let mut r = r.borrow_mut(); if let Some(context) = r.clone() { @@ -36,7 +39,7 @@ fn create_or_get_local_context(shared: &SharedStyleContext) pub struct StandaloneStyleContext<'a> { pub shared: &'a SharedStyleContext, - cached_local_context: Rc<LocalStyleContext>, + cached_local_context: Rc<LocalStyleContext<GeckoComputedValues>>, } impl<'a> StandaloneStyleContext<'a> { @@ -49,12 +52,12 @@ impl<'a> StandaloneStyleContext<'a> { } } -impl<'a> StyleContext<'a, GeckoSelectorImpl> for StandaloneStyleContext<'a> { +impl<'a> StyleContext<'a, GeckoSelectorImpl, GeckoComputedValues> for StandaloneStyleContext<'a> { fn shared_context(&self) -> &'a SharedStyleContext { &self.shared } - fn local_context(&self) -> &LocalStyleContext { + fn local_context(&self) -> &LocalStyleContext<GeckoComputedValues> { &self.cached_local_context } } @@ -64,8 +67,7 @@ pub struct RecalcStyleOnly<'lc> { root: OpaqueNode, } -impl<'lc, N: TNode> DomTraversalContext<N> for RecalcStyleOnly<'lc> - where N::ConcreteElement: ::selectors::Element<Impl=GeckoSelectorImpl> { +impl<'lc, 'ln> DomTraversalContext<GeckoNode<'ln>> for RecalcStyleOnly<'lc> { type SharedContext = SharedStyleContext; #[allow(unsafe_code)] fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self { @@ -78,7 +80,7 @@ impl<'lc, N: TNode> DomTraversalContext<N> for RecalcStyleOnly<'lc> } } - fn process_preorder(&self, node: N) { recalc_style_at(&self.context, self.root, node); } - fn process_postorder(&self, _: N) {} + fn process_preorder(&self, node: GeckoNode<'ln>) { recalc_style_at(&self.context, self.root, node); } + fn process_postorder(&self, _: GeckoNode<'ln>) {} } diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index bb2e58c4ee2..7262f91e47e 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -19,6 +19,7 @@ use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetN use bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; use bindings::{ServoNodeData}; use libc::uintptr_t; +use properties::GeckoComputedValues; use selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PrivateStyleData}; use selectors::Element; use selectors::matching::DeclarationBlock; @@ -35,7 +36,7 @@ use style::dom::{OpaqueNode, TDocument, TElement, TNode, TRestyleDamage, UnsafeN use style::element_state::ElementState; #[allow(unused_imports)] // Used in commented-out code. use style::error_reporting::StdoutErrorReporter; -use style::properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock}; +use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; #[allow(unused_imports)] // Used in commented-out code. use style::properties::{parse_style_attribute}; use style::restyle_hints::ElementSnapshot; @@ -78,7 +79,8 @@ impl<'ln> GeckoNode<'ln> { #[derive(Clone, Copy)] pub struct DummyRestyleDamage; impl TRestyleDamage for DummyRestyleDamage { - fn compute(_: Option<&Arc<ComputedValues>>, _: &ComputedValues) -> Self { DummyRestyleDamage } + type ConcreteComputedValues = GeckoComputedValues; + fn compute(_: Option<&Arc<GeckoComputedValues>>, _: &GeckoComputedValues) -> Self { DummyRestyleDamage } fn rebuild_and_reflow() -> Self { DummyRestyleDamage } } impl BitOr for DummyRestyleDamage { @@ -92,6 +94,7 @@ impl<'ln> TNode for GeckoNode<'ln> { type ConcreteDocument = GeckoDocument<'ln>; type ConcreteElement = GeckoElement<'ln>; type ConcreteRestyleDamage = DummyRestyleDamage; + type ConcreteComputedValues = GeckoComputedValues; fn to_unsafe(&self) -> UnsafeNode { (self.node as usize, 0) @@ -297,7 +300,7 @@ pub struct GeckoElement<'le> { } impl<'le> GeckoElement<'le> { - unsafe fn from_raw(el: *mut RawGeckoElement) -> GeckoElement<'le> { + pub unsafe fn from_raw(el: *mut RawGeckoElement) -> GeckoElement<'le> { GeckoElement { element: el, chain: PhantomData, diff --git a/python/tidy.py b/python/tidy.py index 989e617648b..999d5745577 100644 --- a/python/tidy.py +++ b/python/tidy.py @@ -35,6 +35,7 @@ ignored_files = [ # Generated and upstream code combined with our own. Could use cleanup os.path.join(".", "ports", "gonk", "src", "native_window_glue.cpp"), os.path.join(".", "ports", "geckolib", "bindings.rs"), + os.path.join(".", "ports", "geckolib", "gecko_style_structs.rs"), os.path.join(".", "resources", "hsts_preload.json"), os.path.join(".", "tests", "wpt", "metadata", "MANIFEST.json"), os.path.join(".", "tests", "wpt", "metadata-css", "MANIFEST.json"), @@ -60,6 +61,8 @@ ignored_dirs = [ # Generated and upstream code combined with our own. Could use cleanup os.path.join(".", "target"), os.path.join(".", "ports", "cef"), + # Tooling, generated locally from external repos. + os.path.join(".", "ports", "geckolib", "tools"), # Hidden directories os.path.join(".", "."), ] @@ -260,6 +263,7 @@ def check_rust(file_name, lines): if not file_name.endswith(".rs") or \ file_name.endswith("properties.mako.rs") or \ file_name.endswith(os.path.join("style", "build.rs")) or \ + file_name.endswith(os.path.join("geckolib", "build.rs")) or \ file_name.endswith(os.path.join("unit", "style", "stylesheets.rs")): raise StopIteration comment_depth = 0 diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index c8432c12b30..bd443004076 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -25,10 +25,10 @@ extern crate util; #[cfg(test)] mod writing_modes { use style::logical_geometry::WritingMode; - use style::properties::{INITIAL_VALUES, get_writing_mode}; + use style::properties::{INITIAL_SERVO_VALUES, TComputedValues, get_writing_mode}; #[test] fn initial_writing_mode_is_empty() { - assert_eq!(get_writing_mode(INITIAL_VALUES.get_inheritedbox()), WritingMode::empty()) + assert_eq!(get_writing_mode(INITIAL_SERVO_VALUES.get_inheritedbox()), WritingMode::empty()) } } |