mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Introduce text run and glyph classes
This commit is contained in:
parent
f357e53863
commit
0f5eb549ab
6 changed files with 127 additions and 13 deletions
|
@ -8,13 +8,14 @@ import gfx::geom::{size, rect, point, au, zero_size_au};
|
||||||
import /*layout::*/block::block_layout_methods;
|
import /*layout::*/block::block_layout_methods;
|
||||||
import /*layout::*/inline::inline_layout_methods;
|
import /*layout::*/inline::inline_layout_methods;
|
||||||
import /*layout::*/style::style::*;
|
import /*layout::*/style::style::*;
|
||||||
|
import /*layout::*/text::{text_box, text_layout_methods};
|
||||||
import util::tree;
|
import util::tree;
|
||||||
|
|
||||||
enum box_kind {
|
enum box_kind {
|
||||||
bk_block,
|
bk_block,
|
||||||
bk_inline,
|
bk_inline,
|
||||||
bk_intrinsic(@geom::size<au>),
|
bk_intrinsic(@geom::size<au>),
|
||||||
bk_text(str)
|
bk_text(@text_box)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum box = {
|
enum box = {
|
||||||
|
@ -84,7 +85,7 @@ impl layout_methods for @box {
|
||||||
bk_block { self.reflow_block(available_width) }
|
bk_block { self.reflow_block(available_width) }
|
||||||
bk_inline { self.reflow_inline(available_width) }
|
bk_inline { self.reflow_inline(available_width) }
|
||||||
bk_intrinsic(size) { self.reflow_intrinsic(*size) }
|
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];
|
#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."]
|
#[doc="Dumps the box tree, for debugging."]
|
||||||
fn dump() {
|
fn dump() {
|
||||||
self.dump_indent(0u);
|
self.dump_indent(0u);
|
||||||
|
|
|
@ -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::{box_kind, btree, node_methods, ntree, rd_tree_ops};
|
||||||
import /*layout::*/base::wr_tree_ops;
|
import /*layout::*/base::wr_tree_ops;
|
||||||
import /*layout::*/style::style::{di_block, di_inline, style_methods};
|
import /*layout::*/style::style::{di_block, di_inline, style_methods};
|
||||||
|
import /*layout::*/text::text_box;
|
||||||
import util::tree;
|
import util::tree;
|
||||||
|
|
||||||
export box_builder_methods;
|
export box_builder_methods;
|
||||||
|
@ -118,9 +119,9 @@ impl box_builder_priv for node {
|
||||||
"]
|
"]
|
||||||
fn determine_box_kind() -> box_kind {
|
fn determine_box_kind() -> box_kind {
|
||||||
alt self.rd({ |n| n.kind }) {
|
alt self.rd({ |n| n.kind }) {
|
||||||
nk_img(size) { bk_intrinsic(@size) }
|
nk_img(size) { bk_intrinsic(@size) }
|
||||||
nk_div { bk_block }
|
nk_div { bk_block }
|
||||||
nk_text(s) { bk_text(s) }
|
nk_text(s) { bk_text(@text_box(s)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
src/servo/layout/text.rs
Normal file
41
src/servo/layout/text.rs
Normal file
|
@ -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<text_run>;
|
||||||
|
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ mod layout {
|
||||||
mod display_list;
|
mod display_list;
|
||||||
mod inline;
|
mod inline;
|
||||||
mod layout;
|
mod layout;
|
||||||
|
mod text;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod parser {
|
mod parser {
|
||||||
|
@ -55,6 +56,11 @@ mod platform {
|
||||||
mod osmain;
|
mod osmain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod text {
|
||||||
|
mod glyph;
|
||||||
|
mod text_run;
|
||||||
|
}
|
||||||
|
|
||||||
mod util {
|
mod util {
|
||||||
mod tree;
|
mod tree;
|
||||||
}
|
}
|
||||||
|
@ -66,3 +72,6 @@ mod content {
|
||||||
|
|
||||||
mod opts;
|
mod opts;
|
||||||
mod engine;
|
mod engine;
|
||||||
|
|
||||||
|
import servo_text = text;
|
||||||
|
|
||||||
|
|
30
src/servo/text/glyph.rs
Normal file
30
src/servo/text/glyph.rs
Normal file
|
@ -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<au>;
|
||||||
|
let offset: point<au>;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
40
src/servo/text/text_run.rs
Normal file
40
src/servo/text/text_run.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue