Only restyle viewport-relative nodes on viewport size change

This commit is contained in:
Shing Lyu 2016-06-22 16:44:04 +08:00
parent e7a55ae55e
commit f754cacbd5
28 changed files with 515 additions and 11 deletions

View file

@ -1072,9 +1072,15 @@ impl LayoutThread {
.send(ConstellationMsg::ViewportConstrained(self.id, constraints))
.unwrap();
}
// FIXME (#10104): Only dirty nodes affected by vh/vw/vmin/vmax styles.
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
needs_dirtying = true;
for node in node.traverse_preorder() {
if node.needs_dirty_on_viewport_size_changed() {
node.dirty_self();
node.dirty_descendants();
// TODO(shinglyu): We can skip the traversal if the descendants were already
// dirtied
}
}
}
}

View file

@ -159,7 +159,9 @@ bitflags! {
const SEQUENTIALLY_FOCUSABLE = 0x20,
/// Whether any ancestor is a fragmentation container
const CAN_BE_FRAGMENTED = 0x40
const CAN_BE_FRAGMENTED = 0x40,
#[doc = "Specifies whether this node needs to be dirted when viewport size changed."]
const DIRTY_ON_VIEWPORT_SIZE_CHANGE = 0x80
}
}

View file

@ -36,7 +36,7 @@ use dom::bindings::js::LayoutJS;
use dom::characterdata::LayoutCharacterDataHelpers;
use dom::document::{Document, LayoutDocumentHelpers};
use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
use dom::node::{CAN_BE_FRAGMENTED, HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY};
use dom::node::{CAN_BE_FRAGMENTED, HAS_CHANGED, HAS_DIRTY_DESCENDANTS, IS_DIRTY, DIRTY_ON_VIEWPORT_SIZE_CHANGE};
use dom::node::{Node, LayoutNodeHelpers};
use dom::text::Text;
use gfx_traits::ByteIndex;
@ -193,6 +193,23 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
self.node.set_flag(HAS_DIRTY_DESCENDANTS, value)
}
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
unsafe { self.node.get_flag(DIRTY_ON_VIEWPORT_SIZE_CHANGE) }
}
unsafe fn set_dirty_on_viewport_size_changed(&self) {
self.node.set_flag(DIRTY_ON_VIEWPORT_SIZE_CHANGE, true);
}
fn set_descendants_dirty_on_viewport_size_changed(&self) {
for ref child in self.children() {
unsafe {
child.set_dirty_on_viewport_size_changed();
}
child.set_descendants_dirty_on_viewport_size_changed();
}
}
fn can_be_fragmented(&self) -> bool {
unsafe { self.node.get_flag(CAN_BE_FRAGMENTED) }
}

View file

@ -127,6 +127,19 @@ pub trait TNode : Sized + Copy + Clone {
}
}
fn needs_dirty_on_viewport_size_changed(&self) -> bool;
unsafe fn set_dirty_on_viewport_size_changed(&self);
fn set_descendants_dirty_on_viewport_size_changed(&self) {
for ref child in self.children() {
unsafe {
child.set_dirty_on_viewport_size_changed();
}
child.set_descendants_dirty_on_viewport_size_changed();
}
}
fn can_be_fragmented(&self) -> bool;
unsafe fn set_can_be_fragmented(&self, value: bool);

View file

@ -47,7 +47,7 @@ class Keyword(object):
class Longhand(object):
def __init__(self, style_struct, name, animatable=None, derived_from=None, keyword=None,
predefined_type=None, custom_cascade=False, experimental=False, internal=False,
need_clone=False, need_index=False, gecko_ffi_name=None):
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False):
self.name = name
self.keyword = keyword
self.predefined_type = predefined_type
@ -59,6 +59,7 @@ class Longhand(object):
self.internal = internal
self.need_index = need_index
self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
self.depend_on_viewport_size = depend_on_viewport_size
self.derived_from = (derived_from or "").split()
# This is done like this since just a plain bool argument seemed like

View file

@ -51,6 +51,14 @@
% if product == "gecko" or not gecko_only:
use cssparser::ToCss;
use std::fmt;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(ref vec) = self;
vec.iter().any(|ref x| x.has_viewport_percentage())
}
}
pub mod single_value {
use cssparser::Parser;
@ -274,7 +282,9 @@
<%def name="single_keyword(name, values, **kwargs)">
<%call expr="single_keyword_computed(name, values, **kwargs)">
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
</%call>
</%def>
@ -315,6 +325,8 @@
<%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
use cssparser::ToCss;
use std::fmt;

View file

@ -15,6 +15,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
use std::fmt;
use values::specified::Image;
use values::LocalToCss;
use values::NoViewportPercentage;
pub mod computed_value {
use values::computed;
@ -34,6 +35,8 @@ ${helpers.predefined_type("background-color", "CSSColor",
}
}
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub Option<Image>);
@ -76,6 +79,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
pub mod computed_value {
use values::computed::LengthOrPercentage;
@ -88,6 +92,12 @@ ${helpers.predefined_type("background-color", "CSSColor",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
return self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage();
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue {
@ -207,6 +217,7 @@ ${helpers.single_keyword("background-origin",
use cssparser::{ToCss, Token};
use std::ascii::AsciiExt;
use std::fmt;
use values::HasViewportPercentage;
pub mod computed_value {
use values::computed::LengthOrPercentageOrAuto;
@ -237,6 +248,12 @@ ${helpers.single_keyword("background-origin",
}
}
impl HasViewportPercentage for SpecifiedExplicitSize {
fn has_viewport_percentage(&self) -> bool {
return self.width.has_viewport_percentage() || self.height.has_viewport_percentage();
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedExplicitSize {
@ -260,6 +277,14 @@ ${helpers.single_keyword("background-origin",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::Explicit(ref explicit_size) => explicit_size.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -26,6 +26,7 @@
use app_units::Au;
use cssparser::ToCss;
use std::fmt;
use values::HasViewportPercentage;
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -41,6 +42,14 @@
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub specified::Length);
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(length) = self;
length.has_viewport_percentage()
}
}
pub mod computed_value {
use app_units::Au;
pub type T = Au;

View file

@ -28,6 +28,9 @@
pub use self::computed_value::T as SpecifiedValue;
use values::computed::{Context, ComputedValueAsSpecified};
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
#[allow(non_camel_case_types)]
#[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug)]
@ -94,7 +97,10 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
<%helpers:single_keyword_computed name="float"
values="none left right"
animatable="False"
need_clone="True">
need_clone="True"
gecko_ffi_name="mFloat">
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
@ -146,6 +152,16 @@ ${helpers.single_keyword("clear", "none left right both",
extra_gecko_values="middle-with-baseline") %>
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -252,6 +268,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
pub use self::computed_value::T as SpecifiedValue;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest)
@ -291,6 +310,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
pub use self::computed_value::T as SpecifiedValue;
pub use values::specified::Time as SingleSpecifiedValue;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
use cssparser::ToCss;
@ -469,6 +490,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
}
}
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
@ -592,6 +616,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
Ok(SpecifiedValue(try!(input.parse_comma_separated(SingleSpecifiedValue::parse))))
}
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
@ -615,6 +642,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
need_index="True"
animatable="False">
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
pub mod computed_value {
use cssparser::ToCss;
@ -646,6 +674,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
}
pub use self::computed_value::T as SpecifiedValue;
impl NoViewportPercentage for SpecifiedValue {}
pub use string_cache::Atom as SingleSpecifiedValue;
#[inline]
@ -696,6 +725,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
need_index="True"
animatable="False">
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
pub mod computed_value {
use cssparser::ToCss;
@ -742,6 +772,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
pub use self::computed_value::AnimationIterationCount;
pub use self::computed_value::AnimationIterationCount as SingleSpecifiedValue;
pub use self::computed_value::T as SpecifiedValue;
impl NoViewportPercentage for SpecifiedValue {}
#[inline]
pub fn get_initial_single_value() -> AnimationIterationCount {
@ -885,6 +916,7 @@ ${helpers.single_keyword("-moz-appearance",
use std::fmt::{self, Write};
use url::Url;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -902,6 +934,7 @@ ${helpers.single_keyword("-moz-appearance",
}
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {

View file

@ -11,6 +11,16 @@
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -75,6 +85,9 @@
<%helpers:longhand name="column-count" experimental="True" animatable="False">
use cssparser::ToCss;
use std::fmt;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -144,6 +157,16 @@
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -10,6 +10,7 @@
use cssparser::Token;
use std::ascii::AsciiExt;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
use super::list_style_type;
@ -17,6 +18,7 @@
pub use self::computed_value::ContentItem;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
use super::super::list_style_type;
@ -174,6 +176,7 @@
<%helpers:longhand name="counter-increment" animatable="False">
use std::fmt;
use super::content;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use cssparser::{ToCss, Token, serialize_identifier};
@ -193,6 +196,7 @@
}
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {

View file

@ -16,6 +16,7 @@ ${helpers.predefined_type("opacity",
use cssparser::{self, ToCss};
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -28,6 +29,15 @@ ${helpers.predefined_type("opacity",
pub inset: bool,
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
self.offset_x.has_viewport_percentage() ||
self.offset_y.has_viewport_percentage() ||
self.blur_radius.has_viewport_percentage() ||
self.spread_radius.has_viewport_percentage()
}
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.inset {
@ -169,6 +179,7 @@ ${helpers.predefined_type("opacity",
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
// NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2.
@ -219,6 +230,15 @@ ${helpers.predefined_type("opacity",
}
}
impl HasViewportPercentage for SpecifiedClipRect {
fn has_viewport_percentage(&self) -> bool {
self.top.has_viewport_percentage() ||
self.right.map_or(false, |x| x.has_viewport_percentage()) ||
self.bottom.map_or(false, |x| x.has_viewport_percentage()) ||
self.left.has_viewport_percentage()
}
}
#[derive(Clone, Debug, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedClipRect {
@ -228,6 +248,13 @@ ${helpers.predefined_type("opacity",
pub left: specified::Length,
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(clip) = self;
clip.map_or(false, |x| x.has_viewport_percentage())
}
}
#[derive(Clone, Debug, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(Option<SpecifiedClipRect>);
@ -343,12 +370,29 @@ ${helpers.predefined_type("opacity",
use std::fmt;
use values::LocalToCss;
use values::CSSFloat;
use values::HasViewportPercentage;
use values::specified::{Angle, Length};
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(ref vec) = self;
vec.iter().any(|ref x| x.has_viewport_percentage())
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(Vec<SpecifiedFilter>);
impl HasViewportPercentage for SpecifiedFilter {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedFilter::Blur(length) => length.has_viewport_percentage(),
_ => false
}
}
}
// TODO(pcwalton): `drop-shadow`
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -576,6 +620,7 @@ ${helpers.predefined_type("opacity",
<%helpers:longhand name="transform" animatable="True">
use app_units::Au;
use values::CSSFloat;
use values::HasViewportPercentage;
use cssparser::ToCss;
use std::fmt;
@ -684,6 +729,20 @@ ${helpers.predefined_type("opacity",
}
}
impl HasViewportPercentage for SpecifiedOperation {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedOperation::Translate(_, l1, l2, l3) => {
l1.has_viewport_percentage() ||
l2.has_viewport_percentage() ||
l3.has_viewport_percentage()
},
SpecifiedOperation::Perspective(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for SpecifiedOperation {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -743,6 +802,13 @@ ${helpers.predefined_type("opacity",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(ref specified_ops) = self;
specified_ops.iter().any(|ref x| x.has_viewport_percentage())
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(Vec<SpecifiedOperation>);
@ -1133,6 +1199,7 @@ ${helpers.single_keyword("transform-style",
<%helpers:longhand name="transform-origin" animatable="True">
use app_units::Au;
use values::LocalToCss;
use values::HasViewportPercentage;
use values::specified::{Length, LengthOrPercentage, Percentage};
use cssparser::ToCss;
@ -1150,6 +1217,14 @@ ${helpers.single_keyword("transform-style",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
self.horizontal.has_viewport_percentage() ||
self.vertical.has_viewport_percentage() ||
self.depth.has_viewport_percentage()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue {
@ -1217,6 +1292,7 @@ ${helpers.predefined_type("perspective",
// FIXME: This prop should be animatable
<%helpers:longhand name="perspective-origin" animatable="False">
use values::HasViewportPercentage;
use values::specified::{LengthOrPercentage, Percentage};
use cssparser::ToCss;
@ -1241,6 +1317,12 @@ ${helpers.predefined_type("perspective",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage()
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue {

View file

@ -10,10 +10,13 @@
additional_methods=[Method("compute_font_hash", is_mut=True)]) %>
<%helpers:longhand name="font-family" animatable="False">
use self::computed_value::FontFamily;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
use cssparser::ToCss;
use std::fmt;
@ -128,6 +131,9 @@ ${helpers.single_keyword("font-variant",
<%helpers:longhand name="font-weight" need_clone="True" animatable="True">
use cssparser::ToCss;
use std::fmt;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -251,6 +257,7 @@ ${helpers.single_keyword("font-variant",
use cssparser::ToCss;
use std::fmt;
use values::FONT_MEDIUM_PX;
use values::HasViewportPercentage;
use values::specified::{LengthOrPercentage, Length, Percentage};
impl ToCss for SpecifiedValue {
@ -259,6 +266,13 @@ ${helpers.single_keyword("font-variant",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(length) = self;
return length.has_viewport_percentage()
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub specified::LengthOrPercentage);

View file

@ -64,6 +64,9 @@ ${helpers.single_keyword("color-adjust",
}
}
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
pub type SpecifiedValue = computed_value::T;
#[inline]
@ -104,6 +107,9 @@ ${helpers.single_keyword("color-adjust",
use cssparser::ToCss;
use std::fmt;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]

View file

@ -19,6 +19,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
<%helpers:longhand name="border-spacing" animatable="False">
use app_units::Au;
use values::LocalToCss;
use values::HasViewportPercentage;
use cssparser::ToCss;
use std::fmt;
@ -34,6 +35,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
return self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage()
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue {

View file

@ -11,6 +11,16 @@
use std::fmt;
use values::LocalToCss;
use values::CSSFloat;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::LengthOrPercentage(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -123,7 +133,9 @@
<%helpers:longhand name="text-align" animatable="False">
pub use self::computed_value::T as SpecifiedValue;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
macro_rules! define_text_align {
( $( $name: ident ( $string: expr ) => $discriminant: expr, )+ ) => {
@ -184,6 +196,16 @@
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -248,6 +270,16 @@
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
match *self {
SpecifiedValue::Specified(length) => length.has_viewport_percentage(),
_ => false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -340,10 +372,12 @@ ${helpers.single_keyword("text-justify",
use cssparser::{RGBA, ToCss};
use std::fmt;
use values:: NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use properties::style_struct_traits::{Box, Color, Text};
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -422,7 +456,9 @@ ${helpers.single_keyword("text-justify",
gecko_constant_prefix="NS_STYLE_WHITESPACE"
animatable="False">
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
impl SpecifiedValue {
pub fn allow_wrap(&self) -> bool {
@ -461,11 +497,27 @@ ${helpers.single_keyword("text-justify",
use cssparser::{self, ToCss};
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(ref vec) = self;
vec.iter().any(|ref x| x .has_viewport_percentage())
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(Vec<SpecifiedTextShadow>);
impl HasViewportPercentage for SpecifiedTextShadow {
fn has_viewport_percentage(&self) -> bool {
self.offset_x.has_viewport_percentage() ||
self.offset_y.has_viewport_percentage() ||
self.blur_radius.has_viewport_percentage()
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedTextShadow {

View file

@ -31,6 +31,9 @@ ${helpers.single_keyword("list-style-type", """
use std::fmt;
use url::Url;
use values::LocalToCss;
use values::NoViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -96,6 +99,7 @@ ${helpers.single_keyword("list-style-type", """
<%helpers:longhand name="quotes" animatable="False">
use std::borrow::Cow;
use std::fmt;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use cssparser::{ToCss, Token};
@ -109,6 +113,7 @@ ${helpers.single_keyword("list-style-type", """
}
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {

View file

@ -32,6 +32,7 @@ ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::Curr
use cssparser::ToCss;
use std::fmt;
use values::LocalToCss;
use values::HasViewportPercentage;
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -42,6 +43,14 @@ ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::Curr
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
specified::parse_border_width(input).map(SpecifiedValue)
}
impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
let &SpecifiedValue(length) = self;
length.has_viewport_percentage()
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub specified::Length);

View file

@ -8,9 +8,11 @@
<%helpers:longhand name="cursor" animatable="False">
pub use self::computed_value::T as SpecifiedValue;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
pub mod computed_value {
use cssparser::ToCss;

View file

@ -13,9 +13,11 @@
% endfor
<%helpers:longhand name="z-index" animatable="True">
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
pub type SpecifiedValue = computed_value::T;
pub mod computed_value {
use cssparser::ToCss;

View file

@ -25,8 +25,10 @@ ${helpers.single_keyword("unicode-bidi",
use cssparser::ToCss;
use std::fmt;
use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -32,6 +32,7 @@ use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selectors::matching::DeclarationBlock;
use stylesheets::Origin;
use values::LocalToCss;
use values::HasViewportPercentage;
use values::computed::{self, TContext, ToComputedValue};
use values::specified::BorderStyle;
@ -825,6 +826,19 @@ impl ToCss for PropertyDeclaration {
}
}
impl HasViewportPercentage for PropertyDeclaration {
fn has_viewport_percentage(&self) -> bool {
match *self {
% for property in data.longhands:
PropertyDeclaration::${property.camel_case}(DeclaredValue::Value(ref val)) => {
val.has_viewport_percentage()
},
% endfor
_ => false
}
}
}
impl PropertyDeclaration {
pub fn name(&self) -> PropertyDeclarationName {
match *self {

View file

@ -5,7 +5,7 @@
//! Traversing the DOM tree; the bloom filter.
use context::{SharedStyleContext, StyleContext};
use dom::{OpaqueNode, TNode, TRestyleDamage, UnsafeNode};
use dom::{OpaqueNode, TElement, TNode, TRestyleDamage, UnsafeNode};
use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
use selector_impl::SelectorImplExt;
use selectors::Element;
@ -13,6 +13,7 @@ use selectors::bloom::BloomFilter;
use std::cell::RefCell;
use tid::tid;
use util::opts;
use values::HasViewportPercentage;
/// Every time we do another layout, the old bloom filters are invalid. This is
/// detected by ticking a generation number every layout.
@ -244,5 +245,23 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C,
// NB: flow construction updates the bloom filter on the way up.
put_thread_local_bloom_filter(bf, &unsafe_layout_node, context.shared_context());
// Mark the node as DIRTY_ON_VIEWPORT_SIZE_CHANGE is it uses viewport percentage units.
match node.as_element() {
Some(element) => {
match *element.style_attribute() {
Some(ref property_declaration_block) => {
if property_declaration_block.declarations().any(|d| d.0.has_viewport_percentage()) {
unsafe {
node.set_dirty_on_viewport_size_changed();
}
node.set_descendants_dirty_on_viewport_size_changed();
}
},
None => {}
}
},
None => {}
}
}

View file

@ -82,6 +82,17 @@ pub type CSSFloat = f32;
pub const FONT_MEDIUM_PX: i32 = 16;
pub trait HasViewportPercentage {
fn has_viewport_percentage(&self) -> bool;
}
pub trait NoViewportPercentage {}
impl<T> HasViewportPercentage for T where T: NoViewportPercentage {
fn has_viewport_percentage(&self) -> bool {
false
}
}
pub mod specified {
use app_units::Au;
@ -94,11 +105,12 @@ pub mod specified {
use std::fmt;
use std::ops::Mul;
use style_traits::values::specified::AllowedNumericType;
use super::LocalToCss;
use super::computed::{TContext, ToComputedValue};
use super::{CSSFloat, FONT_MEDIUM_PX};
use super::{CSSFloat, FONT_MEDIUM_PX, HasViewportPercentage, LocalToCss, NoViewportPercentage};
use url::Url;
impl NoViewportPercentage for i32 {} // For PropertyDeclaration::Order
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct CSSColor {
@ -120,6 +132,8 @@ pub mod specified {
}
}
impl NoViewportPercentage for CSSColor {}
impl ToCss for CSSColor {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self.authored {
@ -136,6 +150,8 @@ pub mod specified {
pub authored: Option<String>,
}
impl NoViewportPercentage for CSSRGBA {}
impl ToCss for CSSRGBA {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self.authored {
@ -192,6 +208,12 @@ pub mod specified {
Vmax(CSSFloat)
}
impl HasViewportPercentage for ViewportPercentageLength {
fn has_viewport_percentage(&self) -> bool {
true
}
}
impl ToCss for ViewportPercentageLength {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -257,6 +279,15 @@ pub mod specified {
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for Length {
fn has_viewport_percentage(&self) -> bool {
match *self {
Length::ViewportPercentage(_) => true,
_ => false
}
}
}
impl ToCss for Length {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -875,6 +906,15 @@ pub mod specified {
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for LengthOrPercentage {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentage::Length(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentage {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -925,6 +965,15 @@ pub mod specified {
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for LengthOrPercentageOrAuto {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentageOrAuto::Length(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrAuto {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -975,6 +1024,15 @@ pub mod specified {
None,
}
impl HasViewportPercentage for LengthOrPercentageOrNone {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentageOrNone::Length(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrNone {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -1022,6 +1080,15 @@ pub mod specified {
None,
}
impl HasViewportPercentage for LengthOrNone {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrNone::Length(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrNone {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -1066,6 +1133,15 @@ pub mod specified {
Content
}
impl HasViewportPercentage for LengthOrPercentageOrAutoOrContent {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentageOrAutoOrContent::Length(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrAutoOrContent {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@ -1105,6 +1181,8 @@ pub mod specified {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
impl NoViewportPercentage for BorderRadiusSize {}
impl BorderRadiusSize {
pub fn zero() -> BorderRadiusSize {
let zero = LengthOrPercentage::Length(Length::Absolute(Au(0)));
@ -1145,6 +1223,16 @@ pub mod specified {
Top,
Bottom,
}
impl HasViewportPercentage for PositionComponent {
fn has_viewport_percentage(&self) -> bool {
match *self {
PositionComponent::LengthOrPercentage(length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl PositionComponent {
pub fn parse(input: &mut Parser) -> Result<PositionComponent, ()> {
input.try(LengthOrPercentage::parse)
@ -1433,6 +1521,8 @@ pub mod specified {
"outset" => outset = 2,
}
impl NoViewportPercentage for BorderStyle {}
impl BorderStyle {
pub fn none_or_hidden(&self) -> bool {
matches!(*self, BorderStyle::none | BorderStyle::hidden)
@ -1494,6 +1584,8 @@ pub mod specified {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Number(pub CSSFloat);
impl NoViewportPercentage for Number {}
impl Number {
pub fn parse(input: &mut Parser) -> Result<Number, ()> {
parse_number(input).map(Number)
@ -1532,6 +1624,8 @@ pub mod specified {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Opacity(pub CSSFloat);
impl NoViewportPercentage for Opacity {}
impl Opacity {
pub fn parse(input: &mut Parser) -> Result<Opacity, ()> {
parse_number(input).map(Opacity)
@ -1926,6 +2020,7 @@ pub mod computed {
Auto,
Content
}
impl fmt::Debug for LengthOrPercentageOrAutoOrContent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -1984,6 +2079,7 @@ pub mod computed {
Calc(CalcLengthOrPercentage),
None,
}
impl fmt::Debug for LengthOrPercentageOrNone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -2035,6 +2131,7 @@ pub mod computed {
Length(Au),
None,
}
impl fmt::Debug for LengthOrNone {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {

View file

@ -284,6 +284,17 @@ impl<'ln> TNode for GeckoNode<'ln> {
Gecko_GetNextSibling(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
}
}
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
// Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag,
// so we force them to be dirtied on viewport size change, regardless if
// they use viewport percentage size or not.
// TODO(shinglyu): implement this in Gecko: https://github.com/servo/servo/pull/11890
true
}
// TODO(shinglyu): implement this in Gecko: https://github.com/servo/servo/pull/11890
unsafe fn set_dirty_on_viewport_size_changed(&self) {}
}
#[derive(Clone, Copy)]

View file

@ -24,6 +24,7 @@ mod media_queries;
mod properties;
mod str;
mod stylesheets;
mod value;
mod viewport;
mod writing_modes {

View file

@ -2,6 +2,7 @@
* 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 cssparser::ToCss;
use rustc_serialize::json::Json;
use std::env;
@ -10,8 +11,10 @@ use std::path::Path;
use std::process::Command;
use std::sync::Arc;
use style::computed_values::display::T::inline_block;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue};
use style::values::specified::{Length, LengthOrPercentageOrAuto, LengthOrPercentage};
use style::properties::longhands::border_top_width;
use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock};
use style::values::HasViewportPercentage;
use style::values::specified::{Length, LengthOrPercentageOrAuto, LengthOrPercentage, ViewportPercentageLength};
#[test]
fn properties_list_json() {
@ -91,3 +94,21 @@ fn property_declaration_block_should_serialize_correctly() {
"width: 70px; min-height: 20px; display: inline-block; height: 20px !important;"
);
}
#[test]
fn has_viewport_percentage_for_specified_value() {
//TODO: test all specified value with a HasViewportPercentage impl
let pvw = PropertyDeclaration::BorderTopWidth(
DeclaredValue::Value(border_top_width::SpecifiedValue(
Length::ViewportPercentage(ViewportPercentageLength::Vw(100.))
))
);
assert!(pvw.has_viewport_percentage());
let pabs = PropertyDeclaration::BorderTopWidth(
DeclaredValue::Value(border_top_width::SpecifiedValue(
Length::Absolute(Au(100))
))
);
assert!(!pabs.has_viewport_percentage());
}

15
tests/unit/style/value.rs Normal file
View file

@ -0,0 +1,15 @@
/* 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 style::values::HasViewportPercentage;
use style::values::specified::{ViewportPercentageLength, Length};
#[test]
fn length_has_viewport_percentage() {
let l = Length::ViewportPercentage(ViewportPercentageLength::Vw(100.));
assert!(l.has_viewport_percentage());
let l = Length::Absolute(Au(100));
assert!(!l.has_viewport_percentage());
}