remove @ in LayoutTask.FontContext

This commit is contained in:
patrick kim 2013-12-09 16:28:41 +09:00
parent 5077c771a5
commit f187035e25
6 changed files with 68 additions and 30 deletions

View file

@ -79,7 +79,7 @@ impl FontHandleMethods for FontHandle {
buf: ~[u8], buf: ~[u8],
style: &SpecifiedFontStyle) style: &SpecifiedFontStyle)
-> Result<FontHandle, ()> { -> Result<FontHandle, ()> {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.get().ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| { let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| {
@ -292,7 +292,7 @@ impl<'self> FontHandle {
pub fn new_from_file(fctx: &FontContextHandle, file: &str, pub fn new_from_file(fctx: &FontContextHandle, file: &str,
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> { style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
unsafe { unsafe {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.get().ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
let mut face: FT_Face = ptr::null(); let mut face: FT_Face = ptr::null();
@ -320,7 +320,7 @@ impl<'self> FontHandle {
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str) pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
-> Result<FontHandle, ()> { -> Result<FontHandle, ()> {
unsafe { unsafe {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.get().ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
let mut face: FT_Face = ptr::null(); let mut face: FT_Face = ptr::null();

View file

@ -33,7 +33,7 @@ use layout::util::LayoutDataAccess;
use script::dom::element::HTMLImageElementTypeId; use script::dom::element::HTMLImageElementTypeId;
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId}; use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId};
use script::dom::node::{LayoutView, PostorderNodeTraversal, TextNodeTypeId}; use script::dom::node::{LayoutView, PostorderNodeMutTraversal, TextNodeTypeId};
use servo_util::slot::Slot; use servo_util::slot::Slot;
use servo_util::tree::TreeNodeRef; use servo_util::tree::TreeNodeRef;
use std::util; use std::util;
@ -173,7 +173,7 @@ pub struct FlowConstructor<'self> {
/// The layout context. /// The layout context.
/// ///
/// FIXME(pcwalton): Why does this contain `@`??? That destroys parallelism!!! /// FIXME(pcwalton): Why does this contain `@`??? That destroys parallelism!!!
layout_context: &'self LayoutContext, layout_context: &'self mut LayoutContext,
/// The next flow ID to assign. /// The next flow ID to assign.
/// ///
@ -183,7 +183,7 @@ pub struct FlowConstructor<'self> {
impl<'self> FlowConstructor<'self> { impl<'self> FlowConstructor<'self> {
/// Creates a new flow constructor. /// Creates a new flow constructor.
pub fn init<'a>(layout_context: &'a LayoutContext) -> FlowConstructor<'a> { pub fn init<'a>(layout_context: &'a mut LayoutContext) -> FlowConstructor<'a> {
FlowConstructor { FlowConstructor {
layout_context: layout_context, layout_context: layout_context,
next_flow_id: Slot::init(0), next_flow_id: Slot::init(0),
@ -198,7 +198,7 @@ impl<'self> FlowConstructor<'self> {
} }
/// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining. /// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining.
fn build_box_info_for_image(&self, node: AbstractNode<LayoutView>) -> Option<ImageBoxInfo> { fn build_box_info_for_image(&mut self, node: AbstractNode<LayoutView>) -> Option<ImageBoxInfo> {
// FIXME(pcwalton): Don't copy URLs. // FIXME(pcwalton): Don't copy URLs.
let url = node.with_imm_image_element(|image_element| { let url = node.with_imm_image_element(|image_element| {
image_element.image.as_ref().map(|url| (*url).clone()) image_element.image.as_ref().map(|url| (*url).clone())
@ -215,7 +215,7 @@ impl<'self> FlowConstructor<'self> {
} }
/// Builds a `Box` for the given node. /// Builds a `Box` for the given node.
fn build_box_for_node(&self, node: AbstractNode<LayoutView>) -> @Box { fn build_box_for_node(&mut self, node: AbstractNode<LayoutView>) -> @Box {
let specific = match node.type_id() { let specific = match node.type_id() {
ElementNodeTypeId(HTMLImageElementTypeId) => { ElementNodeTypeId(HTMLImageElementTypeId) => {
match self.build_box_info_for_image(node) { match self.build_box_info_for_image(node) {
@ -234,7 +234,7 @@ impl<'self> FlowConstructor<'self> {
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it /// `#[inline(always)]` because this is performance critical and LLVM will not inline it
/// otherwise. /// otherwise.
#[inline(always)] #[inline(always)]
fn flush_inline_boxes_to_flow(&self, fn flush_inline_boxes_to_flow(&mut self,
boxes: ~[@Box], boxes: ~[@Box],
flow: &mut ~Flow:, flow: &mut ~Flow:,
node: AbstractNode<LayoutView>) { node: AbstractNode<LayoutView>) {
@ -248,7 +248,7 @@ impl<'self> FlowConstructor<'self> {
/// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of /// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of
/// the given flow. /// the given flow.
fn flush_inline_boxes_to_flow_if_necessary(&self, fn flush_inline_boxes_to_flow_if_necessary(&mut self,
opt_boxes: &mut Option<~[@Box]>, opt_boxes: &mut Option<~[@Box]>,
flow: &mut ~Flow:, flow: &mut ~Flow:,
node: AbstractNode<LayoutView>) { node: AbstractNode<LayoutView>) {
@ -261,7 +261,7 @@ impl<'self> FlowConstructor<'self> {
/// Builds the children flows underneath a node with `display: block`. After this call, /// Builds the children flows underneath a node with `display: block`. After this call,
/// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on /// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on
/// whether {ib} splits needed to happen. /// whether {ib} splits needed to happen.
fn build_children_of_block_flow(&self, fn build_children_of_block_flow(&mut self,
flow: &mut ~Flow:, flow: &mut ~Flow:,
node: AbstractNode<LayoutView>) { node: AbstractNode<LayoutView>) {
// Gather up boxes for the inline flows we might need to create. // Gather up boxes for the inline flows we might need to create.
@ -341,7 +341,7 @@ impl<'self> FlowConstructor<'self> {
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
/// to happen. /// to happen.
fn build_flow_for_block(&self, node: AbstractNode<LayoutView>) -> ~Flow: { fn build_flow_for_block(&mut self, node: AbstractNode<LayoutView>) -> ~Flow: {
let base = FlowData::new(self.next_flow_id(), node); let base = FlowData::new(self.next_flow_id(), node);
let box = self.build_box_for_node(node); let box = self.build_box_for_node(node);
let mut flow = ~BlockFlow::from_box(base, box) as ~Flow:; let mut flow = ~BlockFlow::from_box(base, box) as ~Flow:;
@ -351,7 +351,7 @@ impl<'self> FlowConstructor<'self> {
/// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with /// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with
/// a `BlockFlow` underneath it. /// a `BlockFlow` underneath it.
fn build_flow_for_floated_block(&self, node: AbstractNode<LayoutView>, float_type: FloatType) fn build_flow_for_floated_block(&mut self, node: AbstractNode<LayoutView>, float_type: FloatType)
-> ~Flow: { -> ~Flow: {
let base = FlowData::new(self.next_flow_id(), node); let base = FlowData::new(self.next_flow_id(), node);
let box = self.build_box_for_node(node); let box = self.build_box_for_node(node);
@ -363,7 +363,7 @@ impl<'self> FlowConstructor<'self> {
/// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary. /// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary.
/// Returns the `InlineBoxesConstructionResult`, if any. There will be no /// Returns the `InlineBoxesConstructionResult`, if any. There will be no
/// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace. /// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace.
fn build_boxes_for_nonreplaced_inline_content(&self, node: AbstractNode<LayoutView>) fn build_boxes_for_nonreplaced_inline_content(&mut self, node: AbstractNode<LayoutView>)
-> ConstructionResult { -> ConstructionResult {
let mut opt_inline_block_splits = None; let mut opt_inline_block_splits = None;
let mut opt_box_accumulator = None; let mut opt_box_accumulator = None;
@ -429,7 +429,7 @@ impl<'self> FlowConstructor<'self> {
/// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't /// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't
/// render its children, so this just nukes a child's boxes and creates a `Box`. /// render its children, so this just nukes a child's boxes and creates a `Box`.
fn build_boxes_for_replaced_inline_content(&self, node: AbstractNode<LayoutView>) fn build_boxes_for_replaced_inline_content(&mut self, node: AbstractNode<LayoutView>)
-> ConstructionResult { -> ConstructionResult {
for kid in node.children() { for kid in node.children() {
kid.set_flow_construction_result(NoConstructionResult) kid.set_flow_construction_result(NoConstructionResult)
@ -446,7 +446,7 @@ impl<'self> FlowConstructor<'self> {
/// Builds one or more boxes for a node with `display: inline`. This yields an /// Builds one or more boxes for a node with `display: inline`. This yields an
/// `InlineBoxesConstructionResult`. /// `InlineBoxesConstructionResult`.
fn build_boxes_for_inline(&self, node: AbstractNode<LayoutView>) -> ConstructionResult { fn build_boxes_for_inline(&mut self, node: AbstractNode<LayoutView>) -> ConstructionResult {
// Is this node replaced content? // Is this node replaced content?
if !node.is_replaced_content() { if !node.is_replaced_content() {
// Go to a path that concatenates our kids' boxes. // Go to a path that concatenates our kids' boxes.
@ -458,11 +458,11 @@ impl<'self> FlowConstructor<'self> {
} }
} }
impl<'self> PostorderNodeTraversal for FlowConstructor<'self> { impl<'self> PostorderNodeMutTraversal for FlowConstructor<'self> {
// `#[inline(always)]` because this is always called from the traversal function and for some // `#[inline(always)]` because this is always called from the traversal function and for some
// reason LLVM's inlining heuristics go awry here. // reason LLVM's inlining heuristics go awry here.
#[inline(always)] #[inline(always)]
fn process(&self, node: AbstractNode<LayoutView>) -> bool { fn process(&mut self, node: AbstractNode<LayoutView>) -> bool {
// Get the `display` property for this node, and determine whether this node is floated. // Get the `display` property for this node, and determine whether this node is floated.
let (display, float) = match node.type_id() { let (display, float) = match node.type_id() {
ElementNodeTypeId(_) => (node.style().Box.display, node.style().Box.float), ElementNodeTypeId(_) => (node.style().Box.display, node.style().Box.float),

View file

@ -13,7 +13,7 @@ use extra::arc::MutexArc;
/// Data needed by the layout task. /// Data needed by the layout task.
pub struct LayoutContext { pub struct LayoutContext {
font_ctx: @mut FontContext, font_ctx: ~FontContext,
image_cache: MutexArc<LocalImageCache>, image_cache: MutexArc<LocalImageCache>,
screen_size: Rect<Au> screen_size: Rect<Au>
} }

View file

@ -77,9 +77,6 @@ struct LayoutTask {
/// The local image cache. /// The local image cache.
local_image_cache: MutexArc<LocalImageCache>, local_image_cache: MutexArc<LocalImageCache>,
/// The local font context.
font_ctx: @mut FontContext,
/// The size of the viewport. /// The size of the viewport.
screen_size: Option<Size2D<Au>>, screen_size: Option<Size2D<Au>>,
@ -90,6 +87,8 @@ struct LayoutTask {
/// The channel on which messages can be sent to the profiler. /// The channel on which messages can be sent to the profiler.
profiler_chan: ProfilerChan, profiler_chan: ProfilerChan,
opts: Opts
} }
/// The damage computation traversal. /// The damage computation traversal.
@ -229,7 +228,6 @@ impl LayoutTask {
opts: &Opts, opts: &Opts,
profiler_chan: ProfilerChan) profiler_chan: ProfilerChan)
-> LayoutTask { -> LayoutTask {
let fctx = @mut FontContext::new(opts.render_backend, true, profiler_chan.clone());
LayoutTask { LayoutTask {
id: id, id: id,
@ -239,13 +237,13 @@ impl LayoutTask {
render_chan: render_chan, render_chan: render_chan,
image_cache_task: image_cache_task.clone(), image_cache_task: image_cache_task.clone(),
local_image_cache: MutexArc::new(LocalImageCache(image_cache_task)), local_image_cache: MutexArc::new(LocalImageCache(image_cache_task)),
font_ctx: fctx,
screen_size: None, screen_size: None,
display_list: None, display_list: None,
stylist: RWArc::new(new_stylist()), stylist: RWArc::new(new_stylist()),
profiler_chan: profiler_chan, profiler_chan: profiler_chan,
opts: opts.clone()
} }
} }
@ -259,7 +257,8 @@ impl LayoutTask {
// Create a layout context for use in building display lists, hit testing, &c. // Create a layout context for use in building display lists, hit testing, &c.
fn build_layout_context(&self) -> LayoutContext { fn build_layout_context(&self) -> LayoutContext {
let image_cache = self.local_image_cache.clone(); let image_cache = self.local_image_cache.clone();
let font_ctx = self.font_ctx; let font_ctx = ~FontContext::new(self.opts.render_backend, true,
self.profiler_chan.clone());
let screen_size = self.screen_size.unwrap(); let screen_size = self.screen_size.unwrap();
LayoutContext { LayoutContext {
@ -344,9 +343,9 @@ impl LayoutTask {
/// is intertwined with selector matching, making it difficult to compare directly. It is /// is intertwined with selector matching, making it difficult to compare directly. It is
/// marked `#[inline(never)]` to aid benchmarking in sampling profilers. /// marked `#[inline(never)]` to aid benchmarking in sampling profilers.
#[inline(never)] #[inline(never)]
fn construct_flow_tree(&self, layout_context: &LayoutContext, node: AbstractNode<LayoutView>) fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: AbstractNode<LayoutView>)
-> ~Flow: { -> ~Flow: {
node.traverse_postorder(&FlowConstructor::init(layout_context)); node.traverse_postorder_mut(&mut FlowConstructor::init(layout_context));
let result = match *node.mutate_layout_data().ptr { let result = match *node.mutate_layout_data().ptr {
Some(ref mut layout_data) => { Some(ref mut layout_data) => {
@ -441,7 +440,7 @@ impl LayoutTask {
// Construct the flow tree. // Construct the flow tree.
let mut layout_root = profile(time::LayoutTreeBuilderCategory, let mut layout_root = profile(time::LayoutTreeBuilderCategory,
self.profiler_chan.clone(), self.profiler_chan.clone(),
|| self.construct_flow_tree(&layout_ctx, *node)); || self.construct_flow_tree(&mut layout_ctx, *node));
// Propagate damage. // Propagate damage.
layout_root.traverse_preorder(&mut PropagateDamageTraversal { layout_root.traverse_preorder(&mut PropagateDamageTraversal {

View file

@ -26,7 +26,7 @@ impl TextRunScanner {
} }
} }
pub fn scan_for_runs(&mut self, ctx: &LayoutContext, flow: &mut Flow) { pub fn scan_for_runs(&mut self, ctx: &mut LayoutContext, flow: &mut Flow) {
{ {
let inline = flow.as_immutable_inline(); let inline = flow.as_immutable_inline();
// FIXME: this assertion fails on wikipedia, but doesn't seem // FIXME: this assertion fails on wikipedia, but doesn't seem
@ -76,7 +76,7 @@ impl TextRunScanner {
/// responsible for swapping out the list. It is not clear to me (pcwalton) that this is still /// responsible for swapping out the list. It is not clear to me (pcwalton) that this is still
/// necessary. /// necessary.
pub fn flush_clump_to_list(&mut self, pub fn flush_clump_to_list(&mut self,
ctx: &LayoutContext, ctx: &mut LayoutContext,
flow: &mut Flow, flow: &mut Flow,
last_whitespace: bool, last_whitespace: bool,
out_boxes: &mut ~[@Box]) out_boxes: &mut ~[@Box])

View file

@ -1217,6 +1217,20 @@ pub trait PostorderNodeTraversal {
} }
} }
/// A bottom-up, parallelizable traversal.
pub trait PostorderNodeMutTraversal {
/// The operation to perform. Return true to continue or false to stop.
fn process(&mut self, node: AbstractNode<LayoutView>) -> bool;
/// Returns true if this node should be pruned. If this returns true, we skip the operation
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
/// visited. The default implementation never prunes any nodes.
fn should_prune(&self, _node: AbstractNode<LayoutView>) -> bool {
false
}
}
impl AbstractNode<LayoutView> { impl AbstractNode<LayoutView> {
/// Traverses the tree in postorder. /// Traverses the tree in postorder.
/// ///
@ -1241,4 +1255,29 @@ impl AbstractNode<LayoutView> {
traversal.process(self) traversal.process(self)
} }
/// Traverses the tree in postorder.
///
/// TODO(pcwalton): Offer a parallel version with a compatible API.
pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(mut self, traversal: &mut T) -> bool {
if traversal.should_prune(self) {
return true
}
let mut opt_kid = self.first_child();
loop {
match opt_kid {
None => break,
Some(kid) => {
if !kid.traverse_postorder_mut(traversal) {
return false
}
opt_kid = kid.next_sibling()
}
}
}
traversal.process(self)
}
} }