mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
Revert "auto merge of #1356 : ksh8281/servo/remove_@_in_LayoutTask.FontContext, r=pcwalton"
This reverts commite8ffac13d7
, reversing changes made todb923feffe
. Reverting this change because FreeType is *not* thread safe. See the documentation here: http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html "In multi-threaded applications, make sure that the same FT_Library object or any of its children doesn't get accessed in parallel." We will need to use a `MutexArc` instead.
This commit is contained in:
parent
e8ffac13d7
commit
30bbaa49b7
13 changed files with 120 additions and 122 deletions
|
@ -93,7 +93,7 @@ pub struct SolidColorDisplayItem<E> {
|
||||||
/// Renders text.
|
/// Renders text.
|
||||||
pub struct TextDisplayItem<E> {
|
pub struct TextDisplayItem<E> {
|
||||||
base: BaseDisplayItem<E>,
|
base: BaseDisplayItem<E>,
|
||||||
text_run: Arc<~TextRun>,
|
text_run: ~TextRun,
|
||||||
range: Range,
|
range: Range,
|
||||||
color: Color,
|
color: Color,
|
||||||
}
|
}
|
||||||
|
@ -163,8 +163,7 @@ impl<E> DisplayItem<E> {
|
||||||
debug!("Drawing text at {:?}.", text.base.bounds);
|
debug!("Drawing text at {:?}.", text.base.bounds);
|
||||||
|
|
||||||
// FIXME(pcwalton): Allocating? Why?
|
// FIXME(pcwalton): Allocating? Why?
|
||||||
let text_run = text.text_run.get();
|
let font = render_context.font_ctx.get_font_by_descriptor(&text.text_run.font_descriptor).unwrap();
|
||||||
let font = render_context.font_ctx.get_font_by_descriptor(&text_run.font_descriptor).unwrap();
|
|
||||||
|
|
||||||
let font_metrics = font.with_borrow( |font| {
|
let font_metrics = font.with_borrow( |font| {
|
||||||
font.metrics.clone()
|
font.metrics.clone()
|
||||||
|
@ -173,7 +172,7 @@ impl<E> DisplayItem<E> {
|
||||||
let baseline_origin = Point2D(origin.x, origin.y + font_metrics.ascent);
|
let baseline_origin = Point2D(origin.x, origin.y + font_metrics.ascent);
|
||||||
font.with_mut_borrow( |font| {
|
font.with_mut_borrow( |font| {
|
||||||
font.draw_text_into_context(render_context,
|
font.draw_text_into_context(render_context,
|
||||||
text.text_run.get(),
|
&text.text_run,
|
||||||
&text.range,
|
&text.range,
|
||||||
baseline_origin,
|
baseline_origin,
|
||||||
text.color);
|
text.color);
|
||||||
|
@ -184,18 +183,18 @@ impl<E> DisplayItem<E> {
|
||||||
let strikeout_size = font_metrics.strikeout_size;
|
let strikeout_size = font_metrics.strikeout_size;
|
||||||
let strikeout_offset = font_metrics.strikeout_offset;
|
let strikeout_offset = font_metrics.strikeout_offset;
|
||||||
|
|
||||||
if text_run.decoration.underline {
|
if text.text_run.decoration.underline {
|
||||||
let underline_y = baseline_origin.y - underline_offset;
|
let underline_y = baseline_origin.y - underline_offset;
|
||||||
let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y),
|
let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y),
|
||||||
Size2D(width, underline_size));
|
Size2D(width, underline_size));
|
||||||
render_context.draw_solid_color(&underline_bounds, text.color);
|
render_context.draw_solid_color(&underline_bounds, text.color);
|
||||||
}
|
}
|
||||||
if text_run.decoration.overline {
|
if text.text_run.decoration.overline {
|
||||||
let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y),
|
let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y),
|
||||||
Size2D(width, underline_size));
|
Size2D(width, underline_size));
|
||||||
render_context.draw_solid_color(&overline_bounds, text.color);
|
render_context.draw_solid_color(&overline_bounds, text.color);
|
||||||
}
|
}
|
||||||
if text_run.decoration.line_through {
|
if text.text_run.decoration.line_through {
|
||||||
let strikeout_y = baseline_origin.y - strikeout_offset;
|
let strikeout_y = baseline_origin.y - strikeout_offset;
|
||||||
let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y),
|
let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y),
|
||||||
Size2D(width, strikeout_size));
|
Size2D(width, strikeout_size));
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub fn dummy_style() -> FontStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FontContextHandleMethods {
|
pub trait FontContextHandleMethods {
|
||||||
|
fn clone(&self) -> FontContextHandle;
|
||||||
fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
|
fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use font::{CSSFontWeight, FontHandleMethods, FontMetrics, FontTableMethods};
|
||||||
use font::{FontTableTag, FractionalPixel, SpecifiedFontStyle, UsedFontStyle, FontWeight100};
|
use font::{FontTableTag, FractionalPixel, SpecifiedFontStyle, UsedFontStyle, FontWeight100};
|
||||||
use font::{FontWeight200, FontWeight300, FontWeight400, FontWeight500, FontWeight600};
|
use font::{FontWeight200, FontWeight300, FontWeight400, FontWeight500, FontWeight600};
|
||||||
use font::{FontWeight700, FontWeight800, FontWeight900};
|
use font::{FontWeight700, FontWeight800, FontWeight900};
|
||||||
|
use font_context::FontContextHandleMethods;
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::geometry;
|
use servo_util::geometry;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
@ -78,7 +79,7 @@ impl FontHandleMethods for FontHandle {
|
||||||
buf: ~[u8],
|
buf: ~[u8],
|
||||||
style: &SpecifiedFontStyle)
|
style: &SpecifiedFontStyle)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
let ft_ctx: FT_Library = fctx.ctx.get().ctx;
|
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||||
if ft_ctx.is_null() { return Err(()); }
|
if ft_ctx.is_null() { return Err(()); }
|
||||||
|
|
||||||
let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| {
|
let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| {
|
||||||
|
@ -291,7 +292,7 @@ impl<'self> FontHandle {
|
||||||
pub fn new_from_file(fctx: &FontContextHandle, file: &str,
|
pub fn new_from_file(fctx: &FontContextHandle, file: &str,
|
||||||
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ft_ctx: FT_Library = fctx.ctx.get().ctx;
|
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||||
if ft_ctx.is_null() { return Err(()); }
|
if ft_ctx.is_null() { return Err(()); }
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
|
@ -319,7 +320,7 @@ impl<'self> FontHandle {
|
||||||
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
|
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ft_ctx: FT_Library = fctx.ctx.get().ctx;
|
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||||
if ft_ctx.is_null() { return Err(()); }
|
if ft_ctx.is_null() { return Err(()); }
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
|
|
|
@ -11,23 +11,30 @@ use freetype::freetype::{FTErrorMethods, FT_Library};
|
||||||
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};
|
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};
|
||||||
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use extra::arc::Arc;
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
struct FreeTypeLibraryHandle {
|
struct FreeTypeLibraryHandle {
|
||||||
ctx: FT_Library,
|
ctx: FT_Library,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
// FIXME(ksh8281) this value have to use atomic operation for counting ref
|
||||||
|
static mut font_context_ref_count: uint = 0;
|
||||||
|
static mut ft_pointer: Option<FT_Library> = None;
|
||||||
pub struct FontContextHandle {
|
pub struct FontContextHandle {
|
||||||
ctx: Arc<FreeTypeLibraryHandle>,
|
ctx: FreeTypeLibraryHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for FreeTypeLibraryHandle {
|
impl Drop for FontContextHandle {
|
||||||
#[fixed_stack_segment]
|
#[fixed_stack_segment]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
assert!(self.ctx.is_not_null());
|
assert!(self.ctx.ctx.is_not_null());
|
||||||
unsafe { FT_Done_FreeType(self.ctx) };
|
unsafe {
|
||||||
|
assert!(font_context_ref_count >= 1);
|
||||||
|
font_context_ref_count = font_context_ref_count - 1;
|
||||||
|
if font_context_ref_count == 0 {
|
||||||
|
FT_Done_FreeType(self.ctx.ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,17 +42,38 @@ impl FontContextHandle {
|
||||||
#[fixed_stack_segment]
|
#[fixed_stack_segment]
|
||||||
pub fn new() -> FontContextHandle {
|
pub fn new() -> FontContextHandle {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ctx: FT_Library = ptr::null();
|
match ft_pointer {
|
||||||
let result = FT_Init_FreeType(&ctx);
|
Some(ref ctx) => {
|
||||||
if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
|
font_context_ref_count = font_context_ref_count + 1;
|
||||||
FontContextHandle {
|
FontContextHandle {
|
||||||
ctx: Arc::new(FreeTypeLibraryHandle { ctx: ctx }),
|
ctx: FreeTypeLibraryHandle { ctx: ctx.clone() },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let ctx: FT_Library = ptr::null();
|
||||||
|
let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
|
||||||
|
if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
|
||||||
|
ft_pointer = Some(ctx);
|
||||||
|
font_context_ref_count = font_context_ref_count + 1;
|
||||||
|
FontContextHandle {
|
||||||
|
ctx: FreeTypeLibraryHandle { ctx: ctx },
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontContextHandleMethods for FontContextHandle {
|
impl FontContextHandleMethods for FontContextHandle {
|
||||||
|
fn clone(&self) -> FontContextHandle {
|
||||||
|
unsafe {
|
||||||
|
font_context_ref_count = font_context_ref_count + 1;
|
||||||
|
FontContextHandle {
|
||||||
|
ctx: self.ctx.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
|
fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
debug!("Creating font handle for {:s}", name);
|
debug!("Creating font handle for {:s}", name);
|
||||||
|
|
|
@ -19,6 +19,7 @@ use fontconfig::fontconfig::{
|
||||||
|
|
||||||
|
|
||||||
use font::{FontHandleMethods, UsedFontStyle};
|
use font::{FontHandleMethods, UsedFontStyle};
|
||||||
|
use font_context::FontContextHandleMethods;
|
||||||
use font_list::{FontEntry, FontFamily, FontFamilyMap};
|
use font_list::{FontEntry, FontFamily, FontFamilyMap};
|
||||||
use platform::font::FontHandle;
|
use platform::font::FontHandle;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
|
|
@ -8,12 +8,10 @@ use platform::macos::font::FontHandle;
|
||||||
|
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
#[deriving(Clone)]
|
|
||||||
pub struct FontContextHandle {
|
pub struct FontContextHandle {
|
||||||
ctx: ()
|
ctx: ()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
|
||||||
impl FontContextHandle {
|
impl FontContextHandle {
|
||||||
// this is a placeholder until NSFontManager or whatever is bound in here.
|
// this is a placeholder until NSFontManager or whatever is bound in here.
|
||||||
pub fn new() -> FontContextHandle {
|
pub fn new() -> FontContextHandle {
|
||||||
|
@ -22,6 +20,12 @@ impl FontContextHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontContextHandleMethods for FontContextHandle {
|
impl FontContextHandleMethods for FontContextHandle {
|
||||||
|
fn clone(&self) -> FontContextHandle {
|
||||||
|
FontContextHandle {
|
||||||
|
ctx: self.ctx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_font_from_identifier(&self,
|
fn create_font_from_identifier(&self,
|
||||||
name: ~str,
|
name: ~str,
|
||||||
style: UsedFontStyle)
|
style: UsedFontStyle)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! The `Box` type, which represents the leaves of the layout tree.
|
//! The `Box` type, which represents the leaves of the layout tree.
|
||||||
|
|
||||||
use extra::url::Url;
|
use extra::url::Url;
|
||||||
use extra::arc::{MutexArc,Arc};
|
use extra::arc::MutexArc;
|
||||||
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||||
use gfx::color::rgb;
|
use gfx::color::rgb;
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
||||||
|
@ -160,7 +160,7 @@ impl ImageBoxInfo {
|
||||||
/// object.
|
/// object.
|
||||||
pub struct ScannedTextBoxInfo {
|
pub struct ScannedTextBoxInfo {
|
||||||
/// The text run that this represents.
|
/// The text run that this represents.
|
||||||
run: Arc<~TextRun>,
|
run: @TextRun,
|
||||||
|
|
||||||
/// The range within the above text run that this represents.
|
/// The range within the above text run that this represents.
|
||||||
range: Range,
|
range: Range,
|
||||||
|
@ -168,7 +168,7 @@ pub struct ScannedTextBoxInfo {
|
||||||
|
|
||||||
impl ScannedTextBoxInfo {
|
impl ScannedTextBoxInfo {
|
||||||
/// Creates the information specific to a scanned text box from a range and a text run.
|
/// Creates the information specific to a scanned text box from a range and a text run.
|
||||||
pub fn new(run: Arc<~TextRun>, range: Range) -> ScannedTextBoxInfo {
|
pub fn new(run: @TextRun, range: Range) -> ScannedTextBoxInfo {
|
||||||
ScannedTextBoxInfo {
|
ScannedTextBoxInfo {
|
||||||
run: run,
|
run: run,
|
||||||
range: range,
|
range: range,
|
||||||
|
@ -630,12 +630,21 @@ impl Box {
|
||||||
|
|
||||||
// Create the text box.
|
// Create the text box.
|
||||||
do list.with_mut_ref |list| {
|
do list.with_mut_ref |list| {
|
||||||
|
// FIXME(pcwalton): Allocation? Why?!
|
||||||
|
let run = ~TextRun {
|
||||||
|
text: text_box.run.text.clone(),
|
||||||
|
font_descriptor: text_box.run.font_descriptor.clone(),
|
||||||
|
font_metrics: text_box.run.font_metrics.clone(),
|
||||||
|
font_style: text_box.run.font_style.clone(),
|
||||||
|
decoration: text_box.run.decoration.clone(),
|
||||||
|
glyphs: text_box.run.glyphs.clone()
|
||||||
|
};
|
||||||
let text_display_item = ~TextDisplayItem {
|
let text_display_item = ~TextDisplayItem {
|
||||||
base: BaseDisplayItem {
|
base: BaseDisplayItem {
|
||||||
bounds: absolute_box_bounds,
|
bounds: absolute_box_bounds,
|
||||||
extra: ExtraDisplayListData::new(&self),
|
extra: ExtraDisplayListData::new(&self),
|
||||||
},
|
},
|
||||||
text_run: text_box.run.clone(),
|
text_run: run,
|
||||||
range: text_box.range,
|
range: text_box.range,
|
||||||
color: color,
|
color: color,
|
||||||
};
|
};
|
||||||
|
@ -668,7 +677,7 @@ impl Box {
|
||||||
// Draw a rectangle representing the baselines.
|
// Draw a rectangle representing the baselines.
|
||||||
//
|
//
|
||||||
// TODO(Issue #221): Create and use a Line display item for the baseline.
|
// TODO(Issue #221): Create and use a Line display item for the baseline.
|
||||||
let ascent = text_box.run.get().metrics_for_range(
|
let ascent = text_box.run.metrics_for_range(
|
||||||
&text_box.range).ascent;
|
&text_box.range).ascent;
|
||||||
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
|
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
|
||||||
Size2D(absolute_box_bounds.size.width, Au(0)));
|
Size2D(absolute_box_bounds.size.width, Au(0)));
|
||||||
|
@ -781,12 +790,11 @@ impl Box {
|
||||||
}
|
}
|
||||||
ScannedTextBox(ref text_box_info) => {
|
ScannedTextBox(ref text_box_info) => {
|
||||||
let range = &text_box_info.range;
|
let range = &text_box_info.range;
|
||||||
let text_run = text_box_info.run.get();
|
let min_line_width = text_box_info.run.min_width_for_range(range);
|
||||||
let min_line_width = text_run.min_width_for_range(range);
|
|
||||||
|
|
||||||
let mut max_line_width = Au::new(0);
|
let mut max_line_width = Au::new(0);
|
||||||
for line_range in text_run.iter_natural_lines_for_range(range) {
|
for line_range in text_box_info.run.iter_natural_lines_for_range(range) {
|
||||||
let line_metrics = text_run.metrics_for_range(&line_range);
|
let line_metrics = text_box_info.run.metrics_for_range(&line_range);
|
||||||
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,7 +824,7 @@ impl Box {
|
||||||
}
|
}
|
||||||
ScannedTextBox(ref text_box_info) => {
|
ScannedTextBox(ref text_box_info) => {
|
||||||
// Compute the height based on the line-height and font size.
|
// Compute the height based on the line-height and font size.
|
||||||
let (range, run) = (&text_box_info.range, &text_box_info.run.get());
|
let (range, run) = (&text_box_info.range, &text_box_info.run);
|
||||||
let text_bounds = run.metrics_for_range(range).bounding_box;
|
let text_bounds = run.metrics_for_range(range).bounding_box;
|
||||||
let em_size = text_bounds.size.height;
|
let em_size = text_bounds.size.height;
|
||||||
self.calculate_line_height(em_size)
|
self.calculate_line_height(em_size)
|
||||||
|
@ -838,12 +846,11 @@ impl Box {
|
||||||
|
|
||||||
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
|
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
|
||||||
avail_width={})",
|
avail_width={})",
|
||||||
text_box_info.run.get().text.get().len(),
|
text_box_info.run.text.get().len(),
|
||||||
text_box_info.range,
|
text_box_info.range,
|
||||||
max_width);
|
max_width);
|
||||||
|
|
||||||
let text_run = text_box_info.run.get();
|
for (glyphs, offset, slice_range) in text_box_info.run.iter_slices_for_range(
|
||||||
for (glyphs, offset, slice_range) in text_run.iter_slices_for_range(
|
|
||||||
&text_box_info.range) {
|
&text_box_info.range) {
|
||||||
debug!("split_to_width: considering slice (offset={}, range={}, \
|
debug!("split_to_width: considering slice (offset={}, range={}, \
|
||||||
remain_width={})",
|
remain_width={})",
|
||||||
|
@ -851,7 +858,7 @@ impl Box {
|
||||||
slice_range,
|
slice_range,
|
||||||
remaining_width);
|
remaining_width);
|
||||||
|
|
||||||
let metrics = text_run.metrics_for_slice(glyphs, &slice_range);
|
let metrics = text_box_info.run.metrics_for_slice(glyphs, &slice_range);
|
||||||
let advance = metrics.advance_width;
|
let advance = metrics.advance_width;
|
||||||
|
|
||||||
let should_continue;
|
let should_continue;
|
||||||
|
@ -902,23 +909,20 @@ impl Box {
|
||||||
}
|
}
|
||||||
|
|
||||||
let left_box = if left_range.length() > 0 {
|
let left_box = if left_range.length() > 0 {
|
||||||
|
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run, left_range);
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), left_range);
|
|
||||||
let new_size = text_box_info.run.get().
|
|
||||||
metrics_for_range(&left_range).bounding_box.size;
|
|
||||||
let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info));
|
let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info));
|
||||||
new_text_box.set_size(new_size);
|
let new_metrics = new_text_box_info.run.metrics_for_range(&left_range);
|
||||||
|
new_text_box.set_size(new_metrics.bounding_box.size);
|
||||||
Some(new_text_box)
|
Some(new_text_box)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let right_box = right_range.map_default(None, |range: Range| {
|
let right_box = right_range.map_default(None, |range: Range| {
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), range);
|
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run, range);
|
||||||
let new_size = text_box_info.run.get().
|
|
||||||
metrics_for_range(&range).bounding_box.size;
|
|
||||||
let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info));
|
let new_text_box = @Box::new(self.node, ScannedTextBox(new_text_box_info));
|
||||||
new_text_box.set_size(new_size);
|
let new_metrics = new_text_box_info.run.metrics_for_range(&range);
|
||||||
|
new_text_box.set_size(new_metrics.bounding_box.size);
|
||||||
Some(new_text_box)
|
Some(new_text_box)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -971,7 +975,7 @@ impl Box {
|
||||||
/// Cleans up all the memory associated with this box.
|
/// Cleans up all the memory associated with this box.
|
||||||
pub fn teardown(&self) {
|
pub fn teardown(&self) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ScannedTextBox(ref text_box_info) => text_box_info.run.get().teardown(),
|
ScannedTextBox(ref text_box_info) => text_box_info.run.teardown(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ use layout::util::LayoutDataAccess;
|
||||||
use script::dom::element::HTMLImageElementTypeId;
|
use script::dom::element::HTMLImageElementTypeId;
|
||||||
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
||||||
use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId};
|
use script::dom::node::{DocumentFragmentNodeTypeId, DocumentNodeTypeId, ElementNodeTypeId};
|
||||||
use script::dom::node::{LayoutView, PostorderNodeMutTraversal, TextNodeTypeId};
|
use script::dom::node::{LayoutView, PostorderNodeTraversal, TextNodeTypeId};
|
||||||
use servo_util::slot::Slot;
|
use servo_util::slot::Slot;
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
use std::util;
|
use std::util;
|
||||||
|
@ -173,7 +173,7 @@ pub struct FlowConstructor<'self> {
|
||||||
/// The layout context.
|
/// The layout context.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): Why does this contain `@`??? That destroys parallelism!!!
|
/// FIXME(pcwalton): Why does this contain `@`??? That destroys parallelism!!!
|
||||||
layout_context: &'self mut LayoutContext,
|
layout_context: &'self LayoutContext,
|
||||||
|
|
||||||
/// The next flow ID to assign.
|
/// The next flow ID to assign.
|
||||||
///
|
///
|
||||||
|
@ -183,7 +183,7 @@ pub struct FlowConstructor<'self> {
|
||||||
|
|
||||||
impl<'self> FlowConstructor<'self> {
|
impl<'self> FlowConstructor<'self> {
|
||||||
/// Creates a new flow constructor.
|
/// Creates a new flow constructor.
|
||||||
pub fn init<'a>(layout_context: &'a mut LayoutContext) -> FlowConstructor<'a> {
|
pub fn init<'a>(layout_context: &'a LayoutContext) -> FlowConstructor<'a> {
|
||||||
FlowConstructor {
|
FlowConstructor {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
next_flow_id: Slot::init(0),
|
next_flow_id: Slot::init(0),
|
||||||
|
@ -198,7 +198,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining.
|
/// Builds the `ImageBoxInfo` for the given image. This is out of line to guide inlining.
|
||||||
fn build_box_info_for_image(&mut self, node: AbstractNode<LayoutView>) -> Option<ImageBoxInfo> {
|
fn build_box_info_for_image(&self, node: AbstractNode<LayoutView>) -> Option<ImageBoxInfo> {
|
||||||
// FIXME(pcwalton): Don't copy URLs.
|
// FIXME(pcwalton): Don't copy URLs.
|
||||||
let url = node.with_imm_image_element(|image_element| {
|
let url = node.with_imm_image_element(|image_element| {
|
||||||
image_element.image.as_ref().map(|url| (*url).clone())
|
image_element.image.as_ref().map(|url| (*url).clone())
|
||||||
|
@ -215,7 +215,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a `Box` for the given node.
|
/// Builds a `Box` for the given node.
|
||||||
fn build_box_for_node(&mut self, node: AbstractNode<LayoutView>) -> @Box {
|
fn build_box_for_node(&self, node: AbstractNode<LayoutView>) -> @Box {
|
||||||
let specific = match node.type_id() {
|
let specific = match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
ElementNodeTypeId(HTMLImageElementTypeId) => {
|
||||||
match self.build_box_info_for_image(node) {
|
match self.build_box_info_for_image(node) {
|
||||||
|
@ -234,7 +234,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn flush_inline_boxes_to_flow(&mut self,
|
fn flush_inline_boxes_to_flow(&self,
|
||||||
boxes: ~[@Box],
|
boxes: ~[@Box],
|
||||||
flow: &mut ~Flow:,
|
flow: &mut ~Flow:,
|
||||||
node: AbstractNode<LayoutView>) {
|
node: AbstractNode<LayoutView>) {
|
||||||
|
@ -248,7 +248,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
|
|
||||||
/// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of
|
/// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of
|
||||||
/// the given flow.
|
/// the given flow.
|
||||||
fn flush_inline_boxes_to_flow_if_necessary(&mut self,
|
fn flush_inline_boxes_to_flow_if_necessary(&self,
|
||||||
opt_boxes: &mut Option<~[@Box]>,
|
opt_boxes: &mut Option<~[@Box]>,
|
||||||
flow: &mut ~Flow:,
|
flow: &mut ~Flow:,
|
||||||
node: AbstractNode<LayoutView>) {
|
node: AbstractNode<LayoutView>) {
|
||||||
|
@ -261,7 +261,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
/// Builds the children flows underneath a node with `display: block`. After this call,
|
/// Builds the children flows underneath a node with `display: block`. After this call,
|
||||||
/// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on
|
/// other `BlockFlow`s or `InlineFlow`s will be populated underneath this node, depending on
|
||||||
/// whether {ib} splits needed to happen.
|
/// whether {ib} splits needed to happen.
|
||||||
fn build_children_of_block_flow(&mut self,
|
fn build_children_of_block_flow(&self,
|
||||||
flow: &mut ~Flow:,
|
flow: &mut ~Flow:,
|
||||||
node: AbstractNode<LayoutView>) {
|
node: AbstractNode<LayoutView>) {
|
||||||
// Gather up boxes for the inline flows we might need to create.
|
// Gather up boxes for the inline flows we might need to create.
|
||||||
|
@ -341,7 +341,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
|
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
|
||||||
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
|
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
|
||||||
/// to happen.
|
/// to happen.
|
||||||
fn build_flow_for_block(&mut self, node: AbstractNode<LayoutView>) -> ~Flow: {
|
fn build_flow_for_block(&self, node: AbstractNode<LayoutView>) -> ~Flow: {
|
||||||
let base = FlowData::new(self.next_flow_id(), node);
|
let base = FlowData::new(self.next_flow_id(), node);
|
||||||
let box = self.build_box_for_node(node);
|
let box = self.build_box_for_node(node);
|
||||||
let mut flow = ~BlockFlow::from_box(base, box) as ~Flow:;
|
let mut flow = ~BlockFlow::from_box(base, box) as ~Flow:;
|
||||||
|
@ -351,7 +351,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
|
|
||||||
/// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with
|
/// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with
|
||||||
/// a `BlockFlow` underneath it.
|
/// a `BlockFlow` underneath it.
|
||||||
fn build_flow_for_floated_block(&mut self, node: AbstractNode<LayoutView>, float_type: FloatType)
|
fn build_flow_for_floated_block(&self, node: AbstractNode<LayoutView>, float_type: FloatType)
|
||||||
-> ~Flow: {
|
-> ~Flow: {
|
||||||
let base = FlowData::new(self.next_flow_id(), node);
|
let base = FlowData::new(self.next_flow_id(), node);
|
||||||
let box = self.build_box_for_node(node);
|
let box = self.build_box_for_node(node);
|
||||||
|
@ -363,7 +363,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
/// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary.
|
/// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary.
|
||||||
/// Returns the `InlineBoxesConstructionResult`, if any. There will be no
|
/// Returns the `InlineBoxesConstructionResult`, if any. There will be no
|
||||||
/// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace.
|
/// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace.
|
||||||
fn build_boxes_for_nonreplaced_inline_content(&mut self, node: AbstractNode<LayoutView>)
|
fn build_boxes_for_nonreplaced_inline_content(&self, node: AbstractNode<LayoutView>)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let mut opt_inline_block_splits = None;
|
let mut opt_inline_block_splits = None;
|
||||||
let mut opt_box_accumulator = None;
|
let mut opt_box_accumulator = None;
|
||||||
|
@ -429,7 +429,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
|
|
||||||
/// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't
|
/// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't
|
||||||
/// render its children, so this just nukes a child's boxes and creates a `Box`.
|
/// render its children, so this just nukes a child's boxes and creates a `Box`.
|
||||||
fn build_boxes_for_replaced_inline_content(&mut self, node: AbstractNode<LayoutView>)
|
fn build_boxes_for_replaced_inline_content(&self, node: AbstractNode<LayoutView>)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
kid.set_flow_construction_result(NoConstructionResult)
|
kid.set_flow_construction_result(NoConstructionResult)
|
||||||
|
@ -446,7 +446,7 @@ impl<'self> FlowConstructor<'self> {
|
||||||
|
|
||||||
/// Builds one or more boxes for a node with `display: inline`. This yields an
|
/// Builds one or more boxes for a node with `display: inline`. This yields an
|
||||||
/// `InlineBoxesConstructionResult`.
|
/// `InlineBoxesConstructionResult`.
|
||||||
fn build_boxes_for_inline(&mut self, node: AbstractNode<LayoutView>) -> ConstructionResult {
|
fn build_boxes_for_inline(&self, node: AbstractNode<LayoutView>) -> ConstructionResult {
|
||||||
// Is this node replaced content?
|
// Is this node replaced content?
|
||||||
if !node.is_replaced_content() {
|
if !node.is_replaced_content() {
|
||||||
// Go to a path that concatenates our kids' boxes.
|
// Go to a path that concatenates our kids' boxes.
|
||||||
|
@ -458,11 +458,11 @@ impl<'self> FlowConstructor<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> PostorderNodeMutTraversal for FlowConstructor<'self> {
|
impl<'self> PostorderNodeTraversal for FlowConstructor<'self> {
|
||||||
// `#[inline(always)]` because this is always called from the traversal function and for some
|
// `#[inline(always)]` because this is always called from the traversal function and for some
|
||||||
// reason LLVM's inlining heuristics go awry here.
|
// reason LLVM's inlining heuristics go awry here.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn process(&mut self, node: AbstractNode<LayoutView>) -> bool {
|
fn process(&self, node: AbstractNode<LayoutView>) -> bool {
|
||||||
// Get the `display` property for this node, and determine whether this node is floated.
|
// Get the `display` property for this node, and determine whether this node is floated.
|
||||||
let (display, float) = match node.type_id() {
|
let (display, float) = match node.type_id() {
|
||||||
ElementNodeTypeId(_) => (node.style().Box.display, node.style().Box.float),
|
ElementNodeTypeId(_) => (node.style().Box.display, node.style().Box.float),
|
||||||
|
|
|
@ -13,7 +13,7 @@ use extra::arc::MutexArc;
|
||||||
|
|
||||||
/// Data needed by the layout task.
|
/// Data needed by the layout task.
|
||||||
pub struct LayoutContext {
|
pub struct LayoutContext {
|
||||||
font_ctx: ~FontContext,
|
font_ctx: @mut FontContext,
|
||||||
image_cache: MutexArc<LocalImageCache>,
|
image_cache: MutexArc<LocalImageCache>,
|
||||||
screen_size: Rect<Au>
|
screen_size: Rect<Au>
|
||||||
}
|
}
|
||||||
|
|
|
@ -702,7 +702,7 @@ impl Flow for InlineFlow {
|
||||||
},
|
},
|
||||||
ScannedTextBox(ref text_box) => {
|
ScannedTextBox(ref text_box) => {
|
||||||
let range = &text_box.range;
|
let range = &text_box.range;
|
||||||
let run = text_box.run.get();
|
let run = &text_box.run;
|
||||||
|
|
||||||
// Compute the height based on the line-height and font size
|
// Compute the height based on the line-height and font size
|
||||||
let text_bounds = run.metrics_for_range(range).bounding_box;
|
let text_bounds = run.metrics_for_range(range).bounding_box;
|
||||||
|
@ -711,7 +711,7 @@ impl Flow for InlineFlow {
|
||||||
|
|
||||||
// Find the top and bottom of the content area.
|
// Find the top and bottom of the content area.
|
||||||
// Those are used in text-top and text-bottom value of 'vertical-align'
|
// Those are used in text-top and text-bottom value of 'vertical-align'
|
||||||
let text_ascent = run.font_metrics.ascent;
|
let text_ascent = text_box.run.font_metrics.ascent;
|
||||||
|
|
||||||
// Offset from the top of the box is 1/2 of the leading + ascent
|
// Offset from the top of the box is 1/2 of the leading + ascent
|
||||||
let text_offset = text_ascent + (line_height - em_size).scale_by(0.5);
|
let text_offset = text_ascent + (line_height - em_size).scale_by(0.5);
|
||||||
|
|
|
@ -77,6 +77,9 @@ struct LayoutTask {
|
||||||
/// The local image cache.
|
/// The local image cache.
|
||||||
local_image_cache: MutexArc<LocalImageCache>,
|
local_image_cache: MutexArc<LocalImageCache>,
|
||||||
|
|
||||||
|
/// The local font context.
|
||||||
|
font_ctx: @mut FontContext,
|
||||||
|
|
||||||
/// The size of the viewport.
|
/// The size of the viewport.
|
||||||
screen_size: Option<Size2D<Au>>,
|
screen_size: Option<Size2D<Au>>,
|
||||||
|
|
||||||
|
@ -87,8 +90,6 @@ struct LayoutTask {
|
||||||
|
|
||||||
/// The channel on which messages can be sent to the profiler.
|
/// The channel on which messages can be sent to the profiler.
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
|
|
||||||
opts: Opts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The damage computation traversal.
|
/// The damage computation traversal.
|
||||||
|
@ -228,6 +229,7 @@ impl LayoutTask {
|
||||||
opts: &Opts,
|
opts: &Opts,
|
||||||
profiler_chan: ProfilerChan)
|
profiler_chan: ProfilerChan)
|
||||||
-> LayoutTask {
|
-> LayoutTask {
|
||||||
|
let fctx = @mut FontContext::new(opts.render_backend, true, profiler_chan.clone());
|
||||||
|
|
||||||
LayoutTask {
|
LayoutTask {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -237,13 +239,13 @@ impl LayoutTask {
|
||||||
render_chan: render_chan,
|
render_chan: render_chan,
|
||||||
image_cache_task: image_cache_task.clone(),
|
image_cache_task: image_cache_task.clone(),
|
||||||
local_image_cache: MutexArc::new(LocalImageCache(image_cache_task)),
|
local_image_cache: MutexArc::new(LocalImageCache(image_cache_task)),
|
||||||
|
font_ctx: fctx,
|
||||||
screen_size: None,
|
screen_size: None,
|
||||||
|
|
||||||
display_list: None,
|
display_list: None,
|
||||||
|
|
||||||
stylist: RWArc::new(new_stylist()),
|
stylist: RWArc::new(new_stylist()),
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
opts: opts.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +259,7 @@ impl LayoutTask {
|
||||||
// Create a layout context for use in building display lists, hit testing, &c.
|
// Create a layout context for use in building display lists, hit testing, &c.
|
||||||
fn build_layout_context(&self) -> LayoutContext {
|
fn build_layout_context(&self) -> LayoutContext {
|
||||||
let image_cache = self.local_image_cache.clone();
|
let image_cache = self.local_image_cache.clone();
|
||||||
let font_ctx = ~FontContext::new(self.opts.render_backend, true,
|
let font_ctx = self.font_ctx;
|
||||||
self.profiler_chan.clone());
|
|
||||||
let screen_size = self.screen_size.unwrap();
|
let screen_size = self.screen_size.unwrap();
|
||||||
|
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
|
@ -343,9 +344,9 @@ impl LayoutTask {
|
||||||
/// is intertwined with selector matching, making it difficult to compare directly. It is
|
/// is intertwined with selector matching, making it difficult to compare directly. It is
|
||||||
/// marked `#[inline(never)]` to aid benchmarking in sampling profilers.
|
/// marked `#[inline(never)]` to aid benchmarking in sampling profilers.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: AbstractNode<LayoutView>)
|
fn construct_flow_tree(&self, layout_context: &LayoutContext, node: AbstractNode<LayoutView>)
|
||||||
-> ~Flow: {
|
-> ~Flow: {
|
||||||
node.traverse_postorder_mut(&mut FlowConstructor::init(layout_context));
|
node.traverse_postorder(&FlowConstructor::init(layout_context));
|
||||||
|
|
||||||
let result = match *node.mutate_layout_data().ptr {
|
let result = match *node.mutate_layout_data().ptr {
|
||||||
Some(ref mut layout_data) => {
|
Some(ref mut layout_data) => {
|
||||||
|
@ -440,7 +441,7 @@ impl LayoutTask {
|
||||||
// Construct the flow tree.
|
// Construct the flow tree.
|
||||||
let mut layout_root = profile(time::LayoutTreeBuilderCategory,
|
let mut layout_root = profile(time::LayoutTreeBuilderCategory,
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
|| self.construct_flow_tree(&mut layout_ctx, *node));
|
|| self.construct_flow_tree(&layout_ctx, *node));
|
||||||
|
|
||||||
// Propagate damage.
|
// Propagate damage.
|
||||||
layout_root.traverse_preorder(&mut PropagateDamageTraversal {
|
layout_root.traverse_preorder(&mut PropagateDamageTraversal {
|
||||||
|
|
|
@ -11,7 +11,6 @@ use layout::flow::Flow;
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
use gfx::text::util::{CompressWhitespaceNewline, transform_text};
|
use gfx::text::util::{CompressWhitespaceNewline, transform_text};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use extra::arc::Arc;
|
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
|
||||||
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
||||||
|
@ -26,7 +25,7 @@ impl TextRunScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scan_for_runs(&mut self, ctx: &mut LayoutContext, flow: &mut Flow) {
|
pub fn scan_for_runs(&mut self, ctx: &LayoutContext, flow: &mut Flow) {
|
||||||
{
|
{
|
||||||
let inline = flow.as_immutable_inline();
|
let inline = flow.as_immutable_inline();
|
||||||
// FIXME: this assertion fails on wikipedia, but doesn't seem
|
// FIXME: this assertion fails on wikipedia, but doesn't seem
|
||||||
|
@ -76,7 +75,7 @@ impl TextRunScanner {
|
||||||
/// responsible for swapping out the list. It is not clear to me (pcwalton) that this is still
|
/// responsible for swapping out the list. It is not clear to me (pcwalton) that this is still
|
||||||
/// necessary.
|
/// necessary.
|
||||||
pub fn flush_clump_to_list(&mut self,
|
pub fn flush_clump_to_list(&mut self,
|
||||||
ctx: &mut LayoutContext,
|
ctx: &LayoutContext,
|
||||||
flow: &mut Flow,
|
flow: &mut Flow,
|
||||||
last_whitespace: bool,
|
last_whitespace: bool,
|
||||||
out_boxes: &mut ~[@Box])
|
out_boxes: &mut ~[@Box])
|
||||||
|
@ -126,15 +125,14 @@ impl TextRunScanner {
|
||||||
// font group fonts. This is probably achieved by creating the font group above
|
// font group fonts. This is probably achieved by creating the font group above
|
||||||
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
||||||
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style);
|
let fontgroup = ctx.font_ctx.get_resolved_font_for_style(&font_style);
|
||||||
let run = Arc::new(~fontgroup.with_borrow(|fg| fg.create_textrun(transformed_text.clone(), decoration)));
|
let run = @fontgroup.with_borrow(|fg| fg.create_textrun(transformed_text.clone(), decoration));
|
||||||
|
|
||||||
debug!("TextRunScanner: pushing single text box in range: {} ({})",
|
debug!("TextRunScanner: pushing single text box in range: {} ({})",
|
||||||
self.clump,
|
self.clump,
|
||||||
*text);
|
*text);
|
||||||
let range = Range::new(0, run.get().char_len());
|
let range = Range::new(0, run.char_len());
|
||||||
let new_metrics = run.get().metrics_for_range(&range);
|
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(run, range);
|
let new_text_box_info = ScannedTextBoxInfo::new(run, range);
|
||||||
|
let new_metrics = run.metrics_for_range(&range);
|
||||||
let new_box = @old_box.transform(new_metrics.bounding_box.size,
|
let new_box = @old_box.transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info));
|
ScannedTextBox(new_text_box_info));
|
||||||
out_boxes.push(new_box)
|
out_boxes.push(new_box)
|
||||||
|
@ -192,7 +190,7 @@ impl TextRunScanner {
|
||||||
let run = if clump.length() != 0 && run_str.len() > 0 {
|
let run = if clump.length() != 0 && run_str.len() > 0 {
|
||||||
fontgroup.with_borrow( |fg| {
|
fontgroup.with_borrow( |fg| {
|
||||||
fg.fonts[0].with_mut_borrow( |font| {
|
fg.fonts[0].with_mut_borrow( |font| {
|
||||||
Some(Arc::new(~TextRun::new(font, run_str.clone(), decoration)))
|
Some(@TextRun::new(font, run_str.clone(), decoration))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -210,8 +208,8 @@ impl TextRunScanner {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), range);
|
let new_text_box_info = ScannedTextBoxInfo::new(run.unwrap(), range);
|
||||||
let new_metrics = new_text_box_info.run.get().metrics_for_range(&range);
|
let new_metrics = new_text_box_info.run.metrics_for_range(&range);
|
||||||
let new_box = @in_boxes[i].transform(new_metrics.bounding_box.size,
|
let new_box = @in_boxes[i].transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info));
|
ScannedTextBox(new_text_box_info));
|
||||||
out_boxes.push(new_box)
|
out_boxes.push(new_box)
|
||||||
|
|
|
@ -1217,20 +1217,6 @@ pub trait PostorderNodeTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A bottom-up, parallelizable traversal.
|
|
||||||
pub trait PostorderNodeMutTraversal {
|
|
||||||
/// The operation to perform. Return true to continue or false to stop.
|
|
||||||
fn process(&mut self, node: AbstractNode<LayoutView>) -> bool;
|
|
||||||
|
|
||||||
/// Returns true if this node should be pruned. If this returns true, we skip the operation
|
|
||||||
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
|
|
||||||
/// visited. The default implementation never prunes any nodes.
|
|
||||||
fn should_prune(&self, _node: AbstractNode<LayoutView>) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl AbstractNode<LayoutView> {
|
impl AbstractNode<LayoutView> {
|
||||||
/// Traverses the tree in postorder.
|
/// Traverses the tree in postorder.
|
||||||
///
|
///
|
||||||
|
@ -1255,29 +1241,4 @@ impl AbstractNode<LayoutView> {
|
||||||
|
|
||||||
traversal.process(self)
|
traversal.process(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the tree in postorder.
|
|
||||||
///
|
|
||||||
/// TODO(pcwalton): Offer a parallel version with a compatible API.
|
|
||||||
pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(mut self, traversal: &mut T) -> bool {
|
|
||||||
if traversal.should_prune(self) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut opt_kid = self.first_child();
|
|
||||||
loop {
|
|
||||||
match opt_kid {
|
|
||||||
None => break,
|
|
||||||
Some(kid) => {
|
|
||||||
if !kid.traverse_postorder_mut(traversal) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
opt_kid = kid.next_sibling()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
traversal.process(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue