mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
layout: Implement ordered lists, CSS counters, and quotes
per CSS 2.1
§ 12.3-12.5. Only simple alphabetic and numeric counter styles are supported. (This is most of them though.) Although this PR adds a sequential pass to layout, I verified that on pages that contain a reasonable number of ordered lists (Reddit `/r/rust`), the time spent in generated content resolution is dwarfed by the time spent in the parallelizable parts of layout. So I don't expect this to negatively affect our parallelism expect perhaps in pathological cases.
This commit is contained in:
parent
2df4dd9e09
commit
f9cdd05d58
39 changed files with 1704 additions and 537 deletions
|
@ -67,9 +67,11 @@ use std::marker::ContravariantLifetime;
|
|||
use std::mem;
|
||||
use std::sync::mpsc::Sender;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use style::computed_values::content::ContentItem;
|
||||
use style::computed_values::{content, display, white_space};
|
||||
use selectors::parser::{NamespaceConstraint, AttrSelector};
|
||||
use style::legacy::{LengthAttribute, SimpleColorAttribute, UnsignedIntegerAttribute, IntegerAttribute};
|
||||
use style::legacy::{IntegerAttribute, LengthAttribute, SimpleColorAttribute};
|
||||
use style::legacy::{UnsignedIntegerAttribute};
|
||||
use style::node::{TElement, TElementAttributes, TNode};
|
||||
use style::properties::PropertyDeclarationBlock;
|
||||
use url::Url;
|
||||
|
@ -154,10 +156,11 @@ pub trait TLayoutNode {
|
|||
}
|
||||
}
|
||||
|
||||
/// If this is a text node, copies out the text. If this is not a text node, fails.
|
||||
/// If this is a text node or generated content, copies out its content. If this is not a text
|
||||
/// node, fails.
|
||||
///
|
||||
/// FIXME(pcwalton): Don't copy text. Atomically reference count instead.
|
||||
fn text(&self) -> String;
|
||||
/// FIXME(pcwalton): This might have too much copying and/or allocation. Profile this.
|
||||
fn text_content(&self) -> Vec<ContentItem>;
|
||||
|
||||
/// Returns the first child of this node.
|
||||
fn first_child(&self) -> Option<Self>;
|
||||
|
@ -214,19 +217,25 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
fn text(&self) -> String {
|
||||
fn text_content(&self) -> Vec<ContentItem> {
|
||||
unsafe {
|
||||
let text: Option<LayoutJS<Text>> = TextCast::to_layout_js(self.get_jsmanaged());
|
||||
if let Some(text) = text {
|
||||
return (*text.unsafe_get()).characterdata().data_for_layout().to_owned();
|
||||
return vec![
|
||||
ContentItem::String((*text.unsafe_get()).characterdata()
|
||||
.data_for_layout()
|
||||
.to_owned())
|
||||
];
|
||||
}
|
||||
let input: Option<LayoutJS<HTMLInputElement>> = HTMLInputElementCast::to_layout_js(self.get_jsmanaged());
|
||||
let input: Option<LayoutJS<HTMLInputElement>> =
|
||||
HTMLInputElementCast::to_layout_js(self.get_jsmanaged());
|
||||
if let Some(input) = input {
|
||||
return input.get_value_for_layout();
|
||||
return vec![ContentItem::String(input.get_value_for_layout())];
|
||||
}
|
||||
let area: Option<LayoutJS<HTMLTextAreaElement>> = HTMLTextAreaElementCast::to_layout_js(self.get_jsmanaged());
|
||||
let area: Option<LayoutJS<HTMLTextAreaElement>> =
|
||||
HTMLTextAreaElementCast::to_layout_js(self.get_jsmanaged());
|
||||
if let Some(area) = area {
|
||||
return area.get_value_for_layout();
|
||||
return vec![ContentItem::String(area.get_value_for_layout())];
|
||||
}
|
||||
|
||||
panic!("not text!")
|
||||
|
@ -661,16 +670,10 @@ impl<'le> TElementAttributes for LayoutElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_content(content_list: &content::T) -> String {
|
||||
fn get_content(content_list: &content::T) -> Vec<ContentItem> {
|
||||
match *content_list {
|
||||
content::T::Content(ref value) => {
|
||||
let iter = &mut value.clone().into_iter().peekable();
|
||||
match iter.next() {
|
||||
Some(content::ContentItem::StringContent(content)) => content,
|
||||
_ => "".to_owned(),
|
||||
}
|
||||
}
|
||||
_ => "".to_owned(),
|
||||
content::T::Content(ref value) if !value.is_empty() => (*value).clone(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +765,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
fn text(&self) -> String {
|
||||
fn text_content(&self) -> Vec<ContentItem> {
|
||||
if self.pseudo != PseudoElementType::Normal {
|
||||
let layout_data_ref = self.borrow_layout_data();
|
||||
let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap();
|
||||
|
@ -775,7 +778,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
|
|||
return get_content(&after_style.get_box().content)
|
||||
}
|
||||
}
|
||||
self.node.text()
|
||||
self.node.text_content()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue