mirror of
https://github.com/servo/servo.git
synced 2025-07-24 07:40:27 +01:00
Implement getComputedStyle
This commit is contained in:
parent
416931f4be
commit
e484d6b5e3
24 changed files with 886 additions and 152 deletions
|
@ -618,7 +618,7 @@ impl BlockFlow {
|
||||||
|
|
||||||
pub fn transform_requires_layer(&self) -> bool {
|
pub fn transform_requires_layer(&self) -> bool {
|
||||||
// Check if the transform matrix is 2D or 3D
|
// Check if the transform matrix is 2D or 3D
|
||||||
if let Some(ref transform_list) = self.fragment.style().get_effects().transform {
|
if let Some(ref transform_list) = self.fragment.style().get_effects().transform.0 {
|
||||||
for transform in transform_list {
|
for transform in transform_list {
|
||||||
match transform {
|
match transform {
|
||||||
&transform::ComputedOperation::Perspective(..) => {
|
&transform::ComputedOperation::Perspective(..) => {
|
||||||
|
|
|
@ -1117,7 +1117,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode, flotation: float::T)
|
fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode, flotation: float::T)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let flotation = FloatKind::from_property(flotation);
|
let flotation = FloatKind::from_property(flotation);
|
||||||
let marker_fragment = match node.style().get_list().list_style_image {
|
let marker_fragment = match node.style().get_list().list_style_image.0 {
|
||||||
Some(ref url) => {
|
Some(ref url) => {
|
||||||
let image_info = box ImageFragmentInfo::new(node,
|
let image_info = box ImageFragmentInfo::new(node,
|
||||||
Some((*url).clone()),
|
Some((*url).clone()),
|
||||||
|
|
|
@ -361,7 +361,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
// Implements background image, per spec:
|
// Implements background image, per spec:
|
||||||
// http://www.w3.org/TR/CSS21/colors.html#background
|
// http://www.w3.org/TR/CSS21/colors.html#background
|
||||||
let background = style.get_background();
|
let background = style.get_background();
|
||||||
match background.background_image {
|
match background.background_image.0 {
|
||||||
None => {}
|
None => {}
|
||||||
Some(computed::Image::LinearGradient(ref gradient)) => {
|
Some(computed::Image::LinearGradient(ref gradient)) => {
|
||||||
self.build_display_list_for_background_linear_gradient(display_list,
|
self.build_display_list_for_background_linear_gradient(display_list,
|
||||||
|
@ -668,7 +668,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &ClippingRegion) {
|
clip: &ClippingRegion) {
|
||||||
// NB: According to CSS-BACKGROUNDS, box shadows render in *reverse* order (front to back).
|
// NB: According to CSS-BACKGROUNDS, box shadows render in *reverse* order (front to back).
|
||||||
for box_shadow in style.get_effects().box_shadow.iter().rev() {
|
for box_shadow in style.get_effects().box_shadow.0.iter().rev() {
|
||||||
let bounds = shadow_bounds(&absolute_bounds.translate(&Point2D::new(box_shadow.offset_x,
|
let bounds = shadow_bounds(&absolute_bounds.translate(&Point2D::new(box_shadow.offset_x,
|
||||||
box_shadow.offset_y)),
|
box_shadow.offset_y)),
|
||||||
box_shadow.blur_radius,
|
box_shadow.blur_radius,
|
||||||
|
@ -863,7 +863,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
-> ClippingRegion {
|
-> ClippingRegion {
|
||||||
// Account for `clip` per CSS 2.1 § 11.1.2.
|
// Account for `clip` per CSS 2.1 § 11.1.2.
|
||||||
let style_clip_rect = match (self.style().get_box().position,
|
let style_clip_rect = match (self.style().get_box().position,
|
||||||
self.style().get_effects().clip) {
|
self.style().get_effects().clip.0) {
|
||||||
(position::T::absolute, Some(style_clip_rect)) => style_clip_rect,
|
(position::T::absolute, Some(style_clip_rect)) => style_clip_rect,
|
||||||
_ => return (*parent_clip).clone(),
|
_ => return (*parent_clip).clone(),
|
||||||
};
|
};
|
||||||
|
@ -1147,7 +1147,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
|
|
||||||
let mut transform = Matrix4::identity();
|
let mut transform = Matrix4::identity();
|
||||||
|
|
||||||
if let Some(ref operations) = self.style().get_effects().transform {
|
if let Some(ref operations) = self.style().get_effects().transform.0 {
|
||||||
let transform_origin = self.style().get_effects().transform_origin;
|
let transform_origin = self.style().get_effects().transform_origin;
|
||||||
let transform_origin =
|
let transform_origin =
|
||||||
Point3D::new(model::specified(transform_origin.horizontal,
|
Point3D::new(model::specified(transform_origin.horizontal,
|
||||||
|
|
|
@ -1989,7 +1989,7 @@ impl Fragment {
|
||||||
if self.style().get_effects().mix_blend_mode != mix_blend_mode::T::normal {
|
if self.style().get_effects().mix_blend_mode != mix_blend_mode::T::normal {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if self.style().get_effects().transform.is_some() {
|
if self.style().get_effects().transform.0.is_some() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
match self.style().get_used_transform_style() {
|
match self.style().get_used_transform_style() {
|
||||||
|
@ -2036,7 +2036,7 @@ impl Fragment {
|
||||||
let mut overflow = border_box;
|
let mut overflow = border_box;
|
||||||
|
|
||||||
// Box shadows cause us to draw outside our border box.
|
// Box shadows cause us to draw outside our border box.
|
||||||
for box_shadow in self.style().get_effects().box_shadow.iter() {
|
for box_shadow in self.style().get_effects().box_shadow.0.iter() {
|
||||||
let offset = Point2D::new(box_shadow.offset_x, box_shadow.offset_y);
|
let offset = Point2D::new(box_shadow.offset_x, box_shadow.offset_y);
|
||||||
let inflation = box_shadow.spread_radius + box_shadow.blur_radius *
|
let inflation = box_shadow.spread_radius + box_shadow.blur_radius *
|
||||||
BLUR_INFLATION_FACTOR;
|
BLUR_INFLATION_FACTOR;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
use animation;
|
use animation;
|
||||||
use construct::ConstructionResult;
|
use construct::ConstructionResult;
|
||||||
use context::{SharedLayoutContext, heap_size_of_local_context};
|
use context::{SharedLayoutContext, heap_size_of_local_context};
|
||||||
|
use cssparser::ToCss;
|
||||||
use data::LayoutDataWrapper;
|
use data::LayoutDataWrapper;
|
||||||
use display_list_builder::ToGfxColor;
|
use display_list_builder::ToGfxColor;
|
||||||
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
|
@ -55,9 +56,10 @@ use script::dom::node::{LayoutData, Node};
|
||||||
use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse};
|
use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse};
|
||||||
use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse};
|
use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse};
|
||||||
use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType};
|
||||||
use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, ScriptReflow, TrustedNodeAddress};
|
||||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel};
|
use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel};
|
||||||
use script_traits::{ScriptControlChan, StylesheetLoadResponder};
|
use script_traits::{ScriptControlChan, StylesheetLoadResponder};
|
||||||
|
use selectors::parser::PseudoElement;
|
||||||
use serde::json;
|
use serde::json;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -67,20 +69,23 @@ use std::mem::transmute;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::mpsc::{channel, Sender, Receiver, Select};
|
use std::sync::mpsc::{channel, Sender, Receiver, Select};
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
use string_cache::Atom;
|
||||||
use style::computed_values::{filter, mix_blend_mode};
|
use style::computed_values::{filter, mix_blend_mode};
|
||||||
use style::media_queries::{MediaType, MediaQueryList, Device};
|
use style::media_queries::{MediaType, MediaQueryList, Device};
|
||||||
use style::properties::style_structs;
|
use style::properties::style_structs;
|
||||||
|
use style::properties::longhands::{display, position};
|
||||||
use style::selector_matching::Stylist;
|
use style::selector_matching::Stylist;
|
||||||
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
|
use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::cursor::Cursor;
|
use util::cursor::Cursor;
|
||||||
use util::geometry::{Au, MAX_RECT};
|
use util::geometry::{Au, MAX_RECT, ZERO_POINT};
|
||||||
use util::logical_geometry::LogicalPoint;
|
use util::logical_geometry::{LogicalPoint, WritingMode};
|
||||||
use util::mem::HeapSizeOf;
|
use util::mem::HeapSizeOf;
|
||||||
use util::opts;
|
use util::opts;
|
||||||
use util::task::spawn_named_with_send_on_failure;
|
use util::task::spawn_named_with_send_on_failure;
|
||||||
use util::task_state;
|
use util::task_state;
|
||||||
use util::workqueue::WorkQueue;
|
use util::workqueue::WorkQueue;
|
||||||
|
use wrapper::ThreadSafeLayoutNode;
|
||||||
|
|
||||||
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
||||||
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;
|
||||||
|
@ -129,6 +134,9 @@ pub struct LayoutTaskData {
|
||||||
/// A queued response for the client {top, left, width, height} of a node in pixels.
|
/// A queued response for the client {top, left, width, height} of a node in pixels.
|
||||||
pub client_rect_response: Rect<i32>,
|
pub client_rect_response: Rect<i32>,
|
||||||
|
|
||||||
|
/// A queued response for the resolved style property of an element.
|
||||||
|
pub resolved_style_response: Option<String>,
|
||||||
|
|
||||||
/// The list of currently-running animations.
|
/// The list of currently-running animations.
|
||||||
pub running_animations: Vec<Animation>,
|
pub running_animations: Vec<Animation>,
|
||||||
|
|
||||||
|
@ -372,6 +380,7 @@ impl LayoutTask {
|
||||||
content_box_response: Rect::zero(),
|
content_box_response: Rect::zero(),
|
||||||
content_boxes_response: Vec::new(),
|
content_boxes_response: Vec::new(),
|
||||||
client_rect_response: Rect::zero(),
|
client_rect_response: Rect::zero(),
|
||||||
|
resolved_style_response: None,
|
||||||
running_animations: Vec::new(),
|
running_animations: Vec::new(),
|
||||||
visible_rects: Arc::new(HashMap::with_hash_state(Default::default())),
|
visible_rects: Arc::new(HashMap::with_hash_state(Default::default())),
|
||||||
new_animations_receiver: new_animations_receiver,
|
new_animations_receiver: new_animations_receiver,
|
||||||
|
@ -864,6 +873,127 @@ impl LayoutTask {
|
||||||
rw_data.client_rect_response = iterator.client_rect;
|
rw_data.client_rect_response = iterator.client_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute the resolved value of property for a given (pseudo)element.
|
||||||
|
// Stores the result in rw_data.resolved_style_response.
|
||||||
|
// https://drafts.csswg.org/cssom/#resolved-value
|
||||||
|
fn process_resolved_style_request<'a>(&'a self,
|
||||||
|
requested_node: TrustedNodeAddress,
|
||||||
|
pseudo: &Option<PseudoElement>,
|
||||||
|
property: &Atom,
|
||||||
|
layout_root: &mut FlowRef,
|
||||||
|
rw_data: &mut RWGuard<'a>) {
|
||||||
|
// FIXME: Isolate this transmutation into a "bridge" module.
|
||||||
|
// FIXME(rust#16366): The following line had to be moved because of a
|
||||||
|
// rustc bug. It should be in the next unsafe block.
|
||||||
|
let node: LayoutJS<Node> = unsafe {
|
||||||
|
LayoutJS::from_trusted_node_address(requested_node)
|
||||||
|
};
|
||||||
|
let node: &LayoutNode = unsafe {
|
||||||
|
transmute(&node)
|
||||||
|
};
|
||||||
|
|
||||||
|
let layout_node = ThreadSafeLayoutNode::new(node);
|
||||||
|
let layout_node = match pseudo {
|
||||||
|
&Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
|
||||||
|
&Some(PseudoElement::After) => layout_node.get_after_pseudo(),
|
||||||
|
_ => Some(layout_node)
|
||||||
|
};
|
||||||
|
|
||||||
|
let layout_node = match layout_node {
|
||||||
|
None => {
|
||||||
|
// The pseudo doesn't exist, return nothing. Chrome seems to query
|
||||||
|
// the element itself in this case, Firefox uses the resolved value.
|
||||||
|
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006
|
||||||
|
rw_data.resolved_style_response = None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Some(layout_node) => layout_node
|
||||||
|
};
|
||||||
|
|
||||||
|
let style = &*layout_node.style();
|
||||||
|
|
||||||
|
let positioned = match style.get_box().position {
|
||||||
|
position::computed_value::T::relative |
|
||||||
|
/*position::computed_value::T::sticky |*/
|
||||||
|
position::computed_value::T::fixed |
|
||||||
|
position::computed_value::T::absolute => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: determine whether requested property applies to the element.
|
||||||
|
// eg. width does not apply to non-replaced inline elements.
|
||||||
|
// Existing browsers disagree about when left/top/right/bottom apply
|
||||||
|
// (Chrome seems to think they never apply and always returns resolved values).
|
||||||
|
// There are probably other quirks.
|
||||||
|
let applies = true;
|
||||||
|
|
||||||
|
// TODO: we will return neither the computed nor used value for margin and padding.
|
||||||
|
// Firefox returns blank strings for the computed value of shorthands,
|
||||||
|
// so this should be web-compatible.
|
||||||
|
match property.clone() {
|
||||||
|
atom!("margin-bottom") | atom!("margin-top") |
|
||||||
|
atom!("margin-left") | atom!("margin-right") |
|
||||||
|
atom!("padding-bottom") | atom!("padding-top") |
|
||||||
|
atom!("padding-left") | atom!("padding-right")
|
||||||
|
if applies && style.get_box().display != display::computed_value::T::none => {
|
||||||
|
let (margin_padding, side) = match *property {
|
||||||
|
atom!("margin-bottom") => (MarginPadding::Margin, Side::Bottom),
|
||||||
|
atom!("margin-top") => (MarginPadding::Margin, Side::Top),
|
||||||
|
atom!("margin-left") => (MarginPadding::Margin, Side::Left),
|
||||||
|
atom!("margin-right") => (MarginPadding::Margin, Side::Right),
|
||||||
|
atom!("padding-bottom") => (MarginPadding::Padding, Side::Bottom),
|
||||||
|
atom!("padding-top") => (MarginPadding::Padding, Side::Top),
|
||||||
|
atom!("padding-left") => (MarginPadding::Padding, Side::Left),
|
||||||
|
atom!("padding-right") => (MarginPadding::Padding, Side::Right),
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
|
let mut iterator =
|
||||||
|
MarginRetrievingFragmentBorderBoxIterator::new(requested_node,
|
||||||
|
side,
|
||||||
|
margin_padding,
|
||||||
|
style.writing_mode);
|
||||||
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
|
rw_data.resolved_style_response = iterator.result.map(|r| r.to_css_string());
|
||||||
|
},
|
||||||
|
|
||||||
|
atom!("bottom") | atom!("top") | atom!("right") |
|
||||||
|
atom!("left") | atom!("width") | atom!("height")
|
||||||
|
if applies && positioned && style.get_box().display != display::computed_value::T::none => {
|
||||||
|
let layout_data = layout_node.borrow_layout_data();
|
||||||
|
let position = layout_data.as_ref().map(|layout_data| {
|
||||||
|
match layout_data.data.flow_construction_result {
|
||||||
|
ConstructionResult::Flow(ref flow_ref, _) =>
|
||||||
|
flow::base(flow_ref.deref()).stacking_relative_position,
|
||||||
|
// TODO search parents until we find node with a flow ref.
|
||||||
|
_ => ZERO_POINT
|
||||||
|
}
|
||||||
|
}).unwrap_or(ZERO_POINT);
|
||||||
|
let property = match *property {
|
||||||
|
atom!("bottom") => PositionProperty::Bottom,
|
||||||
|
atom!("top") => PositionProperty::Top,
|
||||||
|
atom!("left") => PositionProperty::Left,
|
||||||
|
atom!("right") => PositionProperty::Right,
|
||||||
|
atom!("width") => PositionProperty::Width,
|
||||||
|
atom!("height") => PositionProperty::Height,
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
|
let mut iterator =
|
||||||
|
PositionRetrievingFragmentBorderBoxIterator::new(requested_node,
|
||||||
|
property,
|
||||||
|
position);
|
||||||
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
|
rw_data.resolved_style_response = iterator.result.map(|r| r.to_css_string());
|
||||||
|
},
|
||||||
|
// FIXME: implement used value computation for line-height
|
||||||
|
property => {
|
||||||
|
rw_data.resolved_style_response = style.computed_value_to_string(property.as_slice());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn compute_abs_pos_and_build_display_list<'a>(&'a self,
|
fn compute_abs_pos_and_build_display_list<'a>(&'a self,
|
||||||
data: &Reflow,
|
data: &Reflow,
|
||||||
layout_root: &mut FlowRef,
|
layout_root: &mut FlowRef,
|
||||||
|
@ -1052,15 +1182,14 @@ impl LayoutTask {
|
||||||
|
|
||||||
let mut root_flow = (*rw_data.root_flow.as_ref().unwrap()).clone();
|
let mut root_flow = (*rw_data.root_flow.as_ref().unwrap()).clone();
|
||||||
match data.query_type {
|
match data.query_type {
|
||||||
ReflowQueryType::ContentBoxQuery(node) => {
|
ReflowQueryType::ContentBoxQuery(node) =>
|
||||||
self.process_content_box_request(node, &mut root_flow, &mut rw_data)
|
self.process_content_box_request(node, &mut root_flow, &mut rw_data),
|
||||||
}
|
ReflowQueryType::ContentBoxesQuery(node) =>
|
||||||
ReflowQueryType::ContentBoxesQuery(node) => {
|
self.process_content_boxes_request(node, &mut root_flow, &mut rw_data),
|
||||||
self.process_content_boxes_request(node, &mut root_flow, &mut rw_data)
|
ReflowQueryType::NodeGeometryQuery(node) =>
|
||||||
}
|
self.process_node_geometry_request(node, &mut root_flow, &mut rw_data),
|
||||||
ReflowQueryType::NodeGeometryQuery(node) => {
|
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) =>
|
||||||
self.process_node_geometry_request(node, &mut root_flow, &mut rw_data)
|
self.process_resolved_style_request(node, pseudo, property, &mut root_flow, &mut rw_data),
|
||||||
}
|
|
||||||
ReflowQueryType::NoQuery => {}
|
ReflowQueryType::NoQuery => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,6 +1437,13 @@ impl LayoutRPC for LayoutRPCImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the resolved value for a CSS style property.
|
||||||
|
fn resolved_style(&self) -> ResolvedStyleResponse {
|
||||||
|
let &LayoutRPCImpl(ref rw_data) = self;
|
||||||
|
let rw_data = rw_data.lock().unwrap();
|
||||||
|
ResolvedStyleResponse(rw_data.resolved_style_response.clone())
|
||||||
|
}
|
||||||
|
|
||||||
/// Requests the node containing the point of interest.
|
/// Requests the node containing the point of interest.
|
||||||
fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
|
fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
|
||||||
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
|
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
|
||||||
|
@ -1459,6 +1595,108 @@ impl FragmentBorderBoxIterator for FragmentLocatingFragmentIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Side {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Bottom,
|
||||||
|
Top
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MarginPadding {
|
||||||
|
Margin,
|
||||||
|
Padding
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PositionProperty {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
Width,
|
||||||
|
Height,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PositionRetrievingFragmentBorderBoxIterator {
|
||||||
|
node_address: OpaqueNode,
|
||||||
|
result: Option<Au>,
|
||||||
|
position: Point2D<Au>,
|
||||||
|
property: PositionProperty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PositionRetrievingFragmentBorderBoxIterator {
|
||||||
|
fn new(node_address: OpaqueNode,
|
||||||
|
property: PositionProperty,
|
||||||
|
position: Point2D<Au>) -> PositionRetrievingFragmentBorderBoxIterator {
|
||||||
|
PositionRetrievingFragmentBorderBoxIterator {
|
||||||
|
node_address: node_address,
|
||||||
|
position: position,
|
||||||
|
property: property,
|
||||||
|
result: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FragmentBorderBoxIterator for PositionRetrievingFragmentBorderBoxIterator {
|
||||||
|
fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) {
|
||||||
|
self.result =
|
||||||
|
Some(match self.property {
|
||||||
|
PositionProperty::Left => self.position.x,
|
||||||
|
PositionProperty::Top => self.position.y,
|
||||||
|
PositionProperty::Width => border_box.size.width,
|
||||||
|
PositionProperty::Height => border_box.size.height,
|
||||||
|
// TODO: the following 2 calculations are completely wrong.
|
||||||
|
// They should return the difference between the parent's and this
|
||||||
|
// fragment's border boxes.
|
||||||
|
PositionProperty::Right => border_box.max_x() + self.position.x,
|
||||||
|
PositionProperty::Bottom => border_box.max_y() + self.position.y,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||||
|
fragment.contains_node(self.node_address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MarginRetrievingFragmentBorderBoxIterator {
|
||||||
|
node_address: OpaqueNode,
|
||||||
|
result: Option<Au>,
|
||||||
|
writing_mode: WritingMode,
|
||||||
|
margin_padding: MarginPadding,
|
||||||
|
side: Side,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MarginRetrievingFragmentBorderBoxIterator {
|
||||||
|
fn new(node_address: OpaqueNode, side: Side, margin_padding:
|
||||||
|
MarginPadding, writing_mode: WritingMode) -> MarginRetrievingFragmentBorderBoxIterator {
|
||||||
|
MarginRetrievingFragmentBorderBoxIterator {
|
||||||
|
node_address: node_address,
|
||||||
|
side: side,
|
||||||
|
margin_padding: margin_padding,
|
||||||
|
result: None,
|
||||||
|
writing_mode: writing_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator {
|
||||||
|
fn process(&mut self, fragment: &Fragment, _: &Rect<Au>) {
|
||||||
|
let rect = match self.margin_padding {
|
||||||
|
MarginPadding::Margin => &fragment.margin,
|
||||||
|
MarginPadding::Padding => &fragment.border_padding
|
||||||
|
};
|
||||||
|
self.result = Some(match self.side {
|
||||||
|
Side::Left => rect.left(self.writing_mode),
|
||||||
|
Side::Right => rect.right(self.writing_mode),
|
||||||
|
Side::Bottom => rect.bottom(self.writing_mode),
|
||||||
|
Side::Top => rect.top(self.writing_mode)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||||
|
fragment.contains_node(self.node_address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The default computed value for background-color is transparent (see
|
// The default computed value for background-color is transparent (see
|
||||||
// http://dev.w3.org/csswg/css-backgrounds/#background-color). However, we
|
// http://dev.w3.org/csswg/css-backgrounds/#background-color). However, we
|
||||||
// need to propagate the background color from the root HTML/Body
|
// need to propagate the background color from the root HTML/Body
|
||||||
|
|
|
@ -167,8 +167,8 @@ impl TextRunScanner {
|
||||||
white_space::T::pre => CompressionMode::CompressNone,
|
white_space::T::pre => CompressionMode::CompressNone,
|
||||||
};
|
};
|
||||||
text_transform = inherited_text_style.text_transform;
|
text_transform = inherited_text_style.text_transform;
|
||||||
letter_spacing = inherited_text_style.letter_spacing;
|
letter_spacing = inherited_text_style.letter_spacing.0;
|
||||||
word_spacing = inherited_text_style.word_spacing.unwrap_or(Au(0));
|
word_spacing = inherited_text_style.word_spacing.0.unwrap_or(Au(0));
|
||||||
text_rendering = inherited_text_style.text_rendering;
|
text_rendering = inherited_text_style.text_rendering;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ use msg::constellation_msg::ConstellationChan;
|
||||||
use net_traits::image::base::Image;
|
use net_traits::image::base::Image;
|
||||||
use profile_traits::mem::ProfilerChan;
|
use profile_traits::mem::ProfilerChan;
|
||||||
use util::str::{LengthOrPercentageOrAuto};
|
use util::str::{LengthOrPercentageOrAuto};
|
||||||
|
use selectors::parser::PseudoElement;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::{Cell, UnsafeCell, RefCell};
|
use std::cell::{Cell, UnsafeCell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
@ -304,6 +305,7 @@ no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
|
||||||
no_jsmanaged_fields!(RepetitionStyle);
|
no_jsmanaged_fields!(RepetitionStyle);
|
||||||
no_jsmanaged_fields!(WebGLError);
|
no_jsmanaged_fields!(WebGLError);
|
||||||
no_jsmanaged_fields!(ProfilerChan);
|
no_jsmanaged_fields!(ProfilerChan);
|
||||||
|
no_jsmanaged_fields!(PseudoElement);
|
||||||
|
|
||||||
impl JSTraceable for Box<ScriptChan+Send> {
|
impl JSTraceable for Box<ScriptChan+Send> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -11,9 +11,10 @@ use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||||
use dom::document::DocumentHelpers;
|
use dom::document::DocumentHelpers;
|
||||||
use dom::element::{ElementHelpers, StylePriority};
|
use dom::element::{ElementHelpers, StylePriority};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::{window_from_node, document_from_node, NodeDamage};
|
use dom::node::{window_from_node, document_from_node, NodeDamage, NodeHelpers};
|
||||||
use dom::window::{Window, WindowHelpers};
|
use dom::window::{Window, WindowHelpers};
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
use selectors::parser::PseudoElement;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style::properties::{is_supported_property, longhands_from_shorthand, parse_style_attribute};
|
use style::properties::{is_supported_property, longhands_from_shorthand, parse_style_attribute};
|
||||||
use style::properties::PropertyDeclaration;
|
use style::properties::PropertyDeclaration;
|
||||||
|
@ -27,6 +28,7 @@ pub struct CSSStyleDeclaration {
|
||||||
reflector_: Reflector,
|
reflector_: Reflector,
|
||||||
owner: JS<HTMLElement>,
|
owner: JS<HTMLElement>,
|
||||||
readonly: bool,
|
readonly: bool,
|
||||||
|
pseudo: Option<PseudoElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -56,17 +58,20 @@ fn serialize_list(list: &Vec<PropertyDeclaration>) -> DOMString {
|
||||||
|
|
||||||
impl CSSStyleDeclaration {
|
impl CSSStyleDeclaration {
|
||||||
pub fn new_inherited(owner: &HTMLElement,
|
pub fn new_inherited(owner: &HTMLElement,
|
||||||
|
pseudo: Option<PseudoElement>,
|
||||||
modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
|
modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
|
||||||
CSSStyleDeclaration {
|
CSSStyleDeclaration {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
owner: JS::from_ref(owner),
|
owner: JS::from_ref(owner),
|
||||||
|
pseudo: pseudo,
|
||||||
readonly: modification_access == CSSModificationAccess::Readonly,
|
readonly: modification_access == CSSModificationAccess::Readonly,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(global: &Window, owner: &HTMLElement,
|
pub fn new(global: &Window, owner: &HTMLElement,
|
||||||
|
pseudo: Option<PseudoElement>,
|
||||||
modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
|
modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
|
||||||
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, modification_access),
|
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, pseudo, modification_access),
|
||||||
GlobalRef::Window(global),
|
GlobalRef::Window(global),
|
||||||
CSSStyleDeclarationBinding::Wrap)
|
CSSStyleDeclarationBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +80,7 @@ impl CSSStyleDeclaration {
|
||||||
trait PrivateCSSStyleDeclarationHelpers {
|
trait PrivateCSSStyleDeclarationHelpers {
|
||||||
fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
|
fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
|
||||||
fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
|
fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
|
||||||
|
fn get_computed_style(self, property: &Atom) -> Option<DOMString>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PrivateCSSStyleDeclarationHelpers for &'a CSSStyleDeclaration {
|
impl<'a> PrivateCSSStyleDeclarationHelpers for &'a CSSStyleDeclaration {
|
||||||
|
@ -89,6 +95,13 @@ impl<'a> PrivateCSSStyleDeclarationHelpers for &'a CSSStyleDeclaration {
|
||||||
let element = ElementCast::from_ref(owner.r());
|
let element = ElementCast::from_ref(owner.r());
|
||||||
element.get_important_inline_style_declaration(property).map(|decl| decl.clone())
|
element.get_important_inline_style_declaration(property).map(|decl| decl.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_computed_style(self, property: &Atom) -> Option<DOMString> {
|
||||||
|
let owner = self.owner.root();
|
||||||
|
let node = NodeCast::from_ref(owner.r());
|
||||||
|
let addr = node.to_trusted_node_address();
|
||||||
|
window_from_node(owner.r()).resolved_style_query(addr, self.pseudo.clone(), property)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
||||||
|
@ -129,6 +142,11 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
||||||
// Step 1
|
// Step 1
|
||||||
let property = Atom::from_slice(&property.to_ascii_lowercase());
|
let property = Atom::from_slice(&property.to_ascii_lowercase());
|
||||||
|
|
||||||
|
if self.readonly {
|
||||||
|
// Readonly style declarations are used for getComputedStyle.
|
||||||
|
return self.get_computed_style(&property).unwrap_or("".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
let longhand_properties = longhands_from_shorthand(&property);
|
let longhand_properties = longhands_from_shorthand(&property);
|
||||||
if let Some(longhand_properties) = longhand_properties {
|
if let Some(longhand_properties) = longhand_properties {
|
||||||
|
|
|
@ -135,7 +135,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
||||||
fn Style(self) -> Root<CSSStyleDeclaration> {
|
fn Style(self) -> Root<CSSStyleDeclaration> {
|
||||||
self.style_decl.or_init(|| {
|
self.style_decl.or_init(|| {
|
||||||
let global = window_from_node(self);
|
let global = window_from_node(self);
|
||||||
CSSStyleDeclaration::new(global.r(), self, CSSModificationAccess::ReadWrite)
|
CSSStyleDeclaration::new(global.r(), self, None, CSSModificationAccess::ReadWrite)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,13 @@ partial interface Window {
|
||||||
/*[Replaceable]*/ readonly attribute Performance performance;
|
/*[Replaceable]*/ readonly attribute Performance performance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/cssom/#extensions-to-the-window-interface
|
||||||
|
partial interface Window {
|
||||||
|
//CSSStyleDeclaration getComputedStyle(Element elt, optional DOMString? pseudoElt);
|
||||||
|
[NewObject]
|
||||||
|
CSSStyleDeclaration getComputedStyle(HTMLElement elt, optional DOMString pseudoElt);
|
||||||
|
};
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface
|
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface
|
||||||
partial interface Window {
|
partial interface Window {
|
||||||
//MediaQueryList matchMedia(DOMString query);
|
//MediaQueryList matchMedia(DOMString query);
|
||||||
|
|
|
@ -20,9 +20,11 @@ use dom::bindings::utils::{GlobalStaticData, Reflectable, WindowProxyHandler};
|
||||||
use dom::browsercontext::BrowsingContext;
|
use dom::browsercontext::BrowsingContext;
|
||||||
use dom::console::Console;
|
use dom::console::Console;
|
||||||
use dom::crypto::Crypto;
|
use dom::crypto::Crypto;
|
||||||
|
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
|
||||||
use dom::document::{Document, DocumentHelpers};
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
||||||
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::location::Location;
|
use dom::location::Location;
|
||||||
use dom::navigator::Navigator;
|
use dom::navigator::Navigator;
|
||||||
use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers};
|
use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers};
|
||||||
|
@ -30,7 +32,7 @@ use dom::performance::Performance;
|
||||||
use dom::screen::Screen;
|
use dom::screen::Screen;
|
||||||
use dom::storage::Storage;
|
use dom::storage::Storage;
|
||||||
use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg};
|
use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg};
|
||||||
use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ScriptReflow};
|
use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ResolvedStyleResponse, ScriptReflow};
|
||||||
use page::Page;
|
use page::Page;
|
||||||
use script_task::{TimerSource, ScriptChan, ScriptPort, NonWorkerScriptChan};
|
use script_task::{TimerSource, ScriptChan, ScriptPort, NonWorkerScriptChan};
|
||||||
use script_task::ScriptMsg;
|
use script_task::ScriptMsg;
|
||||||
|
@ -47,6 +49,7 @@ use net_traits::ResourceTask;
|
||||||
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask};
|
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask};
|
||||||
use net_traits::storage_task::{StorageTask, StorageType};
|
use net_traits::storage_task::{StorageTask, StorageType};
|
||||||
use profile_traits::mem;
|
use profile_traits::mem;
|
||||||
|
use string_cache::Atom;
|
||||||
use util::geometry::{self, Au, MAX_RECT};
|
use util::geometry::{self, Au, MAX_RECT};
|
||||||
use util::{breakpoint, opts};
|
use util::{breakpoint, opts};
|
||||||
use util::str::{DOMString,HTML_SPACE_CHARACTERS};
|
use util::str::{DOMString,HTML_SPACE_CHARACTERS};
|
||||||
|
@ -58,10 +61,12 @@ use js::jsapi::{JSContext, HandleValue};
|
||||||
use js::jsapi::{JS_GC, JS_GetRuntime, JSAutoCompartment, JSAutoRequest};
|
use js::jsapi::{JS_GC, JS_GetRuntime, JSAutoCompartment, JSAutoRequest};
|
||||||
use js::rust::Runtime;
|
use js::rust::Runtime;
|
||||||
use js::rust::CompileOptionsWrapper;
|
use js::rust::CompileOptionsWrapper;
|
||||||
|
use selectors::parser::PseudoElement;
|
||||||
use url::{Url, UrlParser};
|
use url::{Url, UrlParser};
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD};
|
use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD};
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, Ref, RefMut, RefCell};
|
use std::cell::{Cell, Ref, RefMut, RefCell};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -539,6 +544,23 @@ impl<'a> WindowMethods for &'a Window {
|
||||||
chan.send(Err(WebDriverJSError::Timeout)).unwrap();
|
chan.send(Err(WebDriverJSError::Timeout)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle
|
||||||
|
fn GetComputedStyle(self,
|
||||||
|
element: &HTMLElement,
|
||||||
|
pseudo: Option<DOMString>) -> Root<CSSStyleDeclaration> {
|
||||||
|
// Steps 1-4.
|
||||||
|
let pseudo = match pseudo.map(|s| s.to_ascii_lowercase()) {
|
||||||
|
Some(ref pseudo) if pseudo == ":before" || pseudo == "::before" =>
|
||||||
|
Some(PseudoElement::Before),
|
||||||
|
Some(ref pseudo) if pseudo == ":after" || pseudo == "::after" =>
|
||||||
|
Some(PseudoElement::After),
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 5.
|
||||||
|
CSSStyleDeclaration::new(self, element, pseudo, CSSModificationAccess::Readonly)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WindowHelpers {
|
pub trait WindowHelpers {
|
||||||
|
@ -553,6 +575,8 @@ pub trait WindowHelpers {
|
||||||
fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au>;
|
fn content_box_query(self, content_box_request: TrustedNodeAddress) -> Rect<Au>;
|
||||||
fn content_boxes_query(self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>>;
|
fn content_boxes_query(self, content_boxes_request: TrustedNodeAddress) -> Vec<Rect<Au>>;
|
||||||
fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32>;
|
fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32>;
|
||||||
|
fn resolved_style_query(self, element: TrustedNodeAddress,
|
||||||
|
pseudo: Option<PseudoElement>, property: &Atom) -> Option<String>;
|
||||||
fn handle_reflow_complete_msg(self, reflow_id: u32);
|
fn handle_reflow_complete_msg(self, reflow_id: u32);
|
||||||
fn set_fragment_name(self, fragment: Option<String>);
|
fn set_fragment_name(self, fragment: Option<String>);
|
||||||
fn steal_fragment_name(self) -> Option<String>;
|
fn steal_fragment_name(self) -> Option<String>;
|
||||||
|
@ -791,6 +815,17 @@ impl<'a> WindowHelpers for &'a Window {
|
||||||
self.layout_rpc.node_geometry().client_rect
|
self.layout_rpc.node_geometry().client_rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolved_style_query(self,
|
||||||
|
element: TrustedNodeAddress,
|
||||||
|
pseudo: Option<PseudoElement>,
|
||||||
|
property: &Atom) -> Option<String> {
|
||||||
|
self.reflow(ReflowGoal::ForScriptQuery,
|
||||||
|
ReflowQueryType::ResolvedStyleQuery(element, pseudo, property.clone()),
|
||||||
|
ReflowReason::Query);
|
||||||
|
let ResolvedStyleResponse(resolved) = self.layout_rpc.resolved_style();
|
||||||
|
resolved
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_reflow_complete_msg(self, reflow_id: u32) {
|
fn handle_reflow_complete_msg(self, reflow_id: u32) {
|
||||||
let last_reflow_id = self.last_reflow_id.get();
|
let last_reflow_id = self.last_reflow_id.get();
|
||||||
if last_reflow_id == reflow_id {
|
if last_reflow_id == reflow_id {
|
||||||
|
@ -1098,6 +1133,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
|
||||||
ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
ReflowQueryType::ContentBoxQuery(_n) => "\tContentBoxQuery",
|
||||||
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
||||||
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
||||||
|
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
|
||||||
});
|
});
|
||||||
|
|
||||||
debug_msg.push_str(match *reason {
|
debug_msg.push_str(match *reason {
|
||||||
|
|
|
@ -21,8 +21,10 @@ use net_traits::PendingAsyncLoad;
|
||||||
use profile_traits::mem::ReportsChan;
|
use profile_traits::mem::ReportsChan;
|
||||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan};
|
use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan};
|
||||||
use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress};
|
use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress};
|
||||||
|
use selectors::parser::PseudoElement;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use string_cache::Atom;
|
||||||
use style::animation::PropertyAnimation;
|
use style::animation::PropertyAnimation;
|
||||||
use style::media_queries::MediaQueryList;
|
use style::media_queries::MediaQueryList;
|
||||||
use style::stylesheets::Stylesheet;
|
use style::stylesheets::Stylesheet;
|
||||||
|
@ -100,8 +102,11 @@ pub trait LayoutRPC {
|
||||||
/// Requests the node containing the point of interest
|
/// Requests the node containing the point of interest
|
||||||
fn hit_test(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()>;
|
fn hit_test(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()>;
|
||||||
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
||||||
|
/// Query layout for the resolved value of a given CSS property
|
||||||
|
fn resolved_style(&self) -> ResolvedStyleResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ContentBoxResponse(pub Rect<Au>);
|
pub struct ContentBoxResponse(pub Rect<Au>);
|
||||||
pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
|
pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
|
||||||
pub struct NodeGeometryResponse {
|
pub struct NodeGeometryResponse {
|
||||||
|
@ -109,6 +114,7 @@ pub struct NodeGeometryResponse {
|
||||||
}
|
}
|
||||||
pub struct HitTestResponse(pub UntrustedNodeAddress);
|
pub struct HitTestResponse(pub UntrustedNodeAddress);
|
||||||
pub struct MouseOverResponse(pub Vec<UntrustedNodeAddress>);
|
pub struct MouseOverResponse(pub Vec<UntrustedNodeAddress>);
|
||||||
|
pub struct ResolvedStyleResponse(pub Option<String>);
|
||||||
|
|
||||||
/// Why we're doing reflow.
|
/// Why we're doing reflow.
|
||||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||||
|
@ -126,6 +132,7 @@ pub enum ReflowQueryType {
|
||||||
ContentBoxQuery(TrustedNodeAddress),
|
ContentBoxQuery(TrustedNodeAddress),
|
||||||
ContentBoxesQuery(TrustedNodeAddress),
|
ContentBoxesQuery(TrustedNodeAddress),
|
||||||
NodeGeometryQuery(TrustedNodeAddress),
|
NodeGeometryQuery(TrustedNodeAddress),
|
||||||
|
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, Atom),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information needed for a reflow.
|
/// Information needed for a reflow.
|
||||||
|
|
|
@ -92,6 +92,14 @@ impl PropertyAnimation {
|
||||||
new_style.$structname().$field)
|
new_style.$structname().$field)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
TransitionProperty::Clip => {
|
||||||
|
AnimatedProperty::Clip(old_style.get_effects().clip.0,
|
||||||
|
new_style.get_effects().clip.0)
|
||||||
|
}
|
||||||
|
TransitionProperty::LetterSpacing => {
|
||||||
|
AnimatedProperty::LetterSpacing(old_style.get_inheritedtext().letter_spacing.0,
|
||||||
|
new_style.get_inheritedtext().letter_spacing.0)
|
||||||
|
}
|
||||||
TransitionProperty::TextShadow => {
|
TransitionProperty::TextShadow => {
|
||||||
AnimatedProperty::TextShadow(old_style.get_effects().text_shadow.clone(),
|
AnimatedProperty::TextShadow(old_style.get_effects().text_shadow.clone(),
|
||||||
new_style.get_effects().text_shadow.clone())
|
new_style.get_effects().text_shadow.clone())
|
||||||
|
@ -100,6 +108,10 @@ impl PropertyAnimation {
|
||||||
AnimatedProperty::Transform(old_style.get_effects().transform.clone(),
|
AnimatedProperty::Transform(old_style.get_effects().transform.clone(),
|
||||||
new_style.get_effects().transform.clone())
|
new_style.get_effects().transform.clone())
|
||||||
}
|
}
|
||||||
|
TransitionProperty::WordSpacing => {
|
||||||
|
AnimatedProperty::WordSpacing(old_style.get_inheritedtext().word_spacing.0,
|
||||||
|
new_style.get_inheritedtext().word_spacing.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,12 +129,10 @@ impl PropertyAnimation {
|
||||||
[BorderTopWidth; get_border; border_top_width],
|
[BorderTopWidth; get_border; border_top_width],
|
||||||
[Bottom; get_positionoffsets; bottom],
|
[Bottom; get_positionoffsets; bottom],
|
||||||
[Color; get_color; color],
|
[Color; get_color; color],
|
||||||
[Clip; get_effects; clip],
|
|
||||||
[FontSize; get_font; font_size],
|
[FontSize; get_font; font_size],
|
||||||
[FontWeight; get_font; font_weight],
|
[FontWeight; get_font; font_weight],
|
||||||
[Height; get_box; height],
|
[Height; get_box; height],
|
||||||
[Left; get_positionoffsets; bottom],
|
[Left; get_positionoffsets; bottom],
|
||||||
[LetterSpacing; get_inheritedtext; letter_spacing],
|
|
||||||
[LineHeight; get_inheritedbox; line_height],
|
[LineHeight; get_inheritedbox; line_height],
|
||||||
[MarginBottom; get_margin; margin_bottom],
|
[MarginBottom; get_margin; margin_bottom],
|
||||||
[MarginLeft; get_margin; margin_left],
|
[MarginLeft; get_margin; margin_left],
|
||||||
|
@ -145,7 +155,6 @@ impl PropertyAnimation {
|
||||||
[VerticalAlign; get_box; vertical_align],
|
[VerticalAlign; get_box; vertical_align],
|
||||||
[Visibility; get_inheritedbox; visibility],
|
[Visibility; get_inheritedbox; visibility],
|
||||||
[Width; get_box; width],
|
[Width; get_box; width],
|
||||||
[WordSpacing; get_inheritedtext; word_spacing],
|
|
||||||
[ZIndex; get_box; z_index]);
|
[ZIndex; get_box; z_index]);
|
||||||
|
|
||||||
let property_animation = PropertyAnimation {
|
let property_animation = PropertyAnimation {
|
||||||
|
@ -186,7 +195,22 @@ impl PropertyAnimation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
AnimatedProperty::Clip(ref start, ref end) => {
|
||||||
|
if let Some(value) = start.interpolate(end, progress) {
|
||||||
|
style.mutate_effects().clip.0 = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimatedProperty::LetterSpacing(ref start, ref end) => {
|
||||||
|
if let Some(value) = start.interpolate(end, progress) {
|
||||||
|
style.mutate_inheritedtext().letter_spacing.0 = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnimatedProperty::WordSpacing(ref start, ref end) => {
|
||||||
|
if let Some(value) = start.interpolate(end, progress) {
|
||||||
|
style.mutate_inheritedtext().word_spacing.0 = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
match_property!(
|
match_property!(
|
||||||
[BackgroundColor; mutate_background; background_color],
|
[BackgroundColor; mutate_background; background_color],
|
||||||
|
@ -202,12 +226,10 @@ impl PropertyAnimation {
|
||||||
[BorderTopWidth; mutate_border; border_top_width],
|
[BorderTopWidth; mutate_border; border_top_width],
|
||||||
[Bottom; mutate_positionoffsets; bottom],
|
[Bottom; mutate_positionoffsets; bottom],
|
||||||
[Color; mutate_color; color],
|
[Color; mutate_color; color],
|
||||||
[Clip; mutate_effects; clip],
|
|
||||||
[FontSize; mutate_font; font_size],
|
[FontSize; mutate_font; font_size],
|
||||||
[FontWeight; mutate_font; font_weight],
|
[FontWeight; mutate_font; font_weight],
|
||||||
[Height; mutate_box; height],
|
[Height; mutate_box; height],
|
||||||
[Left; mutate_positionoffsets; bottom],
|
[Left; mutate_positionoffsets; bottom],
|
||||||
[LetterSpacing; mutate_inheritedtext; letter_spacing],
|
|
||||||
[LineHeight; mutate_inheritedbox; line_height],
|
[LineHeight; mutate_inheritedbox; line_height],
|
||||||
[MarginBottom; mutate_margin; margin_bottom],
|
[MarginBottom; mutate_margin; margin_bottom],
|
||||||
[MarginLeft; mutate_margin; margin_left],
|
[MarginLeft; mutate_margin; margin_left],
|
||||||
|
@ -232,7 +254,6 @@ impl PropertyAnimation {
|
||||||
[VerticalAlign; mutate_box; vertical_align],
|
[VerticalAlign; mutate_box; vertical_align],
|
||||||
[Visibility; mutate_inheritedbox; visibility],
|
[Visibility; mutate_inheritedbox; visibility],
|
||||||
[Width; mutate_box; width],
|
[Width; mutate_box; width],
|
||||||
[WordSpacing; mutate_inheritedtext; word_spacing],
|
|
||||||
[ZIndex; mutate_box; z_index]);
|
[ZIndex; mutate_box; z_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,7 +786,7 @@ fn interpolate_transform_list(from_list: &Vec<TransformOperation>,
|
||||||
result.push_all(from_list);
|
result.push_all(from_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(result)
|
TransformList(Some(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build an equivalent 'identity transform function list' based
|
/// Build an equivalent 'identity transform function list' based
|
||||||
|
@ -809,7 +830,7 @@ impl Interpolate for TransformList {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interpolate(&self, other: &TransformList, time: f32) -> Option<TransformList> {
|
fn interpolate(&self, other: &TransformList, time: f32) -> Option<TransformList> {
|
||||||
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
|
||||||
let result = match (self, other) {
|
let result = match (&self.0, &other.0) {
|
||||||
(&Some(ref from_list), &Some(ref to_list)) => {
|
(&Some(ref from_list), &Some(ref to_list)) => {
|
||||||
// Two lists of transforms
|
// Two lists of transforms
|
||||||
interpolate_transform_list(from_list, &to_list, time)
|
interpolate_transform_list(from_list, &to_list, time)
|
||||||
|
@ -824,9 +845,9 @@ impl Interpolate for TransformList {
|
||||||
let from_list = build_identity_transform_list(to_list);
|
let from_list = build_identity_transform_list(to_list);
|
||||||
interpolate_transform_list(&from_list, to_list, time)
|
interpolate_transform_list(&from_list, to_list, time)
|
||||||
}
|
}
|
||||||
(&None, &None) => {
|
_ => {
|
||||||
// http://dev.w3.org/csswg/css-transforms/#none-none-animation
|
// http://dev.w3.org/csswg/css-transforms/#none-none-animation
|
||||||
None
|
TransformList(None)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -655,7 +655,16 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
computed_value::T::Normal => dest.write_str("normal"),
|
||||||
|
computed_value::T::Length(length) => length.to_css(dest),
|
||||||
|
computed_value::T::Number(number) => write!(dest, "{}", number),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
|
pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -749,6 +758,17 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl ::cssparser::ToCss for T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
% for keyword in vertical_align_keywords:
|
||||||
|
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
||||||
|
% endfor
|
||||||
|
T::Length(value) => value.to_css(dest),
|
||||||
|
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline }
|
pub fn get_initial_value() -> computed_value::T { computed_value::T::baseline }
|
||||||
|
@ -1067,7 +1087,20 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use url::Url;
|
use url::Url;
|
||||||
pub type T = Option<Url>;
|
use cssparser::{ToCss, Token};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<Url>);
|
||||||
|
|
||||||
|
impl ToCss for T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("none"),
|
||||||
|
Some(ref url) => Token::Url(url.to_string().into()).to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -1076,8 +1109,8 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::None => None,
|
SpecifiedValue::None => computed_value::T(None),
|
||||||
SpecifiedValue::Url(ref url) => Some(url.clone()),
|
SpecifiedValue::Url(ref url) => computed_value::T(Some(url.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1124,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
|
|
||||||
|
@ -1249,7 +1282,20 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use values::computed;
|
use values::computed;
|
||||||
pub type T = Option<computed::Image>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<computed::Image>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("none"),
|
||||||
|
Some(computed::Image::Url(ref url)) =>
|
||||||
|
::cssparser::Token::Url(url.to_string().into()).to_css(dest),
|
||||||
|
Some(computed::Image::LinearGradient(ref gradient)) =>
|
||||||
|
gradient.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
@ -1266,7 +1312,7 @@ pub mod longhands {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
|
@ -1281,8 +1327,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue(None) => None,
|
SpecifiedValue(None) => computed_value::T(None),
|
||||||
SpecifiedValue(Some(ref image)) => Some(image.to_computed_value(context)),
|
SpecifiedValue(Some(ref image)) =>
|
||||||
|
computed_value::T(Some(image.to_computed_value(context))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1318,6 +1365,15 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.horizontal.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.vertical.to_css(dest));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SpecifiedValue {
|
impl SpecifiedValue {
|
||||||
fn new(first: specified::PositionComponent, second: specified::PositionComponent)
|
fn new(first: specified::PositionComponent, second: specified::PositionComponent)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ()> {
|
||||||
|
@ -1424,6 +1480,16 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
computed_value::T::Explicit(ref size) => size.to_css(dest),
|
||||||
|
computed_value::T::Cover => dest.write_str("cover"),
|
||||||
|
computed_value::T::Contain => dest.write_str("contain"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub struct SpecifiedExplicitSize {
|
pub struct SpecifiedExplicitSize {
|
||||||
pub width: specified::LengthOrPercentageOrAuto,
|
pub width: specified::LengthOrPercentageOrAuto,
|
||||||
|
@ -1438,6 +1504,15 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::ExplicitSize {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.width.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
self.height.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
Explicit(SpecifiedExplicitSize),
|
Explicit(SpecifiedExplicitSize),
|
||||||
|
@ -1727,6 +1802,15 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
% for weight in range(100, 901, 100):
|
||||||
|
computed_value::T::Weight${weight} => dest.write_str("${weight}"),
|
||||||
|
% endfor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
computed_value::T::Weight400 // normal
|
computed_value::T::Weight400 // normal
|
||||||
|
@ -1909,12 +1993,22 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
pub type T = Option<Au>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<Au>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("normal"),
|
||||||
|
Some(l) => l.to_css(dest),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -1923,8 +2017,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Normal => None,
|
SpecifiedValue::Normal => computed_value::T(None),
|
||||||
SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
|
SpecifiedValue::Specified(l) =>
|
||||||
|
computed_value::T(Some(l.to_computed_value(context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1960,12 +2055,22 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
pub type T = Option<Au>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<Au>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("normal"),
|
||||||
|
Some(l) => l.to_css(dest),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -1974,8 +2079,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Normal => None,
|
SpecifiedValue::Normal => computed_value::T(None),
|
||||||
SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
|
SpecifiedValue::Specified(l) =>
|
||||||
|
computed_value::T(Some(l.to_computed_value(context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2098,7 +2204,9 @@ pub mod longhands {
|
||||||
|
|
||||||
<%self:longhand name="-servo-text-decorations-in-effect"
|
<%self:longhand name="-servo-text-decorations-in-effect"
|
||||||
derived_from="display text-decoration">
|
derived_from="display text-decoration">
|
||||||
use cssparser::RGBA;
|
use cssparser::{RGBA, ToCss};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
@ -2114,6 +2222,13 @@ pub mod longhands {
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::SpecifiedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for SpecifiedValue {
|
||||||
|
fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
// Web compat doesn't matter here.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
SpecifiedValue {
|
SpecifiedValue {
|
||||||
|
@ -2233,6 +2348,14 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.horizontal.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
self.vertical.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
type ComputedValue = computed_value::T;
|
type ComputedValue = computed_value::T;
|
||||||
|
|
||||||
|
@ -2370,12 +2493,22 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
pub type T = Option<Au>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<Au>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("auto"),
|
||||||
|
Some(l) => l.to_css(dest),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -2384,8 +2517,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Auto => None,
|
SpecifiedValue::Auto => computed_value::T(None),
|
||||||
SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
|
SpecifiedValue::Specified(l) =>
|
||||||
|
computed_value::T(Some(l.to_computed_value(context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2420,12 +2554,22 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = Option<u32>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<u32>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("auto"),
|
||||||
|
Some(count) => write!(dest, "{}", count),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -2434,8 +2578,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Auto => None,
|
SpecifiedValue::Auto => computed_value::T(None),
|
||||||
SpecifiedValue::Specified(count) => Some(count)
|
SpecifiedValue::Specified(count) =>
|
||||||
|
computed_value::T(Some(count))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2476,12 +2621,22 @@ pub mod longhands {
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
pub type T = Option<Au>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<Au>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("normal"),
|
||||||
|
Some(l) => l.to_css(dest),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -2490,8 +2645,9 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Normal => None,
|
SpecifiedValue::Normal => computed_value::T(None),
|
||||||
SpecifiedValue::Specified(l) => Some(l.to_computed_value(context))
|
SpecifiedValue::Specified(l) =>
|
||||||
|
computed_value::T(Some(l.to_computed_value(context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2611,7 +2767,8 @@ pub mod longhands {
|
||||||
use values::computed;
|
use values::computed;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub type T = Vec<BoxShadow>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Vec<BoxShadow>);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub struct BoxShadow {
|
pub struct BoxShadow {
|
||||||
|
@ -2635,9 +2792,44 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
let mut iter = self.0.iter();
|
||||||
|
if let Some(shadow) = iter.next() {
|
||||||
|
try!(shadow.to_css(dest));
|
||||||
|
} else {
|
||||||
|
try!(dest.write_str("none"));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
for shadow in iter {
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
try!(shadow.to_css(dest));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::BoxShadow {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
if self.inset {
|
||||||
|
try!(dest.write_str("inset "));
|
||||||
|
}
|
||||||
|
try!(self.blur_radius.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.spread_radius.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.offset_x.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.offset_y.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.color.to_css(dest));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
Vec::new()
|
computed_value::T(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
@ -2653,7 +2845,7 @@ pub mod longhands {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
self.0.iter().map(|value| compute_one_box_shadow(value, context)).collect()
|
computed_value::T(self.0.iter().map(|value| compute_one_box_shadow(value, context)).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2752,7 +2944,38 @@ pub mod longhands {
|
||||||
pub left: Au,
|
pub left: Au,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type T = Option<ClipRect>;
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub struct T(pub Option<ClipRect>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self.0 {
|
||||||
|
None => dest.write_str("auto"),
|
||||||
|
Some(rect) => {
|
||||||
|
try!(dest.write_str("rect("));
|
||||||
|
try!(rect.top.to_css(dest));
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
if let Some(right) = rect.right {
|
||||||
|
try!(right.to_css(dest));
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
} else {
|
||||||
|
try!(dest.write_str("auto, "));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bottom) = rect.bottom {
|
||||||
|
try!(bottom.to_css(dest));
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
} else {
|
||||||
|
try!(dest.write_str("auto, "));
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(rect.left.to_css(dest));
|
||||||
|
try!(dest.write_str(")"));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Copy)]
|
#[derive(Clone, Debug, PartialEq, Copy)]
|
||||||
|
@ -2780,7 +3003,7 @@ pub mod longhands {
|
||||||
try!(dest.write_str("auto, "));
|
try!(dest.write_str("auto, "));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(bottom) = self.right {
|
if let Some(bottom) = self.bottom {
|
||||||
try!(bottom.to_css(dest));
|
try!(bottom.to_css(dest));
|
||||||
try!(dest.write_str(", "));
|
try!(dest.write_str(", "));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2806,7 +3029,7 @@ pub mod longhands {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for SpecifiedValue {
|
impl ToComputedValue for SpecifiedValue {
|
||||||
|
@ -2814,12 +3037,12 @@ pub mod longhands {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
self.0.map(|value| computed_value::ClipRect {
|
computed_value::T(self.0.map(|value| computed_value::ClipRect {
|
||||||
top: value.top.to_computed_value(context),
|
top: value.top.to_computed_value(context),
|
||||||
right: value.right.map(|right| right.to_computed_value(context)),
|
right: value.right.map(|right| right.to_computed_value(context)),
|
||||||
bottom: value.bottom.map(|bottom| bottom.to_computed_value(context)),
|
bottom: value.bottom.map(|bottom| bottom.to_computed_value(context)),
|
||||||
left: value.left.to_computed_value(context),
|
left: value.left.to_computed_value(context),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2903,6 +3126,36 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
let mut iter = self.0.iter();
|
||||||
|
if let Some(shadow) = iter.next() {
|
||||||
|
try!(shadow.to_css(dest));
|
||||||
|
} else {
|
||||||
|
try!(dest.write_str("none"));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
for shadow in iter {
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
try!(shadow.to_css(dest));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::TextShadow {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.offset_x.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.offset_y.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.blur_radius.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.color.to_css(dest));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
let mut iter = self.0.iter();
|
let mut iter = self.0.iter();
|
||||||
|
@ -3103,6 +3356,23 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
let mut iter = self.filters.iter();
|
||||||
|
if let Some(filter) = iter.next() {
|
||||||
|
try!(filter.to_css(dest));
|
||||||
|
} else {
|
||||||
|
try!(dest.write_str("none"));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
for filter in iter {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(filter.to_css(dest));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
let mut iter = self.0.iter();
|
let mut iter = self.0.iter();
|
||||||
|
@ -3120,6 +3390,31 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::Filter {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
computed_value::Filter::Blur(value) => {
|
||||||
|
try!(dest.write_str("blur("));
|
||||||
|
try!(value.to_css(dest));
|
||||||
|
try!(dest.write_str(")"));
|
||||||
|
}
|
||||||
|
computed_value::Filter::Brightness(value) => try!(write!(dest, "brightness({})", value)),
|
||||||
|
computed_value::Filter::Contrast(value) => try!(write!(dest, "contrast({})", value)),
|
||||||
|
computed_value::Filter::Grayscale(value) => try!(write!(dest, "grayscale({})", value)),
|
||||||
|
computed_value::Filter::HueRotate(value) => {
|
||||||
|
try!(dest.write_str("hue-rotate("));
|
||||||
|
try!(value.to_css(dest));
|
||||||
|
try!(dest.write_str(")"));
|
||||||
|
}
|
||||||
|
computed_value::Filter::Invert(value) => try!(write!(dest, "invert({})", value)),
|
||||||
|
computed_value::Filter::Opacity(value) => try!(write!(dest, "opacity({})", value)),
|
||||||
|
computed_value::Filter::Saturate(value) => try!(write!(dest, "saturate({})", value)),
|
||||||
|
computed_value::Filter::Sepia(value) => try!(write!(dest, "sepia({})", value)),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedFilter {
|
impl ToCss for SpecifiedFilter {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -3253,7 +3548,8 @@ pub mod longhands {
|
||||||
Perspective(computed::Length),
|
Perspective(computed::Length),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type T = Option<Vec<ComputedOperation>>;
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct T(pub Option<Vec<ComputedOperation>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::computed_value::ComputedMatrix as SpecifiedMatrix;
|
pub use self::computed_value::ComputedMatrix as SpecifiedMatrix;
|
||||||
|
@ -3290,6 +3586,13 @@ pub mod longhands {
|
||||||
Perspective(specified::Length),
|
Perspective(specified::Length),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
// TODO(pcwalton)
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedOperation {
|
impl ToCss for SpecifiedOperation {
|
||||||
fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, _: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
// TODO(pcwalton)
|
// TODO(pcwalton)
|
||||||
|
@ -3316,7 +3619,7 @@ pub mod longhands {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
None
|
computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
|
@ -3548,7 +3851,7 @@ pub mod longhands {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
if self.0.is_empty() {
|
if self.0.is_empty() {
|
||||||
return None
|
return computed_value::T(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = vec!();
|
let mut result = vec!();
|
||||||
|
@ -3577,7 +3880,7 @@ pub mod longhands {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(result)
|
computed_value::T(Some(result))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
|
@ -3612,6 +3915,16 @@ pub mod longhands {
|
||||||
depth: Length,
|
depth: Length,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.horizontal.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(self.vertical.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
self.depth.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
impl ToCss for SpecifiedValue {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
try!(self.horizontal.to_css(dest));
|
try!(self.horizontal.to_css(dest));
|
||||||
|
@ -3742,6 +4055,14 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToCss for computed_value::T {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.horizontal.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
self.vertical.to_css(dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct SpecifiedValue {
|
pub struct SpecifiedValue {
|
||||||
horizontal: LengthOrPercentage,
|
horizontal: LengthOrPercentage,
|
||||||
|
@ -5542,7 +5863,7 @@ impl ComputedValues {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_multicol(&self) -> bool {
|
pub fn is_multicol(&self) -> bool {
|
||||||
let style = self.get_column();
|
let style = self.get_column();
|
||||||
style.column_count.is_some() || style.column_width.is_some()
|
style.column_count.0.is_some() || style.column_width.0.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -5560,13 +5881,13 @@ impl ComputedValues {
|
||||||
// TODO(gw): Add clip-path, isolation, mask-image, mask-border-source when supported.
|
// TODO(gw): Add clip-path, isolation, mask-image, mask-border-source when supported.
|
||||||
if effects.opacity < 1.0 ||
|
if effects.opacity < 1.0 ||
|
||||||
!effects.filter.is_empty() ||
|
!effects.filter.is_empty() ||
|
||||||
effects.clip.is_some() {
|
effects.clip.0.is_some() {
|
||||||
effects.mix_blend_mode != mix_blend_mode::T::normal ||
|
effects.mix_blend_mode != mix_blend_mode::T::normal ||
|
||||||
return transform_style::T::flat;
|
return transform_style::T::flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if effects.transform_style == transform_style::T::auto {
|
if effects.transform_style == transform_style::T::auto {
|
||||||
if effects.transform.is_some() {
|
if effects.transform.0.is_some() {
|
||||||
return transform_style::T::flat;
|
return transform_style::T::flat;
|
||||||
}
|
}
|
||||||
if effects.perspective != computed::LengthOrNone::None {
|
if effects.perspective != computed::LengthOrNone::None {
|
||||||
|
@ -5579,17 +5900,28 @@ impl ComputedValues {
|
||||||
}
|
}
|
||||||
|
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_${style_struct.name.lower()}
|
pub fn get_${style_struct.name.lower()}
|
||||||
<'a>(&'a self) -> &'a style_structs::${style_struct.name} {
|
<'a>(&'a self) -> &'a style_structs::${style_struct.name} {
|
||||||
&*self.${style_struct.ident}
|
&*self.${style_struct.ident}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mutate_${style_struct.name.lower()}
|
pub fn mutate_${style_struct.name.lower()}
|
||||||
<'a>(&'a mut self) -> &'a mut style_structs::${style_struct.name} {
|
<'a>(&'a mut self) -> &'a mut style_structs::${style_struct.name} {
|
||||||
&mut *Arc::make_unique(&mut self.${style_struct.ident})
|
&mut *Arc::make_unique(&mut self.${style_struct.ident})
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
|
pub fn computed_value_to_string(&self, name: &str) -> Option<String> {
|
||||||
|
match name {
|
||||||
|
% for style_struct in STYLE_STRUCTS:
|
||||||
|
% for longhand in style_struct.longhands:
|
||||||
|
"${longhand.name}" => Some(self.${style_struct.ident}.${longhand.ident}.to_css_string()),
|
||||||
|
% endfor
|
||||||
|
% endfor
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -975,6 +975,16 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for LengthOrPercentage {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self {
|
||||||
|
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||||
|
&LengthOrPercentage::Percentage(percentage)
|
||||||
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
|
@ -1010,6 +1020,17 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for LengthOrPercentageOrAuto {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self {
|
||||||
|
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
|
||||||
|
&LengthOrPercentageOrAuto::Percentage(percentage)
|
||||||
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
|
@ -1045,6 +1066,17 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for LengthOrPercentageOrNone {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self {
|
||||||
|
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
||||||
|
&LengthOrPercentageOrNone::Percentage(percentage) =>
|
||||||
|
write!(dest, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentageOrNone::None => dest.write_str("none"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
pub enum LengthOrNone {
|
pub enum LengthOrNone {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
|
@ -1075,6 +1107,15 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for LengthOrNone {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match self {
|
||||||
|
&LengthOrNone::Length(length) => length.to_css(dest),
|
||||||
|
&LengthOrNone::None => dest.write_str("none"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::Image {
|
impl ToComputedValue for specified::Image {
|
||||||
type ComputedValue = Image;
|
type ComputedValue = Image;
|
||||||
|
|
||||||
|
@ -1116,6 +1157,19 @@ pub mod computed {
|
||||||
pub stops: Vec<ColorStop>,
|
pub stops: Vec<ColorStop>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for LinearGradient {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(dest.write_str("linear-gradient("));
|
||||||
|
try!(self.angle_or_corner.to_css(dest));
|
||||||
|
for stop in self.stops.iter() {
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
try!(stop.to_css(dest));
|
||||||
|
}
|
||||||
|
try!(dest.write_str(")"));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for LinearGradient {
|
impl fmt::Debug for LinearGradient {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let _ = write!(f, "{:?}", self.angle_or_corner);
|
let _ = write!(f, "{:?}", self.angle_or_corner);
|
||||||
|
@ -1137,6 +1191,17 @@ pub mod computed {
|
||||||
pub position: Option<LengthOrPercentage>,
|
pub position: Option<LengthOrPercentage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for ColorStop {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
try!(self.color.to_css(dest));
|
||||||
|
if let Some(position) = self.position {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(position.to_css(dest));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ColorStop {
|
impl fmt::Debug for ColorStop {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let _ = write!(f, "{:?}", self.color);
|
let _ = write!(f, "{:?}", self.color);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use cssparser::ToCss;
|
||||||
|
|
||||||
use euclid::length::Length;
|
use euclid::length::Length;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use euclid::rect::Rect;
|
use euclid::rect::Rect;
|
||||||
|
@ -122,7 +124,14 @@ impl Encodable for Au {
|
||||||
impl fmt::Debug for Au {
|
impl fmt::Debug for Au {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}px", self.to_f64_px())
|
write!(f, "{}px", self.to_f64_px())
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Au {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
write!(dest, "{}px", self.to_f64_px())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Add for Au {
|
impl Add for Au {
|
||||||
type Output = Au;
|
type Output = Au;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
[events-006.htm]
|
[events-006.htm]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[transition padding-left on :before / events]
|
[transition padding-left on :before / events]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
[transition padding-left on :after / events]
|
[transition padding-left on :after / events]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
[pseudo-elements-001.htm]
|
[pseudo-elements-001.htm]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[transition padding-left on :before / values]
|
[transition padding-left on :before / values]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
[transition padding-left on :after / values]
|
[transition padding-left on :after / values]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
[transition padding-left on :before, changing content / values]
|
[transition padding-left on :before, changing content / values]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
[transition padding-left on :after, changing content / values]
|
[transition padding-left on :after, changing content / values]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
[Element-classlist.html]
|
|
||||||
type: testharness
|
|
||||||
[CSS .foo selectors must not match elements without any class]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[computed style must update when setting .className]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[classList.add must not cause the CSS selector to stop matching]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[classList.remove must not break case-sensitive CSS selector matching]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[classList.toggle must not break case-sensitive CSS selector matching]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[CSS class selectors must stop matching when all classes have been removed]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
[id-attribute.html]
|
|
||||||
type: testharness
|
|
||||||
[User agents must associate the element with an id value for purposes of CSS.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Association for CSS is exact and therefore case-sensitive.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Spaces are allowed in an id and still make an association.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Non-ASCII is allowed in an id and still make an association for CSS.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[After setting id via id attribute, CSS association is via the new ID.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[After setting id via setAttribute attribute, CSS association is via the new ID.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[del_effect.html]
|
|
||||||
type: testharness
|
|
||||||
[HTML Test: Text in the del element should be 'line-through']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[ins_effect.html]
|
|
||||||
type: testharness
|
|
||||||
[HTML Test: Text in the ins element should be 'underline']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -533,6 +533,12 @@
|
||||||
"url": "/_mozilla/mozilla/getBoundingClientRect.html"
|
"url": "/_mozilla/mozilla/getBoundingClientRect.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/getComputedStyle.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/getComputedStyle.html",
|
||||||
|
"url": "/_mozilla/mozilla/getComputedStyle.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/getPropertyPriority.html": [
|
"mozilla/getPropertyPriority.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/getPropertyPriority.html",
|
"path": "mozilla/getPropertyPriority.html",
|
||||||
|
@ -974,4 +980,4 @@
|
||||||
"rev": null,
|
"rev": null,
|
||||||
"url_base": "/_mozilla/",
|
"url_base": "/_mozilla/",
|
||||||
"version": 2
|
"version": 2
|
||||||
}
|
}
|
||||||
|
|
45
tests/wpt/mozilla/tests/mozilla/getComputedStyle.html
Normal file
45
tests/wpt/mozilla/tests/mozilla/getComputedStyle.html
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<style>
|
||||||
|
#foo:before {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foo {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="foo"></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var div = document.getElementById("foo");
|
||||||
|
var cs = getComputedStyle(div);
|
||||||
|
assert_equals(cs.getPropertyValue("left"), "auto");
|
||||||
|
assert_equals(cs.getPropertyValue("right"), "auto");
|
||||||
|
assert_equals(cs.getPropertyValue("top"), "auto");
|
||||||
|
assert_equals(cs.getPropertyValue("bottom"), "auto");
|
||||||
|
assert_equals(cs.getPropertyValue("width"), "50px");
|
||||||
|
assert_equals(cs.getPropertyValue("height"), "auto");
|
||||||
|
assert_equals(cs.getPropertyValue("color"), "rgb(0, 0, 0)");
|
||||||
|
}, "Element's resolved values");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var div = document.getElementById("foo");
|
||||||
|
assert_equals(getComputedStyle(div, ':before').getPropertyValue("color"), "rgb(255, 0, 0)");
|
||||||
|
assert_equals(getComputedStyle(div, '::before').getPropertyValue("color"), "rgb(255, 0, 0)");
|
||||||
|
}, "Existing :before pseudoelement");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var div = document.getElementById("foo");
|
||||||
|
assert_equals(getComputedStyle(div, ':after').getPropertyValue("color"), "");
|
||||||
|
assert_equals(getComputedStyle(div, '::after').getPropertyValue("color"), "");
|
||||||
|
}, "Missing :after pseudoelement");
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue