From 5379051ee77f6d70f7d0554a10fd1c61a63b9da9 Mon Sep 17 00:00:00 2001 From: bungeman Date: Thu, 21 Jul 2016 13:32:09 -0700 Subject: [PATCH] Fix SkScalerContext_FreeType::generateFontMetrics. SkScalerContext::generateFontMetrics implementations should not attempt to take into account skew. This implementation should correctly handle bitmap fonts as well. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2165323002 Review-Url: https://codereview.chromium.org/2165323002 --- gm/coloremoji.cpp | 40 +++++++++++++++++-------------- src/ports/SkFontHost_FreeType.cpp | 39 ++++++++++++------------------ 2 files changed, 37 insertions(+), 42 deletions(-) diff --git a/gm/coloremoji.cpp b/gm/coloremoji.cpp index b29040ac29..f4de3e5dce 100644 --- a/gm/coloremoji.cpp +++ b/gm/coloremoji.cpp @@ -77,16 +77,19 @@ protected: const char* text = emojiFont.text; // draw text at different point sizes - const int textSize[] = { 10, 30, 50, }; - const int textYOffset[] = { 10, 40, 100, }; - SkASSERT(sizeof(textSize) == sizeof(textYOffset)); - size_t y_offset = 0; - for (size_t y = 0; y < sizeof(textSize) / sizeof(int); y++) { - paint.setTextSize(SkIntToScalar(textSize[y])); - canvas->drawText(text, strlen(text), 10, SkIntToScalar(textYOffset[y]), paint); - y_offset += textYOffset[y]; + static constexpr SkScalar textSizes[] = { 10, 30, 50, }; + SkPaint::FontMetrics metrics; + SkScalar y = 0; + for (const SkScalar& textSize : textSizes) { + paint.setTextSize(textSize); + paint.getFontMetrics(&metrics); + y += -metrics.fAscent; + canvas->drawText(text, strlen(text), 10, y, paint); + y += metrics.fDescent + metrics.fLeading; } + y += 20; + SkScalar savedY = y; // draw with shaders and image filters for (int makeLinear = 0; makeLinear < 2; makeLinear++) { for (int makeBlur = 0; makeBlur < 2; makeBlur++) { @@ -107,15 +110,15 @@ protected: shaderPaint.setImageFilter(make_grayscale(nullptr)); } shaderPaint.setTextSize(30); - canvas->drawText(text, strlen(text), 380, SkIntToScalar(y_offset), - shaderPaint); - y_offset += 32; + shaderPaint.getFontMetrics(&metrics); + y += -metrics.fAscent; + canvas->drawText(text, strlen(text), 380, y, shaderPaint); + y += metrics.fDescent + metrics.fLeading; } } } - // setup work needed to draw text with different clips - canvas->translate(10, 160); + canvas->translate(10, savedY); paint.setTextSize(40); // compute the bounds of the text @@ -134,22 +137,23 @@ protected: SkRect interiorClip = bounds; interiorClip.inset(boundsQuarterWidth, boundsQuarterHeight); - const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip }; + static const SkRect clipRects[] = { bounds, upperLeftClip, lowerRightClip, interiorClip }; SkPaint clipHairline; clipHairline.setColor(SK_ColorWHITE); clipHairline.setStyle(SkPaint::kStroke_Style); - for (size_t x = 0; x < sizeof(clipRects) / sizeof(SkRect); ++x) { + for (const SkRect& clipRect : clipRects) { + canvas->translate(0, bounds.height()); canvas->save(); - canvas->drawRect(clipRects[x], clipHairline); + canvas->drawRect(clipRect, clipHairline); paint.setAlpha(0x20); canvas->drawText(text, strlen(text), 0, 0, paint); - canvas->clipRect(clipRects[x]); + canvas->clipRect(clipRect); paint.setAlpha(0xFF); canvas->drawText(text, strlen(text), 0, 0, paint); canvas->restore(); - canvas->translate(0, bounds.height() + SkIntToScalar(25)); + canvas->translate(0, SkIntToScalar(25)); } } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 45e4eaead8..2780a32d09 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -1315,10 +1315,6 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics } FT_Face face = fFace; - SkScalar scaleX = fScale.x(); - SkScalar scaleY = fScale.y(); - SkScalar mxy = -fMatrix22Scalar.getSkewX() * scaleY; - SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY; // fetch units/EM from "head" table if needed (ie for bitmap fonts) SkScalar upem = SkIntToScalar(face->units_per_EM); @@ -1335,10 +1331,10 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics SkScalar cap_height = 0.0f; TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); if (os2) { - x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; + x_height = SkIntToScalar(os2->sxHeight) / upem * fScale.y(); avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; if (os2->version != 0xFFFF && os2->version >= 2) { - cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem; + cap_height = SkIntToScalar(os2->sCapHeight) / upem * fScale.y(); } } @@ -1389,8 +1385,7 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f); - leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) - + ascent - descent; + leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) + ascent - descent; xmin = 0.0f; xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; ymin = descent + leading; @@ -1407,13 +1402,13 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics // synthesize elements that were not provided by the os/2 table or format-specific metrics if (!x_height) { - x_height = -ascent; + x_height = -ascent * fScale.y(); } if (!avgCharWidth) { avgCharWidth = xmax - xmin; } if (!cap_height) { - cap_height = -ascent; + cap_height = -ascent * fScale.y(); } // disallow negative linespacing @@ -1421,22 +1416,18 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics leading = 0.0f; } - SkScalar scale = myy; - if (this->isVertical()) { - scale = mxy; - } - metrics->fTop = ymax * scale; - metrics->fAscent = ascent * scale; - metrics->fDescent = descent * scale; - metrics->fBottom = ymin * scale; - metrics->fLeading = leading * scale; - metrics->fAvgCharWidth = avgCharWidth * scale; - metrics->fXMin = xmin * scale; - metrics->fXMax = xmax * scale; + metrics->fTop = ymax * fScale.y(); + metrics->fAscent = ascent * fScale.y(); + metrics->fDescent = descent * fScale.y(); + metrics->fBottom = ymin * fScale.y(); + metrics->fLeading = leading * fScale.y(); + metrics->fAvgCharWidth = avgCharWidth * fScale.y(); + metrics->fXMin = xmin * fScale.y(); + metrics->fXMax = xmax * fScale.y(); metrics->fXHeight = x_height; metrics->fCapHeight = cap_height; - metrics->fUnderlineThickness = underlineThickness * scale; - metrics->fUnderlinePosition = underlinePosition * scale; + metrics->fUnderlineThickness = underlineThickness * fScale.y(); + metrics->fUnderlinePosition = underlinePosition * fScale.y(); } ///////////////////////////////////////////////////////////////////////////////