From 6cd43b445663651ace5a4774ae6b2de6e9e02815 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Sun, 16 Dec 2018 15:57:29 -0500 Subject: [PATCH] Update SkCanonicalizeFont to also update paint Bug: skia: Change-Id: I3bf0ecc133778645826f83f7bc54f9c4f88e5e05 Reviewed-on: https://skia-review.googlesource.com/c/177885 Reviewed-by: Mike Reed Commit-Queue: Mike Reed --- gm/glyph_pos.cpp | 95 ++++++++++++++++++++++++--------------------- src/core/SkFont.cpp | 36 ++++++++--------- 2 files changed, 68 insertions(+), 63 deletions(-) diff --git a/gm/glyph_pos.cpp b/gm/glyph_pos.cpp index ff2a432f8a..c5e43c8130 100644 --- a/gm/glyph_pos.cpp +++ b/gm/glyph_pos.cpp @@ -8,6 +8,7 @@ #include "gm.h" #include "sk_tool_utils.h" #include "SkCanvas.h" +#include "SkFont.h" #include "SkTypeface.h" /* This test tries to define the effect of using hairline strokes on text. @@ -80,57 +81,61 @@ static void drawTestCase(SkCanvas* canvas, SkScalar textScale, SkScalar strokeWidth, SkPaint::Style strokeStyle) { - SkPaint paint; - paint.setColor(SK_ColorBLACK); - paint.setAntiAlias(true); - paint.setTextSize(kTextHeight * textScale); - sk_tool_utils::set_portable_typeface(&paint); - paint.setStrokeWidth(strokeWidth); - paint.setStyle(strokeStyle); + SkPaint paint; + paint.setColor(SK_ColorBLACK); + paint.setAntiAlias(true); + paint.setStrokeWidth(strokeWidth); + paint.setStyle(strokeStyle); - // This demonstrates that we can not measure the text if - // there's a device transform. The canvas total matrix will - // end up being a device transform. - bool drawRef = !(canvas->getTotalMatrix().getType() & - ~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask)); + SkFont font(sk_tool_utils::create_portable_typeface(), kTextHeight * textScale); - SkRect bounds; - if (drawRef) { - SkScalar advance = paint.measureText(kText, sizeof(kText) - 1, &bounds); + // This demonstrates that we can not measure the text if + // there's a device transform. The canvas total matrix will + // end up being a device transform. + bool drawRef = !(canvas->getTotalMatrix().getType() & + ~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask)); - paint.setStrokeWidth(0.0f); - paint.setStyle(SkPaint::kStroke_Style); + SkRect bounds; + if (drawRef) { + SkScalar advance = font.measureText(kText, sizeof(kText) - 1, kUTF8_SkTextEncoding, + &bounds, &paint); - // Green box is the measured text bounds. - paint.setColor(SK_ColorGREEN); - canvas->drawRect(bounds, paint); + paint.setStrokeWidth(0.0f); + paint.setStyle(SkPaint::kStroke_Style); - // Red line is the measured advance from the 0,0 of the text position. - paint.setColor(SK_ColorRED); - canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint); - } - - // Black text is the testcase, eg. the text. - paint.setColor(SK_ColorBLACK); - paint.setStrokeWidth(strokeWidth); - paint.setStyle(strokeStyle); - canvas->drawText(kText, sizeof(kText) - 1, 0.0f, 0.0f, paint); - - if (drawRef) { - SkScalar widths[sizeof(kText) - 1]; - paint.getTextWidths(kText, sizeof(kText) - 1, widths, nullptr); - - paint.setStrokeWidth(0.0f); - paint.setStyle(SkPaint::kStroke_Style); - - // Magenta lines are the positions for the characters. - paint.setColor(SK_ColorMAGENTA); - SkScalar w = bounds.x(); - for (size_t i = 0; i < sizeof(kText) - 1; ++i) { - canvas->drawLine(w, 0.0f, w, 5.0f, paint); - w += widths[i]; - } + // Green box is the measured text bounds. + paint.setColor(SK_ColorGREEN); + canvas->drawRect(bounds, paint); + + // Red line is the measured advance from the 0,0 of the text position. + paint.setColor(SK_ColorRED); + canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint); + } + + // Black text is the testcase, eg. the text. + paint.setColor(SK_ColorBLACK); + paint.setStrokeWidth(strokeWidth); + paint.setStyle(strokeStyle); + canvas->drawSimpleText(kText, sizeof(kText) - 1, kUTF8_SkTextEncoding, 0.0f, 0.0f, font, paint); + + if (drawRef) { + const size_t len = sizeof(kText) - 1; + SkGlyphID glyphs[len]; + const int count = font.textToGlyphs(kText, len, kUTF8_SkTextEncoding, glyphs, len); + SkScalar widths[len]; // len is conservative. we really only need 'count' + font.getWidthsBounds(glyphs, count, widths, nullptr, &paint); + + paint.setStrokeWidth(0.0f); + paint.setStyle(SkPaint::kStroke_Style); + + // Magenta lines are the positions for the characters. + paint.setColor(SK_ColorMAGENTA); + SkScalar w = bounds.x(); + for (size_t i = 0; i < sizeof(kText) - 1; ++i) { + canvas->drawLine(w, 0.0f, w, 5.0f, paint); + w += widths[i]; } + } } DEF_SIMPLE_GM(glyph_pos_h_b, c, 800, 600) { diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp index c692863fdb..56a6bc5f8f 100644 --- a/src/core/SkFont.cpp +++ b/src/core/SkFont.cpp @@ -140,23 +140,29 @@ bool SkFont::hasSomeAntiAliasing() const { class SkCanonicalizeFont { public: - SkCanonicalizeFont(const SkFont& font) : fFont(&font), fScale(0) { + SkCanonicalizeFont(const SkFont& font, const SkPaint* paint) : fFont(&font) { + if (paint) { + fPaint = *paint; + } if (font.isLinearMetrics() || - SkDraw::ShouldDrawTextAsPaths(font, SkPaint(), SkMatrix::I())) + SkDraw::ShouldDrawTextAsPaths(font, fPaint, SkMatrix::I())) { - SkFont* f = fLazy.set(font); + SkFont* f = fLazyFont.set(font); fScale = f->setupForAsPaths(nullptr); fFont = f; + fPaint.reset(); } } const SkFont& getFont() const { return *fFont; } + const SkPaint& getPaint() const { return fPaint; } SkScalar getScale() const { return fScale; } private: - const SkFont* fFont; - SkTLazy fLazy; - SkScalar fScale; + const SkFont* fFont; + SkTLazy fLazyFont; + SkPaint fPaint; + SkScalar fScale = 0; }; @@ -265,7 +271,7 @@ size_t SkFont::breakText(const void* textD, size_t length, SkTextEncoding encodi return length; } - SkCanonicalizeFont canon(*this); + SkCanonicalizeFont canon(*this, nullptr); const SkFont& font = canon.getFont(); SkScalar scale = canon.getScale(); @@ -322,16 +328,11 @@ SkScalar SkFont::measureText(const void* textD, size_t length, SkTextEncoding en return 0; } - SkCanonicalizeFont canon(*this); + SkCanonicalizeFont canon(*this, paint); const SkFont& font = canon.getFont(); SkScalar scale = canon.getScale(); - SkPaint defaultPaint; - // if we had to cannonicalize the font, then we need to also reset the paint - if (!paint || this != &font) { - paint = &defaultPaint; - } - auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, *paint); + auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint()); const char* text = static_cast(textD); const char* stop = text + length; @@ -381,15 +382,14 @@ void VisitGlyphs(const SkFont& origFont, const SkPaint* paint, const uint16_t gl return; } - SkCanonicalizeFont canon(origFont); + SkCanonicalizeFont canon(origFont, paint); const SkFont& font = canon.getFont(); SkScalar scale = canon.getScale(); if (!scale) { scale = 1; } - auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, - paint ? *paint : SkPaint()); + auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint()); handler(cache.get(), glyphs, count, scale); } @@ -468,7 +468,7 @@ bool SkFont::getPath(uint16_t glyphID, SkPath* path) const { } SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const { - SkCanonicalizeFont canon(*this); + SkCanonicalizeFont canon(*this, nullptr); const SkFont& font = canon.getFont(); SkScalar scale = canon.getScale();