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,
|
GlyphCache* CacheGlyph(uint32 glyphIndex,
|
||||||
uint32 dataSize, glyph_data_type dataType, const agg::rect_i& bounds,
|
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);
|
GlyphCache* glyph = fGlyphTable.Lookup(glyphIndex);
|
||||||
if (glyph != NULL)
|
if (glyph != NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
glyph = new(std::nothrow) GlyphCache(glyphIndex, dataSize, dataType,
|
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) {
|
if (glyph == NULL || glyph->data == NULL) {
|
||||||
delete glyph;
|
delete glyph;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -293,7 +295,7 @@ FontCacheEntry::CreateGlyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
|
|||||||
if (render_as_zero_width(glyphCode)) {
|
if (render_as_zero_width(glyphCode)) {
|
||||||
// cache and return a zero width glyph
|
// cache and return a zero width glyph
|
||||||
return fGlyphCache->CacheGlyph(glyphCode, 0, glyph_data_invalid,
|
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
|
// reset to our engine
|
||||||
@@ -310,6 +312,7 @@ FontCacheEntry::CreateGlyph(uint32 glyphCode, FontCacheEntry* fallbackEntry)
|
|||||||
glyph = fGlyphCache->CacheGlyph(glyphCode,
|
glyph = fGlyphCache->CacheGlyph(glyphCode,
|
||||||
engine->DataSize(), engine->DataType(), engine->Bounds(),
|
engine->DataSize(), engine->DataType(), engine->Bounds(),
|
||||||
engine->AdvanceX(), engine->AdvanceY(),
|
engine->AdvanceX(), engine->AdvanceY(),
|
||||||
|
engine->PreciseAdvanceX(), engine->PreciseAdvanceY(),
|
||||||
engine->InsetLeft(), engine->InsetRight());
|
engine->InsetLeft(), engine->InsetRight());
|
||||||
|
|
||||||
if (glyph != NULL)
|
if (glyph != NULL)
|
||||||
@@ -326,7 +329,7 @@ FontCacheEntry::InitAdaptors(const GlyphCache* glyph,
|
|||||||
GlyphGray8Adapter& gray8Adapter, GlyphPathAdapter& pathAdapter,
|
GlyphGray8Adapter& gray8Adapter, GlyphPathAdapter& pathAdapter,
|
||||||
double scale)
|
double scale)
|
||||||
{
|
{
|
||||||
if (!glyph)
|
if (glyph == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(glyph->data_type) {
|
switch(glyph->data_type) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
struct GlyphCache {
|
struct GlyphCache {
|
||||||
GlyphCache(uint32 glyphIndex, uint32 dataSize, glyph_data_type dataType,
|
GlyphCache(uint32 glyphIndex, uint32 dataSize, glyph_data_type dataType,
|
||||||
const agg::rect_i& bounds, float advanceX, float advanceY,
|
const agg::rect_i& bounds, float advanceX, float advanceY,
|
||||||
|
float preciseAdvanceX, float preciseAdvanceY,
|
||||||
float insetLeft, float insetRight)
|
float insetLeft, float insetRight)
|
||||||
:
|
:
|
||||||
glyph_index(glyphIndex),
|
glyph_index(glyphIndex),
|
||||||
@@ -52,6 +53,8 @@ struct GlyphCache {
|
|||||||
bounds(bounds),
|
bounds(bounds),
|
||||||
advance_x(advanceX),
|
advance_x(advanceX),
|
||||||
advance_y(advanceY),
|
advance_y(advanceY),
|
||||||
|
precise_advance_x(preciseAdvanceX),
|
||||||
|
precise_advance_y(preciseAdvanceY),
|
||||||
inset_left(insetLeft),
|
inset_left(insetLeft),
|
||||||
inset_right(insetRight),
|
inset_right(insetRight),
|
||||||
hash_link(NULL)
|
hash_link(NULL)
|
||||||
@@ -70,6 +73,8 @@ struct GlyphCache {
|
|||||||
agg::rect_i bounds;
|
agg::rect_i bounds;
|
||||||
float advance_x;
|
float advance_x;
|
||||||
float advance_y;
|
float advance_y;
|
||||||
|
float precise_advance_x;
|
||||||
|
float precise_advance_y;
|
||||||
float inset_left;
|
float inset_left;
|
||||||
float inset_right;
|
float inset_right;
|
||||||
|
|
||||||
|
|||||||
@@ -624,7 +624,22 @@ FontEngine::PrepareGlyph(uint32 glyphIndex)
|
|||||||
loadFlags |= fGlyphRendering == glyph_ren_subpix ?
|
loadFlags |= fGlyphRendering == glyph_ren_subpix ?
|
||||||
FT_LOAD_TARGET_LCD : FT_LOAD_TARGET_NORMAL;
|
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)
|
if (fLastError != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ class FontEngine {
|
|||||||
{ return fAdvanceX; }
|
{ return fAdvanceX; }
|
||||||
double AdvanceY() const
|
double AdvanceY() const
|
||||||
{ return fAdvanceY; }
|
{ return fAdvanceY; }
|
||||||
|
double PreciseAdvanceX() const
|
||||||
|
{ return fPreciseAdvanceX; }
|
||||||
|
double PreciseAdvanceY() const
|
||||||
|
{ return fPreciseAdvanceY; }
|
||||||
double InsetLeft() const
|
double InsetLeft() const
|
||||||
{ return fInsetLeft; }
|
{ return fInsetLeft; }
|
||||||
double InsetRight() const
|
double InsetRight() const
|
||||||
@@ -136,6 +140,8 @@ class FontEngine {
|
|||||||
agg::rect_i fBounds;
|
agg::rect_i fBounds;
|
||||||
double fAdvanceX;
|
double fAdvanceX;
|
||||||
double fAdvanceY;
|
double fAdvanceY;
|
||||||
|
double fPreciseAdvanceX;
|
||||||
|
double fPreciseAdvanceY;
|
||||||
double fInsetLeft;
|
double fInsetLeft;
|
||||||
double fInsetRight;
|
double fInsetRight;
|
||||||
|
|
||||||
|
|||||||
@@ -253,8 +253,13 @@ GlyphLayoutEngine::LayoutGlyphs(GlyphConsumer& consumer,
|
|||||||
advanceY = 0;
|
advanceY = 0;
|
||||||
} else {
|
} else {
|
||||||
// get next increment for pen position
|
// get next increment for pen position
|
||||||
advanceX = glyph->advance_x;
|
if (spacing == B_CHAR_SPACING) {
|
||||||
advanceY = glyph->advance_y;
|
advanceX = glyph->precise_advance_x;
|
||||||
|
advanceY = glyph->precise_advance_y;
|
||||||
|
} else {
|
||||||
|
advanceX = glyph->advance_x;
|
||||||
|
advanceY = glyph->advance_y;
|
||||||
|
}
|
||||||
|
|
||||||
// adjust for custom spacing
|
// adjust for custom spacing
|
||||||
if (delta != NULL) {
|
if (delta != NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user