mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +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 script::layout_interface::LayoutChan;
|
||||
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 {
|
||||
normal: SmallVec16<Arc<~[PropertyDeclaration]>>,
|
||||
|
@ -43,12 +43,14 @@ pub trait MatchMethods {
|
|||
stylist: &Stylist,
|
||||
layout_chan: &LayoutChan,
|
||||
applicable_declarations: &mut ApplicableDeclarations,
|
||||
initial_values: &ComputedValues,
|
||||
parent: Option<LayoutNode>);
|
||||
|
||||
fn match_node(&self, stylist: &Stylist, applicable_declarations: &mut ApplicableDeclarations);
|
||||
|
||||
unsafe fn cascade_node(&self,
|
||||
parent: Option<LayoutNode>,
|
||||
initial_values: &ComputedValues,
|
||||
applicable_declarations: &ApplicableDeclarations);
|
||||
}
|
||||
|
||||
|
@ -79,6 +81,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
stylist: &Stylist,
|
||||
layout_chan: &LayoutChan,
|
||||
applicable_declarations: &mut ApplicableDeclarations,
|
||||
initial_values: &ComputedValues,
|
||||
parent: Option<LayoutNode>) {
|
||||
self.initialize_layout_data((*layout_chan).clone());
|
||||
|
||||
|
@ -87,7 +90,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
self.cascade_node(parent, applicable_declarations)
|
||||
self.cascade_node(parent, initial_values, applicable_declarations)
|
||||
}
|
||||
|
||||
applicable_declarations.clear();
|
||||
|
@ -96,12 +99,14 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
kid.match_and_cascade_subtree(stylist,
|
||||
layout_chan,
|
||||
applicable_declarations,
|
||||
initial_values,
|
||||
Some(*self))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn cascade_node(&self,
|
||||
parent: Option<LayoutNode>,
|
||||
initial_values: &ComputedValues,
|
||||
applicable_declarations: &ApplicableDeclarations) {
|
||||
macro_rules! cascade_node(
|
||||
($applicable_declarations: expr, $style: ident) => {{
|
||||
|
@ -124,30 +129,33 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let computed_values = match parent_style {
|
||||
Some(ref style) => {
|
||||
Arc::new(cascade($applicable_declarations.as_slice(),
|
||||
Some(style.get())))
|
||||
}
|
||||
None => Arc::new(cascade($applicable_declarations.as_slice(), None)),
|
||||
};
|
||||
|
||||
let mut layout_data_ref = self.mutate_layout_data();
|
||||
match *layout_data_ref.get() {
|
||||
None => fail!("no layout data"),
|
||||
Some(ref mut layout_data) => {
|
||||
let style = &mut layout_data.data.$style;
|
||||
match *style {
|
||||
None => (),
|
||||
Some(ref previous_style) => {
|
||||
layout_data.data.restyle_damage = Some(incremental::compute_damage(
|
||||
previous_style.get(), computed_values.get()).to_int())
|
||||
}
|
||||
}
|
||||
*style = Some(computed_values)
|
||||
}
|
||||
let computed_values = match parent_style {
|
||||
Some(ref style) => {
|
||||
Arc::new(cascade($applicable_declarations.as_slice(),
|
||||
Some(style.get()),
|
||||
initial_values))
|
||||
}
|
||||
None => Arc::new(cascade($applicable_declarations.as_slice(),
|
||||
None,
|
||||
initial_values)),
|
||||
};
|
||||
|
||||
let mut layout_data_ref = self.mutate_layout_data();
|
||||
match *layout_data_ref.get() {
|
||||
None => fail!("no layout data"),
|
||||
Some(ref mut layout_data) => {
|
||||
let style = &mut layout_data.data.$style;
|
||||
match *style {
|
||||
None => (),
|
||||
Some(ref previous_style) => {
|
||||
layout_data.data.restyle_damage = Some(incremental::compute_damage(
|
||||
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 }
|
||||
|
||||
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 }
|
||||
|
||||
/* Begin bidirectionality settings (do not change) */
|
||||
|
@ -106,6 +111,8 @@ ul, ol, dl { page-break-before: avoid }
|
|||
}
|
||||
|
||||
/* Servo additions */
|
||||
:link { color: blue }
|
||||
a:link,
|
||||
area:link,
|
||||
link:link { color: blue }
|
||||
script { display: none }
|
||||
style { display: none }
|
||||
style { display: none }
|
||||
|
|
|
@ -193,9 +193,9 @@ impl BlockFlow {
|
|||
let style = box_.style();
|
||||
|
||||
let (width, maybe_margin_left, maybe_margin_right) =
|
||||
(MaybeAuto::from_style(style.Box.width, remaining_width),
|
||||
MaybeAuto::from_style(style.Margin.margin_left, remaining_width),
|
||||
MaybeAuto::from_style(style.Margin.margin_right, remaining_width));
|
||||
(MaybeAuto::from_style(style.Box.get().width, remaining_width),
|
||||
MaybeAuto::from_style(style.Margin.get().margin_left, remaining_width),
|
||||
MaybeAuto::from_style(style.Margin.get().margin_right, remaining_width));
|
||||
|
||||
let (width, margin_left, margin_right) = self.compute_horiz(width,
|
||||
maybe_margin_left,
|
||||
|
@ -206,7 +206,7 @@ impl BlockFlow {
|
|||
// 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'.
|
||||
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),
|
||||
maybe_margin_left,
|
||||
maybe_margin_right,
|
||||
|
@ -218,7 +218,7 @@ impl BlockFlow {
|
|||
// 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'.
|
||||
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 {
|
||||
self.compute_horiz(Specified(computed_min_width),
|
||||
maybe_margin_left,
|
||||
|
@ -235,13 +235,13 @@ impl BlockFlow {
|
|||
// CSS Section 10.3.5
|
||||
fn compute_float_margins(&self, box_: &Box, remaining_width: Au) -> (Au, Au, Au) {
|
||||
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();
|
||||
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();
|
||||
let shrink_to_fit = geometry::min(self.base.pref_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);
|
||||
debug!("assign_widths_float -- width: {}", width);
|
||||
return (width, margin_left, margin_right);
|
||||
|
@ -376,7 +376,7 @@ impl BlockFlow {
|
|||
// block per CSS 2.1 § 10.5.
|
||||
// TODO: We need to pass in the correct containing block height
|
||||
// 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,
|
||||
Specified(value) => value
|
||||
};
|
||||
|
@ -516,7 +516,7 @@ impl BlockFlow {
|
|||
box_.border.get().top + box_.border.get().bottom;
|
||||
|
||||
//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();
|
||||
|
||||
height = geometry::max(height, height_prop) + noncontent_height;
|
||||
|
@ -719,7 +719,7 @@ impl Flow for BlockFlow {
|
|||
let style = box_.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);
|
||||
// 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();
|
||||
|
||||
// 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();
|
||||
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();
|
||||
|
||||
let (width, margin_left, margin_right) = if self.is_float() {
|
||||
|
|
|
@ -373,7 +373,7 @@ impl Box {
|
|||
}
|
||||
(_, _) => {
|
||||
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 => {
|
||||
height = screen_height - position_offsets.top - position_offsets.bottom;
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ impl Box {
|
|||
}
|
||||
(_, _) => {
|
||||
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 => {
|
||||
width = screen_width - position_offsets.left - position_offsets.right;
|
||||
}
|
||||
|
@ -446,14 +446,14 @@ impl Box {
|
|||
}
|
||||
|
||||
let style = self.style();
|
||||
let width = MaybeAuto::from_style(style.Box.width, Au::new(0)).specified_or_zero();
|
||||
let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
|
||||
let width = MaybeAuto::from_style(style.Box.get().width, Au::new(0)).specified_or_zero();
|
||||
let margin_left = MaybeAuto::from_style(style.Margin.get().margin_left,
|
||||
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();
|
||||
|
||||
let padding_left = self.compute_padding_length(style.Padding.padding_left, Au::new(0));
|
||||
let padding_right = self.compute_padding_length(style.Padding.padding_right, 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.get().padding_right, Au(0));
|
||||
|
||||
width + margin_left + margin_right + padding_left + padding_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,
|
||||
style.Border.border_top_style),
|
||||
width(style.Border.border_right_width,
|
||||
style.Border.border_right_style),
|
||||
width(style.Border.border_bottom_width,
|
||||
style.Border.border_bottom_style),
|
||||
width(style.Border.border_left_width,
|
||||
style.Border.border_left_style)))
|
||||
self.border.set(SideOffsets2D::new(width(style.Border.get().border_top_width,
|
||||
style.Border.get().border_top_style),
|
||||
width(style.Border.get().border_right_width,
|
||||
style.Border.get().border_right_style),
|
||||
width(style.Border.get().border_bottom_width,
|
||||
style.Border.get().border_bottom_style),
|
||||
width(style.Border.get().border_left_width,
|
||||
style.Border.get().border_left_style)))
|
||||
}
|
||||
|
||||
pub fn compute_positioned_offsets(&self, style: &ComputedValues, containing_width: Au, containing_height: Au) {
|
||||
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(),
|
||||
MaybeAuto::from_style(style.PositionOffsets.right, containing_width)
|
||||
MaybeAuto::from_style(style.PositionOffsets.get().right, containing_width)
|
||||
.specified_or_zero(),
|
||||
MaybeAuto::from_style(style.PositionOffsets.bottom, containing_height)
|
||||
MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_height)
|
||||
.specified_or_zero(),
|
||||
MaybeAuto::from_style(style.PositionOffsets.left, containing_width)
|
||||
MaybeAuto::from_style(style.PositionOffsets.get().left, containing_width)
|
||||
.specified_or_zero()));
|
||||
}
|
||||
|
||||
/// Populates the box model padding parameters from the given computed style.
|
||||
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),
|
||||
self.compute_padding_length(style.Padding.padding_right,
|
||||
self.compute_padding_length(style.Padding
|
||||
.get()
|
||||
.padding_right,
|
||||
containing_block_width),
|
||||
self.compute_padding_length(style.Padding.padding_bottom,
|
||||
self.compute_padding_length(style.Padding
|
||||
.get()
|
||||
.padding_bottom,
|
||||
containing_block_width),
|
||||
self.compute_padding_length(style.Padding.padding_left,
|
||||
self.compute_padding_length(style.Padding
|
||||
.get()
|
||||
.padding_left,
|
||||
containing_block_width));
|
||||
self.padding.set(padding)
|
||||
}
|
||||
|
@ -679,28 +687,28 @@ impl Box {
|
|||
}
|
||||
}
|
||||
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
|
||||
match (style.PositionOffsets.left, style.PositionOffsets.right) {
|
||||
match (style.PositionOffsets.get().left, style.PositionOffsets.get().right) {
|
||||
(LPA_Auto, _) => {
|
||||
-MaybeAuto::from_style(style.PositionOffsets.right, block_width)
|
||||
-MaybeAuto::from_style(style.PositionOffsets.get().right, block_width)
|
||||
.specified_or_zero()
|
||||
}
|
||||
(_, _) => {
|
||||
MaybeAuto::from_style(style.PositionOffsets.left, block_width)
|
||||
MaybeAuto::from_style(style.PositionOffsets.get().left, block_width)
|
||||
.specified_or_zero()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, _) => {
|
||||
-MaybeAuto::from_style(style.PositionOffsets.bottom, block_height)
|
||||
-MaybeAuto::from_style(style.PositionOffsets.get().bottom, block_height)
|
||||
.specified_or_zero()
|
||||
}
|
||||
(_, _) => {
|
||||
MaybeAuto::from_style(style.PositionOffsets.top, block_height)
|
||||
MaybeAuto::from_style(style.PositionOffsets.get().top, block_height)
|
||||
.specified_or_zero()
|
||||
}
|
||||
}
|
||||
|
@ -711,7 +719,7 @@ impl Box {
|
|||
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.y = rel_pos.y + top_bottom(self.style(), container_block_size.height);
|
||||
}
|
||||
|
@ -720,9 +728,11 @@ impl Box {
|
|||
match info.get() {
|
||||
&Some(ref info) => {
|
||||
for info in info.parent_info.iter() {
|
||||
if info.style.get().Box.position == position::relative {
|
||||
rel_pos.x = rel_pos.x + left_right(info.style.get(), container_block_size.width);
|
||||
rel_pos.y = rel_pos.y + top_bottom(info.style.get(), container_block_size.height);
|
||||
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.y = rel_pos.y + top_bottom(info.style.get(),
|
||||
container_block_size.height);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -737,7 +747,7 @@ impl Box {
|
|||
#[inline(always)]
|
||||
pub fn clear(&self) -> Option<ClearType> {
|
||||
let style = self.style();
|
||||
match style.Box.clear {
|
||||
match style.Box.get().clear {
|
||||
clear::none => None,
|
||||
clear::left => Some(ClearLeft),
|
||||
clear::right => Some(ClearRight),
|
||||
|
@ -755,20 +765,20 @@ impl Box {
|
|||
debug!("(font style) start");
|
||||
|
||||
// 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 {
|
||||
font_family::FamilyName(ref name) => (*name).clone(),
|
||||
}
|
||||
});
|
||||
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);
|
||||
|
||||
FontStyle {
|
||||
pt_size: font_size,
|
||||
weight: my_style.Font.font_weight,
|
||||
style: my_style.Font.font_style,
|
||||
weight: my_style.Font.get().font_weight,
|
||||
style: my_style.Font.get().font_style,
|
||||
families: font_families,
|
||||
}
|
||||
}
|
||||
|
@ -781,19 +791,19 @@ impl Box {
|
|||
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
|
||||
/// node.
|
||||
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 {
|
||||
self.style().InheritedBox.line_height
|
||||
self.style().InheritedBox.get().line_height
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
|
@ -804,7 +814,7 @@ impl Box {
|
|||
/// model. Therefore, this is a best lower bound approximation, but the end result may actually
|
||||
/// have the various decoration flags turned on afterward.
|
||||
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.
|
||||
|
@ -862,7 +872,7 @@ impl Box {
|
|||
bg_rect.origin.y = box_info.baseline + offset.y - info.font_ascent;
|
||||
bg_rect.size.height = info.font_ascent + info.font_descent;
|
||||
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) {
|
||||
lists.with_mut(|lists| {
|
||||
|
@ -886,14 +896,14 @@ impl Box {
|
|||
bg_rect.size.height = bg_rect.size.height + border.top + border.bottom;
|
||||
|
||||
let style = info.style.get();
|
||||
let top_color = style.resolve_color(style.Border.border_top_color);
|
||||
let right_color = style.resolve_color(style.Border.border_right_color);
|
||||
let bottom_color = style.resolve_color(style.Border.border_bottom_color);
|
||||
let left_color = style.resolve_color(style.Border.border_left_color);
|
||||
let top_style = style.Border.border_top_style;
|
||||
let right_style = style.Border.border_right_style;
|
||||
let bottom_style = style.Border.border_bottom_style;
|
||||
let left_style = style.Border.border_left_style;
|
||||
let top_color = style.resolve_color(style.Border.get().border_top_color);
|
||||
let right_color = style.resolve_color(style.Border.get().border_right_color);
|
||||
let bottom_color = style.resolve_color(style.Border.get().border_bottom_color);
|
||||
let left_color = style.resolve_color(style.Border.get().border_left_color);
|
||||
let top_style = style.Border.get().border_top_style;
|
||||
let right_style = style.Border.get().border_right_style;
|
||||
let bottom_style = style.Border.get().border_bottom_style;
|
||||
let left_style = style.Border.get().border_left_style;
|
||||
|
||||
|
||||
lists.with_mut(|lists| {
|
||||
|
@ -935,7 +945,7 @@ impl Box {
|
|||
// inefficient. What we really want is something like "nearest ancestor element that
|
||||
// doesn't have a box".
|
||||
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) {
|
||||
lists.with_mut(|lists| {
|
||||
let solid_color_display_item = ~SolidColorDisplayItem {
|
||||
|
@ -965,14 +975,14 @@ impl Box {
|
|||
}
|
||||
|
||||
let style = self.style();
|
||||
let top_color = style.resolve_color(style.Border.border_top_color);
|
||||
let right_color = style.resolve_color(style.Border.border_right_color);
|
||||
let bottom_color = style.resolve_color(style.Border.border_bottom_color);
|
||||
let left_color = style.resolve_color(style.Border.border_left_color);
|
||||
let top_style = style.Border.border_top_style;
|
||||
let right_style = style.Border.border_right_style;
|
||||
let bottom_style = style.Border.border_bottom_style;
|
||||
let left_style = style.Border.border_left_style;
|
||||
let top_color = style.resolve_color(style.Border.get().border_top_color);
|
||||
let right_color = style.resolve_color(style.Border.get().border_right_color);
|
||||
let bottom_color = style.resolve_color(style.Border.get().border_bottom_color);
|
||||
let left_color = style.resolve_color(style.Border.get().border_left_color);
|
||||
let top_style = style.Border.get().border_top_style;
|
||||
let right_style = style.Border.get().border_right_style;
|
||||
let bottom_style = style.Border.get().border_bottom_style;
|
||||
let left_style = style.Border.get().border_left_style;
|
||||
|
||||
let mut abs_bounds = abs_bounds.clone();
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1057,7 @@ impl Box {
|
|||
match self.specific {
|
||||
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
|
||||
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.
|
||||
let mut flow_flags = flow::base(flow).flags_info.clone();
|
||||
|
@ -1472,13 +1482,13 @@ impl Box {
|
|||
}
|
||||
ImageBox(ref image_box_info) => {
|
||||
// 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,
|
||||
container_width);
|
||||
|
||||
// FIXME(ksh8281): we shouldn't figure height this way
|
||||
// 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,
|
||||
Au::new(0));
|
||||
|
||||
|
@ -1520,11 +1530,11 @@ impl Box {
|
|||
let width = image_box_info.computed_width();
|
||||
// FIXME(ksh8281): we shouldn't assign height this way
|
||||
// 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,
|
||||
Au::new(0));
|
||||
|
||||
let height = match (self.style().Box.width,
|
||||
let height = match (self.style().Box.get().width,
|
||||
image_box_info.dom_width,
|
||||
height) {
|
||||
(LPA_Auto, None, Auto) => {
|
||||
|
@ -1575,7 +1585,7 @@ impl Box {
|
|||
|
||||
/// Returns true if the contents should be clipped (i.e. if `overflow` is `hidden`).
|
||||
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.
|
||||
|
|
|
@ -628,7 +628,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
|||
let (display, float, position) = match node.type_id() {
|
||||
ElementNodeTypeId(_) => {
|
||||
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_),
|
||||
CommentNodeTypeId |
|
||||
|
@ -730,7 +730,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
|||
//
|
||||
// If you implement other values for this property, you will almost certainly
|
||||
// want to update this check.
|
||||
match self.style().get().InheritedText.white_space {
|
||||
match self.style().get().InheritedText.get().white_space {
|
||||
white_space::normal => true,
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use script::layout_interface::LayoutChan;
|
|||
use servo_msg::constellation_msg::ConstellationChan;
|
||||
use servo_net::local_image_cache::LocalImageCache;
|
||||
use servo_util::geometry::Au;
|
||||
use style::Stylist;
|
||||
use style::{ComputedValues, Stylist};
|
||||
|
||||
#[thread_local]
|
||||
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.
|
||||
stylist: *Stylist,
|
||||
|
||||
/// The initial set of CSS properties.
|
||||
initial_css_values: Arc<ComputedValues>,
|
||||
|
||||
/// The root node at which we're starting the layout.
|
||||
reflow_root: OpaqueNode,
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ static TEXT_ALIGN_SHIFT: u8 = 4;
|
|||
impl FlowFlagsInfo {
|
||||
/// Creates a new set of flow flags from the given style.
|
||||
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);
|
||||
flags.set_override_underline(text_decoration.underline);
|
||||
flags.set_override_overline(text_decoration.overline);
|
||||
|
@ -318,9 +318,9 @@ impl FlowFlagsInfo {
|
|||
// TODO(ksh8281) compute text-decoration-color,style,line
|
||||
let rare_flow_flags = if flags.is_text_decoration_enabled() {
|
||||
Some(~RareFlowFlags {
|
||||
underline_color: style.Color.color.to_gfx_color(),
|
||||
overline_color: style.Color.color.to_gfx_color(),
|
||||
line_through_color: style.Color.color.to_gfx_color(),
|
||||
underline_color: style.Color.get().color.to_gfx_color(),
|
||||
overline_color: style.Color.get().color.to_gfx_color(),
|
||||
line_through_color: style.Color.get().color.to_gfx_color(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -107,7 +107,7 @@ impl RestyleDamage {
|
|||
macro_rules! add_if_not_equal(
|
||||
($old:ident, $new:ident, $damage: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),* ) );
|
||||
}
|
||||
})
|
||||
|
|
|
@ -794,7 +794,7 @@ impl Flow for InlineFlow {
|
|||
//
|
||||
// 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.
|
||||
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
|
||||
// content area. But for now we assume it's zero.
|
||||
|
|
|
@ -55,7 +55,8 @@ use std::comm::Port;
|
|||
use std::ptr;
|
||||
use std::task;
|
||||
use std::util;
|
||||
use style::{AuthorOrigin, Stylesheet, Stylist};
|
||||
use style::{AuthorOrigin, ComputedValues, Stylesheet, Stylist};
|
||||
use style;
|
||||
|
||||
/// Information needed by the layout task.
|
||||
pub struct LayoutTask {
|
||||
|
@ -97,6 +98,9 @@ pub struct LayoutTask {
|
|||
|
||||
stylist: ~Stylist,
|
||||
|
||||
/// The initial set of CSS values.
|
||||
initial_css_values: Arc<ComputedValues>,
|
||||
|
||||
/// The workers that we use for parallel operation.
|
||||
parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>,
|
||||
|
||||
|
@ -302,6 +306,7 @@ impl LayoutTask {
|
|||
|
||||
display_list_collection: None,
|
||||
stylist: ~new_stylist(),
|
||||
initial_css_values: Arc::new(style::initial_values()),
|
||||
parallel_traversal: parallel_traversal,
|
||||
profiler_chan: profiler_chan,
|
||||
opts: opts.clone()
|
||||
|
@ -332,6 +337,7 @@ impl LayoutTask {
|
|||
layout_chan: self.chan.clone(),
|
||||
font_context_info: font_context_info,
|
||||
stylist: &*self.stylist,
|
||||
initial_css_values: self.initial_css_values.clone(),
|
||||
reflow_root: OpaqueNode::from_layout_node(reflow_root),
|
||||
}
|
||||
}
|
||||
|
@ -565,6 +571,7 @@ impl LayoutTask {
|
|||
node.match_and_cascade_subtree(self.stylist,
|
||||
&layout_ctx.layout_chan,
|
||||
&mut applicable_declarations,
|
||||
layout_ctx.initial_css_values.get(),
|
||||
None)
|
||||
}
|
||||
Some(ref mut traversal) => {
|
||||
|
@ -638,6 +645,7 @@ impl LayoutTask {
|
|||
.resolve_color(thread_safe_child.style()
|
||||
.get()
|
||||
.Background
|
||||
.get()
|
||||
.background_color)
|
||||
.to_gfx_color()
|
||||
};
|
||||
|
|
|
@ -163,7 +163,9 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode,
|
|||
} else {
|
||||
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.
|
||||
let mut child_count = 0;
|
||||
|
|
|
@ -160,33 +160,111 @@ pub mod specified {
|
|||
}
|
||||
|
||||
pub mod computed {
|
||||
use cssparser;
|
||||
pub use CSSColor = cssparser::Color;
|
||||
pub use compute_CSSColor = super::super::longhands::computed_as_specified;
|
||||
use super::*;
|
||||
use super::super::longhands;
|
||||
use super::super::{longhands, style_structs};
|
||||
use servo_util::cowarc::CowArc;
|
||||
pub use servo_util::geometry::Au;
|
||||
|
||||
pub struct Context {
|
||||
current_color: cssparser::RGBA,
|
||||
parent_font_size: Au,
|
||||
font_size: Au,
|
||||
font_weight: longhands::font_weight::computed_value::T,
|
||||
position: longhands::position::SpecifiedValue,
|
||||
float: longhands::float::SpecifiedValue,
|
||||
color: longhands::color::computed_value::T,
|
||||
parent_font_weight: longhands::font_weight::computed_value::T,
|
||||
parent_font_size: longhands::font_size::computed_value::T,
|
||||
font_size: longhands::font_size::computed_value::T,
|
||||
positioned: bool,
|
||||
floated: bool,
|
||||
border_top_present: bool,
|
||||
border_right_present: bool,
|
||||
border_bottom_present: bool,
|
||||
border_left_present: bool,
|
||||
is_root_element: bool,
|
||||
border_top_style: longhands::border_top_style::computed_value::T,
|
||||
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,
|
||||
use_parent_font_size: bool,
|
||||
// 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]
|
||||
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 {
|
||||
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::Ex(value) => {
|
||||
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)]
|
||||
pub enum LengthOrPercentage {
|
||||
LP_Length(Au),
|
||||
|
@ -203,7 +294,7 @@ pub mod computed {
|
|||
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
|
||||
-> LengthOrPercentage {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +308,7 @@ pub mod computed {
|
|||
pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto,
|
||||
context: &Context) -> LengthOrPercentageOrAuto {
|
||||
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_Auto => LPA_Auto,
|
||||
}
|
||||
|
@ -232,7 +323,7 @@ pub mod computed {
|
|||
pub fn compute_LengthOrPercentageOrNone(value: specified::LengthOrPercentageOrNone,
|
||||
context: &Context) -> LengthOrPercentageOrNone {
|
||||
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_None => LPN_None,
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use std::ascii::StrAsciiExt;
|
||||
pub use extra::arc::Arc;
|
||||
use servo_util::cowarc::CowArc;
|
||||
pub use cssparser::*;
|
||||
pub use cssparser::ast::*;
|
||||
|
||||
|
@ -25,18 +26,17 @@ def to_rust_ident(name):
|
|||
return name
|
||||
|
||||
class Longhand(object):
|
||||
def __init__(self, name, priority):
|
||||
def __init__(self, name, needed_for_context):
|
||||
self.name = name
|
||||
self.ident = to_rust_ident(name)
|
||||
self.style_struct = THIS_STYLE_STRUCT
|
||||
self.priority = priority
|
||||
self.needed_for_context = needed_for_context
|
||||
|
||||
class Shorthand(object):
|
||||
def __init__(self, name, priority, sub_properties):
|
||||
def __init__(self, name, sub_properties):
|
||||
self.name = name
|
||||
self.ident = to_rust_ident(name)
|
||||
self.sub_properties = [LONGHANDS_BY_NAME[s] for s in sub_properties]
|
||||
self.priority = priority
|
||||
|
||||
class StyleStruct(object):
|
||||
def __init__(self, name, inherited):
|
||||
|
@ -72,13 +72,13 @@ pub mod longhands {
|
|||
pub use super::*;
|
||||
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
|
||||
}
|
||||
|
||||
<%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)
|
||||
LONGHANDS.append(property)
|
||||
LONGHANDS_BY_NAME[name] = property
|
||||
|
@ -101,8 +101,8 @@ pub mod longhands {
|
|||
}
|
||||
</%def>
|
||||
|
||||
<%def name="longhand(name, priority='Normal', no_super=False)">
|
||||
<%self:raw_longhand name="${name}" priority="${priority}">
|
||||
<%def name="longhand(name, needed_for_context=False, no_super=False)">
|
||||
<%self:raw_longhand name="${name}" needed_for_context="${needed_for_context}">
|
||||
${caller.body()}
|
||||
pub fn parse_specified(input: &[ComponentValue])
|
||||
-> Option<DeclaredValue<SpecifiedValue>> {
|
||||
|
@ -111,8 +111,8 @@ pub mod longhands {
|
|||
</%self:raw_longhand>
|
||||
</%def>
|
||||
|
||||
<%def name="single_component_value(name, priority='Normal')">
|
||||
<%self:longhand name="${name}" priority="${priority}">
|
||||
<%def name="single_component_value(name, needed_for_context=False)">
|
||||
<%self:longhand name="${name}" needed_for_context="${needed_for_context}">
|
||||
${caller.body()}
|
||||
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
||||
one_component_value(input).and_then(from_component_value)
|
||||
|
@ -120,8 +120,8 @@ pub mod longhands {
|
|||
</%self:longhand>
|
||||
</%def>
|
||||
|
||||
<%def name="single_keyword_computed(name, values, priority='Normal')">
|
||||
<%self:single_component_value name="${name}" priority="${priority}">
|
||||
<%def name="single_keyword_computed(name, values, needed_for_context=False)">
|
||||
<%self:single_component_value name="${name}" needed_for_context="${needed_for_context}">
|
||||
${caller.body()}
|
||||
pub mod computed_value {
|
||||
#[deriving(Eq, Clone, FromPrimitive)]
|
||||
|
@ -148,8 +148,10 @@ pub mod longhands {
|
|||
</%self:single_component_value>
|
||||
</%def>
|
||||
|
||||
<%def name="single_keyword(name, values, priority='Normal')">
|
||||
<%self:single_keyword_computed name="${name}" values="${values}" priority="${priority}">
|
||||
<%def name="single_keyword(name, values, needed_for_context=False)">
|
||||
<%self:single_keyword_computed name="${name}"
|
||||
values="${values}"
|
||||
needed_for_context="${needed_for_context}">
|
||||
// The computed value is the same as the specified value.
|
||||
pub use to_computed_value = super::computed_as_specified;
|
||||
</%self:single_keyword_computed>
|
||||
|
@ -172,14 +174,14 @@ pub mod longhands {
|
|||
|
||||
// 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"]:
|
||||
${predefined_type("margin-" + side, "LengthOrPercentageOrAuto",
|
||||
"computed::LPA_Length(Au(0))")}
|
||||
% endfor
|
||||
|
||||
${new_style_struct("Padding", False)}
|
||||
${new_style_struct("Padding", is_inherited=False)}
|
||||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type("padding-" + side, "LengthOrPercentage",
|
||||
|
@ -187,33 +189,19 @@ pub mod longhands {
|
|||
"parse_non_negative")}
|
||||
% endfor
|
||||
|
||||
${new_style_struct("Border", False)}
|
||||
${new_style_struct("Border", is_inherited=False)}
|
||||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")}
|
||||
% endfor
|
||||
|
||||
// double groove ridge insed outset
|
||||
<%self:single_keyword_computed name="border-top-style"
|
||||
values="none solid dotted dashed hidden"
|
||||
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>
|
||||
${single_keyword("border-top-style", values="none solid dotted dashed hidden", \
|
||||
needed_for_context=True)}
|
||||
|
||||
% for side in ["right", "bottom", "left"]:
|
||||
<%self:longhand name="border-${side}-style", no_super="True", priority="High">
|
||||
pub use super::border_top_style::get_initial_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
|
||||
}
|
||||
|
||||
<%self:longhand name="border-${side}-style", no_super="True", needed_for_context="True">
|
||||
pub use super::border_top_style::{get_initial_value, parse, to_computed_value};
|
||||
pub type SpecifiedValue = super::border_top_style::SpecifiedValue;
|
||||
pub mod computed_value {
|
||||
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"]:
|
||||
<%self:longhand name="border-${side}-width">
|
||||
use super::super::border_is_present;
|
||||
pub type SpecifiedValue = specified::Length;
|
||||
pub mod computed_value {
|
||||
use super::super::Au;
|
||||
|
@ -250,18 +237,19 @@ pub mod longhands {
|
|||
pub fn parse(input: &[ComponentValue]) -> Option<SpecifiedValue> {
|
||||
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 {
|
||||
if !border_is_present(context.border_${side}_style) {
|
||||
if !context.border_${side}_present {
|
||||
Au(0)
|
||||
} else {
|
||||
computed::compute_Au(value, context, false)
|
||||
computed::compute_Au(value, context)
|
||||
}
|
||||
}
|
||||
</%self:longhand>
|
||||
% endfor
|
||||
|
||||
${new_style_struct("PositionOffsets", False)}
|
||||
${new_style_struct("PositionOffsets", is_inherited=False)}
|
||||
|
||||
% for side in ["top", "right", "bottom", "left"]:
|
||||
${predefined_type(side, "LengthOrPercentageOrAuto",
|
||||
|
@ -270,7 +258,7 @@ pub mod longhands {
|
|||
|
||||
// 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
|
||||
<%self:single_keyword_computed name="display"
|
||||
|
@ -279,16 +267,13 @@ pub mod longhands {
|
|||
table-row table-column-group table-column table-cell table-caption
|
||||
list-item
|
||||
none">
|
||||
#[inline]
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
// if context.is_root_element && value == list_item {
|
||||
// return block
|
||||
// }
|
||||
let positioned = match context.position {
|
||||
position::absolute | position::fixed => true,
|
||||
_ => false
|
||||
};
|
||||
if positioned || context.float != float::none || context.is_root_element {
|
||||
if context.positioned || context.floated || context.is_root_element {
|
||||
match value {
|
||||
// inline_table => table,
|
||||
inline | inline_block
|
||||
|
@ -304,8 +289,8 @@ pub mod longhands {
|
|||
}
|
||||
</%self:single_keyword_computed>
|
||||
|
||||
${single_keyword("position", "static absolute relative fixed")}
|
||||
${single_keyword("float", "none left right")}
|
||||
${single_keyword("position", "static absolute relative fixed", needed_for_context="True")}
|
||||
${single_keyword("float", "none left right", needed_for_context="True")}
|
||||
${single_keyword("clear", "none left right both")}
|
||||
|
||||
// CSS 2.1, Section 10 - Visual formatting model details
|
||||
|
@ -324,7 +309,7 @@ pub mod longhands {
|
|||
"computed::LPN_None",
|
||||
"parse_non_negative")}
|
||||
|
||||
${new_style_struct("InheritedBox", True)}
|
||||
${new_style_struct("InheritedBox", is_inherited=True)}
|
||||
|
||||
<%self:single_component_value name="line-height">
|
||||
#[deriving(Clone)]
|
||||
|
@ -358,12 +343,14 @@ pub mod longhands {
|
|||
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)
|
||||
-> computed_value::T {
|
||||
match value {
|
||||
SpecifiedNormal => Normal,
|
||||
SpecifiedLength(value) => Length(computed::compute_Au(value, context, false)),
|
||||
SpecifiedLength(value) => Length(computed::compute_Au(value, context)),
|
||||
SpecifiedNumber(value) => Number(value),
|
||||
}
|
||||
}
|
||||
|
@ -410,7 +397,9 @@ pub mod longhands {
|
|||
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)
|
||||
-> computed_value::T {
|
||||
match value {
|
||||
|
@ -482,15 +471,15 @@ pub mod longhands {
|
|||
|
||||
// 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",
|
||||
"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 type SpecifiedValue = RGBA;
|
||||
pub mod computed_value {
|
||||
|
@ -510,7 +499,7 @@ pub mod longhands {
|
|||
|
||||
// CSS 2.1, Section 15 - Fonts
|
||||
|
||||
${new_style_struct("Font", True)}
|
||||
${new_style_struct("Font", is_inherited=True)}
|
||||
|
||||
<%self:longhand name="font-family">
|
||||
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-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)]
|
||||
pub enum SpecifiedValue {
|
||||
Bolder,
|
||||
Lighther,
|
||||
Lighter,
|
||||
% for weight in range(100, 901, 100):
|
||||
SpecifiedWeight${weight},
|
||||
% endfor
|
||||
|
@ -612,7 +601,7 @@ pub mod longhands {
|
|||
"bold" => Some(SpecifiedWeight700),
|
||||
"normal" => Some(SpecifiedWeight400),
|
||||
"bolder" => Some(Bolder),
|
||||
"lighter" => Some(Lighther),
|
||||
"lighter" => Some(Lighter),
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
|
@ -647,14 +636,16 @@ pub mod longhands {
|
|||
}
|
||||
}
|
||||
}
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &mut computed::Context)
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T { Weight400 } // normal
|
||||
#[inline]
|
||||
pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context)
|
||||
-> computed_value::T {
|
||||
let result = match value {
|
||||
match value {
|
||||
% for weight in range(100, 901, 100):
|
||||
SpecifiedWeight${weight} => Weight${weight},
|
||||
% endfor
|
||||
Bolder => match context.font_weight {
|
||||
Bolder => match context.parent_font_weight {
|
||||
Weight100 => Weight400,
|
||||
Weight200 => Weight400,
|
||||
Weight300 => Weight400,
|
||||
|
@ -665,7 +656,7 @@ pub mod longhands {
|
|||
Weight800 => Weight900,
|
||||
Weight900 => Weight900,
|
||||
},
|
||||
Lighther => match context.font_weight {
|
||||
Lighter => match context.parent_font_weight {
|
||||
Weight100 => Weight100,
|
||||
Weight200 => Weight100,
|
||||
Weight300 => Weight100,
|
||||
|
@ -676,28 +667,29 @@ pub mod longhands {
|
|||
Weight800 => Weight700,
|
||||
Weight900 => Weight700,
|
||||
},
|
||||
};
|
||||
context.font_weight = result;
|
||||
result
|
||||
}
|
||||
}
|
||||
</%self:single_component_value>
|
||||
|
||||
<%self:single_component_value name="font-size" priority="High">
|
||||
pub use to_computed_value = super::super::common_types::computed::compute_Au;
|
||||
<%self:single_component_value name="font-size" needed_for_context="True">
|
||||
use super::super::common_types::computed::compute_Au_from_parent;
|
||||
pub type SpecifiedValue = specified::Length; // Percentages are the same as em.
|
||||
pub mod computed_value {
|
||||
use super::super::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 {
|
||||
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>
|
||||
/// TODO: support <absolute-size> and <relative-size>
|
||||
pub fn from_component_value(input: &ComponentValue) -> Option<SpecifiedValue> {
|
||||
|
@ -712,12 +704,12 @@ pub mod longhands {
|
|||
|
||||
// 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.)
|
||||
${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">
|
||||
pub use to_computed_value = super::computed_as_specified;
|
||||
|
@ -778,9 +770,9 @@ pub mod shorthands {
|
|||
pub use super::*;
|
||||
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)
|
||||
%>
|
||||
pub mod ${shorthand.ident} {
|
||||
|
@ -1127,7 +1119,7 @@ pub mod style_structs {
|
|||
#[deriving(Eq, Clone)]
|
||||
pub struct ComputedValues {
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
${style_struct.name}: style_structs::${style_struct.name},
|
||||
${style_struct.name}: CowArc<style_structs::${style_struct.name}>,
|
||||
% endfor
|
||||
}
|
||||
|
||||
|
@ -1142,36 +1134,21 @@ impl ComputedValues {
|
|||
pub fn resolve_color(&self, color: computed::CSSColor) -> RGBA {
|
||||
match color {
|
||||
RGBA(rgba) => rgba,
|
||||
CurrentColor => self.Color.color,
|
||||
CurrentColor => self.Color.get().color,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new cascade context.
|
||||
fn new_cascade_context(style_Color: &style_structs::Color,
|
||||
style_Font: &style_structs::Font,
|
||||
style_Box: &style_structs::Box,
|
||||
is_root_element: bool)
|
||||
-> computed::Context {
|
||||
computed::Context {
|
||||
current_color: style_Color.color,
|
||||
parent_font_size: style_Font.font_size,
|
||||
font_size: style_Font.font_size,
|
||||
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
|
||||
/// Returns the initial values for all style structs as defined by the specification.
|
||||
pub fn initial_values() -> ComputedValues {
|
||||
ComputedValues {
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
${style_struct.name}: CowArc::new(style_structs::${style_struct.name} {
|
||||
% for longhand in style_struct.longhands:
|
||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||
% endfor
|
||||
}),
|
||||
% endfor
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
///
|
||||
/// * `initial_values`: The initial set of CSS values as defined by the specification.
|
||||
///
|
||||
/// Returns the computed values.
|
||||
pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
|
||||
parent_style: Option< &ComputedValues >)
|
||||
parent_style: Option< &ComputedValues>,
|
||||
initial_values: &ComputedValues)
|
||||
-> ComputedValues {
|
||||
let is_root_element;
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
|
@ -1197,73 +1177,90 @@ pub fn cascade(applicable_declarations: &[Arc<~[PropertyDeclaration]>],
|
|||
% if style_struct.inherited:
|
||||
style_${style_struct.name} = parent_style.${style_struct.name}.clone();
|
||||
% else:
|
||||
style_${style_struct.name} = style_structs::${style_struct.name} {
|
||||
% for longhand in style_struct.longhands:
|
||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||
% endfor
|
||||
};
|
||||
%endif
|
||||
style_${style_struct.name} = initial_values.${style_struct.name}.clone();
|
||||
% endif
|
||||
% endfor
|
||||
}
|
||||
None => {
|
||||
is_root_element = true;
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
style_${style_struct.name} = style_structs::${style_struct.name} {
|
||||
% for longhand in style_struct.longhands:
|
||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||
% endfor
|
||||
};
|
||||
style_${style_struct.name} = initial_values.${style_struct.name}.clone();
|
||||
% 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 declaration in sub_list.get().iter() {
|
||||
match declaration {
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
% 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)) => {
|
||||
// Overwrite earlier declarations.
|
||||
// TODO: can we avoid a copy?
|
||||
style_${style_struct.name}.${property.ident} =
|
||||
let computed_value =
|
||||
longhands::${property.ident}::to_computed_value(
|
||||
(*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)) => {
|
||||
// This is a bit slow, but this is rare so it shouldn't matter.
|
||||
match parent_style {
|
||||
None => {
|
||||
style_${style_struct.name}.${property.ident} =
|
||||
style_${style_struct.name}.get_mut()
|
||||
.${property.ident} =
|
||||
longhands::${property.ident}::get_initial_value()
|
||||
}
|
||||
Some(ref parent_style) => {
|
||||
style_${style_struct.name}.${property.ident} =
|
||||
style_${style_struct.name}.get_mut()
|
||||
.${property.ident} =
|
||||
parent_style.${style_struct.name}
|
||||
.get()
|
||||
.${property.ident}
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
&${property.ident}_declaration(CSSWideKeyword(Initial)) => {
|
||||
style_${style_struct.name}.${property.ident} =
|
||||
longhands::${property.ident}::get_initial_value()
|
||||
}
|
||||
% endif
|
||||
% endfor
|
||||
% endfor
|
||||
_ => {}
|
||||
% if needed_for_context:
|
||||
_ => {}
|
||||
% endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</%def>
|
||||
|
||||
${apply("High")}
|
||||
${apply("Normal")}
|
||||
${apply(True)}
|
||||
context.use_parent_font_size = false;
|
||||
${apply(False)}
|
||||
|
||||
ComputedValues {
|
||||
% 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 properties::{cascade, PropertyDeclaration, ComputedValues, computed_values};
|
||||
pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes
|
||||
pub use properties::{initial_values};
|
||||
pub use errors::with_errors_silenced;
|
||||
pub use node::{TElement, TNode};
|
||||
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 concurrentmap;
|
||||
pub mod cowarc;
|
||||
pub mod debug;
|
||||
pub mod geometry;
|
||||
pub mod io;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue