mirror of
https://github.com/servo/servo.git
synced 2025-07-16 03:43:38 +01:00
Introduce a script_layout_interface crate and move RestyleDamage to it.
This commit is contained in:
parent
e5cab36671
commit
5c03dd8eb1
24 changed files with 332 additions and 271 deletions
|
@ -31,6 +31,7 @@ profile_traits = {path = "../profile_traits"}
|
|||
range = {path = "../range"}
|
||||
rustc-serialize = "0.3"
|
||||
script = {path = "../script"}
|
||||
script_layout_interface = {path = "../script_layout_interface"}
|
||||
script_traits = {path = "../script_traits"}
|
||||
selectors = {version = "0.6", features = ["heap_size"]}
|
||||
serde_json = "0.7"
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
use flow::{self, Flow};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use incremental::RestyleDamage;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use script_layout_interface::restyle_damage::RestyleDamage;
|
||||
use script_traits::{AnimationState, LayoutMsg as ConstellationMsg};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
|
|
@ -45,12 +45,12 @@ use fragment::SpecificFragmentInfo;
|
|||
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
|
||||
use gfx::display_list::{ClippingRegion, StackingContext};
|
||||
use gfx_traits::{LayerId, StackingContextId};
|
||||
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
|
||||
use layout_debug;
|
||||
use layout_thread::DISPLAY_PORT_SIZE_FACTOR;
|
||||
use model::{CollapsibleMargins, MaybeAuto, specified, specified_or_none};
|
||||
use model::{self, IntrinsicISizes, MarginCollapseInfo};
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -28,7 +28,6 @@ use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo};
|
|||
use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
|
||||
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use incremental::{BUBBLE_ISIZES, RECONSTRUCT_FLOW, RestyleDamage};
|
||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags};
|
||||
use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT};
|
||||
use list_item::{ListItemFlow, ListStyleTypeContent};
|
||||
|
@ -37,6 +36,7 @@ use parallel;
|
|||
use script::layout_interface::is_image_data;
|
||||
use script::layout_interface::{CharacterDataTypeId, ElementTypeId};
|
||||
use script::layout_interface::{HTMLElementTypeId, NodeTypeId};
|
||||
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW, RestyleDamage};
|
||||
use std::borrow::ToOwned;
|
||||
use std::collections::LinkedList;
|
||||
use std::marker::PhantomData;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use construct::ConstructionResult;
|
||||
use incremental::RestyleDamage;
|
||||
use script_layout_interface::restyle_damage::RestyleDamage;
|
||||
use style::servo::PrivateStyleData;
|
||||
|
||||
/// Data that layout associates with a node.
|
||||
|
|
|
@ -19,9 +19,9 @@ use flow_ref::{self, FlowRef};
|
|||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
|
||||
use gfx::display_list::StackingContext;
|
||||
use gfx_traits::StackingContextId;
|
||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint};
|
||||
use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use std::cmp::max;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::flex_direction;
|
||||
|
|
|
@ -36,12 +36,12 @@ use flow_ref::{self, FlowRef, WeakFlowRef};
|
|||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
|
||||
use gfx::display_list::{ClippingRegion, StackingContext};
|
||||
use gfx_traits::{LayerId, LayerType, StackingContextId};
|
||||
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||
use inline::InlineFlow;
|
||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||
use multicol::MulticolFlow;
|
||||
use parallel::FlowParallelInfo;
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||
use std::iter::Zip;
|
||||
use std::slice::IterMut;
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -18,7 +18,6 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
|
|||
use gfx::text::glyph::ByteIndex;
|
||||
use gfx::text::text_run::{TextRun, TextRunSlice};
|
||||
use gfx_traits::{FragmentType, LayerId, LayerType, StackingContextId};
|
||||
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
|
||||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
|
||||
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
|
@ -31,6 +30,7 @@ use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
|
|||
use range::*;
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use script::layout_interface::HTMLCanvasData;
|
||||
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, RestyleDamage};
|
||||
use std::borrow::ToOwned;
|
||||
use std::cmp::{max, min};
|
||||
use std::collections::LinkedList;
|
||||
|
|
|
@ -13,7 +13,7 @@ use flow::InorderFlowTraversal;
|
|||
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils};
|
||||
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use incremental::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
|
||||
use script_layout_interface::restyle_damage::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::{HashMap, LinkedList};
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -3,46 +3,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSOLUTELY_POSITIONED};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::{display, float};
|
||||
use script_layout_interface::restyle_damage::{RestyleDamage, REFLOW, RECONSTRUCT_FLOW};
|
||||
use style::computed_values::float;
|
||||
use style::dom::TRestyleDamage;
|
||||
use style::properties::{ComputedValues, ServoComputedValues};
|
||||
|
||||
bitflags! {
|
||||
#[doc = "Individual layout actions that may be necessary after restyling."]
|
||||
pub flags RestyleDamage: u8 {
|
||||
#[doc = "Repaint the node itself."]
|
||||
#[doc = "Currently unused; need to decide how this propagates."]
|
||||
const REPAINT = 0x01,
|
||||
|
||||
#[doc = "Recompute the overflow regions (bounding box of object and all descendants)."]
|
||||
#[doc = "Propagates down the flow tree because the computation is bottom-up."]
|
||||
const STORE_OVERFLOW = 0x02,
|
||||
|
||||
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
|
||||
#[doc = "Propagates down the flow tree because the computation is"]
|
||||
#[doc = "bottom-up."]
|
||||
const BUBBLE_ISIZES = 0x04,
|
||||
|
||||
#[doc = "Recompute actual inline-sizes and block-sizes, only taking out-of-flow children \
|
||||
into account. \
|
||||
Propagates up the flow tree because the computation is top-down."]
|
||||
const REFLOW_OUT_OF_FLOW = 0x08,
|
||||
|
||||
#[doc = "Recompute actual inline_sizes and block_sizes."]
|
||||
#[doc = "Propagates up the flow tree because the computation is"]
|
||||
#[doc = "top-down."]
|
||||
const REFLOW = 0x10,
|
||||
|
||||
#[doc = "Re-resolve generated content. \
|
||||
Propagates up the flow tree because the computation is inorder."]
|
||||
const RESOLVE_GENERATED_CONTENT = 0x20,
|
||||
|
||||
#[doc = "The entire flow needs to be reconstructed."]
|
||||
const RECONSTRUCT_FLOW = 0x40
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub flags SpecialRestyleDamage: u8 {
|
||||
|
@ -52,221 +15,6 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl TRestyleDamage for RestyleDamage {
|
||||
type ConcreteComputedValues = ServoComputedValues;
|
||||
fn compute(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) ->
|
||||
RestyleDamage { compute_damage(old, new) }
|
||||
|
||||
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
|
||||
///
|
||||
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
||||
/// unnecessary sequential resolution of generated content.
|
||||
fn rebuild_and_reflow() -> RestyleDamage {
|
||||
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl RestyleDamage {
|
||||
/// Supposing a flow has the given `position` property and this damage, returns the damage that
|
||||
/// we should add to the *parent* of this flow.
|
||||
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
||||
if child_is_absolutely_positioned {
|
||||
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
||||
} else {
|
||||
self & (REPAINT | STORE_OVERFLOW | REFLOW | REFLOW_OUT_OF_FLOW |
|
||||
RESOLVE_GENERATED_CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
/// Supposing the *parent* of a flow with the given `position` property has this damage,
|
||||
/// returns the damage that we should add to this flow.
|
||||
pub fn damage_for_child(self,
|
||||
parent_is_absolutely_positioned: bool,
|
||||
child_is_absolutely_positioned: bool)
|
||||
-> RestyleDamage {
|
||||
match (parent_is_absolutely_positioned, child_is_absolutely_positioned) {
|
||||
(false, true) => {
|
||||
// Absolute children are out-of-flow and therefore insulated from changes.
|
||||
//
|
||||
// FIXME(pcwalton): Au contraire, if the containing block dimensions change!
|
||||
self & REPAINT
|
||||
}
|
||||
(true, false) => {
|
||||
// Changing the position of an absolutely-positioned block requires us to reflow
|
||||
// its kids.
|
||||
if self.contains(REFLOW_OUT_OF_FLOW) {
|
||||
self | REFLOW
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO(pcwalton): Take floatedness into account.
|
||||
self & (REPAINT | REFLOW)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RestyleDamage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let mut first_elem = true;
|
||||
|
||||
let to_iter =
|
||||
[ (REPAINT, "Repaint")
|
||||
, (STORE_OVERFLOW, "StoreOverflow")
|
||||
, (BUBBLE_ISIZES, "BubbleISizes")
|
||||
, (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow")
|
||||
, (REFLOW, "Reflow")
|
||||
, (RESOLVE_GENERATED_CONTENT, "ResolveGeneratedContent")
|
||||
, (RECONSTRUCT_FLOW, "ReconstructFlow")
|
||||
];
|
||||
|
||||
for &(damage, damage_str) in &to_iter {
|
||||
if self.contains(damage) {
|
||||
if !first_elem { try!(write!(f, " | ")); }
|
||||
try!(write!(f, "{}", damage_str));
|
||||
first_elem = false;
|
||||
}
|
||||
}
|
||||
|
||||
if first_elem {
|
||||
try!(write!(f, "NoDamage"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: We need the braces inside the RHS due to Rust #8012. This particular
|
||||
// version of this macro might be safe anyway, but we want to avoid silent
|
||||
// breakage on modifications.
|
||||
macro_rules! add_if_not_equal(
|
||||
($old:ident, $new:ident, $damage:ident,
|
||||
[ $($effect:ident),* ], [ $($style_struct_getter:ident.$name:ident),* ]) => ({
|
||||
if $( ($old.$style_struct_getter().$name != $new.$style_struct_getter().$name) )||* {
|
||||
$damage.insert($($effect)|*);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
pub fn compute_damage(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) -> RestyleDamage {
|
||||
let old: &ServoComputedValues = match old {
|
||||
None => return RestyleDamage::rebuild_and_reflow(),
|
||||
Some(cv) => &**cv,
|
||||
};
|
||||
|
||||
let mut damage = RestyleDamage::empty();
|
||||
|
||||
// This should check every CSS property, as enumerated in the fields of
|
||||
// http://doc.servo.org/style/properties/struct.ServoComputedValues.html
|
||||
|
||||
// FIXME: Test somehow that every property is included.
|
||||
|
||||
add_if_not_equal!(old, new, damage,
|
||||
[
|
||||
REPAINT,
|
||||
STORE_OVERFLOW,
|
||||
BUBBLE_ISIZES,
|
||||
REFLOW_OUT_OF_FLOW,
|
||||
REFLOW,
|
||||
RECONSTRUCT_FLOW
|
||||
], [
|
||||
get_box.float, get_box.display, get_box.position, get_counters.content,
|
||||
get_counters.counter_reset, get_counters.counter_increment,
|
||||
get_inheritedbox._servo_under_display_none,
|
||||
get_list.quotes, get_list.list_style_type,
|
||||
|
||||
// If these text or font properties change, we need to reconstruct the flow so that
|
||||
// text shaping is re-run.
|
||||
get_inheritedtext.letter_spacing, get_inheritedtext.text_rendering,
|
||||
get_inheritedtext.text_transform, get_inheritedtext.word_spacing,
|
||||
get_inheritedtext.overflow_wrap, get_inheritedtext.text_justify,
|
||||
get_inheritedtext.white_space, get_inheritedtext.word_break, get_text.text_overflow,
|
||||
get_font.font_family, get_font.font_style, get_font.font_variant, get_font.font_weight,
|
||||
get_font.font_size, get_font.font_stretch,
|
||||
get_inheritedbox.direction, get_inheritedbox.writing_mode,
|
||||
get_inheritedbox.text_orientation,
|
||||
get_text.text_decoration, get_text.unicode_bidi,
|
||||
get_inheritedtable.empty_cells, get_inheritedtable.caption_side,
|
||||
get_column.column_width, get_column.column_count
|
||||
]) || (new.get_box().display == display::T::inline &&
|
||||
add_if_not_equal!(old, new, damage,
|
||||
[REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW,
|
||||
RECONSTRUCT_FLOW], [
|
||||
// For inline boxes only, border/padding styles are used in flow construction (to decide
|
||||
// whether to create fragments for empty flows).
|
||||
get_border.border_top_width, get_border.border_right_width,
|
||||
get_border.border_bottom_width, get_border.border_left_width,
|
||||
get_padding.padding_top, get_padding.padding_right,
|
||||
get_padding.padding_bottom, get_padding.padding_left
|
||||
])) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW ],
|
||||
[get_border.border_top_width, get_border.border_right_width,
|
||||
get_border.border_bottom_width, get_border.border_left_width,
|
||||
get_margin.margin_top, get_margin.margin_right,
|
||||
get_margin.margin_bottom, get_margin.margin_left,
|
||||
get_padding.padding_top, get_padding.padding_right,
|
||||
get_padding.padding_bottom, get_padding.padding_left,
|
||||
get_position.width, get_position.height,
|
||||
get_inheritedtext.line_height,
|
||||
get_inheritedtext.text_align, get_inheritedtext.text_indent,
|
||||
get_table.table_layout,
|
||||
get_inheritedtable.border_collapse,
|
||||
get_inheritedtable.border_spacing,
|
||||
get_column.column_gap,
|
||||
get_position.flex_direction,
|
||||
get_position.flex_wrap,
|
||||
get_position.justify_content,
|
||||
get_position.align_items,
|
||||
get_position.align_content,
|
||||
get_position.order,
|
||||
get_position.flex_basis,
|
||||
get_position.flex_grow,
|
||||
get_position.flex_shrink,
|
||||
get_position.align_self
|
||||
]) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW ], [
|
||||
get_position.top, get_position.left,
|
||||
get_position.right, get_position.bottom
|
||||
]) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT ], [
|
||||
get_color.color, get_background.background_color,
|
||||
get_background.background_image, get_background.background_position,
|
||||
get_background.background_repeat, get_background.background_attachment,
|
||||
get_background.background_clip, get_background.background_origin,
|
||||
get_background.background_size,
|
||||
get_border.border_top_color, get_border.border_right_color,
|
||||
get_border.border_bottom_color, get_border.border_left_color,
|
||||
get_border.border_top_style, get_border.border_right_style,
|
||||
get_border.border_bottom_style, get_border.border_left_style,
|
||||
get_border.border_top_left_radius, get_border.border_top_right_radius,
|
||||
get_border.border_bottom_left_radius, get_border.border_bottom_right_radius,
|
||||
get_position.z_index, get_box._servo_overflow_clip_box,
|
||||
get_inheritedtext._servo_text_decorations_in_effect,
|
||||
get_pointing.cursor, get_pointing.pointer_events,
|
||||
get_effects.box_shadow, get_effects.clip, get_inheritedtext.text_shadow, get_effects.filter,
|
||||
get_effects.transform, get_effects.backface_visibility, get_effects.transform_style,
|
||||
get_effects.transform_origin, get_effects.perspective, get_effects.perspective_origin,
|
||||
get_effects.mix_blend_mode, get_inheritedbox.image_rendering,
|
||||
|
||||
// Note: May require REFLOW et al. if `visibility: collapse` is implemented.
|
||||
get_inheritedbox.visibility
|
||||
]);
|
||||
|
||||
// If the layer requirements of this flow have changed due to the value
|
||||
// of the transform, then reflow is required to rebuild the layers.
|
||||
if old.transform_requires_layer() != new.transform_requires_layer() {
|
||||
damage.insert(RestyleDamage::rebuild_and_reflow());
|
||||
}
|
||||
|
||||
damage
|
||||
}
|
||||
|
||||
pub trait LayoutDamageComputation {
|
||||
fn compute_layout_damage(self) -> SpecialRestyleDamage;
|
||||
fn reflow_entire_document(self);
|
||||
|
|
|
@ -21,10 +21,11 @@ use gfx::display_list::{OpaqueNode, StackingContext};
|
|||
use gfx::font::FontMetrics;
|
||||
use gfx::font_context::FontContext;
|
||||
use gfx_traits::StackingContextId;
|
||||
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RESOLVE_GENERATED_CONTENT};
|
||||
use layout_debug;
|
||||
use model::IntrinsicISizesContribution;
|
||||
use range::{Range, RangeIndex};
|
||||
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use script_layout_interface::restyle_damage::{REPAINT, RESOLVE_GENERATED_CONTENT};
|
||||
use std::cmp::max;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -29,8 +29,7 @@ use gfx::font_context;
|
|||
use gfx::paint_thread::LayoutToPaintMsg;
|
||||
use gfx_traits::{color, Epoch, FragmentType, LayerId, ScrollPolicy, StackingContextId};
|
||||
use heapsize::HeapSizeOf;
|
||||
use incremental::LayoutDamageComputation;
|
||||
use incremental::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW, REFLOW_ENTIRE_DOCUMENT};
|
||||
use incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT};
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use layout_debug;
|
||||
|
@ -51,6 +50,7 @@ use script::layout_interface::OpaqueStyleAndLayoutData;
|
|||
use script::layout_interface::{LayoutRPC, OffsetParentResponse, NodeOverflowResponse, MarginStyleResponse};
|
||||
use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow};
|
||||
use script::reporter::CSSErrorReporter;
|
||||
use script_layout_interface::restyle_damage::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW};
|
||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
|
||||
use script_traits::{StackingContextScrollState, UntrustedNodeAddress};
|
||||
use sequential;
|
||||
|
|
|
@ -47,6 +47,7 @@ extern crate profile_traits;
|
|||
extern crate range;
|
||||
extern crate rustc_serialize;
|
||||
extern crate script;
|
||||
extern crate script_layout_interface;
|
||||
extern crate script_traits;
|
||||
extern crate selectors;
|
||||
extern crate serde_json;
|
||||
|
|
|
@ -19,8 +19,8 @@ use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedC
|
|||
use generated_content;
|
||||
use gfx::display_list::StackingContext;
|
||||
use gfx_traits::StackingContextId;
|
||||
use incremental::RESOLVE_GENERATED_CONTENT;
|
||||
use inline::InlineMetrics;
|
||||
use script_layout_interface::restyle_damage::RESOLVE_GENERATED_CONTENT;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::{list_style_type, position};
|
||||
use style::logical_geometry::LogicalSize;
|
||||
|
|
|
@ -16,7 +16,7 @@ use flow_ref::{self, FlowRef};
|
|||
use fragment::FragmentBorderBoxIterator;
|
||||
use generated_content::ResolveGeneratedContent;
|
||||
use gfx::display_list::{DisplayItem, StackingContext};
|
||||
use incremental::{REFLOW, STORE_OVERFLOW};
|
||||
use script_layout_interface::restyle_damage::{REFLOW, STORE_OVERFLOW};
|
||||
use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList, ComputeAbsolutePositions};
|
||||
use util::opts;
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ use flow_list::MutFlowListIterator;
|
|||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
|
||||
use gfx::display_list::StackingContext;
|
||||
use gfx_traits::StackingContextId;
|
||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};
|
||||
use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -16,9 +16,9 @@ use flow::{self, Flow, FlowClass, OpaqueFlow};
|
|||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
|
||||
use gfx::display_list::StackingContext;
|
||||
use gfx_traits::StackingContextId;
|
||||
use incremental::REFLOW;
|
||||
use layout_debug;
|
||||
use model::MaybeAuto;
|
||||
use script_layout_interface::restyle_damage::REFLOW;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::{border_collapse, border_top_style, vertical_align};
|
||||
|
|
|
@ -10,7 +10,7 @@ use display_list_builder::DisplayListBuildState;
|
|||
use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal};
|
||||
use flow::{PreorderFlowTraversal, self};
|
||||
use gfx::display_list::OpaqueNode;
|
||||
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
|
||||
use std::mem;
|
||||
use style::context::StyleContext;
|
||||
use style::matching::MatchMethods;
|
||||
|
|
|
@ -35,7 +35,6 @@ use data::{LayoutDataFlags, PrivateLayoutData};
|
|||
use gfx::display_list::OpaqueNode;
|
||||
use gfx::text::glyph::ByteIndex;
|
||||
use gfx_traits::{LayerId, LayerType};
|
||||
use incremental::RestyleDamage;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use opaque_node::OpaqueNodeMethods;
|
||||
use range::Range;
|
||||
|
@ -45,6 +44,7 @@ use script::layout_interface::{HTMLCanvasData, HTMLElementTypeId, LayoutCharacte
|
|||
use script::layout_interface::{LayoutDocumentHelpers, LayoutElementHelpers, LayoutJS};
|
||||
use script::layout_interface::{LayoutNodeHelpers, Node, NodeTypeId, OpaqueStyleAndLayoutData};
|
||||
use script::layout_interface::{RawLayoutElementHelpers, Text, TrustedNodeAddress};
|
||||
use script_layout_interface::restyle_damage::RestyleDamage;
|
||||
use selectors::matching::{DeclarationBlock, ElementFlags};
|
||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||
use smallvec::VecLike;
|
||||
|
|
14
components/script_layout_interface/Cargo.toml
Normal file
14
components/script_layout_interface/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "script_layout_interface"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "script_layout_interface"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.7"
|
||||
plugins = {path = "../plugins"}
|
||||
style = {path = "../style"}
|
18
components/script_layout_interface/lib.rs
Normal file
18
components/script_layout_interface/lib.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! This module contains traits in script used generically in the rest of Servo.
|
||||
//! The traits are here instead of in script so that these modules won't have
|
||||
//! to depend on script.
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(plugin)]
|
||||
#![plugin(plugins)]
|
||||
|
||||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate style;
|
||||
|
||||
pub mod restyle_damage;
|
258
components/script_layout_interface/restyle_damage.rs
Normal file
258
components/script_layout_interface/restyle_damage.rs
Normal file
|
@ -0,0 +1,258 @@
|
|||
/* 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::fmt;
|
||||
use std::sync::Arc;
|
||||
use style::computed_values::display;
|
||||
use style::dom::TRestyleDamage;
|
||||
use style::properties::{ComputedValues, ServoComputedValues};
|
||||
|
||||
bitflags! {
|
||||
#[doc = "Individual layout actions that may be necessary after restyling."]
|
||||
pub flags RestyleDamage: u8 {
|
||||
#[doc = "Repaint the node itself."]
|
||||
#[doc = "Currently unused; need to decide how this propagates."]
|
||||
const REPAINT = 0x01,
|
||||
|
||||
#[doc = "Recompute the overflow regions (bounding box of object and all descendants)."]
|
||||
#[doc = "Propagates down the flow tree because the computation is bottom-up."]
|
||||
const STORE_OVERFLOW = 0x02,
|
||||
|
||||
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
|
||||
#[doc = "Propagates down the flow tree because the computation is"]
|
||||
#[doc = "bottom-up."]
|
||||
const BUBBLE_ISIZES = 0x04,
|
||||
|
||||
#[doc = "Recompute actual inline-sizes and block-sizes, only taking out-of-flow children \
|
||||
into account. \
|
||||
Propagates up the flow tree because the computation is top-down."]
|
||||
const REFLOW_OUT_OF_FLOW = 0x08,
|
||||
|
||||
#[doc = "Recompute actual inline_sizes and block_sizes."]
|
||||
#[doc = "Propagates up the flow tree because the computation is"]
|
||||
#[doc = "top-down."]
|
||||
const REFLOW = 0x10,
|
||||
|
||||
#[doc = "Re-resolve generated content. \
|
||||
Propagates up the flow tree because the computation is inorder."]
|
||||
const RESOLVE_GENERATED_CONTENT = 0x20,
|
||||
|
||||
#[doc = "The entire flow needs to be reconstructed."]
|
||||
const RECONSTRUCT_FLOW = 0x40
|
||||
}
|
||||
}
|
||||
|
||||
impl TRestyleDamage for RestyleDamage {
|
||||
type ConcreteComputedValues = ServoComputedValues;
|
||||
fn compute(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) ->
|
||||
RestyleDamage { compute_damage(old, new) }
|
||||
|
||||
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
|
||||
///
|
||||
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
||||
/// unnecessary sequential resolution of generated content.
|
||||
fn rebuild_and_reflow() -> RestyleDamage {
|
||||
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
||||
}
|
||||
}
|
||||
|
||||
impl RestyleDamage {
|
||||
/// Supposing a flow has the given `position` property and this damage, returns the damage that
|
||||
/// we should add to the *parent* of this flow.
|
||||
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
||||
if child_is_absolutely_positioned {
|
||||
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
||||
} else {
|
||||
self & (REPAINT | STORE_OVERFLOW | REFLOW | REFLOW_OUT_OF_FLOW |
|
||||
RESOLVE_GENERATED_CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
/// Supposing the *parent* of a flow with the given `position` property has this damage,
|
||||
/// returns the damage that we should add to this flow.
|
||||
pub fn damage_for_child(self,
|
||||
parent_is_absolutely_positioned: bool,
|
||||
child_is_absolutely_positioned: bool)
|
||||
-> RestyleDamage {
|
||||
match (parent_is_absolutely_positioned, child_is_absolutely_positioned) {
|
||||
(false, true) => {
|
||||
// Absolute children are out-of-flow and therefore insulated from changes.
|
||||
//
|
||||
// FIXME(pcwalton): Au contraire, if the containing block dimensions change!
|
||||
self & REPAINT
|
||||
}
|
||||
(true, false) => {
|
||||
// Changing the position of an absolutely-positioned block requires us to reflow
|
||||
// its kids.
|
||||
if self.contains(REFLOW_OUT_OF_FLOW) {
|
||||
self | REFLOW
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO(pcwalton): Take floatedness into account.
|
||||
self & (REPAINT | REFLOW)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RestyleDamage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let mut first_elem = true;
|
||||
|
||||
let to_iter =
|
||||
[ (REPAINT, "Repaint")
|
||||
, (STORE_OVERFLOW, "StoreOverflow")
|
||||
, (BUBBLE_ISIZES, "BubbleISizes")
|
||||
, (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow")
|
||||
, (REFLOW, "Reflow")
|
||||
, (RESOLVE_GENERATED_CONTENT, "ResolveGeneratedContent")
|
||||
, (RECONSTRUCT_FLOW, "ReconstructFlow")
|
||||
];
|
||||
|
||||
for &(damage, damage_str) in &to_iter {
|
||||
if self.contains(damage) {
|
||||
if !first_elem { try!(write!(f, " | ")); }
|
||||
try!(write!(f, "{}", damage_str));
|
||||
first_elem = false;
|
||||
}
|
||||
}
|
||||
|
||||
if first_elem {
|
||||
try!(write!(f, "NoDamage"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: We need the braces inside the RHS due to Rust #8012. This particular
|
||||
// version of this macro might be safe anyway, but we want to avoid silent
|
||||
// breakage on modifications.
|
||||
macro_rules! add_if_not_equal(
|
||||
($old:ident, $new:ident, $damage:ident,
|
||||
[ $($effect:ident),* ], [ $($style_struct_getter:ident.$name:ident),* ]) => ({
|
||||
if $( ($old.$style_struct_getter().$name != $new.$style_struct_getter().$name) )||* {
|
||||
$damage.insert($($effect)|*);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
fn compute_damage(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) -> RestyleDamage {
|
||||
let old: &ServoComputedValues = match old {
|
||||
None => return RestyleDamage::rebuild_and_reflow(),
|
||||
Some(cv) => &**cv,
|
||||
};
|
||||
|
||||
let mut damage = RestyleDamage::empty();
|
||||
|
||||
// This should check every CSS property, as enumerated in the fields of
|
||||
// http://doc.servo.org/style/properties/struct.ServoComputedValues.html
|
||||
|
||||
// FIXME: Test somehow that every property is included.
|
||||
|
||||
add_if_not_equal!(old, new, damage,
|
||||
[
|
||||
REPAINT,
|
||||
STORE_OVERFLOW,
|
||||
BUBBLE_ISIZES,
|
||||
REFLOW_OUT_OF_FLOW,
|
||||
REFLOW,
|
||||
RECONSTRUCT_FLOW
|
||||
], [
|
||||
get_box.float, get_box.display, get_box.position, get_counters.content,
|
||||
get_counters.counter_reset, get_counters.counter_increment,
|
||||
get_inheritedbox._servo_under_display_none,
|
||||
get_list.quotes, get_list.list_style_type,
|
||||
|
||||
// If these text or font properties change, we need to reconstruct the flow so that
|
||||
// text shaping is re-run.
|
||||
get_inheritedtext.letter_spacing, get_inheritedtext.text_rendering,
|
||||
get_inheritedtext.text_transform, get_inheritedtext.word_spacing,
|
||||
get_inheritedtext.overflow_wrap, get_inheritedtext.text_justify,
|
||||
get_inheritedtext.white_space, get_inheritedtext.word_break, get_text.text_overflow,
|
||||
get_font.font_family, get_font.font_style, get_font.font_variant, get_font.font_weight,
|
||||
get_font.font_size, get_font.font_stretch,
|
||||
get_inheritedbox.direction, get_inheritedbox.writing_mode,
|
||||
get_inheritedbox.text_orientation,
|
||||
get_text.text_decoration, get_text.unicode_bidi,
|
||||
get_inheritedtable.empty_cells, get_inheritedtable.caption_side,
|
||||
get_column.column_width, get_column.column_count
|
||||
]) || (new.get_box().display == display::T::inline &&
|
||||
add_if_not_equal!(old, new, damage,
|
||||
[REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW,
|
||||
RECONSTRUCT_FLOW], [
|
||||
// For inline boxes only, border/padding styles are used in flow construction (to decide
|
||||
// whether to create fragments for empty flows).
|
||||
get_border.border_top_width, get_border.border_right_width,
|
||||
get_border.border_bottom_width, get_border.border_left_width,
|
||||
get_padding.padding_top, get_padding.padding_right,
|
||||
get_padding.padding_bottom, get_padding.padding_left
|
||||
])) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT, STORE_OVERFLOW, BUBBLE_ISIZES, REFLOW_OUT_OF_FLOW, REFLOW ],
|
||||
[get_border.border_top_width, get_border.border_right_width,
|
||||
get_border.border_bottom_width, get_border.border_left_width,
|
||||
get_margin.margin_top, get_margin.margin_right,
|
||||
get_margin.margin_bottom, get_margin.margin_left,
|
||||
get_padding.padding_top, get_padding.padding_right,
|
||||
get_padding.padding_bottom, get_padding.padding_left,
|
||||
get_position.width, get_position.height,
|
||||
get_inheritedtext.line_height,
|
||||
get_inheritedtext.text_align, get_inheritedtext.text_indent,
|
||||
get_table.table_layout,
|
||||
get_inheritedtable.border_collapse,
|
||||
get_inheritedtable.border_spacing,
|
||||
get_column.column_gap,
|
||||
get_position.flex_direction,
|
||||
get_position.flex_wrap,
|
||||
get_position.justify_content,
|
||||
get_position.align_items,
|
||||
get_position.align_content,
|
||||
get_position.order,
|
||||
get_position.flex_basis,
|
||||
get_position.flex_grow,
|
||||
get_position.flex_shrink,
|
||||
get_position.align_self
|
||||
]) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW ], [
|
||||
get_position.top, get_position.left,
|
||||
get_position.right, get_position.bottom
|
||||
]) || add_if_not_equal!(old, new, damage,
|
||||
[ REPAINT ], [
|
||||
get_color.color, get_background.background_color,
|
||||
get_background.background_image, get_background.background_position,
|
||||
get_background.background_repeat, get_background.background_attachment,
|
||||
get_background.background_clip, get_background.background_origin,
|
||||
get_background.background_size,
|
||||
get_border.border_top_color, get_border.border_right_color,
|
||||
get_border.border_bottom_color, get_border.border_left_color,
|
||||
get_border.border_top_style, get_border.border_right_style,
|
||||
get_border.border_bottom_style, get_border.border_left_style,
|
||||
get_border.border_top_left_radius, get_border.border_top_right_radius,
|
||||
get_border.border_bottom_left_radius, get_border.border_bottom_right_radius,
|
||||
get_position.z_index, get_box._servo_overflow_clip_box,
|
||||
get_inheritedtext._servo_text_decorations_in_effect,
|
||||
get_pointing.cursor, get_pointing.pointer_events,
|
||||
get_effects.box_shadow, get_effects.clip, get_inheritedtext.text_shadow, get_effects.filter,
|
||||
get_effects.transform, get_effects.backface_visibility, get_effects.transform_style,
|
||||
get_effects.transform_origin, get_effects.perspective, get_effects.perspective_origin,
|
||||
get_effects.mix_blend_mode, get_inheritedbox.image_rendering,
|
||||
|
||||
// Note: May require REFLOW et al. if `visibility: collapse` is implemented.
|
||||
get_inheritedbox.visibility
|
||||
]);
|
||||
|
||||
// If the layer requirements of this flow have changed due to the value
|
||||
// of the transform, then reflow is required to rebuild the layers.
|
||||
if old.transform_requires_layer() != new.transform_requires_layer() {
|
||||
damage.insert(RestyleDamage::rebuild_and_reflow());
|
||||
}
|
||||
|
||||
damage
|
||||
}
|
10
components/servo/Cargo.lock
generated
10
components/servo/Cargo.lock
generated
|
@ -1157,6 +1157,7 @@ dependencies = [
|
|||
"range 0.0.1",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"script 0.0.1",
|
||||
"script_layout_interface 0.0.1",
|
||||
"script_traits 0.0.1",
|
||||
"selectors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1924,6 +1925,15 @@ dependencies = [
|
|||
"xml5ever 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "script_layout_interface"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugins 0.0.1",
|
||||
"style 0.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "script_tests"
|
||||
version = "0.0.1"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue