aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian J. Burg <burg@cs.washington.edu>2012-10-03 15:13:18 -0700
committerBrian J. Burg <burg@cs.washington.edu>2012-10-03 15:14:29 -0700
commite105f3b5571f0cbfae3fc6a96938d4d039bb660d (patch)
tree69f7e5f7b0eb9703d4c48b82abd838e76b2b1007 /src
parent05ca57e6cda5bd56a9735661222e018bfea13e39 (diff)
downloadservo-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.rs148
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>,