aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2018-01-16 16:26:35 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-17 15:45:36 +0000
commitc65b65dd816b7a9fbd148f577f0271cd555c4df6 (patch)
treebd6e4ed33675f28f7a478bdc53002d4e8b4413b3
parent8baaef9f542597fe786df5f9884830376f691fd6 (diff)
Support scaled color emojis for SDF fallback
This patch enables scaling for overlarge color emojis when trying to render with SDFs, i.e. between 162 and 324 point in normal text rendering mode. Also ensures that we only try to render blobs with bitmap/SDF when the text size will fit in the atlas. Bug: skia: Change-Id: Ib675d99ef22bf66368dc8737ef63db4a5d3d5a9f Reviewed-on: https://skia-review.googlesource.com/94361 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r--include/core/SkPaint.h4
-rw-r--r--src/core/SkDraw.cpp4
-rw-r--r--src/core/SkDraw.h2
-rw-r--r--src/core/SkPaint.cpp8
-rw-r--r--src/gpu/text/GrAtlasGlyphCache.cpp2
-rw-r--r--src/gpu/text/GrAtlasGlyphCache.h3
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp79
-rw-r--r--src/gpu/text/GrAtlasTextContext.h6
8 files changed, 80 insertions, 28 deletions
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 812c885bee..94a7f407e0 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -1762,14 +1762,14 @@ private:
kCanonicalTextSizeForPaths = 64,
};
- static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM);
+ static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);
// Set flags/hinting/textSize up to use for drawing text as paths.
// Returns scale factor to restore the original textSize, since will will
// have change it to kCanonicalTextSizeForPaths.
SkScalar setupForAsPaths();
- static SkScalar MaxCacheSize2();
+ static SkScalar MaxCacheSize2(SkScalar maxLimit);
friend class SkAutoGlyphCache;
friend class SkAutoGlyphCacheNoGamma;
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 5068fb0151..a0f08e5916 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1353,7 +1353,7 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& ori
#include "SkTextToPathIter.h"
#include "SkUtils.h"
-bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
+bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm, SkScalar sizeLimit) {
// hairline glyphs are fast enough so we don't need to cache them
if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
return true;
@@ -1366,7 +1366,7 @@ bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
SkMatrix textM;
SkPaintPriv::MakeTextMatrix(&textM, paint);
- return SkPaint::TooBigToUseCache(ctm, textM);
+ return SkPaint::TooBigToUseCache(ctm, textM, sizeLimit);
}
void SkDraw::drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y,
diff --git a/src/core/SkDraw.h b/src/core/SkDraw.h
index 524f300e42..0561eab2ec 100644
--- a/src/core/SkDraw.h
+++ b/src/core/SkDraw.h
@@ -114,7 +114,7 @@ public:
static RectType ComputeRectType(const SkPaint&, const SkMatrix&,
SkPoint* strokeSize);
- static bool ShouldDrawTextAsPaths(const SkPaint&, const SkMatrix&);
+ static bool ShouldDrawTextAsPaths(const SkPaint&, const SkMatrix&, SkScalar sizeLimit = 1024);
void drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y,
const SkPaint&) const;
void drawPosText_asPaths(const char text[], size_t byteLength, const SkScalar pos[],
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 0987c640c1..d659b41410 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -384,18 +384,18 @@ static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
}
-bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
+bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit) {
SkASSERT(!ctm.hasPerspective());
SkASSERT(!textM.hasPerspective());
SkMatrix matrix;
matrix.setConcat(ctm, textM);
- return tooBig(matrix, MaxCacheSize2());
+ return tooBig(matrix, MaxCacheSize2(maxLimit));
}
-SkScalar SkPaint::MaxCacheSize2() {
+SkScalar SkPaint::MaxCacheSize2(SkScalar maxLimit) {
// we have a self-imposed maximum, just for memory-usage sanity
- const int limit = SkMin32(SkGraphics::GetFontCachePointSizeLimit(), 1024);
+ const int limit = SkMin32(SkGraphics::GetFontCachePointSizeLimit(), maxLimit);
const SkScalar maxSize = SkIntToScalar(limit);
return maxSize * maxSize;
}
diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp
index 421160f28f..edc751ec95 100644
--- a/src/gpu/text/GrAtlasGlyphCache.cpp
+++ b/src/gpu/text/GrAtlasGlyphCache.cpp
@@ -72,6 +72,8 @@ GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim;
fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot;
fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot;
+
+ fGlyphSizeLimit = minPlot;
}
GrAtlasGlyphCache::~GrAtlasGlyphCache() {
diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h
index 223ed6e69f..c4e1528e7b 100644
--- a/src/gpu/text/GrAtlasGlyphCache.h
+++ b/src/gpu/text/GrAtlasGlyphCache.h
@@ -144,6 +144,8 @@ public:
return 0;
}
+ SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
+
bool hasGlyph(GrGlyph* glyph) {
SkASSERT(glyph);
return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
@@ -261,6 +263,7 @@ private:
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrAtlasTextStrike* fPreserveStrike;
GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
+ SkScalar fGlyphSizeLimit;
};
#endif
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 41072ee296..bdbc600cc1 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -12,6 +12,7 @@
#include "SkDrawFilter.h"
#include "SkFindAndPlaceGlyph.h"
#include "SkGr.h"
+#include "SkGraphics.h"
#include "SkMakeUnique.h"
#include "ops/GrMeshDrawOp.h"
@@ -46,12 +47,13 @@ std::unique_ptr<GrAtlasTextContext> GrAtlasTextContext::Make(const Options& opti
return std::unique_ptr<GrAtlasTextContext>(new GrAtlasTextContext(options));
}
-bool GrAtlasTextContext::canDraw(const SkPaint& skPaint,
+bool GrAtlasTextContext::canDraw(const GrAtlasGlyphCache* fontCache,
+ const SkPaint& skPaint,
const SkMatrix& viewMatrix,
const SkSurfaceProps& props,
const GrShaderCaps& shaderCaps) {
return this->canDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps) ||
- !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
+ !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix, fontCache->getGlyphSizeLimit());
}
SkColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd) {
@@ -317,7 +319,8 @@ void GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* targe
return;
}
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
- if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
+ if (this->canDraw(context->getAtlasGlyphCache(), skPaint, viewMatrix, props,
+ *context->caps()->shaderCaps())) {
sk_sp<GrAtlasTextBlob> blob(
this->makeDrawTextBlob(context->getTextBlobCache(), context->getAtlasGlyphCache(),
*context->caps()->shaderCaps(), paint,
@@ -344,7 +347,8 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
if (context->abandoned()) {
return;
- } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shaderCaps())) {
+ } else if (this->canDraw(context->getAtlasGlyphCache(), skPaint, viewMatrix, props,
+ *context->caps()->shaderCaps())) {
sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob(
context->getTextBlobCache(), context->getAtlasGlyphCache(),
*context->caps()->shaderCaps(), paint,
@@ -385,8 +389,8 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
position += rounding;
BmpAppendGlyph(blob, runIndex, fontCache, &currStrike,
- glyph, SkScalarFloorToInt(position.fX),
- SkScalarFloorToInt(position.fY),
+ glyph, SkScalarFloorToScalar(position.fX),
+ SkScalarFloorToScalar(position.fY),
paint.filteredPremulColor(), cache,
SK_Scalar1);
});
@@ -422,7 +426,8 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
position += rounding;
BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph,
- SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY),
+ SkScalarFloorToScalar(position.fX),
+ SkScalarFloorToScalar(position.fY),
paint.filteredPremulColor(), cache, textRatio);
});
@@ -431,8 +436,9 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
GrAtlasGlyphCache* fontCache, GrAtlasTextStrike** strike,
- const SkGlyph& skGlyph, int vx, int vy, GrColor color,
- SkGlyphCache* glyphCache, SkScalar textRatio) {
+ const SkGlyph& skGlyph, SkScalar sx, SkScalar sy,
+ GrColor color, SkGlyphCache* glyphCache,
+ SkScalar textRatio) {
if (!*strike) {
*strike = fontCache->getStrike(glyphCache);
}
@@ -446,12 +452,13 @@ void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
return;
}
+ SkASSERT(skGlyph.fWidth == glyph->width());
+ SkASSERT(skGlyph.fHeight == glyph->height());
+
SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
SkScalar width = SkIntToScalar(glyph->fBounds.width());
SkScalar height = SkIntToScalar(glyph->fBounds.height());
- SkScalar sx = SkIntToScalar(vx);
- SkScalar sy = SkIntToScalar(vy);
dx *= textRatio;
dy *= textRatio;
@@ -651,6 +658,13 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
SkTDArray<char> fallbackTxt;
SkTDArray<SkScalar> fallbackPos;
+ SkTDArray<char> bigFallbackTxt;
+ SkTDArray<SkScalar> bigFallbackPos;
+ SkScalar textSize = paint.skPaint().getTextSize();
+ SkScalar maxTextSize = fontCache->getGlyphSizeLimit();
+ SkScalar bigFallbackTextSize = maxTextSize;
+ SkScalar maxScale = viewMatrix.getMaxScale();
+
bool hasWCoord = viewMatrix.hasPerspective() || fDistanceFieldVerticesAlwaysHaveW;
// Setup distance field paint and text ratio
@@ -689,13 +703,26 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x - advanceX,
- y - advanceY, paint.filteredPremulColor(), cache, textRatio);
+ y - advanceY, paint.filteredPremulColor(), cache, textRatio);
} else {
// can't append color glyph to SDF batch, send to fallback
- fallbackTxt.append(SkToInt(text - lastText), lastText);
- *fallbackPos.append() = pos[0];
- if (2 == scalarsPerPosition) {
- *fallbackPos.append() = pos[1];
+ SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*textRatio;
+ SkScalar scaledGlyphSize = maxDim*maxScale;
+
+ if (!viewMatrix.hasPerspective() && scaledGlyphSize > maxTextSize) {
+ bigFallbackTxt.append(SkToInt(text - lastText), lastText);
+ *bigFallbackPos.append() = maxScale*pos[0];
+ if (2 == scalarsPerPosition) {
+ *bigFallbackPos.append() = maxScale*pos[1];
+ }
+ SkScalar glyphTextSize = SkScalarFloorToScalar(maxTextSize*textSize/maxDim);
+ bigFallbackTextSize = SkTMin(glyphTextSize, bigFallbackTextSize);
+ } else {
+ fallbackTxt.append(SkToInt(text - lastText), lastText);
+ *fallbackPos.append() = pos[0];
+ if (2 == scalarsPerPosition) {
+ *fallbackPos.append() = pos[1];
+ }
}
}
}
@@ -710,6 +737,26 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
fallbackTxt.count(), fallbackPos.begin(),
scalarsPerPosition, offset, SK_Scalar1);
}
+
+ if (bigFallbackTxt.count()) {
+ // Set up paint and matrix to scale glyphs
+ blob->initOverride(runIndex);
+ SkPaint largePaint(paint);
+ largePaint.setTextSize(bigFallbackTextSize);
+ // remove maxScale from viewMatrix and move it into textRatio
+ // this keeps the base glyph size consistent regardless of matrix scale
+ SkMatrix modMatrix(viewMatrix);
+ SkScalar invScale = SkScalarInvert(maxScale);
+ modMatrix.preScale(invScale, invScale);
+ SkScalar bigFallbackTextRatio = textSize*maxScale/bigFallbackTextSize;
+ SkPoint modOffset(offset);
+ modOffset *= maxScale;
+ GrTextUtils::Paint textPaint(&largePaint, paint.dstColorSpaceInfo());
+ GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, textPaint,
+ scalerContextFlags, modMatrix, bigFallbackTxt.begin(),
+ bigFallbackTxt.count(), bigFallbackPos.begin(),
+ scalarsPerPosition, modOffset, bigFallbackTextRatio);
+ }
}
// TODO: merge with BmpAppendGlyph
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index 9c44128f52..b03ffa3fbf 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -44,8 +44,8 @@ public:
static std::unique_ptr<GrAtlasTextContext> Make(const Options& options);
- bool canDraw(const SkPaint&, const SkMatrix& viewMatrix, const SkSurfaceProps&,
- const GrShaderCaps&);
+ bool canDraw(const GrAtlasGlyphCache* fontCache, const SkPaint&, const SkMatrix& viewMatrix,
+ const SkSurfaceProps&, const GrShaderCaps&);
void drawText(GrContext*, GrTextUtils::Target*, const GrClip&, const SkPaint&,
const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
@@ -131,7 +131,7 @@ private:
const SkMatrix& viewMatrix) const;
static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
- GrAtlasTextStrike**, const SkGlyph&, int left, int top,
+ GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy,
GrColor color, SkGlyphCache*, SkScalar textRatio);
static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,