diff options
author | Brian J. Burg <burg@cs.washington.edu> | 2012-10-03 15:13:18 -0700 |
---|---|---|
committer | Brian J. Burg <burg@cs.washington.edu> | 2012-10-03 15:14:29 -0700 |
commit | e105f3b5571f0cbfae3fc6a96938d4d039bb660d (patch) | |
tree | 69f7e5f7b0eb9703d4c48b82abd838e76b2b1007 /src | |
parent | 05ca57e6cda5bd56a9735661222e018bfea13e39 (diff) | |
download | servo-e105f3b5571f0cbfae3fc6a96938d4d039bb660d.tar.gz servo-e105f3b5571f0cbfae3fc6a96938d4d039bb660d.zip |
Implement DetailedGlyph and some storage helpers, such as the lookup table and its records.
Diffstat (limited to 'src')
-rw-r--r-- | src/servo/text/glyph.rs | 148 |
1 files changed, 137 insertions, 11 deletions
diff --git a/src/servo/text/glyph.rs b/src/servo/text/glyph.rs index d08c4994b22..2b54c366324 100644 --- a/src/servo/text/glyph.rs +++ b/src/servo/text/glyph.rs @@ -1,27 +1,30 @@ -export GlyphIndex, GlyphPos, Glyph; - use au = gfx::geometry; use au::au; +use core::cmp::{Ord, Eq}; +use core::dvec::DVec; use geom::point::Point2D; +use std::sort; +use servo_util::vec::*; + +export GlyphIndex, GlyphPos, Glyph; -/** The index of a particular glyph within a font */ struct CompressedGlyph { mut value : u32 } + +/// The index of a particular glyph within a font type GlyphIndex = u32; -enum BreakTypeFlags { - BREAK_TYPE_NONE = 0x0, - BREAK_TYPE_NORMAL = 0x1, - BREAK_TYPE_HYPEN = 0x2, -} +const BREAK_TYPE_NONE : u8 = 0x0u8; +const BREAK_TYPE_NORMAL : u8 = 0x1u8; +const BREAK_TYPE_HYPEN : u8 = 0x2u8; // TODO: make this more type-safe. const FLAG_CHAR_IS_SPACE : u32 = 0x10000000u32; -// These two bits store a BreakTypeFlags +// These two bits store some BREAK_TYPE_* flags const FLAG_CAN_BREAK_MASK : u32 = 0x60000000u32; -const FLAG_CAN_BREAK_SHIFT : u32 = 29u32; +const FLAG_CAN_BREAK_SHIFT : u32 = 29; const FLAG_IS_SIMPLE_GLYPH : u32 = 0x80000000u32; // glyph advance; in au's. @@ -51,7 +54,6 @@ const FLAG_CHAR_IS_NEWLINE : u32 = 0x00000010u32; const FLAG_CHAR_IS_LOW_SURROGATE : u32 = 0x00000020u32; const CHAR_IDENTITY_FLAGS_MASK : u32 = 0x00000038u32; - pure fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool { ((glyphId as u32) & GLYPH_ID_MASK) == glyphId } @@ -189,6 +191,130 @@ impl CompressedGlyph { } } +struct DetailedGlyph { + // The GlyphIndex, or the unicode codepoint if glyph is missing. + index: u32, + // glyph's advance, in the text's direction (RTL or RTL) + advance: au, + // glyph's offset from the font's em-box (from top-left) + offset: Point2D<au> +} + +// cg = CompressedGlyph, +// dg = DetailedGlyph + +struct DetailedGlyphRecord { + // source character/CompressedGlyph offset in the TextRun + cg_offset: u32, + // offset into the detailed glyphs buffer + dg_offset: uint +} + +impl DetailedGlyphRecord : Ord { + pure fn lt(other: &DetailedGlyphRecord) -> bool { self.cg_offset < other.cg_offset } + pure fn le(other: &DetailedGlyphRecord) -> bool { self.cg_offset <= other.cg_offset } + pure fn ge(other: &DetailedGlyphRecord) -> bool { self.cg_offset >= other.cg_offset } + pure fn gt(other: &DetailedGlyphRecord) -> bool { self.cg_offset > other.cg_offset } +} + +impl DetailedGlyphRecord : Eq { + pure fn eq(other : &DetailedGlyphRecord) -> bool { self.cg_offset == other.cg_offset } + pure fn ne(other : &DetailedGlyphRecord) -> bool { self.cg_offset != other.cg_offset } +} + +// Manages the lookup table for detailed glyphs. +struct DetailedGlyphStore { + dg_buffer: DVec<DetailedGlyph>, + dg_lookup: DVec<DetailedGlyphRecord>, + mut lookup_is_sorted: bool, +} + +fn DetailedGlyphStore() -> DetailedGlyphStore { + DetailedGlyphStore { + dg_buffer: DVec(), + dg_lookup: DVec(), + lookup_is_sorted: false + } +} + +impl DetailedGlyphStore { + fn add_glyphs_for_cg(cg_offset: u32, glyphs: &[DetailedGlyph]) { + let entry = DetailedGlyphRecord { + cg_offset: cg_offset, + dg_offset: self.dg_buffer.len() + }; + + /* + TODO: don't actually assert this until asserts are compiled + in/out based on severity, debug/release, etc. + + See Rust Issue #3647, #2228, #3627 for related information. + + do self.dg_lookup.borrow |arr| { + assert !arr.contains(entry) + } + */ + + self.dg_lookup.push(entry); + self.dg_buffer.push_all(glyphs); + self.lookup_is_sorted = false; + } + + // not pure; may perform a deferred sort. + fn get_glyphs_for_cg(&self, cg_offset: u32, count: uint) -> &[DetailedGlyph] { + assert count > 0 && count < self.dg_buffer.len(); + self.ensure_sorted(); + + let key = DetailedGlyphRecord { + cg_offset: cg_offset, + dg_offset: 0 // unused + }; + + do self.dg_lookup.borrow |records : &[DetailedGlyphRecord]| { + match records.binary_search_index(&key) { + None => fail ~"Invalid index not found in detailed glyph lookup table!", + Some(i) => { + do self.dg_buffer.borrow |glyphs : &[DetailedGlyph]| { + assert i + count < glyphs.len(); + // return a view into the buffer + vec::view(glyphs, i, count) + } + } + } + } + } + + /*priv*/ fn ensure_sorted() { + if self.lookup_is_sorted { + return; + } + + do self.dg_lookup.borrow_mut |arr| { + sort::quick_sort3(arr); + }; + self.lookup_is_sorted = true; + } +} + +// Public data structure and API for storing glyph data +struct GlyphStore { + mut cg_buffer: ~[CompressedGlyph], + dg_store: DetailedGlyphStore, +} + +// Initializes the glyph store, but doesn't actually shape anything. +// Use the set_glyph, set_glyphs() methods to store glyph data. +// Use the get_glyph_data method to retrieve glyph data for a char.. +fn GlyphStore(text: ~str) { + +} + +impl GlyphStore { + +} + +// XXX: legacy glyphs below. rip out once converted to new glyphs + /** The position of a glyph on the screen. */ struct GlyphPos { advance: Point2D<au>, |