aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ben Wagner <bungeman@google.com>2018-04-30 15:39:15 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-03 01:00:08 +0000
commit20fa1e94a0847e3db1567d468810f61a1b3dafb9 (patch)
treed9da3b420bbe00ef0e6839aba8882edacfcc8f62
parent0caef298c2ff935b622673e09cd542151dc2ecc0 (diff)
Update SkRandomScalerContext to handle mask filters.
SkRandomScalarContext would apply all path and mask filters twice, once on the proxy and once to itself. This also changes the SkScalerContext mask generation in anticipation of removing the mask format overrides. This also changes the textblobrandomfont test to fix the line spacing and emoji handling. Change-Id: Ib2a633d49ccb801a1849dd982185f44c1d2ea85f Reviewed-on: https://skia-review.googlesource.com/124644 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
-rw-r--r--gm/textblobrandomfont.cpp85
-rw-r--r--src/core/SkScalerContext.cpp15
-rw-r--r--tools/fonts/SkRandomScalerContext.cpp160
3 files changed, 120 insertions, 140 deletions
diff --git a/gm/textblobrandomfont.cpp b/gm/textblobrandomfont.cpp
index 2e6468a6fc..4aad888dbc 100644
--- a/gm/textblobrandomfont.cpp
+++ b/gm/textblobrandomfont.cpp
@@ -37,19 +37,23 @@ protected:
// make textbloben
SkPaint paint;
paint.setTextSize(32);
+ paint.setAntiAlias(true);
paint.setLCDRenderText(true);
// Setup our random scaler context
- sk_sp<SkTypeface> orig(sk_tool_utils::create_portable_typeface(
- "sans-serif", SkFontStyle::Bold()));
- if (nullptr == orig) {
- orig = SkTypeface::MakeDefault();
+ auto typeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
+ if (!typeface) {
+ typeface = SkTypeface::MakeDefault();
}
- paint.setTypeface(sk_make_sp<SkRandomTypeface>(orig, paint, false));
+ paint.setColor(SK_ColorMAGENTA);
+ paint.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
+ SkScalar y = 0;
SkRect bounds;
paint.measureText(text, strlen(text), &bounds);
- sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, 0);
+ y -= bounds.fTop;
+ sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, y);
+ y += bounds.fBottom;
// A8
const char* bigtext1 = "The quick brown fox";
@@ -58,20 +62,23 @@ protected:
paint.setSubpixelText(false);
paint.setLCDRenderText(false);
paint.measureText(bigtext1, strlen(bigtext1), &bounds);
- SkScalar offset = bounds.height();
- sk_tool_utils::add_to_text_blob(&builder, bigtext1, paint, 0, offset);
+ y -= bounds.fTop;
+ sk_tool_utils::add_to_text_blob(&builder, bigtext1, paint, 0, y);
+ y += bounds.fBottom;
paint.measureText(bigtext2, strlen(bigtext2), &bounds);
- offset += bounds.height();
- sk_tool_utils::add_to_text_blob(&builder, bigtext2, paint, 0, offset);
+ y -= bounds.fTop;
+ sk_tool_utils::add_to_text_blob(&builder, bigtext2, paint, 0, y);
+ y += bounds.fBottom;
// color emoji
if (sk_sp<SkTypeface> origEmoji = sk_tool_utils::emoji_typeface()) {
+ paint.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
const char* emojiText = sk_tool_utils::emoji_sample_text();
paint.measureText(emojiText, strlen(emojiText), &bounds);
- offset += bounds.height();
- paint.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
- sk_tool_utils::add_to_text_blob(&builder, emojiText, paint, 0, offset);
+ y -= bounds.fTop;
+ sk_tool_utils::add_to_text_blob(&builder, emojiText, paint, 0, y);
+ y += bounds.fBottom;
}
// build
@@ -88,6 +95,8 @@ protected:
void onDraw(SkCanvas* canvas) override {
// This GM exists to test a specific feature of the GPU backend.
+ // This GM uses sk_tool_utils::makeSurface which doesn't work well with vias.
+ // This GM uses SkRandomTypeface which doesn't work well with serialization.
if (nullptr == canvas->getGrContext()) {
skiagm::GM::DrawGpuOnlyMessage(canvas);
return;
@@ -100,37 +109,43 @@ protected:
canvas->imageInfo().refColorSpace());
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
auto surface(sk_tool_utils::makeSurface(canvas, info, &props));
- if (surface) {
+ if (!surface) {
+ const char* text = "This test requires a surface";
+ size_t len = strlen(text);
SkPaint paint;
- paint.setAntiAlias(true);
+ canvas->drawText(text, len, 10, 100, paint);
+ return;
+ }
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ SkCanvas* c = surface->getCanvas();
- SkCanvas* c = surface->getCanvas();
+ SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
+ SkScalar yOffset = 5;
+ for (int i = 0; i < 1; i++) {
+ // fiddle the canvas to force regen of textblobs
+ canvas->rotate(i % 2 ? 0.0f : -0.05f);
- int stride = SkScalarCeilToInt(fBlob->bounds().height());
- int yOffset = stride / 8;
- for (int i = 0; i < 1; i++) {
- // fiddle the canvas to force regen of textblobs
- canvas->rotate(i % 2 ? 0.0f : -0.05f);
- canvas->drawTextBlob(fBlob, 10.0f, SkIntToScalar(yOffset), paint);
- yOffset += stride;
+ canvas->drawTextBlob(fBlob, 10, yOffset, paint);
+ yOffset += stride;
- // This will draw as black boxes
- c->drawTextBlob(fBlob, 10, SkIntToScalar(yOffset), paint);
+ // this will test lcd masks when not requested
+ // on cpu this currently causes unspecified behavior, so avoid until it is fixed
+ if (canvas->getGrContext()) {
+ c->drawTextBlob(fBlob, 10, yOffset, paint);
surface->draw(canvas, 0, 0, nullptr);
+ }
+ yOffset += stride;
- // free gpu resources and verify
- yOffset += stride;
+ // free gpu resources and verify
+ if (canvas->getGrContext()) {
canvas->getGrContext()->freeGpuResources();
- canvas->drawTextBlob(fBlob, 10, SkIntToScalar(yOffset), paint);
-
- yOffset += stride;
}
- } else {
- const char* text = "This test requires a surface";
- size_t len = strlen(text);
- SkPaint paint;
- canvas->drawText(text, len, 10, 100, paint);
+ canvas->drawTextBlob(fBlob, 10, yOffset, paint);
+ yOffset += stride;
}
}
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 7ad3a030bb..232129c478 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -76,13 +76,22 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
bool generatingImageFromPath = fGenerateImageFromPath;
if (!generatingImageFromPath) {
generateMetrics(glyph);
+ if (glyph->fMaskFormat == MASK_FORMAT_UNKNOWN) {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+ }
} else {
SkPath devPath;
generatingImageFromPath = this->internalGetPath(glyph->getPackedID(), &devPath);
if (!generatingImageFromPath) {
generateMetrics(glyph);
+ if (glyph->fMaskFormat == MASK_FORMAT_UNKNOWN) {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+ }
} else {
generateAdvance(glyph);
+ if (glyph->fMaskFormat == MASK_FORMAT_UNKNOWN) {
+ glyph->fMaskFormat = fRec.fMaskFormat;
+ }
const SkIRect ir = devPath.getBounds().roundOut();
if (ir.isEmpty() || !SkRectPriv::Is16Bit(ir)) {
@@ -94,7 +103,7 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
glyph->fHeight = SkToU16(ir.height());
if (glyph->fWidth > 0) {
- switch (fRec.fMaskFormat) {
+ switch (glyph->fMaskFormat) {
case SkMask::kLCD16_Format:
glyph->fWidth += 2;
glyph->fLeft -= 1;
@@ -116,10 +125,6 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
return;
}
- if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
- glyph->fMaskFormat = fRec.fMaskFormat;
- }
-
// If we are going to create the mask, then we cannot keep the color
if (generatingImageFromPath && SkMask::kARGB32_Format == glyph->fMaskFormat) {
glyph->fMaskFormat = SkMask::kA8_Format;
diff --git a/tools/fonts/SkRandomScalerContext.cpp b/tools/fonts/SkRandomScalerContext.cpp
index feeca48073..2d472129a1 100644
--- a/tools/fonts/SkRandomScalerContext.cpp
+++ b/tools/fonts/SkRandomScalerContext.cpp
@@ -43,8 +43,10 @@ SkRandomScalerContext::SkRandomScalerContext(sk_sp<SkRandomTypeface> face,
const SkDescriptor* desc,
bool fakeIt)
: SkScalerContext(std::move(face), effects, desc)
- , fFakeIt(fakeIt) {
- fProxy = this->getRandomTypeface()->proxy()->createScalerContext(effects, desc);
+ , fProxy(getRandomTypeface()->proxy()->createScalerContext(SkScalerContextEffects(), desc))
+ , fFakeIt(fakeIt)
+{
+ fProxy->forceGenerateImageFromPath();
}
unsigned SkRandomScalerContext::generateGlyphCount() {
@@ -61,118 +63,77 @@ void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
// Here we will change the mask format of the glyph
- // NOTE this is being overridden by the base class
- SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
+ // NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
switch (glyph->getGlyphID() % 4) {
- case 0:
- format = SkMask::kLCD16_Format;
- break;
- case 1:
- format = SkMask::kA8_Format;
- break;
- case 2:
- format = SkMask::kARGB32_Format;
- break;
- case 3:
- format = SkMask::kBW_Format;
- break;
+ case 0: glyph->fMaskFormat = SkMask::kLCD16_Format; break;
+ case 1: glyph->fMaskFormat = SkMask::kA8_Format; break;
+ case 2: glyph->fMaskFormat = SkMask::kARGB32_Format; break;
+ case 3: glyph->fMaskFormat = SkMask::kBW_Format; break;
}
fProxy->getMetrics(glyph);
- glyph->fMaskFormat = format;
- if (fFakeIt) {
+ if (fFakeIt || (glyph->getGlyphID() % 4) != 2) {
return;
}
- if (SkMask::kARGB32_Format == format) {
- SkPath path;
- sk_ignore_unused_variable(fProxy->getPath(glyph->getPackedID(), &path));
-
- SkRect storage;
- const SkPaint& paint = this->getRandomTypeface()->paint();
- const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
- &storage,
- SkPaint::kFill_Style);
- SkIRect ibounds;
- newBounds.roundOut(&ibounds);
- glyph->fLeft = ibounds.fLeft;
- glyph->fTop = ibounds.fTop;
- glyph->fWidth = ibounds.width();
- glyph->fHeight = ibounds.height();
- } else {
- SkPath devPath;
- this->internalGetPath(glyph->getPackedID(), &devPath);
-
- // just use devPath
- const SkIRect ir = devPath.getBounds().roundOut();
-
- if (ir.isEmpty() || !SkRectPriv::Is16Bit(ir)) {
- glyph->fLeft = 0;
- glyph->fTop = 0;
- glyph->fWidth = 0;
- glyph->fHeight = 0;
- return;
- }
- glyph->fLeft = ir.fLeft;
- glyph->fTop = ir.fTop;
- glyph->fWidth = SkToU16(ir.width());
- glyph->fHeight = SkToU16(ir.height());
-
- if (glyph->fWidth > 0) {
- switch (glyph->fMaskFormat) {
- case SkMask::kLCD16_Format:
- glyph->fWidth += 2;
- glyph->fLeft -= 1;
- break;
- default:
- break;
- }
- }
+
+ SkPath path;
+ if (!fProxy->getPath(glyph->getPackedID(), &path)) {
+ return;
}
+ glyph->fMaskFormat = SkMask::kARGB32_Format;
+
+ SkRect storage;
+ const SkPaint& paint = this->getRandomTypeface()->paint();
+ const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
+ &storage,
+ SkPaint::kFill_Style);
+ SkIRect ibounds;
+ newBounds.roundOut(&ibounds);
+ glyph->fLeft = ibounds.fLeft;
+ glyph->fTop = ibounds.fTop;
+ glyph->fWidth = ibounds.width();
+ glyph->fHeight = ibounds.height();
}
void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
+ // TODO: can force down but not up
+ /*
SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
switch (glyph.getGlyphID() % 4) {
- case 0:
- format = SkMask::kLCD16_Format;
- break;
- case 1:
- format = SkMask::kA8_Format;
- break;
- case 2:
- format = SkMask::kARGB32_Format;
- break;
- case 3:
- format = SkMask::kBW_Format;
- break;
+ case 0: format = SkMask::kLCD16_Format; break;
+ case 1: format = SkMask::kA8_Format; break;
+ case 2: format = SkMask::kARGB32_Format; break;
+ case 3: format = SkMask::kBW_Format; break;
}
const_cast<SkGlyph&>(glyph).fMaskFormat = format;
+ */
- // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force
- // our proxy context to generate the image from paths.
- if (!fFakeIt) {
- if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
- SkPath path;
- sk_ignore_unused_variable(fProxy->getPath(glyph.getPackedID(), &path));
-
- SkBitmap bm;
- bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
- glyph.fImage, glyph.rowBytes());
- bm.eraseColor(0);
-
- SkCanvas canvas(bm);
- canvas.translate(-SkIntToScalar(glyph.fLeft),
- -SkIntToScalar(glyph.fTop));
- canvas.drawPath(path, this->getRandomTypeface()->paint());
- } else {
- fProxy->forceGenerateImageFromPath();
- fProxy->getImage(glyph);
- fProxy->forceOffGenerateImageFromPath();
- }
- } else {
+ if (fFakeIt) {
sk_bzero(glyph.fImage, glyph.computeImageSize());
+ return;
+ }
+
+ if (SkMask::kARGB32_Format != glyph.fMaskFormat) {
+ fProxy->getImage(glyph);
+ return;
+ }
+
+ // If the format is ARGB, just draw the glyph from path.
+ SkPath path;
+ if (!fProxy->getPath(glyph.getPackedID(), &path)) {
+ fProxy->getImage(glyph);
+ return;
}
+
+ SkBitmap bm;
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
+ bm.eraseColor(0);
+
+ SkCanvas canvas(bm);
+ canvas.translate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
+ canvas.drawPath(path, this->getRandomTypeface()->paint());
}
bool SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
@@ -185,8 +146,6 @@ void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
///////////////////////////////////////////////////////////////////////////////
-#include "SkTypefaceCache.h"
-
SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
: SkTypeface(proxy->fontStyle(), false)
, fProxy(std::move(proxy))
@@ -213,8 +172,9 @@ SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
return fProxy->openStream(ttcIndex);
}
-void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
- bool* isLocal) const {
+void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
+ // TODO: anything that uses this typeface isn't correctly serializable, since this typeface
+ // cannot be deserialized.
fProxy->getFontDescriptor(desc, isLocal);
}