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:
parent
8baaef9f54
commit
c65b65dd81
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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[],
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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*,
|
||||
|
Loading…
Reference in New Issue
Block a user