mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Thread RenderContext and LayoutContext throughout computations needing task assets, such as document URL, font cache, or image cache.
This commit is contained in:
parent
bcdc2ac597
commit
972791bb9f
18 changed files with 221 additions and 212 deletions
|
@ -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. */ }
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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])))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")]
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue