Update SkCanonicalizeFont to also update paint

Bug: skia:
Change-Id: I3bf0ecc133778645826f83f7bc54f9c4f88e5e05
Reviewed-on: https://skia-review.googlesource.com/c/177885
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2018-12-16 15:57:29 -05:00 committed by Skia Commit-Bot
parent 1d6ae2e8f5
commit 6cd43b4456
2 changed files with 68 additions and 63 deletions

View File

@ -8,6 +8,7 @@
#include "gm.h" #include "gm.h"
#include "sk_tool_utils.h" #include "sk_tool_utils.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkFont.h"
#include "SkTypeface.h" #include "SkTypeface.h"
/* This test tries to define the effect of using hairline strokes on text. /* 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 textScale,
SkScalar strokeWidth, SkScalar strokeWidth,
SkPaint::Style strokeStyle) { SkPaint::Style strokeStyle) {
SkPaint paint; SkPaint paint;
paint.setColor(SK_ColorBLACK); paint.setColor(SK_ColorBLACK);
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setTextSize(kTextHeight * textScale); paint.setStrokeWidth(strokeWidth);
sk_tool_utils::set_portable_typeface(&paint); paint.setStyle(strokeStyle);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(strokeStyle);
// This demonstrates that we can not measure the text if SkFont font(sk_tool_utils::create_portable_typeface(), kTextHeight * textScale);
// 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));
SkRect bounds; // This demonstrates that we can not measure the text if
if (drawRef) { // there's a device transform. The canvas total matrix will
SkScalar advance = paint.measureText(kText, sizeof(kText) - 1, &bounds); // end up being a device transform.
bool drawRef = !(canvas->getTotalMatrix().getType() &
~(SkMatrix::kIdentity_Mask | SkMatrix::kTranslate_Mask));
paint.setStrokeWidth(0.0f); SkRect bounds;
paint.setStyle(SkPaint::kStroke_Style); if (drawRef) {
SkScalar advance = font.measureText(kText, sizeof(kText) - 1, kUTF8_SkTextEncoding,
&bounds, &paint);
// Green box is the measured text bounds. paint.setStrokeWidth(0.0f);
paint.setColor(SK_ColorGREEN); paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(bounds, paint);
// Red line is the measured advance from the 0,0 of the text position. // Green box is the measured text bounds.
paint.setColor(SK_ColorRED); paint.setColor(SK_ColorGREEN);
canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint); canvas->drawRect(bounds, paint);
}
// Red line is the measured advance from the 0,0 of the text position.
// Black text is the testcase, eg. the text. paint.setColor(SK_ColorRED);
paint.setColor(SK_ColorBLACK); canvas->drawLine(0.0f, 0.0f, advance, 0.0f, paint);
paint.setStrokeWidth(strokeWidth); }
paint.setStyle(strokeStyle);
canvas->drawText(kText, sizeof(kText) - 1, 0.0f, 0.0f, paint); // Black text is the testcase, eg. the text.
paint.setColor(SK_ColorBLACK);
if (drawRef) { paint.setStrokeWidth(strokeWidth);
SkScalar widths[sizeof(kText) - 1]; paint.setStyle(strokeStyle);
paint.getTextWidths(kText, sizeof(kText) - 1, widths, nullptr); canvas->drawSimpleText(kText, sizeof(kText) - 1, kUTF8_SkTextEncoding, 0.0f, 0.0f, font, paint);
paint.setStrokeWidth(0.0f); if (drawRef) {
paint.setStyle(SkPaint::kStroke_Style); const size_t len = sizeof(kText) - 1;
SkGlyphID glyphs[len];
// Magenta lines are the positions for the characters. const int count = font.textToGlyphs(kText, len, kUTF8_SkTextEncoding, glyphs, len);
paint.setColor(SK_ColorMAGENTA); SkScalar widths[len]; // len is conservative. we really only need 'count'
SkScalar w = bounds.x(); font.getWidthsBounds(glyphs, count, widths, nullptr, &paint);
for (size_t i = 0; i < sizeof(kText) - 1; ++i) {
canvas->drawLine(w, 0.0f, w, 5.0f, paint); paint.setStrokeWidth(0.0f);
w += widths[i]; 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) { DEF_SIMPLE_GM(glyph_pos_h_b, c, 800, 600) {

View File

@ -140,23 +140,29 @@ bool SkFont::hasSomeAntiAliasing() const {
class SkCanonicalizeFont { class SkCanonicalizeFont {
public: 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() || 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); fScale = f->setupForAsPaths(nullptr);
fFont = f; fFont = f;
fPaint.reset();
} }
} }
const SkFont& getFont() const { return *fFont; } const SkFont& getFont() const { return *fFont; }
const SkPaint& getPaint() const { return fPaint; }
SkScalar getScale() const { return fScale; } SkScalar getScale() const { return fScale; }
private: private:
const SkFont* fFont; const SkFont* fFont;
SkTLazy<SkFont> fLazy; SkTLazy<SkFont> fLazyFont;
SkScalar fScale; SkPaint fPaint;
SkScalar fScale = 0;
}; };
@ -265,7 +271,7 @@ size_t SkFont::breakText(const void* textD, size_t length, SkTextEncoding encodi
return length; return length;
} }
SkCanonicalizeFont canon(*this); SkCanonicalizeFont canon(*this, nullptr);
const SkFont& font = canon.getFont(); const SkFont& font = canon.getFont();
SkScalar scale = canon.getScale(); SkScalar scale = canon.getScale();
@ -322,16 +328,11 @@ SkScalar SkFont::measureText(const void* textD, size_t length, SkTextEncoding en
return 0; return 0;
} }
SkCanonicalizeFont canon(*this); SkCanonicalizeFont canon(*this, paint);
const SkFont& font = canon.getFont(); const SkFont& font = canon.getFont();
SkScalar scale = canon.getScale(); SkScalar scale = canon.getScale();
SkPaint defaultPaint; auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint());
// 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);
const char* text = static_cast<const char*>(textD); const char* text = static_cast<const char*>(textD);
const char* stop = text + length; const char* stop = text + length;
@ -381,15 +382,14 @@ void VisitGlyphs(const SkFont& origFont, const SkPaint* paint, const uint16_t gl
return; return;
} }
SkCanonicalizeFont canon(origFont); SkCanonicalizeFont canon(origFont, paint);
const SkFont& font = canon.getFont(); const SkFont& font = canon.getFont();
SkScalar scale = canon.getScale(); SkScalar scale = canon.getScale();
if (!scale) { if (!scale) {
scale = 1; scale = 1;
} }
auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, auto cache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, canon.getPaint());
paint ? *paint : SkPaint());
handler(cache.get(), glyphs, count, scale); 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 { SkScalar SkFont::getMetrics(SkFontMetrics* metrics) const {
SkCanonicalizeFont canon(*this); SkCanonicalizeFont canon(*this, nullptr);
const SkFont& font = canon.getFont(); const SkFont& font = canon.getFont();
SkScalar scale = canon.getScale(); SkScalar scale = canon.getScale();