From 23e895c1558cdb13116a72787c0b2ab96b0072fa Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 May 2012 17:35:50 -0700 Subject: [PATCH] servo: Introduce text run and glyph classes Source-Repo: https://github.com/servo/servo Source-Revision: 0f5eb549ab5c32dc118112311618938e55629b68 --- servo/src/servo/layout/base.rs | 13 ++------- servo/src/servo/layout/box_builder.rs | 7 +++-- servo/src/servo/layout/text.rs | 41 +++++++++++++++++++++++++++ servo/src/servo/servo.rc | 9 ++++++ servo/src/servo/text/glyph.rs | 30 ++++++++++++++++++++ servo/src/servo/text/text_run.rs | 40 ++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 servo/src/servo/layout/text.rs create mode 100644 servo/src/servo/text/glyph.rs create mode 100644 servo/src/servo/text/text_run.rs diff --git a/servo/src/servo/layout/base.rs b/servo/src/servo/layout/base.rs index cb036504d85d..d0f822673c30 100644 --- a/servo/src/servo/layout/base.rs +++ b/servo/src/servo/layout/base.rs @@ -8,13 +8,14 @@ import gfx::geom::{size, rect, point, au, zero_size_au}; import /*layout::*/block::block_layout_methods; import /*layout::*/inline::inline_layout_methods; import /*layout::*/style::style::*; +import /*layout::*/text::{text_box, text_layout_methods}; import util::tree; enum box_kind { bk_block, bk_inline, bk_intrinsic(@geom::size), - bk_text(str) + bk_text(@text_box) } enum box = { @@ -84,7 +85,7 @@ impl layout_methods for @box { bk_block { self.reflow_block(available_width) } bk_inline { self.reflow_inline(available_width) } bk_intrinsic(size) { self.reflow_intrinsic(*size) } - bk_text(s) { self.reflow_text(s) } + bk_text(subbox) { self.reflow_text(available_width, subbox) } } } @@ -95,14 +96,6 @@ impl layout_methods for @box { #debug["reflow_intrinsic size=%?", self.bounds]; } - #[doc="The reflow routine for text frames."] - fn reflow_text(text: str) { - self.bounds.size = { - mut width: au(text.len() as int * 60 * 10), - mut height: au(60 * 14) - }; - } - #[doc="Dumps the box tree, for debugging."] fn dump() { self.dump_indent(0u); diff --git a/servo/src/servo/layout/box_builder.rs b/servo/src/servo/layout/box_builder.rs index 1a5cac2f75fd..7d911fd5d258 100644 --- a/servo/src/servo/layout/box_builder.rs +++ b/servo/src/servo/layout/box_builder.rs @@ -7,6 +7,7 @@ import /*layout::*/base::{bk_block, bk_inline, bk_intrinsic, bk_text, box}; import /*layout::*/base::{box_kind, btree, node_methods, ntree, rd_tree_ops}; import /*layout::*/base::wr_tree_ops; import /*layout::*/style::style::{di_block, di_inline, style_methods}; +import /*layout::*/text::text_box; import util::tree; export box_builder_methods; @@ -118,9 +119,9 @@ impl box_builder_priv for node { "] fn determine_box_kind() -> box_kind { alt self.rd({ |n| n.kind }) { - nk_img(size) { bk_intrinsic(@size) } - nk_div { bk_block } - nk_text(s) { bk_text(s) } + nk_img(size) { bk_intrinsic(@size) } + nk_div { bk_block } + nk_text(s) { bk_text(@text_box(s)) } } } } diff --git a/servo/src/servo/layout/text.rs b/servo/src/servo/layout/text.rs new file mode 100644 index 000000000000..fb8666b64033 --- /dev/null +++ b/servo/src/servo/layout/text.rs @@ -0,0 +1,41 @@ +#[doc="Text layout."] + +import gfx::geom::au; +import /*layout::*/base::*; // FIXME: Can't get around import *; resolve bug. +import servo_text::text_run::text_run; + +class text_box { + let text: str; + let mut run: option; + + new(text: str) { + self.text = text; + self.run = none; + } +} + +#[doc="The main reflow routine for text layout."] +impl text_layout_methods for @box { + fn reflow_text(_available_width: au, subbox: @text_box) { + alt self.kind { + bk_text(*) { /* ok */ } + _ { fail "expected text box in reflow_text!" } + }; + + let run = text_run(subbox.text); + subbox.run = some(run); + run.shape(); + + self.bounds.size = { + mut width: + alt vec::last_opt(run.glyphs.get()) { + some(glyph) { + au(*glyph.pos.offset.x + *glyph.pos.advance.x) + } + none { au(0) } + }, + mut height: au(60 * 14) + }; + } +} + diff --git a/servo/src/servo/servo.rc b/servo/src/servo/servo.rc index 3f41a5ce0dfb..64b32d505c32 100755 --- a/servo/src/servo/servo.rc +++ b/servo/src/servo/servo.rc @@ -43,6 +43,7 @@ mod layout { mod display_list; mod inline; mod layout; + mod text; } mod parser { @@ -55,6 +56,11 @@ mod platform { mod osmain; } +mod text { + mod glyph; + mod text_run; +} + mod util { mod tree; } @@ -66,3 +72,6 @@ mod content { mod opts; mod engine; + +import servo_text = text; + diff --git a/servo/src/servo/text/glyph.rs b/servo/src/servo/text/glyph.rs new file mode 100644 index 000000000000..e2781ee036f3 --- /dev/null +++ b/servo/src/servo/text/glyph.rs @@ -0,0 +1,30 @@ +import gfx::geom::{au, point, px_to_au}; + +#[doc="The position of a glyph on the screen."] +class glyph_pos { + let advance: point; + let offset: point; + + new(hb_pos: harfbuzz::hb_glyph_position_t) { + self.advance = { + mut x: px_to_au(hb_pos.x_advance as int), + mut y: px_to_au(hb_pos.y_advance as int) + }; + self.offset = { + mut x: px_to_au(hb_pos.x_offset as int), + mut y: px_to_au(hb_pos.y_offset as int) + }; + } +} + +#[doc="A single glyph."] +class glyph { + let codepoint: uint; + let pos: glyph_pos; + + new(codepoint: uint, pos: glyph_pos) { + self.codepoint = codepoint; + self.pos = pos; + } +} + diff --git a/servo/src/servo/text/text_run.rs b/servo/src/servo/text/text_run.rs new file mode 100644 index 000000000000..79a6169dee47 --- /dev/null +++ b/servo/src/servo/text/text_run.rs @@ -0,0 +1,40 @@ +import libc::{c_void}; +import libc::types::common::c99::int32_t; +import text::glyph::{glyph, glyph_pos}; + +#[doc="A single, unbroken line of text."] +class text_run { + let text: str; + let mut glyphs: option<[glyph]>; + + new(text: str) { + self.text = text; + self.glyphs = none; + } + + #[doc=" + Shapes text. This determines the location of each glyph and determines + line break positions. + "] + fn shape() { + let mut glyphs = []; + let mut cur_x = 0u; + for self.text.each_char { + |ch| + // TODO: Use HarfBuzz! + let hb_pos = { + x_advance: 10 as int32_t, + y_advance: 0 as int32_t, + x_offset: cur_x as int32_t, + y_offset: 0 as int32_t, + var: 0 + }; + + vec::push(glyphs, glyph(ch as uint, glyph_pos(hb_pos))); + cur_x += 10u; + }; + + self.glyphs = some(/* move */ glyphs); + } +} +