diff options
-rw-r--r-- | gm/textblobrandomfont.cpp | 85 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 15 | ||||
-rw-r--r-- | tools/fonts/SkRandomScalerContext.cpp | 160 |
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); } |