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.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user