Update Skia's handling of vertical text when freetype metrics are available.
This is a cherry-pick of a larger change going into upstream Skia at...
https://codereview.appspot.com/6554064/
bug: 7124435
Change-Id: Id8b030afaf493741e133b592a4e08a3fd90ec2f3
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index d77ebb9..6c03bf9 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -174,6 +174,7 @@
FT_Matrix fMatrix22;
uint32_t fLoadGlyphFlags;
bool fDoLinearMetrics;
+ bool fUseVertMetrics;
FT_Error setupSize();
void emboldenOutline(FT_Outline* outline);
@@ -777,6 +778,7 @@
fScaleY = SkScalarToFixed(sy);
// compute the flags we send to Load_Glyph
+ fUseVertMetrics = false;
{
FT_Int32 loadFlags = FT_LOAD_DEFAULT;
bool linearMetrics = false;
@@ -833,6 +835,12 @@
// See http://code.google.com/p/skia/issues/detail?id=222.
loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
+ // Use vertical layout if requested and supported.
+ if ((fRec.fFlags & SkScalerContext::kVertical_Flag) && FT_HAS_VERTICAL(fFace)) {
+ loadFlags |= FT_LOAD_VERTICAL_LAYOUT;
+ fUseVertMetrics = true;
+ }
+
fLoadGlyphFlags = loadFlags;
fDoLinearMetrics = linearMetrics;
}
@@ -1002,6 +1010,20 @@
bbox->xMax = (bbox->xMax + 63) & ~63;
bbox->yMax = (bbox->yMax + 63) & ~63;
}
+
+ // Must come after snapToPixelBoundary so that the width and height are
+ // consistent. Otherwise asserts will fire later on when generating the
+ // glyph image.
+ if (fUseVertMetrics) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ bbox->xMin += vector.x;
+ bbox->xMax += vector.x;
+ bbox->yMin += vector.y;
+ bbox->yMax += vector.y;
+ }
}
void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
@@ -1072,6 +1094,16 @@
FT_GlyphSlot_Own_Bitmap(fFace->glyph);
FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
}
+
+ if (fUseVertMetrics) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
+ fFace->glyph->bitmap_top += SkFDot6Floor(vector.y);
+ }
+
glyph->fWidth = SkToU16(fFace->glyph->bitmap.width);
glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows);
glyph->fTop = -SkToS16(fFace->glyph->bitmap_top);
@@ -1095,8 +1127,17 @@
glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
}
- if ((fRec.fFlags & SkScalerContext::kVertical_Flag)
- && fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+ if (fUseVertMetrics) {
+ if (fDoLinearMetrics) {
+ glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
+ glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
+ } else {
+ glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x);
+ glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y);
+ }
+
+ } else if ((fRec.fFlags & SkScalerContext::kVertical_Flag)
+ && fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
//TODO: do we need to specially handle SubpixelPositioning and Kerning?
@@ -1537,6 +1578,14 @@
emboldenOutline(&fFace->glyph->outline);
}
+ if (fUseVertMetrics) {
+ FT_Vector vector;
+ vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
+ vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
+ FT_Vector_Transform(&vector, &fMatrix22);
+ FT_Outline_Translate(&fFace->glyph->outline, vector.x, vector.y);
+ }
+
FT_Outline_Funcs funcs;
funcs.move_to = move_proc;