Check that mask to path fallback happens
BUG=chromium:876767
Change-Id: I6aadf329af836a1e03aa85b34a58830be00ff750
Reviewed-on: https://skia-review.googlesource.com/150135
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Khusal Sagar <khushalsagar@chromium.org>
diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp
index dc79fc3..30d30dc 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -765,7 +765,7 @@
if (glyph.fWidth > 0) {
if (glyph.fMaskFormat == SkMask::kSDF_Format) {
- if (glyph_too_big_for_atlas(glyph)) {
+ if (SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
SkRect glyphRect =
rect_to_draw(glyph, glyphPos, textRatio, true);
if (!glyphRect.isEmpty()) {
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index 3cfee0f..04339ac 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -76,6 +76,12 @@
return {lookupX, lookupY};
}
+
+ static constexpr uint16_t kSkSideTooBigForAtlas = 256;
+
+ inline static bool GlyphTooBigForAtlas(const SkGlyph& glyph) {
+ return glyph.fWidth > kSkSideTooBigForAtlas || glyph.fHeight > kSkSideTooBigForAtlas;
+ }
};
class SkGlyphRun {
@@ -343,10 +349,6 @@
}
}
-inline static bool glyph_too_big_for_atlas(const SkGlyph& glyph) {
- return glyph.fWidth > 256 || glyph.fHeight > 256;
-}
-
inline static SkRect rect_to_draw(
const SkGlyph& glyph, SkPoint origin, SkScalar textScale, bool isDFT) {
@@ -406,7 +408,7 @@
auto eachGlyph =
[perGlyph{std::move(perGlyph)}, perPath{std::move(perPath)}]
(const SkGlyph& glyph, SkPoint pt, SkPoint mappedPt) {
- if (glyph_too_big_for_atlas(glyph)) {
+ if (SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
SkScalar sx = SkScalarFloorToScalar(mappedPt.fX),
sy = SkScalarFloorToScalar(mappedPt.fY);
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index c23e9a5..8a2fc0d 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "Resources.h"
#include "SkDraw.h"
#include "SkGraphics.h"
#include "SkMutex.h"
@@ -350,6 +351,85 @@
discardableManager->unlockAndDeleteAll();
}
+sk_sp<SkTextBlob> make_blob_causing_fallback(
+ sk_sp<SkTypeface> targetTf, const SkTypeface* glyphTf, skiatest::Reporter* reporter) {
+ SkPaint paint;
+ paint.setSubpixelText(true);
+ paint.setTextSize(96);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setTextAlign(SkPaint::kLeft_Align);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setHinting(SkPaint::kNormal_Hinting);
+
+ paint.setTypeface(targetTf);
+
+ REPORTER_ASSERT(reporter, !SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I()));
+
+ char s[] = "Skia";
+ int runSize = strlen(s);
+
+ SkTextBlobBuilder builder;
+ SkRect bounds = SkRect::MakeIWH(100, 100);
+ const auto& runBuffer = builder.allocRunPosH(paint, runSize, 10, &bounds);
+ SkASSERT(runBuffer.utf8text == nullptr);
+ SkASSERT(runBuffer.clusters == nullptr);
+
+ glyphTf->charsToGlyphs(s, SkTypeface::kUTF8_Encoding, runBuffer.glyphs, runSize);
+
+ SkRect glyphBounds;
+ paint.measureText(runBuffer.glyphs, 2, &glyphBounds);
+
+ REPORTER_ASSERT(reporter, glyphBounds.width() > SkGlyphCacheCommon::kSkSideTooBigForAtlas);
+
+ for (int i = 0; i < runSize; i++) {
+ runBuffer.pos[i] = i * 10;
+ }
+
+ return builder.make();
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFallback,
+ reporter, ctxInfo) {
+ sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
+ SkStrikeServer server(discardableManager.get());
+ SkStrikeClient client(discardableManager, false);
+
+ SkPaint paint;
+
+ auto serverTf = MakeResourceAsTypeface("fonts/HangingS.ttf");
+ // TODO: when the cq bots can handle this font remove the check.
+ if (serverTf == nullptr) {
+ return;
+ }
+ auto serverTfData = server.serializeTypeface(serverTf.get());
+
+ auto serverBlob = make_blob_causing_fallback(serverTf, serverTf.get(), reporter);
+
+ const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);
+ SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server,
+ MakeSettings(ctxInfo.grContext()));
+ cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
+
+ std::vector<uint8_t> serverStrikeData;
+ server.writeStrikeData(&serverStrikeData);
+
+ // Client.
+ auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
+ REPORTER_ASSERT(reporter,
+ client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
+
+ auto clientBlob = make_blob_causing_fallback(clientTf, serverTf.get(), reporter);
+
+ SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext());
+ SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext());
+ compare_blobs(expected, actual, reporter);
+ REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
+ SkStrikeCache::ValidateGlyphCacheDataSize();
+
+ // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
+ discardableManager->unlockAndDeleteAll();
+}
+
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxInfo) {
sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
SkStrikeServer server(discardableManager.get());