Implement missing glyph handling, making the glyph retrieval the following:
1. If the glyph is cached, return it, as before. 2. Try to find a glyph in the fallback font, as before. 3. Check for ignorable characters as per Unicode and cache and return a zero width glyph (rendering as completely invisible). 4. Reset to the original font. 5. Check for whitespace as per Unicode and cache and return the normal space glyph. 6. If there still is no valid glyphIndex, continue with index 0 which caches and returns the usual "missing glyph box". This implements the Unicode suggestions on how to handle missing glyphs and closes #7077. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40174 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -187,6 +187,74 @@ FontCacheEntry::HasGlyphs(const char* utf8String, ssize_t length) const
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
render_as_space(uint32 glyphCode)
|
||||
{
|
||||
// whitespace: render as space
|
||||
// as per Unicode PropList.txt: White_Space
|
||||
return (glyphCode >= 0x0009 && glyphCode <= 0x000d)
|
||||
// control characters
|
||||
|| (glyphCode == 0x0085)
|
||||
// another control
|
||||
|| (glyphCode == 0x00a0)
|
||||
// no-break space
|
||||
|| (glyphCode == 0x1680)
|
||||
// ogham space mark
|
||||
|| (glyphCode == 0x180e)
|
||||
// mongolian vowel separator
|
||||
|| (glyphCode >= 0x2000 && glyphCode <= 0x200a)
|
||||
// en quand, hair space
|
||||
|| (glyphCode >= 0x2028 && glyphCode <= 0x2029)
|
||||
// line and paragraph separators
|
||||
|| (glyphCode == 0x202f)
|
||||
// narrow no-break space
|
||||
|| (glyphCode == 0x205f)
|
||||
// medium math space
|
||||
|| (glyphCode == 0x3000)
|
||||
// ideographic space
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
render_as_zero_width(uint32 glyphCode)
|
||||
{
|
||||
// ignorable chars: render as invisible
|
||||
// as per Unicode DerivedCoreProperties.txt: Default_Ignorable_Code_Point
|
||||
return (glyphCode == 0x00ad)
|
||||
// soft hyphen
|
||||
|| (glyphCode == 0x034f)
|
||||
// combining grapheme joiner
|
||||
|| (glyphCode >= 0x115f && glyphCode <= 0x1160)
|
||||
// hangul fillers
|
||||
|| (glyphCode >= 0x17b4 && glyphCode <= 0x17b5)
|
||||
// ignorable khmer vowels
|
||||
|| (glyphCode >= 0x180b && glyphCode <= 0x180d)
|
||||
// variation selectors
|
||||
|| (glyphCode >= 0x200b && glyphCode <= 0x200f)
|
||||
// zero width space, cursive joiners, ltr marks
|
||||
|| (glyphCode >= 0x202a && glyphCode <= 0x202e)
|
||||
// left to right embed, override
|
||||
|| (glyphCode >= 0x2060 && glyphCode <= 0x206f)
|
||||
// word joiner, invisible math operators, reserved
|
||||
|| (glyphCode == 0x3164)
|
||||
// hangul filler
|
||||
|| (glyphCode >= 0xfe00 && glyphCode <= 0xfe0f)
|
||||
// variation selectors
|
||||
|| (glyphCode == 0xfeff)
|
||||
// zero width no-break space
|
||||
|| (glyphCode == 0xffa0)
|
||||
// halfwidth hangul filler
|
||||
|| (glyphCode >= 0xfff0 && glyphCode <= 0xfff8)
|
||||
// reserved
|
||||
|| (glyphCode >= 0x1d173 && glyphCode <= 0x1d17a)
|
||||
// musical symbols
|
||||
|| (glyphCode >= 0xe0000 && glyphCode <= 0xe01ef)
|
||||
// variation selectors, tag space, reserved
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
const GlyphCache*
|
||||
FontCacheEntry::Glyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
|
||||
{
|
||||
@@ -212,7 +280,24 @@ FontCacheEntry::Glyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
|
||||
glyphIndex = engine->GlyphIndexForGlyphCode(glyphCode);
|
||||
}
|
||||
|
||||
if (glyphIndex != 0 && engine->PrepareGlyph(glyphIndex)) {
|
||||
if (glyphIndex == 0) {
|
||||
if (render_as_zero_width(glyphCode)) {
|
||||
// cache and return a zero width glyph
|
||||
return fGlyphCache->CacheGlyph(glyphCode, 0, glyph_data_invalid,
|
||||
agg::rect_i(0, 0, -1, -1), 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// reset to our engine
|
||||
engine = &fEngine;
|
||||
if (render_as_space(glyphCode)) {
|
||||
// get the normal space glyph
|
||||
glyphIndex = engine->GlyphIndexForGlyphCode(0x20 /* space */);
|
||||
} else {
|
||||
// render the "missing glyph box" (by simply keeping glyphIndex 0)
|
||||
}
|
||||
}
|
||||
|
||||
if (engine->PrepareGlyph(glyphIndex)) {
|
||||
glyph = fGlyphCache->CacheGlyph(glyphCode,
|
||||
engine->DataSize(), engine->DataType(), engine->Bounds(),
|
||||
engine->AdvanceX(), engine->AdvanceY(),
|
||||
@@ -220,8 +305,8 @@ FontCacheEntry::Glyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
|
||||
|
||||
if (glyph != NULL)
|
||||
engine->WriteGlyphTo(glyph->data);
|
||||
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user