Thread RenderContext and LayoutContext throughout computations needing task assets, such as document URL, font cache, or image cache.

This commit is contained in:
Brian J. Burg 2012-09-17 17:24:10 -07:00
parent bcdc2ac597
commit 972791bb9f
18 changed files with 221 additions and 212 deletions

View file

@ -1,7 +1,8 @@
#[doc="Applies the appropriate CSS style to boxes."] #[doc="Applies the appropriate CSS style to boxes."]
use au = gfx::geometry; use au = gfx::geometry;
use layout::base::{Box, SpecifiedStyle}; use layout::base::{Box, SpecifiedStyle, BoxTree};
use layout::context::LayoutContext;
use layout::traverse_parallel::top_down_traversal; use layout::traverse_parallel::top_down_traversal;
use image::ImageHolder; use image::ImageHolder;
use resource::image_cache_task::ImageCacheTask; use resource::image_cache_task::ImageCacheTask;
@ -32,35 +33,29 @@ impl CSSValue<CSSFontSize> : ResolveMethods<CSSFontSize> {
struct StyleApplicator { struct StyleApplicator {
box: @Box, box: @Box,
doc_url: &Url,
image_cache_task: ImageCacheTask,
reflow: fn~(), reflow: fn~(),
} }
// TODO: normalize this into a normal preorder tree traversal function // TODO: normalize this into a normal preorder tree traversal function
fn apply_style(box: @Box, doc_url: &Url, image_cache_task: ImageCacheTask, reflow: fn~()) { fn apply_style(layout_ctx: &LayoutContext, box: @Box, reflow: fn~()) {
let applicator = StyleApplicator { let applicator = StyleApplicator {
box: box, box: box,
doc_url: doc_url,
image_cache_task: image_cache_task,
reflow: reflow reflow: reflow
}; };
applicator.apply_css_style(); applicator.apply_css_style(layout_ctx);
} }
// TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values. // TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values.
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout #[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
boxes."] boxes."]
fn inheritance_wrapper(box : @Box, doc_url: &Url, image_cache_task: ImageCacheTask, reflow: fn~()) { fn inheritance_wrapper(layout_ctx: &LayoutContext, box : @Box, reflow: fn~()) {
let applicator = StyleApplicator { let applicator = StyleApplicator {
box: box, box: box,
doc_url: doc_url,
image_cache_task: image_cache_task,
reflow: reflow reflow: reflow
}; };
applicator.apply_style(); applicator.apply_style(layout_ctx);
} }
/* /*
@ -104,12 +99,11 @@ fn resolve_width(box : @Box) {
}*/ }*/
impl StyleApplicator { impl StyleApplicator {
fn apply_css_style() { fn apply_css_style(layout_ctx: &LayoutContext) {
let doc_url = copy *self.doc_url;
let image_cache_task = self.image_cache_task;
let reflow = copy self.reflow; let reflow = copy self.reflow;
do top_down_traversal(self.box) |box, move doc_url| {
inheritance_wrapper(box, &doc_url, image_cache_task, reflow); do BoxTree.each_child(self.box) |child| {
inheritance_wrapper(layout_ctx, child, reflow); true
} }
} }
@ -120,7 +114,7 @@ impl StyleApplicator {
value for the given type of element and use that instead. value for the given type of element and use that instead.
"] "]
fn apply_style() { fn apply_style(layout_ctx: &LayoutContext) {
// Right now, we only handle images. // Right now, we only handle images.
do self.box.node.read |node| { do self.box.node.read |node| {
@ -133,8 +127,8 @@ impl StyleApplicator {
if url.is_some() { if url.is_some() {
// FIXME: Some sort of BASE HREF support! // FIXME: Some sort of BASE HREF support!
// FIXME: Parse URLs! // FIXME: Parse URLs!
let new_url = make_url(option::unwrap(url), Some(copy *self.doc_url)); let new_url = make_url(option::unwrap(url), Some(copy layout_ctx.doc_url));
self.box.data.background_image = Some(ImageHolder(new_url, self.image_cache_task, self.reflow)) self.box.data.background_image = Some(ImageHolder(new_url, layout_ctx.image_cache, self.reflow))
}; };
} }
_ => { /* Ignore. */ } _ => { /* Ignore. */ }

View file

@ -10,6 +10,7 @@ use dom::base::{LayoutData};
use util::color::{Color, rgb}; use util::color::{Color, rgb};
use util::color::css_colors::{white, black}; use util::color::css_colors::{white, black};
use dom::base::NodeTree; use dom::base::NodeTree;
use layout::context::LayoutContext;
type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>, type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>,
mut display_type : CSSValue<CSSDisplay>, mut display_type : CSSValue<CSSDisplay>,
@ -114,7 +115,7 @@ impl Node : StylePriv {
trait StyleMethods { trait StyleMethods {
fn initialize_style_for_subtree() -> ~[@LayoutData]; fn initialize_style_for_subtree() -> ~[@LayoutData];
fn style() -> SpecifiedStyle; fn style() -> SpecifiedStyle;
fn recompute_style_for_subtree(styles : ARC<Stylesheet>); fn recompute_style_for_subtree(ctx: &LayoutContext, styles : ARC<Stylesheet>);
} }
impl Node : StyleMethods { impl Node : StyleMethods {
@ -145,31 +146,20 @@ impl Node : StyleMethods {
#[doc=" #[doc="
Performs CSS selector matching on a subtree. Performs CSS selector matching on a subtree.
This is, importantly, the function that updates the layout data for the node (the reader- This is, importantly, the function that updates the layout data for the node (the reader-
auxiliary box in the RCU model) with the computed style. auxiliary box in the RCU model) with the computed style.
"] "]
fn recompute_style_for_subtree(styles : ARC<Stylesheet>) { fn recompute_style_for_subtree(ctx: &LayoutContext, styles : ARC<Stylesheet>) {
listen(|ack_chan| { let mut i = 0u;
let mut i = 0u;
// Compute the styles of each of our children in parallel
for NodeTree.each_child(self) |kid| {
i = i + 1u;
let new_styles = clone(&styles);
// Compute the styles of each of our children in parallel kid.recompute_style_for_subtree(ctx, new_styles);
for NodeTree.each_child(self) |kid| { }
i = i + 1u;
let new_styles = clone(&styles);
task::spawn(|| {
kid.recompute_style_for_subtree(new_styles);
ack_chan.send(());
})
}
self.match_css_style(*get(&styles)); self.match_css_style(*get(&styles));
// Make sure we have finished updating the tree before returning
while i > 0 {
ack_chan.recv();
i = i - 1u;
}
})
} }
} }

View file

@ -3,13 +3,14 @@ use gfx::render_task::{draw_solid_color, draw_image, draw_glyphs};
use gfx::geometry::*; use gfx::geometry::*;
use geom::rect::Rect; use geom::rect::Rect;
use image::base::Image; use image::base::Image;
use render_task::RenderContext;
use std::arc::{ARC, clone}; use std::arc::{ARC, clone};
use dvec::DVec; use dvec::DVec;
use text::glyph::Glyph; use text::glyph::Glyph;
struct DisplayItem { struct DisplayItem {
draw: ~fn((&DisplayItem), (&DrawTarget)), draw: ~fn((&DisplayItem), (&RenderContext)),
bounds : Rect<au>, // TODO: whose coordinate system should this use? bounds : Rect<au>, // TODO: whose coordinate system should this use?
data : DisplayItemData data : DisplayItemData
} }
@ -30,21 +31,21 @@ struct GlyphRun {
glyphs: ~[Glyph] glyphs: ~[Glyph]
} }
fn draw_SolidColor(self: &DisplayItem, ctx: &DrawTarget) { fn draw_SolidColor(self: &DisplayItem, ctx: &RenderContext) {
match self.data { match self.data {
SolidColorData(r,g,b) => draw_solid_color(ctx, &self.bounds, r, g, b), SolidColorData(r,g,b) => draw_solid_color(ctx, &self.bounds, r, g, b),
_ => fail _ => fail
} }
} }
fn draw_Glyphs(self: &DisplayItem, ctx: &DrawTarget) { fn draw_Glyphs(self: &DisplayItem, ctx: &RenderContext) {
match self.data { match self.data {
GlyphData(run) => draw_glyphs(ctx, self.bounds, &run), GlyphData(run) => draw_glyphs(ctx, self.bounds, &run),
_ => fail _ => fail
} }
} }
fn draw_Image(self: &DisplayItem, ctx: &DrawTarget) { fn draw_Image(self: &DisplayItem, ctx: &RenderContext) {
match self.data { match self.data {
ImageData(img) => draw_image(ctx, self.bounds, img), ImageData(img) => draw_image(ctx, self.bounds, img),
_ => fail _ => fail
@ -81,11 +82,11 @@ fn Image(bounds: Rect<au>, image: ARC<~image::base::Image>) -> DisplayItem {
type DisplayList = DVec<~DisplayItem>; type DisplayList = DVec<~DisplayItem>;
trait DisplayListMethods { trait DisplayListMethods {
fn draw(ctx: &DrawTarget); fn draw(ctx: &RenderContext);
} }
impl DisplayList : DisplayListMethods { impl DisplayList : DisplayListMethods {
fn draw(ctx: &DrawTarget) { fn draw(ctx: &RenderContext) {
for self.each |item| { for self.each |item| {
#debug["drawing %?", item]; #debug["drawing %?", item];
item.draw(item, ctx); item.draw(item, ctx);

View file

@ -19,6 +19,7 @@ use std::arc::ARC;
use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t}; use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t};
use std::cell::Cell; use std::cell::Cell;
use compositor::Compositor; use compositor::Compositor;
use servo_text::font_cache::FontCache;
use pipes::{Port, Chan}; use pipes::{Port, Chan};
@ -29,6 +30,11 @@ pub enum Msg {
ExitMsg(pipes::Chan<()>) ExitMsg(pipes::Chan<()>)
} }
struct RenderContext {
canvas: &DrawTarget,
font_cache: @FontCache,
}
type RenderTask = comm::Chan<Msg>; type RenderTask = comm::Chan<Msg>;
fn RenderTask<C: Compositor Send>(+compositor: C) -> RenderTask { fn RenderTask<C: Compositor Send>(+compositor: C) -> RenderTask {
@ -37,6 +43,8 @@ fn RenderTask<C: Compositor Send>(+compositor: C) -> RenderTask {
let mut draw_target_ch = draw_target_ch; let mut draw_target_ch = draw_target_ch;
let mut draw_target_po = draw_target_po; let mut draw_target_po = draw_target_po;
let font_cache = FontCache();
debug!("renderer: beginning rendering loop"); debug!("renderer: beginning rendering loop");
compositor.begin_drawing(draw_target_ch); compositor.begin_drawing(draw_target_ch);
@ -56,8 +64,13 @@ fn RenderTask<C: Compositor Send>(+compositor: C) -> RenderTask {
let draw_target_ch = option::unwrap(draw_target_ch); let draw_target_ch = option::unwrap(draw_target_ch);
do draw_target.with_ref |draw_target| { do draw_target.with_ref |draw_target| {
clear(draw_target); let ctx = RenderContext {
display_list.draw(draw_target) canvas: draw_target,
font_cache: font_cache
};
clear(&ctx);
display_list.draw(&ctx)
} }
#debug("renderer: returning surface"); #debug("renderer: returning surface");
@ -94,37 +107,37 @@ impl Rect<au> : ToAzureRect {
} }
} }
pub fn draw_solid_color(draw_target: &DrawTarget, bounds: &Rect<au>, r: u8, g: u8, b: u8) { pub fn draw_solid_color(ctx: &RenderContext, bounds: &Rect<au>, r: u8, g: u8, b: u8) {
let color = Color(r.to_float() as AzFloat, let color = Color(r.to_float() as AzFloat,
g.to_float() as AzFloat, g.to_float() as AzFloat,
b.to_float() as AzFloat, b.to_float() as AzFloat,
1f as AzFloat); 1f as AzFloat);
draw_target.fill_rect(bounds.to_azure_rect(), ColorPattern(color)); ctx.canvas.fill_rect(bounds.to_azure_rect(), ColorPattern(color));
} }
pub fn draw_image(draw_target: &DrawTarget, bounds: Rect<au>, image: ARC<~Image>) { pub fn draw_image(ctx: &RenderContext, bounds: Rect<au>, image: ARC<~Image>) {
let image = std::arc::get(&image); let image = std::arc::get(&image);
let size = Size2D(image.width as i32, image.height as i32); let size = Size2D(image.width as i32, image.height as i32);
let stride = image.width * 4; let stride = image.width * 4;
let azure_surface = draw_target.create_source_surface_from_data(image.data, size, stride as i32, let azure_surface = ctx.canvas.create_source_surface_from_data(image.data, size, stride as i32,
B8G8R8A8); B8G8R8A8);
let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), let source_rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat),
Size2D(image.width as AzFloat, image.height as AzFloat)); Size2D(image.width as AzFloat, image.height as AzFloat));
let dest_rect = bounds.to_azure_rect(); let dest_rect = bounds.to_azure_rect();
let draw_surface_options = DrawSurfaceOptions(Linear, true); let draw_surface_options = DrawSurfaceOptions(Linear, true);
let draw_options = DrawOptions(1.0f as AzFloat, 0); let draw_options = DrawOptions(1.0f as AzFloat, 0);
draw_target.draw_surface(azure_surface, dest_rect, source_rect, draw_surface_options, ctx.canvas.draw_surface(azure_surface, dest_rect, source_rect, draw_surface_options,
draw_options); draw_options);
} }
pub fn draw_glyphs(draw_target: &DrawTarget, bounds: Rect<au>, text_run: &GlyphRun) { pub fn draw_glyphs(ctx: &RenderContext, bounds: Rect<au>, text_run: &GlyphRun) {
use ptr::{addr_of, null}; use ptr::{addr_of, null};
use vec::raw::to_ptr; use vec::raw::to_ptr;
use libc::types::common::c99::{uint16_t, uint32_t}; use libc::types::common::c99::{uint16_t, uint32_t};
use geom::point::Point2D; use geom::point::Point2D;
use text::font_library::FontLibrary; use text::font_cache::FontCache;
use text::font::Font; use text::font::Font;
use azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE}; use azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE};
use azure::bindgen::{AzCreateScaledFontWithCairo, use azure::bindgen::{AzCreateScaledFontWithCairo,
@ -133,10 +146,10 @@ pub fn draw_glyphs(draw_target: &DrawTarget, bounds: Rect<au>, text_run: &GlyphR
AzReleaseColorPattern}; AzReleaseColorPattern};
use azure::cairo::bindgen::cairo_scaled_font_destroy; use azure::cairo::bindgen::cairo_scaled_font_destroy;
let draw_target = draw_target.azure_draw_target; let draw_target = ctx.canvas.azure_draw_target;
// FIXME: The font library should not be created here // FIXME: The font library should not be created here
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let nfont: AzNativeFont = { let nfont: AzNativeFont = {
@ -182,7 +195,8 @@ pub fn draw_glyphs(draw_target: &DrawTarget, bounds: Rect<au>, text_run: &GlyphR
mNumGlyphs: azglyphs.len() as uint32_t mNumGlyphs: azglyphs.len() as uint32_t
}}; }};
AzDrawTargetFillGlyphs(draw_target, azfont, addr_of(glyphbuf), // TODO: this call needs to move into azure_hl.rs
AzDrawTargetFillGlyphs(ctx.canvas.azure_draw_target, azfont, addr_of(glyphbuf),
pattern, addr_of(options), null()); pattern, addr_of(options), null());
AzReleaseColorPattern(pattern); AzReleaseColorPattern(pattern);
@ -249,8 +263,8 @@ fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t {
return cfont; return cfont;
} }
fn clear(draw_target: &DrawTarget) { fn clear(ctx: &RenderContext) {
let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat)); let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat));
let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), Size2D(800 as AzFloat, 600 as AzFloat)); let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat), Size2D(800 as AzFloat, 600 as AzFloat));
draw_target.fill_rect(rect, pattern); ctx.canvas.fill_rect(rect, pattern);
} }

View file

@ -14,6 +14,7 @@ use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use image::{Image, ImageHolder}; use image::{Image, ImageHolder};
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::debug::DebugMethods; use layout::debug::DebugMethods;
use layout::inline::InlineFlowData; use layout::inline::InlineFlowData;
use layout::root::RootFlowData; use layout::root::RootFlowData;
@ -85,29 +86,29 @@ impl @FlowContext : cmp::Eq {
} }
impl @FlowContext { impl @FlowContext {
fn bubble_widths() { fn bubble_widths(ctx: &LayoutContext) {
match self.kind { match self.kind {
BlockFlow(*) => self.bubble_widths_block(), BlockFlow(*) => self.bubble_widths_block(ctx),
InlineFlow(*) => self.bubble_widths_inline(), InlineFlow(*) => self.bubble_widths_inline(ctx),
RootFlow(*) => self.bubble_widths_root(), RootFlow(*) => self.bubble_widths_root(ctx),
_ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind) _ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
} }
} }
fn assign_widths() { fn assign_widths(ctx: &LayoutContext) {
match self.kind { match self.kind {
BlockFlow(*) => self.assign_widths_block(), BlockFlow(*) => self.assign_widths_block(ctx),
InlineFlow(*) => self.assign_widths_inline(), InlineFlow(*) => self.assign_widths_inline(ctx),
RootFlow(*) => self.assign_widths_root(), RootFlow(*) => self.assign_widths_root(ctx),
_ => fail fmt!("Tried to assign_widths of flow: %?", self.kind) _ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
} }
} }
fn assign_height() { fn assign_height(ctx: &LayoutContext) {
match self.kind { match self.kind {
BlockFlow(*) => self.assign_height_block(), BlockFlow(*) => self.assign_height_block(ctx),
InlineFlow(*) => self.assign_height_inline(), InlineFlow(*) => self.assign_height_inline(ctx),
RootFlow(*) => self.assign_height_root(), RootFlow(*) => self.assign_height_root(ctx),
_ => fail fmt!("Tried to assign_height of flow: %?", self.kind) _ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
} }
} }
@ -224,9 +225,7 @@ impl @Box {
// how to compute its own min and pref widths, and should // how to compute its own min and pref widths, and should
// probably cache them. // probably cache them.
TextBox(d) => d.runs.foldl(au(0), |sum, run| { TextBox(d) => d.runs.foldl(au(0), |sum, run| {
let ret = au::max(sum, run.min_break_width()); au::max(sum, run.min_break_width())
debug!("text min width: %?px", au::to_px(ret));
ret
}) })
} }
} }
@ -248,9 +247,7 @@ impl @Box {
// how to compute its own min and pref widths, and should // how to compute its own min and pref widths, and should
// probably cache them. // probably cache them.
TextBox(d) => d.runs.foldl(au(0), |sum, run| { TextBox(d) => d.runs.foldl(au(0), |sum, run| {
let ret = au::max(sum, run.size().width); au::max(sum, run.size().width)
debug!("text pref width: %?px", au::to_px(ret));
ret
}) })
} }
} }

View file

@ -4,6 +4,7 @@ use geom::point::Point2D;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use layout::base::{Box, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::base::{Box, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::context::LayoutContext;
use util::tree; use util::tree;
struct BlockFlowData { struct BlockFlowData {
@ -21,9 +22,9 @@ trait BlockLayout {
pure fn access_block<T>(fn(&&BlockFlowData) -> T) -> T; pure fn access_block<T>(fn(&&BlockFlowData) -> T) -> T;
pure fn with_block_box(fn(&&@Box) -> ()) -> (); pure fn with_block_box(fn(&&@Box) -> ()) -> ();
fn bubble_widths_block(); fn bubble_widths_block(ctx: &LayoutContext);
fn assign_widths_block(); fn assign_widths_block(ctx: &LayoutContext);
fn assign_height_block(); fn assign_height_block(ctx: &LayoutContext);
} }
impl @FlowContext : BlockLayout { impl @FlowContext : BlockLayout {
@ -71,7 +72,7 @@ impl @FlowContext : BlockLayout {
/* TODO: floats */ /* TODO: floats */
/* TODO: absolute contexts */ /* TODO: absolute contexts */
/* TODO: inline-blocks */ /* TODO: inline-blocks */
fn bubble_widths_block() { fn bubble_widths_block(ctx: &LayoutContext) {
assert self.starts_block_flow(); assert self.starts_block_flow();
let mut min_width = au(0); let mut min_width = au(0);
@ -103,7 +104,7 @@ impl @FlowContext : BlockLayout {
Dual boxes consume some width first, and the remainder is assigned to Dual boxes consume some width first, and the remainder is assigned to
all child (block) contexts. */ all child (block) contexts. */
fn assign_widths_block() { fn assign_widths_block(ctx: &LayoutContext) {
assert self.starts_block_flow(); assert self.starts_block_flow();
let mut remaining_width = self.data.position.size.width; let mut remaining_width = self.data.position.size.width;
@ -125,7 +126,7 @@ impl @FlowContext : BlockLayout {
} }
} }
fn assign_height_block() { fn assign_height_block(ctx: &LayoutContext) {
assert self.starts_block_flow(); assert self.starts_block_flow();
let mut cur_y = au(0); let mut cur_y = au(0);

View file

@ -8,13 +8,14 @@ use dom::base::{Element, Text, Node, Doctype, Comment, NodeTree};
use layout::base::{Box, BoxData, GenericBox, ImageBox, TextBox, BoxTree}; use layout::base::{Box, BoxData, GenericBox, ImageBox, TextBox, BoxTree};
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree}; use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::inline::InlineFlowData; use layout::inline::InlineFlowData;
use layout::root::RootFlowData; use layout::root::RootFlowData;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use option::is_none; use option::is_none;
use util::tree; use util::tree;
use servo_text::text_run::TextRun; use servo_text::text_run::TextRun;
use servo_text::font_library::FontLibrary; use servo_text::font_cache::FontCache;
export LayoutTreeBuilder; export LayoutTreeBuilder;
@ -41,7 +42,7 @@ impl LayoutTreeBuilder {
/** Creates necessary box(es) and flow context(s) for the current DOM node, /** Creates necessary box(es) and flow context(s) for the current DOM node,
and recurses on its children. */ and recurses on its children. */
fn construct_recursively(cur_node: Node, parent_ctx: @FlowContext, parent_box: @Box) { fn construct_recursively(layout_ctx: &LayoutContext, cur_node: Node, parent_ctx: @FlowContext, parent_box: @Box) {
let style = cur_node.style(); let style = cur_node.style();
// DEBUG // DEBUG
@ -60,7 +61,7 @@ impl LayoutTreeBuilder {
}; };
// first, create the proper box kind, based on node characteristics // first, create the proper box kind, based on node characteristics
let box_data = match cur_node.create_box_data(display) { let box_data = match cur_node.create_box_data(layout_ctx, display) {
None => return, None => return,
Some(data) => data Some(data) => data
}; };
@ -116,7 +117,7 @@ impl LayoutTreeBuilder {
} }
// recurse // recurse
do NodeTree.each_child(cur_node) |child_node| { do NodeTree.each_child(cur_node) |child_node| {
self.construct_recursively(child_node, next_ctx, new_box); true self.construct_recursively(layout_ctx, child_node, next_ctx, new_box); true
} }
// Fixup any irregularities, such as split inlines (CSS 2.1 Section 9.2.1.1) // Fixup any irregularities, such as split inlines (CSS 2.1 Section 9.2.1.1)
@ -145,11 +146,11 @@ impl LayoutTreeBuilder {
/** entry point for box creation. Should only be /** entry point for box creation. Should only be
called on root DOM element. */ called on root DOM element. */
fn construct_trees(root: Node) -> Result<@Box, ()> { fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@Box, ()> {
self.root_ctx = Some(self.make_ctx(RootFlow(RootFlowData()), tree::empty())); self.root_ctx = Some(self.make_ctx(RootFlow(RootFlowData()), tree::empty()));
self.root_box = Some(self.make_box(root, self.root_ctx.get(), GenericBox)); self.root_box = Some(self.make_box(root, self.root_ctx.get(), GenericBox));
self.construct_recursively(root, self.root_ctx.get(), self.root_box.get()); self.construct_recursively(layout_ctx, root, self.root_ctx.get(), self.root_box.get());
return Ok(self.root_box.get()) return Ok(self.root_box.get())
} }
@ -167,18 +168,17 @@ impl LayoutTreeBuilder {
} }
trait PrivateBuilderMethods { trait PrivateBuilderMethods {
fn create_box_data(display: CSSDisplay) -> Option<BoxData>; fn create_box_data(layout_ctx: &LayoutContext, display: CSSDisplay) -> Option<BoxData>;
} }
impl Node : PrivateBuilderMethods { impl Node : PrivateBuilderMethods {
fn create_box_data(display: CSSDisplay) -> Option<BoxData> { fn create_box_data(layout_ctx: &LayoutContext, display: CSSDisplay) -> Option<BoxData> {
do self.read |node| { do self.read |node| {
match node.kind { match node.kind {
~Doctype(*) | ~Comment(*) => None, ~Doctype(*) | ~Comment(*) => None,
~Text(string) => { ~Text(string) => {
// TODO: clean this up. Fonts should not be created here. // TODO: clean this up. Fonts should not be created here.
let flib = FontLibrary(); let font = layout_ctx.font_cache.get_test_font();
let font = flib.get_test_font();
let run = TextRun(font, string); let run = TextRun(font, string);
Some(TextBox(TextBoxData(copy string, ~[move run]))) Some(TextBox(TextBoxData(copy string, ~[move run])))
} }

View file

@ -6,6 +6,7 @@ use dom::rcu;
use geom::point::Point2D; use geom::point::Point2D;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use layout::context::LayoutContext;
use layout::base::{FlowContext, InlineFlow, BoxTree, ImageBox, TextBox, GenericBox}; use layout::base::{FlowContext, InlineFlow, BoxTree, ImageBox, TextBox, GenericBox};
use num::Num; use num::Num;
use util::tree; use util::tree;
@ -24,9 +25,9 @@ trait InlineLayout {
pure fn starts_inline_flow() -> bool; pure fn starts_inline_flow() -> bool;
pure fn access_inline<T>(fn(&&InlineFlowData) -> T) -> T; pure fn access_inline<T>(fn(&&InlineFlowData) -> T) -> T;
fn bubble_widths_inline(); fn bubble_widths_inline(ctx: &LayoutContext);
fn assign_widths_inline(); fn assign_widths_inline(ctx: &LayoutContext);
fn assign_height_inline(); fn assign_height_inline(ctx: &LayoutContext);
} }
impl @FlowContext : InlineLayout { impl @FlowContext : InlineLayout {
@ -39,7 +40,7 @@ impl @FlowContext : InlineLayout {
} }
} }
fn bubble_widths_inline() { fn bubble_widths_inline(ctx: &LayoutContext) {
assert self.starts_inline_flow(); assert self.starts_inline_flow();
let mut min_width = au(0); let mut min_width = au(0);
@ -66,7 +67,7 @@ impl @FlowContext : InlineLayout {
/* Recursively (top-down) determines the actual width of child /* Recursively (top-down) determines the actual width of child
contexts and boxes. When called on this context, the context has contexts and boxes. When called on this context, the context has
had its width set by the parent context. */ had its width set by the parent context. */
fn assign_widths_inline() { fn assign_widths_inline(ctx: &LayoutContext) {
assert self.starts_inline_flow(); assert self.starts_inline_flow();
/* Perform inline flow with the available width. */ /* Perform inline flow with the available width. */
@ -117,7 +118,7 @@ impl @FlowContext : InlineLayout {
} // fn assign_widths_inline } // fn assign_widths_inline
fn assign_height_inline() { fn assign_height_inline(ctx: &LayoutContext) {
// Don't need to set box or ctx heights, since that is done // Don't need to set box or ctx heights, since that is done
// during inline flowing. // during inline flowing.
} }

View file

@ -13,10 +13,12 @@ use dom::event::{Event, ReflowEvent};
use gfx::render_task; use gfx::render_task;
use layout::base::Box; use layout::base::Box;
use layout::box_builder::LayoutTreeBuilder; use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext;
use render_task::RenderTask; use render_task::RenderTask;
use resource::image_cache_task::ImageCacheTask; use resource::image_cache_task::ImageCacheTask;
use std::arc::ARC; use std::arc::ARC;
use std::net::url::Url; use std::net::url::Url;
use servo_text::font_cache::FontCache;
use layout::traverse::*; use layout::traverse::*;
use comm::*; use comm::*;
@ -35,52 +37,61 @@ fn LayoutTask(render_task: RenderTask, image_cache_task: ImageCacheTask) -> Layo
// This just keeps our dom aux objects alive // This just keeps our dom aux objects alive
let mut layout_data_refs = ~[]; let mut layout_data_refs = ~[];
let font_cache = FontCache();
loop { loop {
match request.recv() { match request.recv() {
PingMsg(ping_channel) => ping_channel.send(content_task::PongMsg), PingMsg(ping_channel) => ping_channel.send(content_task::PongMsg),
ExitMsg => { ExitMsg => {
debug!("layout: ExitMsg received"); debug!("layout: ExitMsg received");
break; break;
} }
BuildMsg(node, styles, doc_url, event_chan) => { BuildMsg(node, styles, doc_url, event_chan) => {
debug!("layout: received layout request for: %s", doc_url.to_str()); debug!("layout: received layout request for: %s", doc_url.to_str());
debug!("layout: parsed Node tree"); debug!("layout: parsed Node tree");
node.dump(); node.dump();
do util::time::time(~"layout") { let layout_ctx = LayoutContext {
layout_data_refs += node.initialize_style_for_subtree(); image_cache: image_cache_task,
node.recompute_style_for_subtree(styles); font_cache: font_cache,
doc_url: doc_url,
let root_box: @Box; };
let builder = LayoutTreeBuilder();
match builder.construct_trees(node) { do util::time::time(~"layout") {
Ok(root) => root_box = root, layout_data_refs += node.initialize_style_for_subtree();
Err(*) => fail ~"Root node should always exist" node.recompute_style_for_subtree(&layout_ctx, styles);
}
let root_box: @Box;
debug!("layout: constructed Box tree"); let builder = LayoutTreeBuilder();
root_box.dump(); match builder.construct_trees(&layout_ctx, node) {
Ok(root) => root_box = root,
debug!("layout: constructed Flow tree"); Err(*) => fail ~"Root node should always exist"
root_box.ctx.dump(); }
/* resolve styles (convert relative values) down the box tree */ debug!("layout: constructed Box tree");
let reflow_cb: fn~() = || event_chan.send(ReflowEvent); root_box.dump();
apply_style(root_box, &doc_url, image_cache_task, reflow_cb);
debug!("layout: constructed Flow tree");
/* perform layout passes over the flow tree */ root_box.ctx.dump();
let root_flow = root_box.ctx;
do root_flow.traverse_postorder |f| { f.bubble_widths() } /* resolve styles (convert relative values) down the box tree */
root_flow.data.position.origin = au::zero_point(); let reflow_cb: fn~() = || event_chan.send(ReflowEvent);
root_flow.data.position.size.width = au::from_px(800); // TODO: window/frame size apply_style(&layout_ctx, root_box, reflow_cb);
do root_flow.traverse_preorder |f| { f.assign_widths() }
do root_flow.traverse_postorder |f| { f.assign_height() } /* perform layout passes over the flow tree */
let root_flow = root_box.ctx;
let dlist = build_display_list(root_box); do root_flow.traverse_postorder |f| { f.bubble_widths(&layout_ctx) }
render_task.send(render_task::RenderMsg(dlist)); // TODO: window/frame size should be set inside RootBox::assign_widths
root_flow.data.position.origin = au::zero_point();
root_flow.data.position.size.width = au::from_px(800);
// end TODO
do root_flow.traverse_preorder |f| { f.assign_widths(&layout_ctx) }
do root_flow.traverse_postorder |f| { f.assign_height(&layout_ctx) }
let dlist = build_display_list(root_box);
render_task.send(render_task::RenderMsg(dlist));
}
} }
}
} }
} }
} }

View file

@ -4,6 +4,7 @@ use geom::point::Point2D;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use layout::base::{Box, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::base::{Box, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::context::LayoutContext;
use util::tree; use util::tree;
struct RootFlowData { struct RootFlowData {
@ -20,9 +21,9 @@ trait RootLayout {
pure fn starts_root_flow() -> bool; pure fn starts_root_flow() -> bool;
pure fn access_root<T>(fn(&&RootFlowData) -> T) -> T; pure fn access_root<T>(fn(&&RootFlowData) -> T) -> T;
fn bubble_widths_root(); fn bubble_widths_root(ctx: &LayoutContext);
fn assign_widths_root(); fn assign_widths_root(ctx: &LayoutContext);
fn assign_height_root(); fn assign_height_root(ctx: &LayoutContext);
} }
impl @FlowContext : RootLayout { impl @FlowContext : RootLayout {
@ -42,21 +43,21 @@ impl @FlowContext : RootLayout {
} }
/* defer to the block algorithm */ /* defer to the block algorithm */
fn bubble_widths_root() { fn bubble_widths_root(ctx: &LayoutContext) {
assert self.starts_root_flow(); assert self.starts_root_flow();
self.bubble_widths_block() self.bubble_widths_block(ctx)
} }
fn assign_widths_root() { fn assign_widths_root(ctx: &LayoutContext) {
assert self.starts_root_flow(); assert self.starts_root_flow();
/* TODO: should determine frame width here, not in /* TODO: should determine frame width here, not in
LayoutTask. Until then, defer to block. */ LayoutTask. Until then, defer to block. */
self.assign_widths_block() } self.assign_widths_block(ctx) }
fn assign_height_root() { fn assign_height_root(ctx: &LayoutContext) {
assert self.starts_root_flow(); assert self.starts_root_flow();
self.assign_height_block(); self.assign_height_block(ctx);
} }
} }

View file

@ -4,8 +4,9 @@ use au = gfx::geometry;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use servo_text::text_run::TextRun; use servo_text::text_run::TextRun;
use servo_text::font_library::FontLibrary; use servo_text::font_cache::FontCache;
use layout::base::{TextBox, Box}; use layout::base::{TextBox, Box};
use layout::context::LayoutContext;
struct TextBoxData { struct TextBoxData {
text: ~str, text: ~str,
@ -20,20 +21,18 @@ fn TextBoxData(text: ~str, runs: ~[TextRun]) -> TextBoxData {
} }
trait TextLayout { trait TextLayout {
fn reflow_text(); fn reflow_text(ctx: &LayoutContext);
} }
#[doc="The main reflow routine for text layout."] #[doc="The main reflow routine for text layout."]
impl @Box : TextLayout { impl @Box : TextLayout {
fn reflow_text() { fn reflow_text(ctx: &LayoutContext) {
let d = match self.kind { let d = match self.kind {
TextBox(d) => { d } TextBox(d) => { d }
_ => { fail ~"expected text box in reflow_text!" } _ => { fail ~"expected text box in reflow_text!" }
}; };
// FIXME: The font library should not be initialized here let font = ctx.font_cache.get_test_font();
let flib = FontLibrary();
let font = flib.get_test_font();
// Do line breaking. // Do line breaking.
let mut current = TextRun(font, d.text); let mut current = TextRun(font, d.text);

View file

@ -4,28 +4,28 @@ use layout::base::{Box, BoxTree};
use layout::base::{FlowContext, FlowTree}; use layout::base::{FlowContext, FlowTree};
trait BoxTraversals { trait BoxTraversals {
fn traverse_preorder(preorder_cb: ~fn(@Box)); fn traverse_preorder(preorder_cb: &fn(@Box));
} }
impl @Box : BoxTraversals { impl @Box : BoxTraversals {
fn traverse_preorder(preorder_cb: ~fn(@Box)) { fn traverse_preorder(preorder_cb: &fn(@Box)) {
preorder_cb(self); preorder_cb(self);
do BoxTree.each_child(self) |child| { child.traverse_preorder(preorder_cb); true } do BoxTree.each_child(self) |child| { child.traverse_preorder(preorder_cb); true }
} }
} }
trait FlowContextTraversals { trait FlowContextTraversals {
fn traverse_preorder(preorder_cb: ~fn(@FlowContext)); fn traverse_preorder(preorder_cb: &fn(@FlowContext));
fn traverse_postorder(postorder_cb: ~fn(@FlowContext)); fn traverse_postorder(postorder_cb: &fn(@FlowContext));
} }
impl @FlowContext : FlowContextTraversals { impl @FlowContext : FlowContextTraversals {
fn traverse_preorder(preorder_cb: ~fn(@FlowContext)) { fn traverse_preorder(preorder_cb: &fn(@FlowContext)) {
preorder_cb(self); preorder_cb(self);
do FlowTree.each_child(self) |child| { child.traverse_preorder(preorder_cb); true } do FlowTree.each_child(self) |child| { child.traverse_preorder(preorder_cb); true }
} }
fn traverse_postorder(postorder_cb: ~fn(@FlowContext)) { fn traverse_postorder(postorder_cb: &fn(@FlowContext)) {
do FlowTree.each_child(self) |child| { child.traverse_postorder(postorder_cb); true } do FlowTree.each_child(self) |child| { child.traverse_postorder(postorder_cb); true }
postorder_cb(self); postorder_cb(self);
} }

View file

@ -55,6 +55,7 @@ mod layout {
mod base; mod base;
mod block; mod block;
mod box_builder; mod box_builder;
mod context;
mod debug; mod debug;
mod display_list_builder; mod display_list_builder;
mod inline; mod inline;
@ -97,12 +98,12 @@ mod platform {
mod text { mod text {
export glyph; export glyph;
export text_run; export text_run;
export font_library;
export font; export font;
export font_cache;
export shaper; export shaper;
mod font; mod font;
mod font_library; mod font_cache;
mod glyph; mod glyph;
mod native_font { mod native_font {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]

View file

@ -1,3 +1,4 @@
pub use font_cache::FontCache;
export Font, FontMetrics, test_font_bin, create_test_font; export Font, FontMetrics, test_font_bin, create_test_font;
use glyph::GlyphIndex; use glyph::GlyphIndex;
@ -5,7 +6,6 @@ use vec_to_ptr = vec::raw::to_ptr;
use libc::{ c_int, c_double, c_ulong }; use libc::{ c_int, c_double, c_ulong };
use ptr::{ null, addr_of }; use ptr::{ null, addr_of };
use native_font::NativeFont; use native_font::NativeFont;
use font_library::FontLibrary;
#[doc = " #[doc = "
A font handle. Layout can use this to calculate glyph metrics A font handle. Layout can use this to calculate glyph metrics
@ -13,7 +13,7 @@ and the renderer can use it to render text.
"] "]
struct Font { struct Font {
// A back reference to keep the library alive // A back reference to keep the library alive
lib: @FontLibrary, lib: @FontCache,
fontbuf: @~[u8], fontbuf: @~[u8],
native_font: NativeFont, native_font: NativeFont,
metrics: FontMetrics metrics: FontMetrics
@ -36,7 +36,7 @@ impl Font {
} }
} }
fn Font(lib: @FontLibrary, fontbuf: @~[u8], +native_font: NativeFont, +metrics: FontMetrics) -> Font { fn Font(lib: @FontCache, fontbuf: @~[u8], +native_font: NativeFont, +metrics: FontMetrics) -> Font {
Font { Font {
lib: lib, lib: lib,
fontbuf : fontbuf, fontbuf : fontbuf,
@ -67,7 +67,7 @@ fn should_destruct_on_fail_without_leaking() {
#[test]; #[test];
#[should_fail]; #[should_fail];
let lib = FontLibrary(); let lib = FontCache();
let _font = lib.get_test_font(); let _font = lib.get_test_font();
fail; fail;
} }
@ -75,7 +75,7 @@ fn should_destruct_on_fail_without_leaking() {
fn should_get_glyph_indexes() { fn should_get_glyph_indexes() {
#[test]; #[test];
let lib = FontLibrary(); let lib = FontCache();
let font = lib.get_test_font(); let font = lib.get_test_font();
let glyph_idx = font.glyph_index('w'); let glyph_idx = font.glyph_index('w');
assert glyph_idx == Some(40u); assert glyph_idx == Some(40u);
@ -84,7 +84,7 @@ fn should_get_glyph_indexes() {
fn should_get_glyph_advance() { fn should_get_glyph_advance() {
#[test]; #[test];
let lib = FontLibrary(); let lib = FontCache();
let font = lib.get_test_font(); let font = lib.get_test_font();
let x = font.glyph_h_advance(40u); let x = font.glyph_h_advance(40u);
assert x == 15; assert x == 15;
@ -100,7 +100,7 @@ fn should_get_glyph_advance_stress() {
let (chan, port) = pipes::stream(); let (chan, port) = pipes::stream();
ports += [@move port]; ports += [@move port];
do task::spawn { do task::spawn {
let lib = FontLibrary(); let lib = FontCache();
let font = lib.get_test_font(); let font = lib.get_test_font();
let x = font.glyph_h_advance(40u); let x = font.glyph_h_advance(40u);
assert x == 15; assert x == 15;
@ -118,7 +118,7 @@ fn should_be_able_to_create_instances_in_multiple_threads() {
for iter::repeat(10u) { for iter::repeat(10u) {
do task::spawn { do task::spawn {
let lib = FontLibrary(); let lib = FontCache();
let _font = lib.get_test_font(); let _font = lib.get_test_font();
} }
} }

View file

@ -1,20 +1,19 @@
export FontLibrary, native; export FontCache, native;
use font::{Font, test_font_bin}; use font::{Font, test_font_bin};
struct FontLibrary { struct FontCache {
// FIXME: This is a hack to hold onto a boxed reference to // FIXME: This is a hack to hold onto a boxed reference to
// the self pointer until explicit self types work on methods. // the self pointer until explicit self types work on methods.
// This is a huge space leak. // This is a huge space leak.
mut at_self: Option<@FontLibrary>, mut at_self: Option<@FontCache>,
native_lib: native::NativeFontLibrary, native_lib: native::NativeFontCache,
drop { drop {
native::destroy_native_lib(&self.native_lib); native::destroy_native_lib(&self.native_lib);
} }
} }
impl FontLibrary { impl FontCache {
fn get_font() -> @Font { fn get_font() -> @Font {
assert self.at_self.is_some(); assert self.at_self.is_some();
match create_font(self.at_self.get(), &self.native_lib) { match create_font(self.at_self.get(), &self.native_lib) {
@ -28,8 +27,8 @@ impl FontLibrary {
} }
} }
fn FontLibrary() -> @FontLibrary { fn FontCache() -> @FontCache {
let lib = @FontLibrary { let lib = @FontCache {
mut at_self: None, mut at_self: None,
native_lib: native::create_native_lib() native_lib: native::create_native_lib()
}; };
@ -38,7 +37,7 @@ fn FontLibrary() -> @FontLibrary {
return lib; return lib;
} }
fn create_font(lib: @FontLibrary, native_lib: &native::NativeFontLibrary) -> Result<@Font, ()> { fn create_font(lib: @FontCache, native_lib: &native::NativeFontCache) -> Result<@Font, ()> {
let font_bin = @test_font_bin(); let font_bin = @test_font_bin();
let native_font = native_font::create(native_lib, font_bin); let native_font = native_font::create(native_lib, font_bin);
let native_font = if native_font.is_ok() { let native_font = if native_font.is_ok() {
@ -57,9 +56,9 @@ mod native {
use freetype::{FT_Library, FT_Error}; use freetype::{FT_Library, FT_Error};
use freetype::bindgen::{FT_Init_FreeType, FT_Done_FreeType}; use freetype::bindgen::{FT_Init_FreeType, FT_Done_FreeType};
type NativeFontLibrary = FT_Library; type NativeFontCache = FT_Library;
fn create_native_lib() -> NativeFontLibrary { fn create_native_lib() -> NativeFontCache {
let lib: FT_Library = null(); let lib: FT_Library = null();
let res = FT_Init_FreeType(addr_of(lib)); let res = FT_Init_FreeType(addr_of(lib));
// FIXME: error handling // FIXME: error handling
@ -67,7 +66,7 @@ mod native {
return lib; return lib;
} }
fn destroy_native_lib(native_lib: &NativeFontLibrary) { fn destroy_native_lib(native_lib: &NativeFontCache) {
assert native_lib.is_not_null(); assert native_lib.is_not_null();
FT_Done_FreeType(*native_lib); FT_Done_FreeType(*native_lib);
} }
@ -75,14 +74,14 @@ mod native {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
mod native { mod native {
type NativeFontLibrary = (); type NativeFontCache = ();
fn create_native_lib() -> NativeFontLibrary { () } fn create_native_lib() -> NativeFontCache { () }
fn destroy_native_lib(_native_lib: &NativeFontLibrary) { } fn destroy_native_lib(_native_lib: &NativeFontCache) { }
} }
#[test] #[test]
fn should_get_fonts() { fn should_get_fonts() {
let lib = FontLibrary(); let lib = FontCache();
lib.get_font(); lib.get_font();
} }

View file

@ -9,7 +9,7 @@ font resources needed by the graphics layer to draw glyphs.
export NativeFont, create; export NativeFont, create;
use font_library::native::NativeFontLibrary; use font_cache::native::NativeFontCache;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
type NativeFont/& = quartz_native_font::QuartzNativeFont; type NativeFont/& = quartz_native_font::QuartzNativeFont;
@ -18,12 +18,12 @@ type NativeFont/& = quartz_native_font::QuartzNativeFont;
type NativeFont/& = ft_native_font::FreeTypeNativeFont; type NativeFont/& = ft_native_font::FreeTypeNativeFont;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn create(_native_lib: &NativeFontLibrary, buf: @~[u8]) -> Result<NativeFont, ()> { fn create(_native_lib: &NativeFontCache, buf: @~[u8]) -> Result<NativeFont, ()> {
quartz_native_font::create(buf) quartz_native_font::create(buf)
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn create(native_lib: &NativeFontLibrary, buf: @~[u8]) -> Result<NativeFont, ()> { fn create(native_lib: &NativeFontCache, buf: @~[u8]) -> Result<NativeFont, ()> {
ft_native_font::create(native_lib, buf) ft_native_font::create(native_lib, buf)
} }

View file

@ -10,7 +10,7 @@ use glyph::{Glyph, GlyphPos};
use ptr::{null, addr_of, offset}; use ptr::{null, addr_of, offset};
use gfx::geometry::au; use gfx::geometry::au;
use geom::point::Point2D; use geom::point::Point2D;
use font_library::FontLibrary; use font_cache::FontCache;
use unsafe::reinterpret_cast; use unsafe::reinterpret_cast;
use harfbuzz::{HB_MEMORY_MODE_READONLY, use harfbuzz::{HB_MEMORY_MODE_READONLY,
@ -148,7 +148,7 @@ fn should_get_glyph_indexes() {
#[test]; #[test];
#[ignore(cfg(target_os = "macos"), reason = "bad metrics")]; #[ignore(cfg(target_os = "macos"), reason = "bad metrics")];
let lib = FontLibrary(); let lib = FontCache();
let font = lib.get_test_font(); let font = lib.get_test_font();
let glyphs = shape_text(font, ~"firecracker"); let glyphs = shape_text(font, ~"firecracker");
let idxs = glyphs.map(|glyph| glyph.index); let idxs = glyphs.map(|glyph| glyph.index);
@ -159,7 +159,7 @@ fn should_get_glyph_h_advance() {
#[test]; #[test];
#[ignore(cfg(target_os = "macos"), reason = "bad metrics")]; #[ignore(cfg(target_os = "macos"), reason = "bad metrics")];
let lib = FontLibrary(); let lib = FontCache();
let font = lib.get_test_font(); let font = lib.get_test_font();
let glyphs = shape_text(font, ~"firecracker"); let glyphs = shape_text(font, ~"firecracker");
let actual = glyphs.map(|g| g.pos.advance.x); let actual = glyphs.map(|g| g.pos.advance.x);

View file

@ -3,7 +3,7 @@ use geom::point::Point2D;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::au; use gfx::geometry::au;
use libc::{c_void}; use libc::{c_void};
use font_library::FontLibrary; use font_cache::FontCache;
use font::Font; use font::Font;
use glyph::Glyph; use glyph::Glyph;
use shaper::shape_text; use shaper::shape_text;
@ -135,7 +135,7 @@ fn iter_indivisible_slices(font: &Font, text: &r/str,
#[test] #[test]
fn test_calc_min_break_width1() { fn test_calc_min_break_width1() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let actual = calc_min_break_width(font, ~"firecracker"); let actual = calc_min_break_width(font, ~"firecracker");
let expected = au::from_px(84); let expected = au::from_px(84);
@ -144,7 +144,7 @@ fn test_calc_min_break_width1() {
#[test] #[test]
fn test_calc_min_break_width2() { fn test_calc_min_break_width2() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let actual = calc_min_break_width(font, ~"firecracker yumyum"); let actual = calc_min_break_width(font, ~"firecracker yumyum");
let expected = au::from_px(84); let expected = au::from_px(84);
@ -153,7 +153,7 @@ fn test_calc_min_break_width2() {
#[test] #[test]
fn test_calc_min_break_width3() { fn test_calc_min_break_width3() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let actual = calc_min_break_width(font, ~"yumyum firecracker"); let actual = calc_min_break_width(font, ~"yumyum firecracker");
let expected = au::from_px(84); let expected = au::from_px(84);
@ -162,7 +162,7 @@ fn test_calc_min_break_width3() {
#[test] #[test]
fn test_calc_min_break_width4() { fn test_calc_min_break_width4() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let actual = calc_min_break_width(font, ~"yumyum firecracker yumyum"); let actual = calc_min_break_width(font, ~"yumyum firecracker yumyum");
let expected = au::from_px(84); let expected = au::from_px(84);
@ -171,7 +171,7 @@ fn test_calc_min_break_width4() {
#[test] #[test]
fn test_iter_indivisible_slices() { fn test_iter_indivisible_slices() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let mut slices = ~[]; let mut slices = ~[];
for iter_indivisible_slices(font, "firecracker yumyum woopwoop") |slice| { for iter_indivisible_slices(font, "firecracker yumyum woopwoop") |slice| {
@ -182,7 +182,7 @@ fn test_iter_indivisible_slices() {
#[test] #[test]
fn test_iter_indivisible_slices_trailing_whitespace() { fn test_iter_indivisible_slices_trailing_whitespace() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let mut slices = ~[]; let mut slices = ~[];
for iter_indivisible_slices(font, "firecracker ") |slice| { for iter_indivisible_slices(font, "firecracker ") |slice| {
@ -193,7 +193,7 @@ fn test_iter_indivisible_slices_trailing_whitespace() {
#[test] #[test]
fn test_iter_indivisible_slices_leading_whitespace() { fn test_iter_indivisible_slices_leading_whitespace() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let mut slices = ~[]; let mut slices = ~[];
for iter_indivisible_slices(font, " firecracker") |slice| { for iter_indivisible_slices(font, " firecracker") |slice| {
@ -204,7 +204,7 @@ fn test_iter_indivisible_slices_leading_whitespace() {
#[test] #[test]
fn test_iter_indivisible_slices_empty() { fn test_iter_indivisible_slices_empty() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let mut slices = ~[]; let mut slices = ~[];
for iter_indivisible_slices(font, "") |slice| { for iter_indivisible_slices(font, "") |slice| {
@ -215,7 +215,7 @@ fn test_iter_indivisible_slices_empty() {
#[test] #[test]
fn test_split() { fn test_split() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let run = TextRun(font, ~"firecracker yumyum"); let run = TextRun(font, ~"firecracker yumyum");
let break_runs = run.split(font, run.min_break_width()); let break_runs = run.split(font, run.min_break_width());
@ -225,7 +225,7 @@ fn test_split() {
#[test] #[test]
fn test_split2() { fn test_split2() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let run = TextRun(font, ~"firecracker yum yum yum yum yum"); let run = TextRun(font, ~"firecracker yum yum yum yum yum");
let break_runs = run.split(font, run.min_break_width()); let break_runs = run.split(font, run.min_break_width());
@ -235,7 +235,7 @@ fn test_split2() {
#[test] #[test]
fn test_split3() { fn test_split3() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let run = TextRun(font, ~"firecracker firecracker"); let run = TextRun(font, ~"firecracker firecracker");
let break_runs = run.split(font, run.min_break_width() + au::from_px(10)); let break_runs = run.split(font, run.min_break_width() + au::from_px(10));
@ -247,7 +247,7 @@ fn test_split3() {
#[test] #[test]
#[ignore(cfg(target_os = "macos"))] #[ignore(cfg(target_os = "macos"))]
fn should_calculate_the_total_size() { fn should_calculate_the_total_size() {
let flib = FontLibrary(); let flib = FontCache();
let font = flib.get_test_font(); let font = flib.get_test_font();
let run = TextRun(font, ~"firecracker"); let run = TextRun(font, ~"firecracker");
let expected = Size2D(au::from_px(84), au::from_px(20)); let expected = Size2D(au::from_px(84), au::from_px(20));