diff options
Diffstat (limited to 'src/gpu/text/GrTextContext.cpp')
-rw-r--r-- | src/gpu/text/GrTextContext.cpp | 121 |
1 files changed, 117 insertions, 4 deletions
diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index d57055a511..4631991985 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -196,12 +196,10 @@ void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, } cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags()); - SkASSERT(it.positioning() == SkTextBlobRunIterator::kFull_Positioning); if (CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), fOptions)) { - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*)it.glyphs(), - textLen, it.pos(), 2, origin); + this->drawDFGlyphRun(cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, it.glyphRun(), origin); } else { DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, @@ -577,6 +575,50 @@ void GrTextContext::drawDFPosText(GrTextBlob* blob, int runIndex, fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, paint, scalerContextFlags); } +void GrTextContext::drawDFGlyphRun(GrTextBlob* blob, int runIndex, + GrGlyphCache* glyphCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, + SkScalerContextFlags scalerContextFlags, + const SkMatrix& viewMatrix, const SkGlyphRun& glyphRun, + const SkPoint& offset) const { + bool hasWCoord = viewMatrix.hasPerspective() || fOptions.fDistanceFieldVerticesAlwaysHaveW; + + // Setup distance field paint and text ratio + SkScalar textRatio; + SkPaint dfPaint(paint); + SkScalerContextFlags flags; + InitDistanceFieldPaint(blob, &dfPaint, viewMatrix, fOptions, &textRatio, &flags); + blob->setHasDistanceField(); + blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), + paint.skPaint().isAntiAlias(), hasWCoord); + + FallbackGlyphRunHelper fallbackTextHelper(viewMatrix, paint, glyphCache->getGlyphSizeLimit(), + textRatio); + + sk_sp<GrTextStrike> currStrike; + + { + auto cache = blob->setupCache(runIndex, props, flags, dfPaint, nullptr); + + const SkPoint* positionCursor = glyphRun.positions().data(); + for (auto glyphID : glyphRun.shuntGlyphsIDs()) { + const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID); + SkPoint glyphPos = offset + *positionCursor++; + if (glyph.fWidth > 0) { + if (glyph.fMaskFormat == SkMask::kSDF_Format) { + DfAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, glyphPos.fX, + glyphPos.fY, paint.filteredPremulColor(), cache.get(), textRatio); + } else { + // can't append non-SDF glyph to SDF batch, send to fallback + fallbackTextHelper.appendText(glyph, glyphID, glyphPos); + } + } + } + } + + fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, paint, scalerContextFlags); +} + // TODO: merge with BmpAppendGlyph void GrTextContext::DfAppendGlyph(GrTextBlob* blob, int runIndex, GrGlyphCache* grGlyphCache, sk_sp<GrTextStrike>* strike, @@ -689,6 +731,77 @@ void GrTextContext::FallbackTextHelper::initializeForDraw(SkPaint* paint, SkScal /////////////////////////////////////////////////////////////////////////////////////////////////// +void GrTextContext::FallbackGlyphRunHelper::appendText( + const SkGlyph& glyph, SkGlyphID glyphID, SkPoint glyphPos) { + SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio; + if (SkScalarNearlyZero(maxDim)) return; + + if (!fUseTransformedFallback) { + if (!fViewMatrix.isScaleTranslate() || maxDim*fMaxScale > fMaxTextSize) { + fUseTransformedFallback = true; + fMaxTextSize -= 2; // Subtract 2 to account for the bilerp pad around the glyph + } + } + + fFallbackTxt.push_back(glyphID); + if (fUseTransformedFallback) { + // If there's a glyph in the font that's particularly large, it's possible + // that fScaledFallbackTextSize may end up minimizing too much. We'd rather skip + // that glyph than make the others blurry, so we set a minimum size of half the + // maximum text size to avoid this case. + SkScalar glyphTextSize = + SkTMax(SkScalarFloorToScalar(fTextSize * fMaxTextSize/maxDim), 0.5f*fMaxTextSize); + fTransformedFallbackTextSize = SkTMin(glyphTextSize, fTransformedFallbackTextSize); + } + fFallbackPos.push_back(glyphPos); +} + +void GrTextContext::FallbackGlyphRunHelper::drawText( + GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags) { + if (!fFallbackTxt.empty()) { + blob->initOverride(runIndex); + blob->setHasBitmap(); + blob->setSubRunHasW(runIndex, fViewMatrix.hasPerspective()); + const SkPaint& skPaint = paint.skPaint(); + SkColor textColor = paint.filteredPremulColor(); + + SkScalar textRatio = SK_Scalar1; + SkPaint fallbackPaint(skPaint); + SkMatrix matrix = fViewMatrix; + this->initializeForDraw(&fallbackPaint, &textRatio, &matrix); + SkExclusiveStrikePtr cache = + blob->setupCache(runIndex, props, scalerContextFlags, fallbackPaint, &matrix); + + sk_sp<GrTextStrike> currStrike; + auto glyphPos = fFallbackPos.begin(); + for (auto glyphID : fFallbackTxt) { + const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID); + if (!fUseTransformedFallback) { + fViewMatrix.mapPoints(&*glyphPos, 1); + glyphPos->fX = SkScalarFloorToScalar(glyphPos->fX); + glyphPos->fY = SkScalarFloorToScalar(glyphPos->fY); + } + GrTextContext::BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, + glyphPos->fX, glyphPos->fY, textColor, + cache.get(), textRatio, fUseTransformedFallback); + glyphPos++; + } + } +} + +void GrTextContext::FallbackGlyphRunHelper::initializeForDraw( + SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const { + if (!fUseTransformedFallback) return; + + paint->setTextSize(fTransformedFallbackTextSize); + *textRatio = fTextSize / fTransformedFallbackTextSize; + *matrix = SkMatrix::I(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + + #if GR_TEST_UTILS #include "GrRenderTargetContext.h" |