mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
layout: Implement basic style sharing.
No improvement on the rainbow page, but necessary for some other optimizations we want to do.
This commit is contained in:
parent
cf8203848a
commit
1678cc9a88
16 changed files with 502 additions and 274 deletions
|
@ -13,7 +13,7 @@ use layout::wrapper::LayoutNode;
|
||||||
use extra::arc::Arc;
|
use extra::arc::Arc;
|
||||||
use script::layout_interface::LayoutChan;
|
use script::layout_interface::LayoutChan;
|
||||||
use servo_util::smallvec::{SmallVec, SmallVec0, SmallVec16};
|
use servo_util::smallvec::{SmallVec, SmallVec0, SmallVec16};
|
||||||
use style::{After, Before, PropertyDeclaration, Stylist, TNode, cascade};
|
use style::{After, Before, ComputedValues, PropertyDeclaration, Stylist, TNode, cascade};
|
||||||
|
|
||||||
pub struct ApplicableDeclarations {
|
pub struct ApplicableDeclarations {
|
||||||
normal: SmallVec16<Arc<~[PropertyDeclaration]>>,
|
normal: SmallVec16<Arc<~[PropertyDeclaration]>>,
|
||||||
|
@ -43,12 +43,14 @@ pub trait MatchMethods {
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
layout_chan: &LayoutChan,
|
layout_chan: &LayoutChan,
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
applicable_declarations: &mut ApplicableDeclarations,
|
||||||
|
initial_values: &ComputedValues,
|
||||||
parent: Option<LayoutNode>);
|
parent: Option<LayoutNode>);
|
||||||
|
|
||||||
fn match_node(&self, stylist: &Stylist, applicable_declarations: &mut ApplicableDeclarations);
|
fn match_node(&self, stylist: &Stylist, applicable_declarations: &mut ApplicableDeclarations);
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
|
initial_values: &ComputedValues,
|
||||||
applicable_declarations: &ApplicableDeclarations);
|
applicable_declarations: &ApplicableDeclarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +81,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
layout_chan: &LayoutChan,
|
layout_chan: &LayoutChan,
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
applicable_declarations: &mut ApplicableDeclarations,
|
||||||
|
initial_values: &ComputedValues,
|
||||||
parent: Option<LayoutNode>) {
|
parent: Option<LayoutNode>) {
|
||||||
self.initialize_layout_data((*layout_chan).clone());
|
self.initialize_layout_data((*layout_chan).clone());
|
||||||
|
|
||||||
|
@ -87,7 +90,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.cascade_node(parent, applicable_declarations)
|
self.cascade_node(parent, initial_values, applicable_declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
applicable_declarations.clear();
|
applicable_declarations.clear();
|
||||||
|
@ -96,12 +99,14 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
kid.match_and_cascade_subtree(stylist,
|
kid.match_and_cascade_subtree(stylist,
|
||||||
layout_chan,
|
layout_chan,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
|
initial_values,
|
||||||
Some(*self))
|
Some(*self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
|
initial_values: &ComputedValues,
|
||||||
applicable_declarations: &ApplicableDeclarations) {
|
applicable_declarations: &ApplicableDeclarations) {
|
||||||
macro_rules! cascade_node(
|
macro_rules! cascade_node(
|
||||||
($applicable_declarations: expr, $style: ident) => {{
|
($applicable_declarations: expr, $style: ident) => {{
|
||||||
|
@ -124,30 +129,33 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let computed_values = match parent_style {
|
let computed_values = match parent_style {
|
||||||
Some(ref style) => {
|
Some(ref style) => {
|
||||||
Arc::new(cascade($applicable_declarations.as_slice(),
|
Arc::new(cascade($applicable_declarations.as_slice(),
|
||||||
Some(style.get())))
|
Some(style.get()),
|
||||||
}
|
initial_values))
|
||||||
None => Arc::new(cascade($applicable_declarations.as_slice(), None)),
|
}
|
||||||
};
|
None => Arc::new(cascade($applicable_declarations.as_slice(),
|
||||||
|
None,
|
||||||
let mut layout_data_ref = self.mutate_layout_data();
|
initial_values)),
|
||||||
match *layout_data_ref.get() {
|
};
|
||||||
None => fail!("no layout data"),
|
|
||||||
Some(ref mut layout_data) => {
|
let mut layout_data_ref = self.mutate_layout_data();
|
||||||
let style = &mut layout_data.data.$style;
|
match *layout_data_ref.get() {
|
||||||
match *style {
|
None => fail!("no layout data"),
|
||||||
None => (),
|
Some(ref mut layout_data) => {
|
||||||
Some(ref previous_style) => {
|
let style = &mut layout_data.data.$style;
|
||||||
layout_data.data.restyle_damage = Some(incremental::compute_damage(
|
match *style {
|
||||||
previous_style.get(), computed_values.get()).to_int())
|
None => (),
|
||||||
}
|
Some(ref previous_style) => {
|
||||||
}
|
layout_data.data.restyle_damage = Some(incremental::compute_damage(
|
||||||
*style = Some(computed_values)
|
previous_style.get(), computed_values.get()).to_int())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
*style = Some(computed_values)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
|
|
|
@ -88,7 +88,12 @@ u, ins { text-decoration: underline }
|
||||||
br:before { content: "\A"; white-space: pre-line }
|
br:before { content: "\A"; white-space: pre-line }
|
||||||
|
|
||||||
center { text-align: center }
|
center { text-align: center }
|
||||||
:link, :visited { text-decoration: underline }
|
a:link,
|
||||||
|
a:visited,
|
||||||
|
area:link,
|
||||||
|
area:visited,
|
||||||
|
link:link,
|
||||||
|
link:visited { text-decoration: underline }
|
||||||
:focus { outline: thin dotted invert }
|
:focus { outline: thin dotted invert }
|
||||||
|
|
||||||
/* Begin bidirectionality settings (do not change) */
|
/* Begin bidirectionality settings (do not change) */
|
||||||
|
@ -106,6 +111,8 @@ ul, ol, dl { page-break-before: avoid }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Servo additions */
|
/* Servo additions */
|
||||||
:link { color: blue }
|
a:link,
|
||||||
|
area:link,
|
||||||
|
link:link { color: blue }
|
||||||
script { display: none }
|
script { display: none }
|
||||||
style { display: none }
|
style { display: none }
|
||||||
|
|
|
@ -193,9 +193,9 @@ impl BlockFlow {
|
||||||
let style = box_.style();
|
let style = box_.style();
|
||||||
|
|
||||||
let (width, maybe_margin_left, maybe_margin_right) =
|
let (width, maybe_margin_left, maybe_margin_right) =
|
||||||
(MaybeAuto::from_style(style.Box.width, remaining_width),
|
(MaybeAuto::from_style(style.Box.get().width, remaining_width),
|
||||||
MaybeAuto::from_style(style.Margin.margin_left, remaining_width),
|
MaybeAuto::from_style(style.Margin.get().margin_left, remaining_width),
|
||||||
MaybeAuto::from_style(style.Margin.margin_right, remaining_width));
|
MaybeAuto::from_style(style.Margin.get().margin_right, remaining_width));
|
||||||
|
|
||||||
let (width, margin_left, margin_right) = self.compute_horiz(width,
|
let (width, margin_left, margin_right) = self.compute_horiz(width,
|
||||||
maybe_margin_left,
|
maybe_margin_left,
|
||||||
|
@ -206,7 +206,7 @@ impl BlockFlow {
|
||||||
// If the tentative used width is greater than 'max-width', width should be recalculated,
|
// If the tentative used width is greater than 'max-width', width should be recalculated,
|
||||||
// but this time using the computed value of 'max-width' as the computed value for 'width'.
|
// but this time using the computed value of 'max-width' as the computed value for 'width'.
|
||||||
let (width, margin_left, margin_right) = {
|
let (width, margin_left, margin_right) = {
|
||||||
match specified_or_none(style.Box.max_width, remaining_width) {
|
match specified_or_none(style.Box.get().max_width, remaining_width) {
|
||||||
Some(value) if value < width => self.compute_horiz(Specified(value),
|
Some(value) if value < width => self.compute_horiz(Specified(value),
|
||||||
maybe_margin_left,
|
maybe_margin_left,
|
||||||
maybe_margin_right,
|
maybe_margin_right,
|
||||||
|
@ -218,7 +218,7 @@ impl BlockFlow {
|
||||||
// If the resulting width is smaller than 'min-width', width should be recalculated,
|
// If the resulting width is smaller than 'min-width', width should be recalculated,
|
||||||
// but this time using the value of 'min-width' as the computed value for 'width'.
|
// but this time using the value of 'min-width' as the computed value for 'width'.
|
||||||
let (width, margin_left, margin_right) = {
|
let (width, margin_left, margin_right) = {
|
||||||
let computed_min_width = specified(style.Box.min_width, remaining_width);
|
let computed_min_width = specified(style.Box.get().min_width, remaining_width);
|
||||||
if computed_min_width > width {
|
if computed_min_width > width {
|
||||||
self.compute_horiz(Specified(computed_min_width),
|
self.compute_horiz(Specified(computed_min_width),
|
||||||
maybe_margin_left,
|
maybe_margin_left,
|
||||||
|
@ -235,13 +235,13 @@ impl BlockFlow {
|
||||||
// CSS Section 10.3.5
|
// CSS Section 10.3.5
|
||||||
fn compute_float_margins(&self, box_: &Box, remaining_width: Au) -> (Au, Au, Au) {
|
fn compute_float_margins(&self, box_: &Box, remaining_width: Au) -> (Au, Au, Au) {
|
||||||
let style = box_.style();
|
let style = box_.style();
|
||||||
let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
|
let margin_left = MaybeAuto::from_style(style.Margin.get().margin_left,
|
||||||
remaining_width).specified_or_zero();
|
remaining_width).specified_or_zero();
|
||||||
let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
|
let margin_right = MaybeAuto::from_style(style.Margin.get().margin_right,
|
||||||
remaining_width).specified_or_zero();
|
remaining_width).specified_or_zero();
|
||||||
let shrink_to_fit = geometry::min(self.base.pref_width,
|
let shrink_to_fit = geometry::min(self.base.pref_width,
|
||||||
geometry::max(self.base.min_width, remaining_width));
|
geometry::max(self.base.min_width, remaining_width));
|
||||||
let width = MaybeAuto::from_style(style.Box.width,
|
let width = MaybeAuto::from_style(style.Box.get().width,
|
||||||
remaining_width).specified_or_default(shrink_to_fit);
|
remaining_width).specified_or_default(shrink_to_fit);
|
||||||
debug!("assign_widths_float -- width: {}", width);
|
debug!("assign_widths_float -- width: {}", width);
|
||||||
return (width, margin_left, margin_right);
|
return (width, margin_left, margin_right);
|
||||||
|
@ -376,7 +376,7 @@ impl BlockFlow {
|
||||||
// block per CSS 2.1 § 10.5.
|
// block per CSS 2.1 § 10.5.
|
||||||
// TODO: We need to pass in the correct containing block height
|
// TODO: We need to pass in the correct containing block height
|
||||||
// for absolutely positioned elems
|
// for absolutely positioned elems
|
||||||
height = match MaybeAuto::from_style(style.Box.height, height) {
|
height = match MaybeAuto::from_style(style.Box.get().height, height) {
|
||||||
Auto => height,
|
Auto => height,
|
||||||
Specified(value) => value
|
Specified(value) => value
|
||||||
};
|
};
|
||||||
|
@ -516,7 +516,7 @@ impl BlockFlow {
|
||||||
box_.border.get().top + box_.border.get().bottom;
|
box_.border.get().top + box_.border.get().bottom;
|
||||||
|
|
||||||
//TODO(eatkinson): compute heights properly using the 'height' property.
|
//TODO(eatkinson): compute heights properly using the 'height' property.
|
||||||
let height_prop = MaybeAuto::from_style(box_.style().Box.height,
|
let height_prop = MaybeAuto::from_style(box_.style().Box.get().height,
|
||||||
Au::new(0)).specified_or_zero();
|
Au::new(0)).specified_or_zero();
|
||||||
|
|
||||||
height = geometry::max(height, height_prop) + noncontent_height;
|
height = geometry::max(height, height_prop) + noncontent_height;
|
||||||
|
@ -719,7 +719,7 @@ impl Flow for BlockFlow {
|
||||||
let style = box_.style();
|
let style = box_.style();
|
||||||
|
|
||||||
// The text alignment of a block flow is the text alignment of its box's style.
|
// The text alignment of a block flow is the text alignment of its box's style.
|
||||||
self.base.flags_info.flags.set_text_align(style.InheritedText.text_align);
|
self.base.flags_info.flags.set_text_align(style.InheritedText.get().text_align);
|
||||||
|
|
||||||
box_.assign_width(remaining_width);
|
box_.assign_width(remaining_width);
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
|
@ -729,9 +729,9 @@ impl Flow for BlockFlow {
|
||||||
let available_width = remaining_width - box_.noncontent_width();
|
let available_width = remaining_width - box_.noncontent_width();
|
||||||
|
|
||||||
// Top and bottom margins for blocks are 0 if auto.
|
// Top and bottom margins for blocks are 0 if auto.
|
||||||
let margin_top = MaybeAuto::from_style(style.Margin.margin_top,
|
let margin_top = MaybeAuto::from_style(style.Margin.get().margin_top,
|
||||||
remaining_width).specified_or_zero();
|
remaining_width).specified_or_zero();
|
||||||
let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom,
|
let margin_bottom = MaybeAuto::from_style(style.Margin.get().margin_bottom,
|
||||||
remaining_width).specified_or_zero();
|
remaining_width).specified_or_zero();
|
||||||
|
|
||||||
let (width, margin_left, margin_right) = if self.is_float() {
|
let (width, margin_left, margin_right) = if self.is_float() {
|
||||||
|
|
|
@ -373,7 +373,7 @@ impl Box {
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
y = position_offsets.top;
|
y = position_offsets.top;
|
||||||
match MaybeAuto::from_style(self.style().Box.height, Au(0)) {
|
match MaybeAuto::from_style(self.style().Box.get().height, Au(0)) {
|
||||||
Auto => {
|
Auto => {
|
||||||
height = screen_height - position_offsets.top - position_offsets.bottom;
|
height = screen_height - position_offsets.top - position_offsets.bottom;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ impl Box {
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
x = position_offsets.left;
|
x = position_offsets.left;
|
||||||
match MaybeAuto::from_style(self.style().Box.width, Au(0)) {
|
match MaybeAuto::from_style(self.style().Box.get().width, Au(0)) {
|
||||||
Auto => {
|
Auto => {
|
||||||
width = screen_width - position_offsets.left - position_offsets.right;
|
width = screen_width - position_offsets.left - position_offsets.right;
|
||||||
}
|
}
|
||||||
|
@ -446,14 +446,14 @@ impl Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let width = MaybeAuto::from_style(style.Box.width, Au::new(0)).specified_or_zero();
|
let width = MaybeAuto::from_style(style.Box.get().width, Au::new(0)).specified_or_zero();
|
||||||
let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
|
let margin_left = MaybeAuto::from_style(style.Margin.get().margin_left,
|
||||||
Au::new(0)).specified_or_zero();
|
Au::new(0)).specified_or_zero();
|
||||||
let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
|
let margin_right = MaybeAuto::from_style(style.Margin.get().margin_right,
|
||||||
Au::new(0)).specified_or_zero();
|
Au::new(0)).specified_or_zero();
|
||||||
|
|
||||||
let padding_left = self.compute_padding_length(style.Padding.padding_left, Au::new(0));
|
let padding_left = self.compute_padding_length(style.Padding.get().padding_left, Au(0));
|
||||||
let padding_right = self.compute_padding_length(style.Padding.padding_right, Au::new(0));
|
let padding_right = self.compute_padding_length(style.Padding.get().padding_right, Au(0));
|
||||||
|
|
||||||
width + margin_left + margin_right + padding_left + padding_right +
|
width + margin_left + margin_right + padding_left + padding_right +
|
||||||
self.border.get().left + self.border.get().right
|
self.border.get().left + self.border.get().right
|
||||||
|
@ -480,37 +480,45 @@ impl Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.border.set(SideOffsets2D::new(width(style.Border.border_top_width,
|
self.border.set(SideOffsets2D::new(width(style.Border.get().border_top_width,
|
||||||
style.Border.border_top_style),
|
style.Border.get().border_top_style),
|
||||||
width(style.Border.border_right_width,
|
width(style.Border.get().border_right_width,
|
||||||
style.Border.border_right_style),
|
style.Border.get().border_right_style),
|
||||||
width(style.Border.border_bottom_width,
|
width(style.Border.get().border_bottom_width,
|
||||||
style.Border.border_bottom_style),
|
style.Border.get().border_bottom_style),
|
||||||
width(style.Border.border_left_width,
|
width(style.Border.get().border_left_width,
|
||||||
style.Border.border_left_style)))
|
style.Border.get().border_left_style)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_positioned_offsets(&self, style: &ComputedValues, containing_width: Au, containing_height: Au) {
|
pub fn compute_positioned_offsets(&self, style: &ComputedValues, containing_width: Au, containing_height: Au) {
|
||||||
self.position_offsets.set(SideOffsets2D::new(
|
self.position_offsets.set(SideOffsets2D::new(
|
||||||
MaybeAuto::from_style(style.PositionOffsets.top, containing_height)
|
MaybeAuto::from_style(style.PositionOffsets.get().top, containing_height)
|
||||||
.specified_or_zero(),
|
.specified_or_zero(),
|
||||||
MaybeAuto::from_style(style.PositionOffsets.right, containing_width)
|
MaybeAuto::from_style(style.PositionOffsets.get().right, containing_width)
|
||||||
.specified_or_zero(),
|
.specified_or_zero(),
|
||||||
MaybeAuto::from_style(style.PositionOffsets.bottom, containing_height)
|
MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_height)
|
||||||
.specified_or_zero(),
|
.specified_or_zero(),
|
||||||
MaybeAuto::from_style(style.PositionOffsets.left, containing_width)
|
MaybeAuto::from_style(style.PositionOffsets.get().left, containing_width)
|
||||||
.specified_or_zero()));
|
.specified_or_zero()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Populates the box model padding parameters from the given computed style.
|
/// Populates the box model padding parameters from the given computed style.
|
||||||
pub fn compute_padding(&self, style: &ComputedValues, containing_block_width: Au) {
|
pub fn compute_padding(&self, style: &ComputedValues, containing_block_width: Au) {
|
||||||
let padding = SideOffsets2D::new(self.compute_padding_length(style.Padding.padding_top,
|
let padding = SideOffsets2D::new(self.compute_padding_length(style.Padding
|
||||||
|
.get()
|
||||||
|
.padding_top,
|
||||||
containing_block_width),
|
containing_block_width),
|
||||||
self.compute_padding_length(style.Padding.padding_right,
|
self.compute_padding_length(style.Padding
|
||||||
|
.get()
|
||||||
|
.padding_right,
|
||||||
containing_block_width),
|
containing_block_width),
|
||||||
self.compute_padding_length(style.Padding.padding_bottom,
|
self.compute_padding_length(style.Padding
|
||||||
|
.get()
|
||||||
|
.padding_bottom,
|
||||||
containing_block_width),
|
containing_block_width),
|
||||||
self.compute_padding_length(style.Padding.padding_left,
|
self.compute_padding_length(style.Padding
|
||||||
|
.get()
|
||||||
|
.padding_left,
|
||||||
containing_block_width));
|
containing_block_width));
|
||||||
self.padding.set(padding)
|
self.padding.set(padding)
|
||||||
}
|
}
|
||||||
|
@ -679,28 +687,28 @@ impl Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn relative_position(&self, container_block_size: &Size2D<Au>) -> Point2D<Au> {
|
pub fn relative_position(&self, container_block_size: &Size2D<Au>) -> Point2D<Au> {
|
||||||
fn left_right(style: &ComputedValues,block_width: Au) -> Au {
|
fn left_right(style: &ComputedValues, block_width: Au) -> Au {
|
||||||
// TODO(ksh8281) : consider RTL(right-to-left) culture
|
// TODO(ksh8281) : consider RTL(right-to-left) culture
|
||||||
match (style.PositionOffsets.left, style.PositionOffsets.right) {
|
match (style.PositionOffsets.get().left, style.PositionOffsets.get().right) {
|
||||||
(LPA_Auto, _) => {
|
(LPA_Auto, _) => {
|
||||||
-MaybeAuto::from_style(style.PositionOffsets.right, block_width)
|
-MaybeAuto::from_style(style.PositionOffsets.get().right, block_width)
|
||||||
.specified_or_zero()
|
.specified_or_zero()
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
MaybeAuto::from_style(style.PositionOffsets.left, block_width)
|
MaybeAuto::from_style(style.PositionOffsets.get().left, block_width)
|
||||||
.specified_or_zero()
|
.specified_or_zero()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn top_bottom(style: &ComputedValues,block_height: Au) -> Au {
|
fn top_bottom(style: &ComputedValues,block_height: Au) -> Au {
|
||||||
match (style.PositionOffsets.top, style.PositionOffsets.bottom) {
|
match (style.PositionOffsets.get().top, style.PositionOffsets.get().bottom) {
|
||||||
(LPA_Auto, _) => {
|
(LPA_Auto, _) => {
|
||||||
-MaybeAuto::from_style(style.PositionOffsets.bottom, block_height)
|
-MaybeAuto::from_style(style.PositionOffsets.get().bottom, block_height)
|
||||||
.specified_or_zero()
|
.specified_or_zero()
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
MaybeAuto::from_style(style.PositionOffsets.top, block_height)
|
MaybeAuto::from_style(style.PositionOffsets.get().top, block_height)
|
||||||
.specified_or_zero()
|
.specified_or_zero()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,7 +719,7 @@ impl Box {
|
||||||
y: Au::new(0),
|
y: Au::new(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.style().Box.position == position::relative {
|
if self.style().Box.get().position == position::relative {
|
||||||
rel_pos.x = rel_pos.x + left_right(self.style(), container_block_size.width);
|
rel_pos.x = rel_pos.x + left_right(self.style(), container_block_size.width);
|
||||||
rel_pos.y = rel_pos.y + top_bottom(self.style(), container_block_size.height);
|
rel_pos.y = rel_pos.y + top_bottom(self.style(), container_block_size.height);
|
||||||
}
|
}
|
||||||
|
@ -720,9 +728,11 @@ impl Box {
|
||||||
match info.get() {
|
match info.get() {
|
||||||
&Some(ref info) => {
|
&Some(ref info) => {
|
||||||
for info in info.parent_info.iter() {
|
for info in info.parent_info.iter() {
|
||||||
if info.style.get().Box.position == position::relative {
|
if info.style.get().Box.get().position == position::relative {
|
||||||
rel_pos.x = rel_pos.x + left_right(info.style.get(), container_block_size.width);
|
rel_pos.x = rel_pos.x + left_right(info.style.get(),
|
||||||
rel_pos.y = rel_pos.y + top_bottom(info.style.get(), container_block_size.height);
|
container_block_size.width);
|
||||||
|
rel_pos.y = rel_pos.y + top_bottom(info.style.get(),
|
||||||
|
container_block_size.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -737,7 +747,7 @@ impl Box {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&self) -> Option<ClearType> {
|
pub fn clear(&self) -> Option<ClearType> {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
match style.Box.clear {
|
match style.Box.get().clear {
|
||||||
clear::none => None,
|
clear::none => None,
|
||||||
clear::left => Some(ClearLeft),
|
clear::left => Some(ClearLeft),
|
||||||
clear::right => Some(ClearRight),
|
clear::right => Some(ClearRight),
|
||||||
|
@ -755,20 +765,20 @@ impl Box {
|
||||||
debug!("(font style) start");
|
debug!("(font style) start");
|
||||||
|
|
||||||
// FIXME: Too much allocation here.
|
// FIXME: Too much allocation here.
|
||||||
let font_families = my_style.Font.font_family.map(|family| {
|
let font_families = my_style.Font.get().font_family.map(|family| {
|
||||||
match *family {
|
match *family {
|
||||||
font_family::FamilyName(ref name) => (*name).clone(),
|
font_family::FamilyName(ref name) => (*name).clone(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
debug!("(font style) font families: `{:?}`", font_families);
|
debug!("(font style) font families: `{:?}`", font_families);
|
||||||
|
|
||||||
let font_size = my_style.Font.font_size.to_f64().unwrap() / 60.0;
|
let font_size = my_style.Font.get().font_size.to_f64().unwrap() / 60.0;
|
||||||
debug!("(font style) font size: `{:f}px`", font_size);
|
debug!("(font style) font size: `{:f}px`", font_size);
|
||||||
|
|
||||||
FontStyle {
|
FontStyle {
|
||||||
pt_size: font_size,
|
pt_size: font_size,
|
||||||
weight: my_style.Font.font_weight,
|
weight: my_style.Font.get().font_weight,
|
||||||
style: my_style.Font.font_style,
|
style: my_style.Font.get().font_style,
|
||||||
families: font_families,
|
families: font_families,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -781,19 +791,19 @@ impl Box {
|
||||||
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
|
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
|
||||||
/// node.
|
/// node.
|
||||||
pub fn text_align(&self) -> text_align::T {
|
pub fn text_align(&self) -> text_align::T {
|
||||||
self.style().InheritedText.text_align
|
self.style().InheritedText.get().text_align
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line_height(&self) -> line_height::T {
|
pub fn line_height(&self) -> line_height::T {
|
||||||
self.style().InheritedBox.line_height
|
self.style().InheritedBox.get().line_height
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vertical_align(&self) -> vertical_align::T {
|
pub fn vertical_align(&self) -> vertical_align::T {
|
||||||
self.style().Box.vertical_align
|
self.style().Box.get().vertical_align
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn white_space(&self) -> white_space::T {
|
pub fn white_space(&self) -> white_space::T {
|
||||||
self.style().InheritedText.white_space
|
self.style().InheritedText.get().white_space
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the text decoration of this box, according to the style of the nearest ancestor
|
/// Returns the text decoration of this box, according to the style of the nearest ancestor
|
||||||
|
@ -804,7 +814,7 @@ impl Box {
|
||||||
/// model. Therefore, this is a best lower bound approximation, but the end result may actually
|
/// model. Therefore, this is a best lower bound approximation, but the end result may actually
|
||||||
/// have the various decoration flags turned on afterward.
|
/// have the various decoration flags turned on afterward.
|
||||||
pub fn text_decoration(&self) -> text_decoration::T {
|
pub fn text_decoration(&self) -> text_decoration::T {
|
||||||
self.style().Text.text_decoration
|
self.style().Text.get().text_decoration
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sum of margin, border, and padding on the left.
|
/// Returns the sum of margin, border, and padding on the left.
|
||||||
|
@ -862,7 +872,7 @@ impl Box {
|
||||||
bg_rect.origin.y = box_info.baseline + offset.y - info.font_ascent;
|
bg_rect.origin.y = box_info.baseline + offset.y - info.font_ascent;
|
||||||
bg_rect.size.height = info.font_ascent + info.font_descent;
|
bg_rect.size.height = info.font_ascent + info.font_descent;
|
||||||
let background_color = info.style.get().resolve_color(
|
let background_color = info.style.get().resolve_color(
|
||||||
info.style.get().Background.background_color);
|
info.style.get().Background.get().background_color);
|
||||||
|
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
lists.with_mut(|lists| {
|
lists.with_mut(|lists| {
|
||||||
|
@ -886,14 +896,14 @@ impl Box {
|
||||||
bg_rect.size.height = bg_rect.size.height + border.top + border.bottom;
|
bg_rect.size.height = bg_rect.size.height + border.top + border.bottom;
|
||||||
|
|
||||||
let style = info.style.get();
|
let style = info.style.get();
|
||||||
let top_color = style.resolve_color(style.Border.border_top_color);
|
let top_color = style.resolve_color(style.Border.get().border_top_color);
|
||||||
let right_color = style.resolve_color(style.Border.border_right_color);
|
let right_color = style.resolve_color(style.Border.get().border_right_color);
|
||||||
let bottom_color = style.resolve_color(style.Border.border_bottom_color);
|
let bottom_color = style.resolve_color(style.Border.get().border_bottom_color);
|
||||||
let left_color = style.resolve_color(style.Border.border_left_color);
|
let left_color = style.resolve_color(style.Border.get().border_left_color);
|
||||||
let top_style = style.Border.border_top_style;
|
let top_style = style.Border.get().border_top_style;
|
||||||
let right_style = style.Border.border_right_style;
|
let right_style = style.Border.get().border_right_style;
|
||||||
let bottom_style = style.Border.border_bottom_style;
|
let bottom_style = style.Border.get().border_bottom_style;
|
||||||
let left_style = style.Border.border_left_style;
|
let left_style = style.Border.get().border_left_style;
|
||||||
|
|
||||||
|
|
||||||
lists.with_mut(|lists| {
|
lists.with_mut(|lists| {
|
||||||
|
@ -935,7 +945,7 @@ impl Box {
|
||||||
// inefficient. What we really want is something like "nearest ancestor element that
|
// inefficient. What we really want is something like "nearest ancestor element that
|
||||||
// doesn't have a box".
|
// doesn't have a box".
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let background_color = style.resolve_color(style.Background.background_color);
|
let background_color = style.resolve_color(style.Background.get().background_color);
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
lists.with_mut(|lists| {
|
lists.with_mut(|lists| {
|
||||||
let solid_color_display_item = ~SolidColorDisplayItem {
|
let solid_color_display_item = ~SolidColorDisplayItem {
|
||||||
|
@ -965,14 +975,14 @@ impl Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let top_color = style.resolve_color(style.Border.border_top_color);
|
let top_color = style.resolve_color(style.Border.get().border_top_color);
|
||||||
let right_color = style.resolve_color(style.Border.border_right_color);
|
let right_color = style.resolve_color(style.Border.get().border_right_color);
|
||||||
let bottom_color = style.resolve_color(style.Border.border_bottom_color);
|
let bottom_color = style.resolve_color(style.Border.get().border_bottom_color);
|
||||||
let left_color = style.resolve_color(style.Border.border_left_color);
|
let left_color = style.resolve_color(style.Border.get().border_left_color);
|
||||||
let top_style = style.Border.border_top_style;
|
let top_style = style.Border.get().border_top_style;
|
||||||
let right_style = style.Border.border_right_style;
|
let right_style = style.Border.get().border_right_style;
|
||||||
let bottom_style = style.Border.border_bottom_style;
|
let bottom_style = style.Border.get().border_bottom_style;
|
||||||
let left_style = style.Border.border_left_style;
|
let left_style = style.Border.get().border_left_style;
|
||||||
|
|
||||||
let mut abs_bounds = abs_bounds.clone();
|
let mut abs_bounds = abs_bounds.clone();
|
||||||
abs_bounds.origin.x = abs_bounds.origin.x + self.noncontent_inline_left();
|
abs_bounds.origin.x = abs_bounds.origin.x + self.noncontent_inline_left();
|
||||||
|
@ -1029,7 +1039,7 @@ impl Box {
|
||||||
box_bounds, absolute_box_bounds, self.debug_str());
|
box_bounds, absolute_box_bounds, self.debug_str());
|
||||||
debug!("Box::build_display_list: dirty={}, offset={}", *dirty, offset);
|
debug!("Box::build_display_list: dirty={}, offset={}", *dirty, offset);
|
||||||
|
|
||||||
if self.style().InheritedBox.visibility != visibility::visible {
|
if self.style().InheritedBox.get().visibility != visibility::visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,7 +1057,7 @@ impl Box {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
||||||
ScannedTextBox(ref text_box) => {
|
ScannedTextBox(ref text_box) => {
|
||||||
let text_color = self.style().Color.color.to_gfx_color();
|
let text_color = self.style().Color.get().color.to_gfx_color();
|
||||||
|
|
||||||
// Set the various text display item flags.
|
// Set the various text display item flags.
|
||||||
let mut flow_flags = flow::base(flow).flags_info.clone();
|
let mut flow_flags = flow::base(flow).flags_info.clone();
|
||||||
|
@ -1472,13 +1482,13 @@ impl Box {
|
||||||
}
|
}
|
||||||
ImageBox(ref image_box_info) => {
|
ImageBox(ref image_box_info) => {
|
||||||
// TODO(ksh8281): compute border,margin,padding
|
// TODO(ksh8281): compute border,margin,padding
|
||||||
let width = ImageBoxInfo::style_length(self.style().Box.width,
|
let width = ImageBoxInfo::style_length(self.style().Box.get().width,
|
||||||
image_box_info.dom_width,
|
image_box_info.dom_width,
|
||||||
container_width);
|
container_width);
|
||||||
|
|
||||||
// FIXME(ksh8281): we shouldn't figure height this way
|
// FIXME(ksh8281): we shouldn't figure height this way
|
||||||
// now, we don't know about size of parent's height
|
// now, we don't know about size of parent's height
|
||||||
let height = ImageBoxInfo::style_length(self.style().Box.height,
|
let height = ImageBoxInfo::style_length(self.style().Box.get().height,
|
||||||
image_box_info.dom_height,
|
image_box_info.dom_height,
|
||||||
Au::new(0));
|
Au::new(0));
|
||||||
|
|
||||||
|
@ -1520,11 +1530,11 @@ impl Box {
|
||||||
let width = image_box_info.computed_width();
|
let width = image_box_info.computed_width();
|
||||||
// FIXME(ksh8281): we shouldn't assign height this way
|
// FIXME(ksh8281): we shouldn't assign height this way
|
||||||
// we don't know about size of parent's height
|
// we don't know about size of parent's height
|
||||||
let height = ImageBoxInfo::style_length(self.style().Box.height,
|
let height = ImageBoxInfo::style_length(self.style().Box.get().height,
|
||||||
image_box_info.dom_height,
|
image_box_info.dom_height,
|
||||||
Au::new(0));
|
Au::new(0));
|
||||||
|
|
||||||
let height = match (self.style().Box.width,
|
let height = match (self.style().Box.get().width,
|
||||||
image_box_info.dom_width,
|
image_box_info.dom_width,
|
||||||
height) {
|
height) {
|
||||||
(LPA_Auto, None, Auto) => {
|
(LPA_Auto, None, Auto) => {
|
||||||
|
@ -1575,7 +1585,7 @@ impl Box {
|
||||||
|
|
||||||
/// Returns true if the contents should be clipped (i.e. if `overflow` is `hidden`).
|
/// Returns true if the contents should be clipped (i.e. if `overflow` is `hidden`).
|
||||||
pub fn needs_clip(&self) -> bool {
|
pub fn needs_clip(&self) -> bool {
|
||||||
self.style().Box.overflow == overflow::hidden
|
self.style().Box.get().overflow == overflow::hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a debugging string describing this box.
|
/// Returns a debugging string describing this box.
|
||||||
|
|
|
@ -628,7 +628,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
let (display, float, position) = match node.type_id() {
|
let (display, float, position) = match node.type_id() {
|
||||||
ElementNodeTypeId(_) => {
|
ElementNodeTypeId(_) => {
|
||||||
let style = node.style().get();
|
let style = node.style().get();
|
||||||
(style.Box.display, style.Box.float, style.Box.position)
|
(style.Box.get().display, style.Box.get().float, style.Box.get().position)
|
||||||
}
|
}
|
||||||
TextNodeTypeId => (display::inline, float::none, position::static_),
|
TextNodeTypeId => (display::inline, float::none, position::static_),
|
||||||
CommentNodeTypeId |
|
CommentNodeTypeId |
|
||||||
|
@ -730,7 +730,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
||||||
//
|
//
|
||||||
// If you implement other values for this property, you will almost certainly
|
// If you implement other values for this property, you will almost certainly
|
||||||
// want to update this check.
|
// want to update this check.
|
||||||
match self.style().get().InheritedText.white_space {
|
match self.style().get().InheritedText.get().white_space {
|
||||||
white_space::normal => true,
|
white_space::normal => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use script::layout_interface::LayoutChan;
|
||||||
use servo_msg::constellation_msg::ConstellationChan;
|
use servo_msg::constellation_msg::ConstellationChan;
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use style::Stylist;
|
use style::{ComputedValues, Stylist};
|
||||||
|
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;
|
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;
|
||||||
|
@ -55,6 +55,9 @@ pub struct LayoutContext {
|
||||||
/// FIXME(pcwalton): Make this no longer an unsafe pointer once we have fast `RWArc`s.
|
/// FIXME(pcwalton): Make this no longer an unsafe pointer once we have fast `RWArc`s.
|
||||||
stylist: *Stylist,
|
stylist: *Stylist,
|
||||||
|
|
||||||
|
/// The initial set of CSS properties.
|
||||||
|
initial_css_values: Arc<ComputedValues>,
|
||||||
|
|
||||||
/// The root node at which we're starting the layout.
|
/// The root node at which we're starting the layout.
|
||||||
reflow_root: OpaqueNode,
|
reflow_root: OpaqueNode,
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,7 +309,7 @@ static TEXT_ALIGN_SHIFT: u8 = 4;
|
||||||
impl FlowFlagsInfo {
|
impl FlowFlagsInfo {
|
||||||
/// Creates a new set of flow flags from the given style.
|
/// Creates a new set of flow flags from the given style.
|
||||||
pub fn new(style: &ComputedValues) -> FlowFlagsInfo {
|
pub fn new(style: &ComputedValues) -> FlowFlagsInfo {
|
||||||
let text_decoration = style.Text.text_decoration;
|
let text_decoration = style.Text.get().text_decoration;
|
||||||
let mut flags = FlowFlags(0);
|
let mut flags = FlowFlags(0);
|
||||||
flags.set_override_underline(text_decoration.underline);
|
flags.set_override_underline(text_decoration.underline);
|
||||||
flags.set_override_overline(text_decoration.overline);
|
flags.set_override_overline(text_decoration.overline);
|
||||||
|
@ -318,9 +318,9 @@ impl FlowFlagsInfo {
|
||||||
// TODO(ksh8281) compute text-decoration-color,style,line
|
// TODO(ksh8281) compute text-decoration-color,style,line
|
||||||
let rare_flow_flags = if flags.is_text_decoration_enabled() {
|
let rare_flow_flags = if flags.is_text_decoration_enabled() {
|
||||||
Some(~RareFlowFlags {
|
Some(~RareFlowFlags {
|
||||||
underline_color: style.Color.color.to_gfx_color(),
|
underline_color: style.Color.get().color.to_gfx_color(),
|
||||||
overline_color: style.Color.color.to_gfx_color(),
|
overline_color: style.Color.get().color.to_gfx_color(),
|
||||||
line_through_color: style.Color.color.to_gfx_color(),
|
line_through_color: style.Color.get().color.to_gfx_color(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl RestyleDamage {
|
||||||
macro_rules! add_if_not_equal(
|
macro_rules! add_if_not_equal(
|
||||||
($old:ident, $new:ident, $damage:ident,
|
($old:ident, $new:ident, $damage:ident,
|
||||||
[ $($effect:ident),* ], [ $($style_struct:ident.$name:ident),* ]) => ({
|
[ $($effect:ident),* ], [ $($style_struct:ident.$name:ident),* ]) => ({
|
||||||
if $( ($old.$style_struct.$name != $new.$style_struct.$name) )||* {
|
if $( ($old.$style_struct.get().$name != $new.$style_struct.get().$name) )||* {
|
||||||
$damage.union_in_place( restyle_damage!( $($effect),* ) );
|
$damage.union_in_place( restyle_damage!( $($effect),* ) );
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -794,7 +794,7 @@ impl Flow for InlineFlow {
|
||||||
//
|
//
|
||||||
// The spec does not state which font to use. Previous versions of the code used
|
// The spec does not state which font to use. Previous versions of the code used
|
||||||
// the parent's font; this code uses the current font.
|
// the parent's font; this code uses the current font.
|
||||||
let parent_text_top = cur_box.style().Font.font_size;
|
let parent_text_top = cur_box.style().Font.get().font_size;
|
||||||
|
|
||||||
// We should calculate the distance from baseline to the bottom of the parent's
|
// We should calculate the distance from baseline to the bottom of the parent's
|
||||||
// content area. But for now we assume it's zero.
|
// content area. But for now we assume it's zero.
|
||||||
|
|
|
@ -55,7 +55,8 @@ use std::comm::Port;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::task;
|
use std::task;
|
||||||
use std::util;
|
use std::util;
|
||||||
use style::{AuthorOrigin, Stylesheet, Stylist};
|
use style::{AuthorOrigin, ComputedValues, Stylesheet, Stylist};
|
||||||
|
use style;
|
||||||
|
|
||||||
/// Information needed by the layout task.
|
/// Information needed by the layout task.
|
||||||
pub struct LayoutTask {
|
pub struct LayoutTask {
|
||||||
|
@ -97,6 +98,9 @@ pub struct LayoutTask {
|
||||||
|
|
||||||
stylist: ~Stylist,
|
stylist: ~Stylist,
|
||||||
|
|
||||||
|
/// The initial set of CSS values.
|
||||||
|
initial_css_values: Arc<ComputedValues>,
|
||||||
|
|
||||||
/// The workers that we use for parallel operation.
|
/// The workers that we use for parallel operation.
|
||||||
parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>,
|
parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>,
|
||||||
|
|
||||||
|
@ -302,6 +306,7 @@ impl LayoutTask {
|
||||||
|
|
||||||
display_list_collection: None,
|
display_list_collection: None,
|
||||||
stylist: ~new_stylist(),
|
stylist: ~new_stylist(),
|
||||||
|
initial_css_values: Arc::new(style::initial_values()),
|
||||||
parallel_traversal: parallel_traversal,
|
parallel_traversal: parallel_traversal,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
opts: opts.clone()
|
opts: opts.clone()
|
||||||
|
@ -332,6 +337,7 @@ impl LayoutTask {
|
||||||
layout_chan: self.chan.clone(),
|
layout_chan: self.chan.clone(),
|
||||||
font_context_info: font_context_info,
|
font_context_info: font_context_info,
|
||||||
stylist: &*self.stylist,
|
stylist: &*self.stylist,
|
||||||
|
initial_css_values: self.initial_css_values.clone(),
|
||||||
reflow_root: OpaqueNode::from_layout_node(reflow_root),
|
reflow_root: OpaqueNode::from_layout_node(reflow_root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,6 +571,7 @@ impl LayoutTask {
|
||||||
node.match_and_cascade_subtree(self.stylist,
|
node.match_and_cascade_subtree(self.stylist,
|
||||||
&layout_ctx.layout_chan,
|
&layout_ctx.layout_chan,
|
||||||
&mut applicable_declarations,
|
&mut applicable_declarations,
|
||||||
|
layout_ctx.initial_css_values.get(),
|
||||||
None)
|
None)
|
||||||
}
|
}
|
||||||
Some(ref mut traversal) => {
|
Some(ref mut traversal) => {
|
||||||
|
@ -638,6 +645,7 @@ impl LayoutTask {
|
||||||
.resolve_color(thread_safe_child.style()
|
.resolve_color(thread_safe_child.style()
|
||||||
.get()
|
.get()
|
||||||
.Background
|
.Background
|
||||||
|
.get()
|
||||||
.background_color)
|
.background_color)
|
||||||
.to_gfx_color()
|
.to_gfx_color()
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,7 +163,9 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode,
|
||||||
} else {
|
} else {
|
||||||
node.parent_node()
|
node.parent_node()
|
||||||
};
|
};
|
||||||
node.cascade_node(parent_opt, &applicable_declarations);
|
node.cascade_node(parent_opt,
|
||||||
|
layout_context.initial_css_values.get(),
|
||||||
|
&applicable_declarations);
|
||||||
|
|
||||||
// Enqueue kids.
|
// Enqueue kids.
|
||||||
let mut child_count = 0;
|
let mut child_count = 0;
|
||||||
|
|
|
@ -160,33 +160,111 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod computed {
|
pub mod computed {
|
||||||
use cssparser;
|
|
||||||
pub use CSSColor = cssparser::Color;
|
pub use CSSColor = cssparser::Color;
|
||||||
pub use compute_CSSColor = super::super::longhands::computed_as_specified;
|
pub use compute_CSSColor = super::super::longhands::computed_as_specified;
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::super::longhands;
|
use super::super::{longhands, style_structs};
|
||||||
|
use servo_util::cowarc::CowArc;
|
||||||
pub use servo_util::geometry::Au;
|
pub use servo_util::geometry::Au;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
current_color: cssparser::RGBA,
|
color: longhands::color::computed_value::T,
|
||||||
parent_font_size: Au,
|
parent_font_weight: longhands::font_weight::computed_value::T,
|
||||||
font_size: Au,
|
parent_font_size: longhands::font_size::computed_value::T,
|
||||||
font_weight: longhands::font_weight::computed_value::T,
|
font_size: longhands::font_size::computed_value::T,
|
||||||
position: longhands::position::SpecifiedValue,
|
positioned: bool,
|
||||||
float: longhands::float::SpecifiedValue,
|
floated: bool,
|
||||||
|
border_top_present: bool,
|
||||||
|
border_right_present: bool,
|
||||||
|
border_bottom_present: bool,
|
||||||
|
border_left_present: bool,
|
||||||
is_root_element: bool,
|
is_root_element: bool,
|
||||||
border_top_style: longhands::border_top_style::computed_value::T,
|
use_parent_font_size: bool,
|
||||||
border_right_style: longhands::border_top_style::computed_value::T,
|
|
||||||
border_bottom_style: longhands::border_top_style::computed_value::T,
|
|
||||||
border_left_style: longhands::border_top_style::computed_value::T,
|
|
||||||
// TODO, as needed: root font size, viewport size, etc.
|
// TODO, as needed: root font size, viewport size, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn border_is_present(border_style: longhands::border_top_style::computed_value::T) -> bool {
|
||||||
|
match border_style {
|
||||||
|
longhands::border_top_style::none | longhands::border_top_style::hidden => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(color: &CowArc<style_structs::Color>,
|
||||||
|
font: &CowArc<style_structs::Font>,
|
||||||
|
css_box: &CowArc<style_structs::Box>,
|
||||||
|
border: &CowArc<style_structs::Border>,
|
||||||
|
is_root_element: bool)
|
||||||
|
-> Context {
|
||||||
|
let mut context = Context {
|
||||||
|
color: color.get().color,
|
||||||
|
parent_font_weight: font.get().font_weight,
|
||||||
|
parent_font_size: font.get().font_size,
|
||||||
|
font_size: font.get().font_size,
|
||||||
|
positioned: false,
|
||||||
|
floated: false,
|
||||||
|
border_top_present: false,
|
||||||
|
border_right_present: false,
|
||||||
|
border_bottom_present: false,
|
||||||
|
border_left_present: false,
|
||||||
|
is_root_element: is_root_element,
|
||||||
|
use_parent_font_size: true,
|
||||||
|
};
|
||||||
|
context.set_position(css_box.get().position);
|
||||||
|
context.set_float(css_box.get().float);
|
||||||
|
context.set_border_top_style(border.get().border_top_style);
|
||||||
|
context.set_border_right_style(border.get().border_right_style);
|
||||||
|
context.set_border_bottom_style(border.get().border_bottom_style);
|
||||||
|
context.set_border_left_style(border.get().border_left_style);
|
||||||
|
context
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_color(&mut self, color: longhands::color::computed_value::T) {
|
||||||
|
self.color = color
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_position(&mut self, position: longhands::position::computed_value::T) {
|
||||||
|
self.positioned = match position {
|
||||||
|
longhands::position::absolute | longhands::position::fixed => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_font_size(&mut self, font_size: longhands::font_size::computed_value::T) {
|
||||||
|
self.font_size = font_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_float(&mut self, float: longhands::float::computed_value::T) {
|
||||||
|
self.floated = float != longhands::float::none
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_top_style(&mut self,
|
||||||
|
style: longhands::border_top_style::computed_value::T) {
|
||||||
|
self.border_top_present = border_is_present(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_right_style(&mut self,
|
||||||
|
style: longhands::border_top_style::computed_value::T) {
|
||||||
|
self.border_right_present = border_is_present(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_bottom_style(&mut self,
|
||||||
|
style: longhands::border_top_style::computed_value::T) {
|
||||||
|
self.border_bottom_present = border_is_present(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_border_left_style(&mut self,
|
||||||
|
style: longhands::border_top_style::computed_value::T) {
|
||||||
|
self.border_left_present = border_is_present(style)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compute_Au(value: specified::Length, context: &Context, em_is_parent: bool) -> Au {
|
pub fn compute_Au(value: specified::Length, context: &Context) -> Au {
|
||||||
match value {
|
match value {
|
||||||
specified::Au_(value) => value,
|
specified::Au_(value) => value,
|
||||||
specified::Em(value) if em_is_parent => context.parent_font_size.scale_by(value),
|
|
||||||
specified::Em(value) => context.font_size.scale_by(value),
|
specified::Em(value) => context.font_size.scale_by(value),
|
||||||
specified::Ex(value) => {
|
specified::Ex(value) => {
|
||||||
let x_height = 0.5; // TODO: find that from the font
|
let x_height = 0.5; // TODO: find that from the font
|
||||||
|
@ -195,6 +273,19 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A special version of `compute_Au` used for `font-size`.
|
||||||
|
#[inline]
|
||||||
|
pub fn compute_Au_from_parent(value: specified::Length, context: &Context) -> Au {
|
||||||
|
match value {
|
||||||
|
specified::Au_(value) => value,
|
||||||
|
specified::Em(value) => context.parent_font_size.scale_by(value),
|
||||||
|
specified::Ex(value) => {
|
||||||
|
let x_height = 0.5; // TODO: find that from the font
|
||||||
|
context.font_size.scale_by(value * x_height)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq, Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
LP_Length(Au),
|
LP_Length(Au),
|
||||||
|
@ -203,7 +294,7 @@ pub mod computed {
|
||||||
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
|
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
|
||||||
-> LengthOrPercentage {
|
-> LengthOrPercentage {
|
||||||
match value {
|
match value {
|
||||||
specified::LP_Length(value) => LP_Length(compute_Au(value, context, false)),
|
specified::LP_Length(value) => LP_Length(compute_Au(value, context)),
|
||||||
specified::LP_Percentage(value) => LP_Percentage(value),
|
specified::LP_Percentage(value) => LP_Percentage(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +308,7 @@ pub mod computed {
|
||||||
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto,
|
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto,
|
||||||
context: &Context) -> LengthOrPercentageOrAuto {
|
context: &Context) -> LengthOrPercentageOrAuto {
|
||||||
match value {
|
match value {
|
||||||
specified::LPA_Length(value) => LPA_Length(compute_Au(value, context, false)),
|
specified::LPA_Length(value) => LPA_Length(compute_Au(value, context)),
|
||||||
specified::LPA_Percentage(value) => LPA_Percentage(value),
|
specified::LPA_Percentage(value) => LPA_Percentage(value),
|
||||||
specified::LPA_Auto => LPA_Auto,
|
specified::LPA_Auto => LPA_Auto,
|
||||||
}
|
}
|
||||||
|
@ -232,7 +323,7 @@ pub mod computed {
|
||||||
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone,
|
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone,
|
||||||
context: &Context) -> LengthOrPercentageOrNone {
|
context: &Context) -> LengthOrPercentageOrNone {
|
||||||
match value {
|
match value {
|
||||||
specified::LPN_Length(value) => LPN_Length(compute_Au(value, context, false)),
|
specified::LPN_Length(value) => LPN_Length(compute_Au(value, context)),
|
||||||
specified::LPN_Percentage(value) => LPN_Percentage(value),
|
specified::LPN_Percentage(value) => LPN_Percentage(value),
|
||||||
specified::LPN_None => LPN_None,
|
specified::LPN_None => LPN_None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use std::ascii::StrAsciiExt;
|
use std::ascii::StrAsciiExt;
|
||||||
pub use extra::arc::Arc;
|
pub use extra::arc::Arc;
|
||||||
|
use servo_util::cowarc::CowArc;
|
||||||
pub use cssparser::*;
|
pub use cssparser::*;
|
||||||
pub use cssparser::ast::*;
|
pub use cssparser::ast::*;
|
||||||
|
|
||||||
|
@ -25,18 +26,17 @@ def to_rust_ident(name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
class Longhand(object):
|
class Longhand(object):
|
||||||
def __init__(self, name, priority):
|
def __init__(self, name, needed_for_context):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ident = to_rust_ident(name)
|
self.ident = to_rust_ident(name)
|
||||||
self.style_struct = THIS_STYLE_STRUCT
|
self.style_struct = THIS_STYLE_STRUCT
|
||||||
self.priority = priority
|
self.needed_for_context = needed_for_context
|
||||||
|
|
||||||
class Shorthand(object):
|
class Shorthand(object):
|
||||||
def __init__(self, name, priority, sub_properties):
|
def __init__(self, name, sub_properties):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ident = to_rust_ident(name)
|
self.ident = to_rust_ident(name)
|
||||||
self.sub_properties = [LONGHANDS_BY_NAME[s] for s in sub_properties]
|
self.sub_properties = [LONGHANDS_BY_NAME[s] for s in sub_properties]
|
||||||
self.priority = priority
|
|
||||||
|
|
||||||
class StyleStruct(object):
|
class StyleStruct(object):
|
||||||
def __init__(self, name, inherited):
|
def __init__(self, name, inherited):
|
||||||
|
@ -72,13 +72,13 @@ pub mod longhands {
|
||||||
pub use super::*;
|
pub use super::*;
|
||||||
pub use std;
|
pub use std;
|
||||||
|
|
||||||
pub fn computed_as_specified<T>(value: T, _context: &mut computed::Context) -> T {
|
pub fn computed_as_specified<T>(value: T, _context: &computed::Context) -> T {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
<%def name="raw_longhand(name, priority='Normal', no_super=False)">
|
<%def name="raw_longhand(name, needed_for_context=False, no_super=False)">
|
||||||
<%
|
<%
|
||||||
property = Longhand(name, priority)
|
property = Longhand(name, needed_for_context)
|
||||||
THIS_STYLE_STRUCT.longhands.append(property)
|
THIS_STYLE_STRUCT.longhands.append(property)
|
||||||
LONGHANDS.append(property)
|
LONGHANDS.append(property)
|
||||||
LONGHANDS_BY_NAME[name] = property
|
LONGHANDS_BY_NAME[name] = property
|
||||||
|
@ -101,8 +101,8 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="longhand(name, priority='Normal', no_super=False)">
|
<%def name="longhand(name, needed_for_context=False, no_super=False)">
|
||||||
<%self:raw_longhand name="${name}" priority="${priority}">
|
<%self:raw_longhand name="${name}" needed_for_context="${needed_for_context}">
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
pub fn parse_specified(input: &[ComponentValue])
|
pub fn parse_specified(input: &[ComponentValue])
|
||||||
-> Option<DeclaredValue<SpecifiedValue>> {
|
-> Option<DeclaredValue<SpecifiedValue>> {
|
||||||
|
@ -111,8 +111,8 @@ pub mod longhands {
|
||||||
</%self:raw_longhand>
|
</%self:raw_longhand>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="single_component_value(name, priority='Normal')">
|
<%def name="single_component_value(name, needed_for_context=False)">
|
||||||
<%self:longhand name="${name}" priority="${priority}">
|
<%self:longhand name="${name}" needed_for_context="${needed_for_context}">
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
||||||
one_component_value(input).and_then(from_component_value)
|
one_component_value(input).and_then(from_component_value)
|
||||||
|
@ -120,8 +120,8 @@ pub mod longhands {
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="single_keyword_computed(name, values, priority='Normal')">
|
<%def name="single_keyword_computed(name, values, needed_for_context=False)">
|
||||||
<%self:single_component_value name="${name}" priority="${priority}">
|
<%self:single_component_value name="${name}" needed_for_context="${needed_for_context}">
|
||||||
${caller.body()}
|
${caller.body()}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
#[deriving(Eq, Clone, FromPrimitive)]
|
#[deriving(Eq, Clone, FromPrimitive)]
|
||||||
|
@ -148,8 +148,10 @@ pub mod longhands {
|
||||||
</%self:single_component_value>
|
</%self:single_component_value>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="single_keyword(name, values, priority='Normal')">
|
<%def name="single_keyword(name, values, needed_for_context=False)">
|
||||||
<%self:single_keyword_computed name="${name}" values="${values}" priority="${priority}">
|
<%self:single_keyword_computed name="${name}"
|
||||||
|
values="${values}"
|
||||||
|
needed_for_context="${needed_for_context}">
|
||||||
// The computed value is the same as the specified value.
|
// The computed value is the same as the specified value.
|
||||||
pub use to_computed_value = super::computed_as_specified;
|
pub use to_computed_value = super::computed_as_specified;
|
||||||
</%self:single_keyword_computed>
|
</%self:single_keyword_computed>
|
||||||
|
@ -172,14 +174,14 @@ pub mod longhands {
|
||||||
|
|
||||||
// CSS 2.1, Section 8 - Box model
|
// CSS 2.1, Section 8 - Box model
|
||||||
|
|
||||||
${new_style_struct("Margin", False)}
|
${new_style_struct("Margin", is_inherited=False)}
|
||||||
|
|
||||||
% for side in ["top", "right", "bottom", "left"]:
|
% for side in ["top", "right", "bottom", "left"]:
|
||||||
${predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
|
${predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
|
||||||
"computed::LPA_Length(Au(0))")}
|
"computed::LPA_Length(Au(0))")}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
${new_style_struct("Padding", False)}
|
${new_style_struct("Padding", is_inherited=False)}
|
||||||
|
|
||||||
% for side in ["top", "right", "bottom", "left"]:
|
% for side in ["top", "right", "bottom", "left"]:
|
||||||
${predefined_type("padding-" + side, "LengthOrPercentage",
|
${predefined_type("padding-" + side, "LengthOrPercentage",
|
||||||
|
@ -187,33 +189,19 @@ pub mod longhands {
|
||||||
"parse_non_negative")}
|
"parse_non_negative")}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
${new_style_struct("Border", False)}
|
${new_style_struct("Border", is_inherited=False)}
|
||||||
|
|
||||||
% for side in ["top", "right", "bottom", "left"]:
|
% for side in ["top", "right", "bottom", "left"]:
|
||||||
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
// double groove ridge insed outset
|
// double groove ridge insed outset
|
||||||
<%self:single_keyword_computed name="border-top-style"
|
${single_keyword("border-top-style", values="none solid dotted dashed hidden", \
|
||||||
values="none solid dotted dashed hidden"
|
needed_for_context=True)}
|
||||||
priority="High">
|
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
|
||||||
-> computed_value::T {
|
|
||||||
context.border_top_style = value;
|
|
||||||
value
|
|
||||||
}
|
|
||||||
</%self:single_keyword_computed>
|
|
||||||
% for side in ["right", "bottom", "left"]:
|
% for side in ["right", "bottom", "left"]:
|
||||||
<%self:longhand name="border-${side}-style", no_super="True", priority="High">
|
<%self:longhand name="border-${side}-style", no_super="True", needed_for_context="True">
|
||||||
pub use super::border_top_style::get_initial_value;
|
pub use super::border_top_style::{get_initial_value, parse, to_computed_value};
|
||||||
pub use super::border_top_style::parse;
|
|
||||||
|
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
|
||||||
-> computed_value::T {
|
|
||||||
context.border_${side}_style = value;
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type SpecifiedValue = super::border_top_style::SpecifiedValue;
|
pub type SpecifiedValue = super::border_top_style::SpecifiedValue;
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
pub type T = super::super::border_top_style::computed_value::T;
|
pub type T = super::super::border_top_style::computed_value::T;
|
||||||
|
@ -238,7 +226,6 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
% for side in ["top", "right", "bottom", "left"]:
|
% for side in ["top", "right", "bottom", "left"]:
|
||||||
<%self:longhand name="border-${side}-width">
|
<%self:longhand name="border-${side}-width">
|
||||||
use super::super::border_is_present;
|
|
||||||
pub type SpecifiedValue = specified::Length;
|
pub type SpecifiedValue = specified::Length;
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use super::super::Au;
|
use super::super::Au;
|
||||||
|
@ -250,18 +237,19 @@ pub mod longhands {
|
||||||
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
||||||
one_component_value(input).and_then(parse_border_width)
|
one_component_value(input).and_then(parse_border_width)
|
||||||
}
|
}
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
#[inline]
|
||||||
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
-> computed_value::T {
|
-> computed_value::T {
|
||||||
if !border_is_present(context.border_${side}_style) {
|
if !context.border_${side}_present {
|
||||||
Au(0)
|
Au(0)
|
||||||
} else {
|
} else {
|
||||||
computed::compute_Au(value, context, false)
|
computed::compute_Au(value, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
${new_style_struct("PositionOffsets", False)}
|
${new_style_struct("PositionOffsets", is_inherited=False)}
|
||||||
|
|
||||||
% for side in ["top", "right", "bottom", "left"]:
|
% for side in ["top", "right", "bottom", "left"]:
|
||||||
${predefined_type(side, "LengthOrPercentageOrAuto",
|
${predefined_type(side, "LengthOrPercentageOrAuto",
|
||||||
|
@ -270,7 +258,7 @@ pub mod longhands {
|
||||||
|
|
||||||
// CSS 2.1, Section 9 - Visual formatting model
|
// CSS 2.1, Section 9 - Visual formatting model
|
||||||
|
|
||||||
${new_style_struct("Box", False)}
|
${new_style_struct("Box", is_inherited=False)}
|
||||||
|
|
||||||
// TODO: don't parse values we don't support
|
// TODO: don't parse values we don't support
|
||||||
<%self:single_keyword_computed name="display"
|
<%self:single_keyword_computed name="display"
|
||||||
|
@ -279,16 +267,13 @@ pub mod longhands {
|
||||||
table-row table-column-group table-column table-cell table-caption
|
table-row table-column-group table-column table-cell table-caption
|
||||||
list-item
|
list-item
|
||||||
none">
|
none">
|
||||||
|
#[inline]
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
-> computed_value::T {
|
-> computed_value::T {
|
||||||
// if context.is_root_element && value == list_item {
|
// if context.is_root_element && value == list_item {
|
||||||
// return block
|
// return block
|
||||||
// }
|
// }
|
||||||
let positioned = match context.position {
|
if context.positioned || context.floated || context.is_root_element {
|
||||||
position::absolute | position::fixed => true,
|
|
||||||
_ => false
|
|
||||||
};
|
|
||||||
if positioned || context.float != float::none || context.is_root_element {
|
|
||||||
match value {
|
match value {
|
||||||
// inline_table => table,
|
// inline_table => table,
|
||||||
inline | inline_block
|
inline | inline_block
|
||||||
|
@ -304,8 +289,8 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
</%self:single_keyword_computed>
|
</%self:single_keyword_computed>
|
||||||
|
|
||||||
${single_keyword("position", "static absolute relative fixed")}
|
${single_keyword("position", "static absolute relative fixed", needed_for_context="True")}
|
||||||
${single_keyword("float", "none left right")}
|
${single_keyword("float", "none left right", needed_for_context="True")}
|
||||||
${single_keyword("clear", "none left right both")}
|
${single_keyword("clear", "none left right both")}
|
||||||
|
|
||||||
// CSS 2.1, Section 10 - Visual formatting model details
|
// CSS 2.1, Section 10 - Visual formatting model details
|
||||||
|
@ -324,7 +309,7 @@ pub mod longhands {
|
||||||
"computed::LPN_None",
|
"computed::LPN_None",
|
||||||
"parse_non_negative")}
|
"parse_non_negative")}
|
||||||
|
|
||||||
${new_style_struct("InheritedBox", True)}
|
${new_style_struct("InheritedBox", is_inherited=True)}
|
||||||
|
|
||||||
<%self:single_component_value name="line-height">
|
<%self:single_component_value name="line-height">
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -358,12 +343,14 @@ pub mod longhands {
|
||||||
Number(CSSFloat),
|
Number(CSSFloat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T { Normal }
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T { Normal }
|
||||||
|
#[inline]
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
-> computed_value::T {
|
-> computed_value::T {
|
||||||
match value {
|
match value {
|
||||||
SpecifiedNormal => Normal,
|
SpecifiedNormal => Normal,
|
||||||
SpecifiedLength(value) => Length(computed::compute_Au(value, context, false)),
|
SpecifiedLength(value) => Length(computed::compute_Au(value, context)),
|
||||||
SpecifiedNumber(value) => Number(value),
|
SpecifiedNumber(value) => Number(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -410,7 +397,9 @@ pub mod longhands {
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T { baseline }
|
#[inline]
|
||||||
|
pub fn get_initial_value() -> computed_value::T { baseline }
|
||||||
|
#[inline]
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
-> computed_value::T {
|
-> computed_value::T {
|
||||||
match value {
|
match value {
|
||||||
|
@ -482,15 +471,15 @@ pub mod longhands {
|
||||||
|
|
||||||
// CSS 2.1, Section 14 - Colors and Backgrounds
|
// CSS 2.1, Section 14 - Colors and Backgrounds
|
||||||
|
|
||||||
${new_style_struct("Background", False)}
|
${new_style_struct("Background", is_inherited=False)}
|
||||||
|
|
||||||
${predefined_type("background-color", "CSSColor",
|
${predefined_type("background-color", "CSSColor",
|
||||||
"RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
|
"RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")}
|
||||||
|
|
||||||
|
|
||||||
${new_style_struct("Color", True)}
|
${new_style_struct("Color", is_inherited=True)}
|
||||||
|
|
||||||
<%self:raw_longhand name="color">
|
<%self:raw_longhand name="color" needed_for_context="True">
|
||||||
pub use to_computed_value = super::computed_as_specified;
|
pub use to_computed_value = super::computed_as_specified;
|
||||||
pub type SpecifiedValue = RGBA;
|
pub type SpecifiedValue = RGBA;
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
@ -510,7 +499,7 @@ pub mod longhands {
|
||||||
|
|
||||||
// CSS 2.1, Section 15 - Fonts
|
// CSS 2.1, Section 15 - Fonts
|
||||||
|
|
||||||
${new_style_struct("Font", True)}
|
${new_style_struct("Font", is_inherited=True)}
|
||||||
|
|
||||||
<%self:longhand name="font-family">
|
<%self:longhand name="font-family">
|
||||||
pub use to_computed_value = super::computed_as_specified;
|
pub use to_computed_value = super::computed_as_specified;
|
||||||
|
@ -593,11 +582,11 @@ pub mod longhands {
|
||||||
${single_keyword("font-style", "normal italic oblique")}
|
${single_keyword("font-style", "normal italic oblique")}
|
||||||
${single_keyword("font-variant", "normal")} // Add small-caps when supported
|
${single_keyword("font-variant", "normal")} // Add small-caps when supported
|
||||||
|
|
||||||
<%self:single_component_value name="font-weight" priority="High">
|
<%self:single_component_value name="font-weight">
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
Bolder,
|
Bolder,
|
||||||
Lighther,
|
Lighter,
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
SpecifiedWeight${weight},
|
SpecifiedWeight${weight},
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -612,7 +601,7 @@ pub mod longhands {
|
||||||
"bold" => Some(SpecifiedWeight700),
|
"bold" => Some(SpecifiedWeight700),
|
||||||
"normal" => Some(SpecifiedWeight400),
|
"normal" => Some(SpecifiedWeight400),
|
||||||
"bolder" => Some(Bolder),
|
"bolder" => Some(Bolder),
|
||||||
"lighter" => Some(Lighther),
|
"lighter" => Some(Lighter),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -647,14 +636,16 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
|
#[inline]
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
|
||||||
|
#[inline]
|
||||||
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
-> computed_value::T {
|
-> computed_value::T {
|
||||||
let result = match value {
|
match value {
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
SpecifiedWeight${weight} => Weight${weight},
|
SpecifiedWeight${weight} => Weight${weight},
|
||||||
% endfor
|
% endfor
|
||||||
Bolder => match context.font_weight {
|
Bolder => match context.parent_font_weight {
|
||||||
Weight100 => Weight400,
|
Weight100 => Weight400,
|
||||||
Weight200 => Weight400,
|
Weight200 => Weight400,
|
||||||
Weight300 => Weight400,
|
Weight300 => Weight400,
|
||||||
|
@ -665,7 +656,7 @@ pub mod longhands {
|
||||||
Weight800 => Weight900,
|
Weight800 => Weight900,
|
||||||
Weight900 => Weight900,
|
Weight900 => Weight900,
|
||||||
},
|
},
|
||||||
Lighther => match context.font_weight {
|
Lighter => match context.parent_font_weight {
|
||||||
Weight100 => Weight100,
|
Weight100 => Weight100,
|
||||||
Weight200 => Weight100,
|
Weight200 => Weight100,
|
||||||
Weight300 => Weight100,
|
Weight300 => Weight100,
|
||||||
|
@ -676,28 +667,29 @@ pub mod longhands {
|
||||||
Weight800 => Weight700,
|
Weight800 => Weight700,
|
||||||
Weight900 => Weight700,
|
Weight900 => Weight700,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
context.font_weight = result;
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
</%self:single_component_value>
|
</%self:single_component_value>
|
||||||
|
|
||||||
<%self:single_component_value name="font-size" priority="High">
|
<%self:single_component_value name="font-size" needed_for_context="True">
|
||||||
pub use to_computed_value = super::super::common_types::computed::compute_Au;
|
use super::super::common_types::computed::compute_Au_from_parent;
|
||||||
pub type SpecifiedValue = specified::Length; // Percentages are the same as em.
|
pub type SpecifiedValue = specified::Length; // Percentages are the same as em.
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use super::super::Au;
|
use super::super::Au;
|
||||||
pub type T = Au;
|
pub type T = Au;
|
||||||
}
|
}
|
||||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
|
||||||
-> computed_value::T {
|
|
||||||
let result = computed::compute_Au(value, context, true);
|
|
||||||
context.font_size = result;
|
|
||||||
result
|
|
||||||
}
|
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||||
Au::from_px(16) // medium
|
Au::from_px(16) // medium
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||||
|
-> computed_value::T {
|
||||||
|
if !context.use_parent_font_size {
|
||||||
|
// We already computed this element's font size; no need to compute it again.
|
||||||
|
return context.font_size
|
||||||
|
}
|
||||||
|
compute_Au_from_parent(value, context)
|
||||||
|
}
|
||||||
/// <length> | <percentage>
|
/// <length> | <percentage>
|
||||||
/// TODO: support <absolute-size> and <relative-size>
|
/// TODO: support <absolute-size> and <relative-size>
|
||||||
pub fn from_component_value(input: &ComponentValue) -> Option<SpecifiedValue> {
|
pub fn from_component_value(input: &ComponentValue) -> Option<SpecifiedValue> {
|
||||||
|
@ -712,12 +704,12 @@ pub mod longhands {
|
||||||
|
|
||||||
// CSS 2.1, Section 16 - Text
|
// CSS 2.1, Section 16 - Text
|
||||||
|
|
||||||
${new_style_struct("InheritedText", True)}
|
${new_style_struct("InheritedText", is_inherited=True)}
|
||||||
|
|
||||||
// TODO: initial value should be 'start' (CSS Text Level 3, direction-dependent.)
|
// TODO: initial value should be 'start' (CSS Text Level 3, direction-dependent.)
|
||||||
${single_keyword("text-align", "left right center justify")}
|
${single_keyword("text-align", "left right center justify")}
|
||||||
|
|
||||||
${new_style_struct("Text", False)}
|
${new_style_struct("Text", is_inherited=False)}
|
||||||
|
|
||||||
<%self:longhand name="text-decoration">
|
<%self:longhand name="text-decoration">
|
||||||
pub use to_computed_value = super::computed_as_specified;
|
pub use to_computed_value = super::computed_as_specified;
|
||||||
|
@ -778,9 +770,9 @@ pub mod shorthands {
|
||||||
pub use super::*;
|
pub use super::*;
|
||||||
pub use super::longhands::*;
|
pub use super::longhands::*;
|
||||||
|
|
||||||
<%def name="shorthand(name, sub_properties, priority='Normal')">
|
<%def name="shorthand(name, sub_properties, needed_for_context=False)">
|
||||||
<%
|
<%
|
||||||
shorthand = Shorthand(name, priority, sub_properties.split())
|
shorthand = Shorthand(name, sub_properties.split())
|
||||||
SHORTHANDS.append(shorthand)
|
SHORTHANDS.append(shorthand)
|
||||||
%>
|
%>
|
||||||
pub mod ${shorthand.ident} {
|
pub mod ${shorthand.ident} {
|
||||||
|
@ -1127,7 +1119,7 @@ pub mod style_structs {
|
||||||
#[deriving(Eq, Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
pub struct ComputedValues {
|
pub struct ComputedValues {
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
${style_struct.name}: style_structs::${style_struct.name},
|
${style_struct.name}: CowArc<style_structs::${style_struct.name}>,
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1142,36 +1134,21 @@ impl ComputedValues {
|
||||||
pub fn resolve_color(&self, color: computed::CSSColor) -> RGBA {
|
pub fn resolve_color(&self, color: computed::CSSColor) -> RGBA {
|
||||||
match color {
|
match color {
|
||||||
RGBA(rgba) => rgba,
|
RGBA(rgba) => rgba,
|
||||||
CurrentColor => self.Color.color,
|
CurrentColor => self.Color.get().color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new cascade context.
|
/// Returns the initial values for all style structs as defined by the specification.
|
||||||
fn new_cascade_context(style_Color: &style_structs::Color,
|
pub fn initial_values() -> ComputedValues {
|
||||||
style_Font: &style_structs::Font,
|
ComputedValues {
|
||||||
style_Box: &style_structs::Box,
|
% for style_struct in STYLE_STRUCTS:
|
||||||
is_root_element: bool)
|
${style_struct.name}: CowArc::new(style_structs::${style_struct.name} {
|
||||||
-> computed::Context {
|
% for longhand in style_struct.longhands:
|
||||||
computed::Context {
|
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||||
current_color: style_Color.color,
|
% endfor
|
||||||
parent_font_size: style_Font.font_size,
|
}),
|
||||||
font_size: style_Font.font_size,
|
% endfor
|
||||||
font_weight: style_Font.font_weight,
|
|
||||||
position: style_Box.position,
|
|
||||||
float: style_Box.float,
|
|
||||||
is_root_element: is_root_element,
|
|
||||||
border_top_style: longhands::border_top_style::get_initial_value(),
|
|
||||||
border_right_style: longhands::border_top_style::get_initial_value(),
|
|
||||||
border_bottom_style: longhands::border_top_style::get_initial_value(),
|
|
||||||
border_left_style: longhands::border_top_style::get_initial_value(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn border_is_present(border_style: longhands::border_top_style::computed_value::T) -> bool {
|
|
||||||
match border_style {
|
|
||||||
longhands::border_top_style::hidden | longhands::border_top_style::none => false,
|
|
||||||
_ => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,9 +1159,12 @@ fn border_is_present(border_style: longhands::border_top_style::computed_value::
|
||||||
///
|
///
|
||||||
/// * `parent_style`: The parent style, if applicable; if `None`, this is the root node.
|
/// * `parent_style`: The parent style, if applicable; if `None`, this is the root node.
|
||||||
///
|
///
|
||||||
|
/// * `initial_values`: The initial set of CSS values as defined by the specification.
|
||||||
|
///
|
||||||
/// Returns the computed values.
|
/// Returns the computed values.
|
||||||
pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
|
pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
|
||||||
parent_style: Option< &ComputedValues >)
|
parent_style: Option< &ComputedValues>,
|
||||||
|
initial_values: &ComputedValues)
|
||||||
-> ComputedValues {
|
-> ComputedValues {
|
||||||
let is_root_element;
|
let is_root_element;
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
|
@ -1197,73 +1177,90 @@ pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
|
||||||
% if style_struct.inherited:
|
% if style_struct.inherited:
|
||||||
style_${style_struct.name} = parent_style.${style_struct.name}.clone();
|
style_${style_struct.name} = parent_style.${style_struct.name}.clone();
|
||||||
% else:
|
% else:
|
||||||
style_${style_struct.name} = style_structs::${style_struct.name} {
|
style_${style_struct.name} = initial_values.${style_struct.name}.clone();
|
||||||
% for longhand in style_struct.longhands:
|
% endif
|
||||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
|
||||||
% endfor
|
|
||||||
};
|
|
||||||
%endif
|
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
is_root_element = true;
|
is_root_element = true;
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
style_${style_struct.name} = style_structs::${style_struct.name} {
|
style_${style_struct.name} = initial_values.${style_struct.name}.clone();
|
||||||
% for longhand in style_struct.longhands:
|
|
||||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
|
||||||
% endfor
|
|
||||||
};
|
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut context = new_cascade_context(&style_Color, &style_Font, &style_Box, is_root_element);
|
let mut context = computed::Context::new(&style_Color,
|
||||||
|
&style_Font,
|
||||||
|
&style_Box,
|
||||||
|
&style_Border,
|
||||||
|
is_root_element);
|
||||||
|
|
||||||
<%def name="apply(priority)">
|
<%def name="apply(needed_for_context)">
|
||||||
for sub_list in applicable_declarations.iter() {
|
for sub_list in applicable_declarations.iter() {
|
||||||
for declaration in sub_list.get().iter() {
|
for declaration in sub_list.get().iter() {
|
||||||
match declaration {
|
match declaration {
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
% for property in style_struct.longhands:
|
% for property in style_struct.longhands:
|
||||||
% if property.priority == priority:
|
% if (property.needed_for_context and needed_for_context) or not \
|
||||||
|
needed_for_context:
|
||||||
&${property.ident}_declaration(SpecifiedValue(ref value)) => {
|
&${property.ident}_declaration(SpecifiedValue(ref value)) => {
|
||||||
// Overwrite earlier declarations.
|
let computed_value =
|
||||||
// TODO: can we avoid a copy?
|
|
||||||
style_${style_struct.name}.${property.ident} =
|
|
||||||
longhands::${property.ident}::to_computed_value(
|
longhands::${property.ident}::to_computed_value(
|
||||||
(*value).clone(),
|
(*value).clone(),
|
||||||
&mut context)
|
&context);
|
||||||
|
% if property.needed_for_context and needed_for_context:
|
||||||
|
context.set_${property.ident}(computed_value)
|
||||||
|
% elif not needed_for_context:
|
||||||
|
// Overwrite earlier declarations.
|
||||||
|
style_${style_struct.name}.get_mut().${property.ident} =
|
||||||
|
computed_value
|
||||||
|
% endif
|
||||||
}
|
}
|
||||||
|
&${property.ident}_declaration(CSSWideKeyword(Initial)) => {
|
||||||
|
let computed_value =
|
||||||
|
longhands::${property.ident}::get_initial_value();
|
||||||
|
% if property.needed_for_context and needed_for_context:
|
||||||
|
context.set_${property.ident}(computed_value)
|
||||||
|
% elif not needed_for_context:
|
||||||
|
// Overwrite earlier declarations.
|
||||||
|
style_${style_struct.name}.get_mut().${property.ident} =
|
||||||
|
computed_value
|
||||||
|
% endif
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
% if not needed_for_context:
|
||||||
&${property.ident}_declaration(CSSWideKeyword(Inherit)) => {
|
&${property.ident}_declaration(CSSWideKeyword(Inherit)) => {
|
||||||
// This is a bit slow, but this is rare so it shouldn't matter.
|
// This is a bit slow, but this is rare so it shouldn't matter.
|
||||||
match parent_style {
|
match parent_style {
|
||||||
None => {
|
None => {
|
||||||
style_${style_struct.name}.${property.ident} =
|
style_${style_struct.name}.get_mut()
|
||||||
|
.${property.ident} =
|
||||||
longhands::${property.ident}::get_initial_value()
|
longhands::${property.ident}::get_initial_value()
|
||||||
}
|
}
|
||||||
Some(ref parent_style) => {
|
Some(ref parent_style) => {
|
||||||
style_${style_struct.name}.${property.ident} =
|
style_${style_struct.name}.get_mut()
|
||||||
|
.${property.ident} =
|
||||||
parent_style.${style_struct.name}
|
parent_style.${style_struct.name}
|
||||||
|
.get()
|
||||||
.${property.ident}
|
.${property.ident}
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&${property.ident}_declaration(CSSWideKeyword(Initial)) => {
|
|
||||||
style_${style_struct.name}.${property.ident} =
|
|
||||||
longhands::${property.ident}::get_initial_value()
|
|
||||||
}
|
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
_ => {}
|
% if needed_for_context:
|
||||||
|
_ => {}
|
||||||
|
% endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
${apply("High")}
|
${apply(True)}
|
||||||
${apply("Normal")}
|
context.use_parent_font_size = false;
|
||||||
|
${apply(False)}
|
||||||
|
|
||||||
ComputedValues {
|
ComputedValues {
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub use stylesheets::Stylesheet;
|
||||||
pub use selector_matching::{Stylist, StylesheetOrigin, UserAgentOrigin, AuthorOrigin, UserOrigin};
|
pub use selector_matching::{Stylist, StylesheetOrigin, UserAgentOrigin, AuthorOrigin, UserOrigin};
|
||||||
pub use properties::{cascade, PropertyDeclaration, ComputedValues, computed_values};
|
pub use properties::{cascade, PropertyDeclaration, ComputedValues, computed_values};
|
||||||
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||||
|
pub use properties::{initial_values};
|
||||||
pub use errors::with_errors_silenced;
|
pub use errors::with_errors_silenced;
|
||||||
pub use node::{TElement, TNode};
|
pub use node::{TElement, TNode};
|
||||||
pub use selectors::{PseudoElement, Before, After, AttrSelector, SpecificNamespace, AnyNamespace};
|
pub use selectors::{PseudoElement, Before, After, AttrSelector, SpecificNamespace, AnyNamespace};
|
||||||
|
|
100
src/components/util/cowarc.rs
Normal file
100
src/components/util/cowarc.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! An atomically reference counted type that copies itself on mutation.
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
use std::ptr;
|
||||||
|
use std::sync::atomics::{AtomicUint, SeqCst};
|
||||||
|
|
||||||
|
struct CowArcAlloc<T> {
|
||||||
|
ref_count: AtomicUint,
|
||||||
|
data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe_no_drop_flag]
|
||||||
|
pub struct CowArc<T> {
|
||||||
|
priv ptr: *mut CowArcAlloc<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe_destructor]
|
||||||
|
impl<T> Drop for CowArc<T> {
|
||||||
|
#[inline]
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.ptr != ptr::mut_null() && (*self.ptr).ref_count.fetch_sub(1, SeqCst) == 1 {
|
||||||
|
let _kill_it: ~CowArcAlloc<T> = cast::transmute(self.ptr);
|
||||||
|
self.ptr = ptr::mut_null()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Eq + Freeze + Clone> Eq for CowArc<T> {
|
||||||
|
fn eq(&self, other: &CowArc<T>) -> bool {
|
||||||
|
self.get() == other.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Freeze + Clone> Clone for CowArc<T> {
|
||||||
|
#[inline]
|
||||||
|
fn clone(&self) -> CowArc<T> {
|
||||||
|
unsafe {
|
||||||
|
drop((*self.ptr).ref_count.fetch_add(1, SeqCst));
|
||||||
|
}
|
||||||
|
CowArc {
|
||||||
|
ptr: self.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:Freeze + Clone> CowArc<T> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(value: T) -> CowArc<T> {
|
||||||
|
let alloc = ~CowArcAlloc {
|
||||||
|
ref_count: AtomicUint::new(1),
|
||||||
|
data: value,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
CowArc {
|
||||||
|
ptr: cast::transmute(alloc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn shared(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
(*self.ptr).ref_count.load(SeqCst) != 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get<'a>(&'a self) -> &'a T {
|
||||||
|
unsafe {
|
||||||
|
cast::transmute(&(*self.ptr).data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn get_mut<'a>(&'a mut self) -> &'a mut T {
|
||||||
|
unsafe {
|
||||||
|
if (*self.ptr).ref_count.load(SeqCst) == 1 {
|
||||||
|
return cast::transmute(&mut (*self.ptr).data)
|
||||||
|
}
|
||||||
|
|
||||||
|
let copy = ~CowArcAlloc {
|
||||||
|
ref_count: AtomicUint::new(1),
|
||||||
|
data: (*self.ptr).data.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
*self = CowArc {
|
||||||
|
ptr: cast::transmute(copy),
|
||||||
|
};
|
||||||
|
|
||||||
|
cast::transmute(&mut (*self.ptr).data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ extern mod native;
|
||||||
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
pub mod concurrentmap;
|
pub mod concurrentmap;
|
||||||
|
pub mod cowarc;
|
||||||
pub mod debug;
|
pub mod debug;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue