From d9d14326ca3acb76b37202f2926f9d7cff44b3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 26 Feb 2014 10:36:52 +0100 Subject: [PATCH] app_server: Implemented support for B_CHAR_SPACING. It doesn't yield quiet the expected results, yet. When hinting is turned on, FontEngine takes a measurement of the precise advance values for each cached glyph by invoking FT_Load_Glyph() with the FT_LOAD_NO_HINTING flag, before loading the glyph for real without that flag. In GlyphLayoutEngine.h, the precise advance value is used for B_CHAR_SPACING. The intended result is that glyphs are rendered hinted (according to global Appearance settings), but spaced along the base-line with precise, unhinted advance values. An application would use this for example to implement precise page or print preview and also for zooming text without altering the placement of glyphs. For Gobe Productive, problems can be observed, because we don't implement this correctly, yet. --- src/servers/app/font/FontCacheEntry.cpp | 11 +++++++---- src/servers/app/font/FontCacheEntry.h | 5 +++++ src/servers/app/font/FontEngine.cpp | 17 ++++++++++++++++- src/servers/app/font/FontEngine.h | 6 ++++++ src/servers/app/font/GlyphLayoutEngine.h | 9 +++++++-- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/servers/app/font/FontCacheEntry.cpp b/src/servers/app/font/FontCacheEntry.cpp index 8c8ac0232a..39b64d295e 100644 --- a/src/servers/app/font/FontCacheEntry.cpp +++ b/src/servers/app/font/FontCacheEntry.cpp @@ -96,14 +96,16 @@ public: GlyphCache* CacheGlyph(uint32 glyphIndex, uint32 dataSize, glyph_data_type dataType, const agg::rect_i& bounds, - float advanceX, float advanceY, float insetLeft, float insetRight) + float advanceX, float advanceY, float preciseAdvanceX, + float preciseAdvanceY, float insetLeft, float insetRight) { GlyphCache* glyph = fGlyphTable.Lookup(glyphIndex); if (glyph != NULL) return NULL; glyph = new(std::nothrow) GlyphCache(glyphIndex, dataSize, dataType, - bounds, advanceX, advanceY, insetLeft, insetRight); + bounds, advanceX, advanceY, preciseAdvanceX, preciseAdvanceY, + insetLeft, insetRight); if (glyph == NULL || glyph->data == NULL) { delete glyph; return NULL; @@ -293,7 +295,7 @@ FontCacheEntry::CreateGlyph(uint32 glyphCode, FontCacheEntry* fallbackEntry) 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); + agg::rect_i(0, 0, -1, -1), 0, 0, 0, 0, 0, 0); } // reset to our engine @@ -310,6 +312,7 @@ FontCacheEntry::CreateGlyph(uint32 glyphCode, FontCacheEntry* fallbackEntry) glyph = fGlyphCache->CacheGlyph(glyphCode, engine->DataSize(), engine->DataType(), engine->Bounds(), engine->AdvanceX(), engine->AdvanceY(), + engine->PreciseAdvanceX(), engine->PreciseAdvanceY(), engine->InsetLeft(), engine->InsetRight()); if (glyph != NULL) @@ -326,7 +329,7 @@ FontCacheEntry::InitAdaptors(const GlyphCache* glyph, GlyphGray8Adapter& gray8Adapter, GlyphPathAdapter& pathAdapter, double scale) { - if (!glyph) + if (glyph == NULL) return; switch(glyph->data_type) { diff --git a/src/servers/app/font/FontCacheEntry.h b/src/servers/app/font/FontCacheEntry.h index 138d930c80..abe085adec 100644 --- a/src/servers/app/font/FontCacheEntry.h +++ b/src/servers/app/font/FontCacheEntry.h @@ -43,6 +43,7 @@ struct GlyphCache { GlyphCache(uint32 glyphIndex, uint32 dataSize, glyph_data_type dataType, const agg::rect_i& bounds, float advanceX, float advanceY, + float preciseAdvanceX, float preciseAdvanceY, float insetLeft, float insetRight) : glyph_index(glyphIndex), @@ -52,6 +53,8 @@ struct GlyphCache { bounds(bounds), advance_x(advanceX), advance_y(advanceY), + precise_advance_x(preciseAdvanceX), + precise_advance_y(preciseAdvanceY), inset_left(insetLeft), inset_right(insetRight), hash_link(NULL) @@ -70,6 +73,8 @@ struct GlyphCache { agg::rect_i bounds; float advance_x; float advance_y; + float precise_advance_x; + float precise_advance_y; float inset_left; float inset_right; diff --git a/src/servers/app/font/FontEngine.cpp b/src/servers/app/font/FontEngine.cpp index bb028951f7..c6e269d764 100644 --- a/src/servers/app/font/FontEngine.cpp +++ b/src/servers/app/font/FontEngine.cpp @@ -624,7 +624,22 @@ FontEngine::PrepareGlyph(uint32 glyphIndex) loadFlags |= fGlyphRendering == glyph_ren_subpix ? FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_NORMAL; - fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags); + if (fHinting) { + // Load without hinting to get precise advance values + // for B_CHAR_SPACING + fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags + | FT_LOAD_NO_HINTING); + } else { + fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags); + } + + fPreciseAdvanceX = int26p6_to_dbl(fFace->glyph->advance.x); + fPreciseAdvanceY = int26p6_to_dbl(fFace->glyph->advance.y); + + if (fHinting) { + // Need to load again with hinting. + fLastError = FT_Load_Glyph(fFace, glyphIndex, loadFlags); + } if (fLastError != 0) return false; diff --git a/src/servers/app/font/FontEngine.h b/src/servers/app/font/FontEngine.h index b401102b04..d599d07e8a 100644 --- a/src/servers/app/font/FontEngine.h +++ b/src/servers/app/font/FontEngine.h @@ -105,6 +105,10 @@ class FontEngine { { return fAdvanceX; } double AdvanceY() const { return fAdvanceY; } + double PreciseAdvanceX() const + { return fPreciseAdvanceX; } + double PreciseAdvanceY() const + { return fPreciseAdvanceY; } double InsetLeft() const { return fInsetLeft; } double InsetRight() const @@ -136,6 +140,8 @@ class FontEngine { agg::rect_i fBounds; double fAdvanceX; double fAdvanceY; + double fPreciseAdvanceX; + double fPreciseAdvanceY; double fInsetLeft; double fInsetRight; diff --git a/src/servers/app/font/GlyphLayoutEngine.h b/src/servers/app/font/GlyphLayoutEngine.h index 6ed1d3ae60..b1fc624f32 100644 --- a/src/servers/app/font/GlyphLayoutEngine.h +++ b/src/servers/app/font/GlyphLayoutEngine.h @@ -253,8 +253,13 @@ GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer, advanceY = 0; } else { // get next increment for pen position - advanceX = glyph->advance_x; - advanceY = glyph->advance_y; + if (spacing == B_CHAR_SPACING) { + advanceX = glyph->precise_advance_x; + advanceY = glyph->precise_advance_y; + } else { + advanceX = glyph->advance_x; + advanceY = glyph->advance_y; + } // adjust for custom spacing if (delta != NULL) {