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>
This commit is contained in:
Jim Van Verth 2018-01-16 16:26:35 -05:00 committed by Skia Commit-Bot
parent 8baaef9f54
commit c65b65dd81
8 changed files with 80 additions and 28 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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[],

View File

@ -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;
}

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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*,