mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Implement DetailedGlyph and some storage helpers, such as the lookup table and its records.
This commit is contained in:
parent
05ca57e6cd
commit
e105f3b557
1 changed files with 137 additions and 11 deletions
|
@ -1,27 +1,30 @@
|
||||||
export GlyphIndex, GlyphPos, Glyph;
|
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use au::au;
|
use au::au;
|
||||||
|
use core::cmp::{Ord, Eq};
|
||||||
|
use core::dvec::DVec;
|
||||||
use geom::point::Point2D;
|
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 {
|
struct CompressedGlyph {
|
||||||
mut value : u32
|
mut value : u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The index of a particular glyph within a font
|
||||||
type GlyphIndex = u32;
|
type GlyphIndex = u32;
|
||||||
|
|
||||||
enum BreakTypeFlags {
|
const BREAK_TYPE_NONE : u8 = 0x0u8;
|
||||||
BREAK_TYPE_NONE = 0x0,
|
const BREAK_TYPE_NORMAL : u8 = 0x1u8;
|
||||||
BREAK_TYPE_NORMAL = 0x1,
|
const BREAK_TYPE_HYPEN : u8 = 0x2u8;
|
||||||
BREAK_TYPE_HYPEN = 0x2,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make this more type-safe.
|
// TODO: make this more type-safe.
|
||||||
|
|
||||||
const FLAG_CHAR_IS_SPACE : u32 = 0x10000000u32;
|
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_MASK : u32 = 0x60000000u32;
|
||||||
const FLAG_CAN_BREAK_SHIFT : u32 = 29u32;
|
const FLAG_CAN_BREAK_SHIFT : u32 = 29;
|
||||||
const FLAG_IS_SIMPLE_GLYPH : u32 = 0x80000000u32;
|
const FLAG_IS_SIMPLE_GLYPH : u32 = 0x80000000u32;
|
||||||
|
|
||||||
// glyph advance; in au's.
|
// 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 FLAG_CHAR_IS_LOW_SURROGATE : u32 = 0x00000020u32;
|
||||||
const CHAR_IDENTITY_FLAGS_MASK : u32 = 0x00000038u32;
|
const CHAR_IDENTITY_FLAGS_MASK : u32 = 0x00000038u32;
|
||||||
|
|
||||||
|
|
||||||
pure fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool {
|
pure fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool {
|
||||||
((glyphId as u32) & GLYPH_ID_MASK) == glyphId
|
((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. */
|
/** The position of a glyph on the screen. */
|
||||||
struct GlyphPos {
|
struct GlyphPos {
|
||||||
advance: Point2D<au>,
|
advance: Point2D<au>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue