diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.cpp | 485 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.h | 42 | ||||
-rw-r--r-- | src/gpu/text/GrTextUtils.cpp | 458 | ||||
-rw-r--r-- | src/gpu/text/GrTextUtils.h | 68 |
4 files changed, 517 insertions, 536 deletions
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index e5a8745fe1..40294a289f 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -7,8 +7,10 @@ #include "GrAtlasTextContext.h" #include "GrContext.h" #include "GrTextBlobCache.h" +#include "SkDistanceFieldGen.h" #include "SkDraw.h" #include "SkDrawFilter.h" +#include "SkFindAndPlaceGlyph.h" #include "SkGr.h" #include "ops/GrMeshDrawOp.h" @@ -24,7 +26,7 @@ bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, const GrShaderCaps& shaderCaps) { - return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps) || + return CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderCaps) || !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); } @@ -178,27 +180,26 @@ void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob, if (!runPaint.modifyForRun(it)) { continue; } - if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) { + if (CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: { - GrTextUtils::DrawDFText(cacheBlob, run, fontCache, props, runPaint, - scalerContextFlags, viewMatrix, - (const char*)it.glyphs(), textLen, x + offset.x(), - y + offset.y()); + DrawDFText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), + y + offset.y()); break; } case SkTextBlob::kHorizontal_Positioning: { SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); - GrTextUtils::DrawDFPosText( - cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, - viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, dfOffset); + DrawDFPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, + dfOffset); break; } case SkTextBlob::kFull_Positioning: { SkPoint dfOffset = SkPoint::Make(x, y); - GrTextUtils::DrawDFPosText( - cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, - viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, dfOffset); + DrawDFPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, + dfOffset); break; } } @@ -207,22 +208,19 @@ void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob, } else { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: - GrTextUtils::DrawBmpText(cacheBlob, run, fontCache, props, runPaint, - scalerContextFlags, viewMatrix, - (const char*)it.glyphs(), textLen, x + offset.x(), - y + offset.y()); + DrawBmpText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), + y + offset.y()); break; case SkTextBlob::kHorizontal_Positioning: - GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, - scalerContextFlags, viewMatrix, - (const char*)it.glyphs(), textLen, it.pos(), 1, - SkPoint::Make(x, y + offset.y())); + DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, + SkPoint::Make(x, y + offset.y())); break; case SkTextBlob::kFull_Positioning: - GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, - scalerContextFlags, viewMatrix, - (const char*)it.glyphs(), textLen, it.pos(), 2, - SkPoint::Make(x, y)); + DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, + SkPoint::Make(x, y)); break; } } @@ -246,12 +244,12 @@ GrAtlasTextContext::MakeDrawTextBlob(GrTextBlobCache* blobCache, sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1); blob->initThrowawayBlob(viewMatrix, x, y); - if (GrTextUtils::CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { - GrTextUtils::DrawDFText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, - viewMatrix, text, byteLength, x, y); + if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { + DrawDFText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, x, y); } else { - GrTextUtils::DrawBmpText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, - viewMatrix, text, byteLength, x, y); + DrawBmpText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, x, y); } return blob; } @@ -275,12 +273,12 @@ GrAtlasTextContext::MakeDrawPosTextBlob(GrTextBlobCache* blobCache, sk_sp<GrAtlasTextBlob> blob = blobCache->makeBlob(glyphCount, 1); blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); - if (GrTextUtils::CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { - GrTextUtils::DrawDFPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, - viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); + if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { + DrawDFPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, pos, scalarsPerPosition, offset); } else { - GrTextUtils::DrawBmpPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, - viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); + DrawBmpPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, pos, scalarsPerPosition, offset); } return blob; } @@ -339,6 +337,425 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta byteLength, pos, scalarsPerPosition, offset, regionClipBounds); } +void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, uint32_t scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y) { + SkASSERT(byteLength == 0 || text != nullptr); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // Ensure the blob is set for bitmaptext + blob->setHasBitmap(); + + GrAtlasTextStrike* currStrike = nullptr; + + SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); + SkFindAndPlaceGlyph::ProcessText(paint.skPaint().getTextEncoding(), text, byteLength, {x, y}, + viewMatrix, paint.skPaint().getTextAlign(), cache, + [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { + position += rounding; + BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, + glyph, SkScalarFloorToInt(position.fX), + SkScalarFloorToInt(position.fY), + paint.filteredPremulColor(), cache); + }); + + SkGlyphCache::AttachCache(cache); +} + +void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, + uint32_t scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, const SkScalar pos[], + int scalarsPerPosition, const SkPoint& offset) { + SkASSERT(byteLength == 0 || text != nullptr); + SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + // Ensure the blob is set for bitmaptext + blob->setHasBitmap(); + + GrAtlasTextStrike* currStrike = nullptr; + + SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); + + SkFindAndPlaceGlyph::ProcessPosText( + paint.skPaint().getTextEncoding(), text, byteLength, offset, viewMatrix, pos, + scalarsPerPosition, paint.skPaint().getTextAlign(), cache, + [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { + position += rounding; + BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, + SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), + paint.filteredPremulColor(), cache); + }); + + SkGlyphCache::AttachCache(cache); +} + +void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, GrAtlasTextStrike** strike, + const SkGlyph& skGlyph, int vx, int vy, GrColor color, + SkGlyphCache* cache) { + if (!*strike) { + *strike = fontCache->getStrike(cache); + } + + GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), + skGlyph.getSubXFixed(), + skGlyph.getSubYFixed(), + GrGlyph::kCoverage_MaskStyle); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, cache); + if (!glyph) { + return; + } + + int x = vx + glyph->fBounds.fLeft; + int y = vy + glyph->fBounds.fTop; + + int width = glyph->fBounds.width(); + int height = glyph->fBounds.height(); + + SkRect r; + r.fLeft = SkIntToScalar(x); + r.fTop = SkIntToScalar(y); + r.fRight = r.fLeft + SkIntToScalar(width); + r.fBottom = r.fTop + SkIntToScalar(height); + + blob->appendGlyph(runIndex, r, color, *strike, glyph, cache, skGlyph, SkIntToScalar(vx), + SkIntToScalar(vy), 1.0f, true); +} + +static const int kMinDFFontSize = 18; +static const int kSmallDFFontSize = 32; +static const int kSmallDFFontLimit = 32; +static const int kMediumDFFontSize = 72; +static const int kMediumDFFontLimit = 72; +static const int kLargeDFFontSize = 162; +#ifdef SK_BUILD_FOR_ANDROID +static const int kLargeDFFontLimit = 384; +#else +static const int kLargeDFFontLimit = 2 * kLargeDFFontSize; +#endif + +bool GrAtlasTextContext::CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, + const SkSurfaceProps& props, + const GrShaderCaps& caps) { + if (!viewMatrix.hasPerspective()) { + SkScalar maxScale = viewMatrix.getMaxScale(); + SkScalar scaledTextSize = maxScale * skPaint.getTextSize(); + // Hinted text looks far better at small resolutions + // Scaling up beyond 2x yields undesireable artifacts + if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) { + return false; + } + + bool useDFT = props.isUseDeviceIndependentFonts(); +#if SK_FORCE_DISTANCE_FIELD_TEXT + useDFT = true; +#endif + + if (!useDFT && scaledTextSize < kLargeDFFontSize) { + return false; + } + } + + // rasterizers and mask filters modify alpha, which doesn't + // translate well to distance + if (skPaint.getRasterizer() || skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { + return false; + } + + // TODO: add some stroking support + if (skPaint.getStyle() != SkPaint::kFill_Style) { + return false; + } + + return true; +} + +void GrAtlasTextContext::InitDistanceFieldPaint(GrAtlasTextBlob* blob, + SkPaint* skPaint, + SkScalar* textRatio, + const SkMatrix& viewMatrix) { + SkScalar textSize = skPaint->getTextSize(); + SkScalar scaledTextSize = textSize; + + if (viewMatrix.hasPerspective()) { + // for perspective, we simply force to the medium size + // TODO: compute a size based on approximate screen area + scaledTextSize = kMediumDFFontLimit; + } else { + SkScalar maxScale = viewMatrix.getMaxScale(); + // if we have non-unity scale, we need to choose our base text size + // based on the SkPaint's text size multiplied by the max scale factor + // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? + if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { + scaledTextSize *= maxScale; + } + } + + // We have three sizes of distance field text, and within each size 'bucket' there is a floor + // and ceiling. A scale outside of this range would require regenerating the distance fields + SkScalar dfMaskScaleFloor; + SkScalar dfMaskScaleCeil; + if (scaledTextSize <= kSmallDFFontLimit) { + dfMaskScaleFloor = kMinDFFontSize; + dfMaskScaleCeil = kSmallDFFontLimit; + *textRatio = textSize / kSmallDFFontSize; + skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); + } else if (scaledTextSize <= kMediumDFFontLimit) { + dfMaskScaleFloor = kSmallDFFontLimit; + dfMaskScaleCeil = kMediumDFFontLimit; + *textRatio = textSize / kMediumDFFontSize; + skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); + } else { + dfMaskScaleFloor = kMediumDFFontLimit; + dfMaskScaleCeil = kLargeDFFontLimit; + *textRatio = textSize / kLargeDFFontSize; + skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); + } + + // Because there can be multiple runs in the blob, we want the overall maxMinScale, and + // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale + // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can + // tolerate before we'd have to move to a large mip size. When we actually test these values + // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test + // against these values to decide if we can reuse or not(ie, will a given scale change our mip + // level) + SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); + blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); + + skPaint->setAntiAlias(true); + skPaint->setLCDRenderText(false); + skPaint->setAutohinted(false); + skPaint->setHinting(SkPaint::kNormal_Hinting); + skPaint->setSubpixelText(true); +} + +void GrAtlasTextContext::DrawDFText(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, uint32_t scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y) { + SkASSERT(byteLength == 0 || text != nullptr); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + const SkPaint& skPaint = paint.skPaint(); + SkPaint::GlyphCacheProc glyphCacheProc = + SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), skPaint.isDevKernText(), true); + SkAutoDescriptor desc; + SkScalerContextEffects effects; + // We apply the fake-gamma by altering the distance in the shader, so we ignore the + // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). + skPaint.getScalerContextDescriptor(&effects, &desc, props, SkPaint::kNone_ScalerContextFlags, + nullptr); + SkGlyphCache* origPaintCache = + SkGlyphCache::DetachCache(skPaint.getTypeface(), effects, desc.getDesc()); + + SkTArray<SkScalar> positions; + + const char* textPtr = text; + SkScalar stopX = 0; + SkScalar stopY = 0; + SkScalar origin = 0; + switch (skPaint.getTextAlign()) { + case SkPaint::kRight_Align: origin = SK_Scalar1; break; + case SkPaint::kCenter_Align: origin = SK_ScalarHalf; break; + case SkPaint::kLeft_Align: origin = 0; break; + } + + SkAutoKern autokern; + const char* stop = text + byteLength; + while (textPtr < stop) { + // don't need x, y here, since all subpixel variants will have the + // same advance + const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr); + + SkScalar width = SkFloatToScalar(glyph.fAdvanceX) + autokern.adjust(glyph); + positions.push_back(stopX + origin * width); + + SkScalar height = SkFloatToScalar(glyph.fAdvanceY); + positions.push_back(stopY + origin * height); + + stopX += width; + stopY += height; + } + SkASSERT(textPtr == stop); + + SkGlyphCache::AttachCache(origPaintCache); + + // now adjust starting point depending on alignment + SkScalar alignX = stopX; + SkScalar alignY = stopY; + if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { + alignX = SkScalarHalf(alignX); + alignY = SkScalarHalf(alignY); + } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) { + alignX = 0; + alignY = 0; + } + x -= alignX; + y -= alignY; + SkPoint offset = SkPoint::Make(x, y); + + DrawDFPosText(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, positions.begin(), 2, offset); +} + +void GrAtlasTextContext::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, uint32_t scalerContextFlags, + const SkMatrix& viewMatrix, const char text[], + size_t byteLength, const SkScalar pos[], + int scalarsPerPosition, const SkPoint& offset) { + SkASSERT(byteLength == 0 || text != nullptr); + SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); + + // nothing to draw + if (text == nullptr || byteLength == 0) { + return; + } + + SkTDArray<char> fallbackTxt; + SkTDArray<SkScalar> fallbackPos; + + // Setup distance field paint and text ratio + SkScalar textRatio; + SkPaint dfPaint(paint); + GrAtlasTextContext::InitDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); + blob->setHasDistanceField(); + blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), + paint.skPaint().isAntiAlias()); + + GrAtlasTextStrike* currStrike = nullptr; + + // We apply the fake-gamma by altering the distance in the shader, so we ignore the + // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). + SkGlyphCache* cache = + blob->setupCache(runIndex, props, SkPaint::kNone_ScalerContextFlags, dfPaint, nullptr); + SkPaint::GlyphCacheProc glyphCacheProc = + SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), dfPaint.isDevKernText(), true); + + const char* stop = text + byteLength; + + if (SkPaint::kLeft_Align == dfPaint.getTextAlign()) { + while (text < stop) { + const char* lastText = text; + // the last 2 parameters are ignored + const SkGlyph& glyph = glyphCacheProc(cache, &text); + + if (glyph.fWidth) { + SkScalar x = offset.x() + pos[0]; + SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); + + if (!DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x, y, + paint.filteredPremulColor(), cache, textRatio, viewMatrix)) { + // couldn't append, send to fallback + fallbackTxt.append(SkToInt(text - lastText), lastText); + *fallbackPos.append() = pos[0]; + if (2 == scalarsPerPosition) { + *fallbackPos.append() = pos[1]; + } + } + } + pos += scalarsPerPosition; + } + } else { + SkScalar alignMul = + SkPaint::kCenter_Align == dfPaint.getTextAlign() ? SK_ScalarHalf : SK_Scalar1; + while (text < stop) { + const char* lastText = text; + // the last 2 parameters are ignored + const SkGlyph& glyph = glyphCacheProc(cache, &text); + + if (glyph.fWidth) { + SkScalar x = offset.x() + pos[0]; + SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); + + SkScalar advanceX = SkFloatToScalar(glyph.fAdvanceX) * alignMul * textRatio; + SkScalar advanceY = SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio; + + if (!DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x - advanceX, + y - advanceY, paint.filteredPremulColor(), cache, textRatio, + viewMatrix)) { + // couldn't append, send to fallback + fallbackTxt.append(SkToInt(text - lastText), lastText); + *fallbackPos.append() = pos[0]; + if (2 == scalarsPerPosition) { + *fallbackPos.append() = pos[1]; + } + } + } + pos += scalarsPerPosition; + } + } + + SkGlyphCache::AttachCache(cache); + if (fallbackTxt.count()) { + blob->initOverride(runIndex); + GrAtlasTextContext::DrawBmpPosText(blob, runIndex, fontCache, props, paint, + scalerContextFlags, viewMatrix, fallbackTxt.begin(), + fallbackTxt.count(), fallbackPos.begin(), + scalarsPerPosition, offset); + } +} + +bool GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* cache, GrAtlasTextStrike** strike, + const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, + GrColor color, SkGlyphCache* glyphCache, SkScalar textRatio, + const SkMatrix& viewMatrix) { + if (!*strike) { + *strike = cache->getStrike(glyphCache); + } + + GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), + skGlyph.getSubXFixed(), + skGlyph.getSubYFixed(), + GrGlyph::kDistance_MaskStyle); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache); + if (!glyph) { + return true; + } + + // fallback to color glyph support + if (kA8_GrMaskFormat != glyph->fMaskFormat) { + return false; + } + + SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); + SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); + SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2 * SK_DistanceFieldInset); + SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2 * SK_DistanceFieldInset); + + SkScalar scale = textRatio; + dx *= scale; + dy *= scale; + width *= scale; + height *= scale; + sx += dx; + sy += dy; + SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); + + blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx - dx, + sy - dy, scale, false); + return true; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// #if GR_TEST_UTILS diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h index 905adc0577..cd7cdf1a90 100644 --- a/src/gpu/text/GrAtlasTextContext.h +++ b/src/gpu/text/GrAtlasTextContext.h @@ -79,6 +79,48 @@ private: const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset); + + // Functions for appending BMP text to GrAtlasTextBlob + static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + uint32_t scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y); + + static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + uint32_t scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, const SkScalar pos[], + int scalarsPerPosition, const SkPoint& offset); + + // functions for appending distance field text + static bool CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, + const SkSurfaceProps& props, const GrShaderCaps& caps); + + static void DrawDFText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + uint32_t scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, SkScalar x, SkScalar y); + + static void DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, + const SkSurfaceProps&, const GrTextUtils::Paint& paint, + uint32_t scalerContextFlags, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, const SkScalar pos[], + int scalarsPerPosition, const SkPoint& offset); + + static void InitDistanceFieldPaint(GrAtlasTextBlob* blob, + SkPaint* skPaint, + SkScalar* textRatio, + const SkMatrix& viewMatrix); + + static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, + GrAtlasTextStrike**, const SkGlyph&, int left, int top, + GrColor color, SkGlyphCache*); + + static bool DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, + GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy, + GrColor color, SkGlyphCache* cache, SkScalar textRatio, + const SkMatrix& viewMatrix); + const GrDistanceFieldAdjustTable* dfAdjustTable() const { return fDistanceAdjustTable.get(); } sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp index d5eac10d23..999cf8d690 100644 --- a/src/gpu/text/GrTextUtils.cpp +++ b/src/gpu/text/GrTextUtils.cpp @@ -6,37 +6,16 @@ */ #include "GrTextUtils.h" -#include "GrAtlasGlyphCache.h" -#include "GrAtlasTextBlob.h" -#include "GrBlurUtils.h" -#include "GrCaps.h" #include "GrContext.h" -#include "SkDistanceFieldGen.h" #include "SkDrawFilter.h" #include "SkDrawProcs.h" -#include "SkFindAndPlaceGlyph.h" #include "SkGlyphCache.h" #include "SkGr.h" #include "SkPaint.h" -#include "SkRect.h" #include "SkTextBlobRunIterator.h" #include "SkTextMapStateProc.h" #include "SkTextToPathIter.h" -namespace { -static const int kMinDFFontSize = 18; -static const int kSmallDFFontSize = 32; -static const int kSmallDFFontLimit = 32; -static const int kMediumDFFontSize = 72; -static const int kMediumDFFontLimit = 72; -static const int kLargeDFFontSize = 162; -#ifdef SK_BUILD_FOR_ANDROID -static const int kLargeDFFontLimit = 384; -#else -static const int kLargeDFFontLimit = 2 * kLargeDFFontSize; -#endif -}; - void GrTextUtils::Paint::initFilteredColor() { // This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors if (fDstColorSpaceInfo->colorSpace()) { @@ -79,416 +58,24 @@ bool GrTextUtils::RunPaint::modifyForRun(const SkTextBlobRunIterator& run) { return true; } -void GrTextUtils::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache* fontCache, - const SkSurfaceProps& props, const GrTextUtils::Paint& paint, - uint32_t scalerContextFlags, const SkMatrix& viewMatrix, - const char text[], size_t byteLength, SkScalar x, SkScalar y) { - SkASSERT(byteLength == 0 || text != nullptr); - - // nothing to draw - if (text == nullptr || byteLength == 0) { - return; - } - - // Ensure the blob is set for bitmaptext - blob->setHasBitmap(); - - GrAtlasTextStrike* currStrike = nullptr; - - SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); - SkFindAndPlaceGlyph::ProcessText( - paint.skPaint().getTextEncoding(), text, byteLength, - {x, y}, viewMatrix, paint.skPaint().getTextAlign(), - cache, - [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { - position += rounding; - BmpAppendGlyph( - blob, runIndex, fontCache, &currStrike, glyph, - SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), - paint.filteredPremulColor(), cache); - } - ); - - SkGlyphCache::AttachCache(cache); -} - -void GrTextUtils::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache* fontCache, - const SkSurfaceProps& props, const GrTextUtils::Paint& paint, - uint32_t scalerContextFlags, const SkMatrix& viewMatrix, - const char text[], size_t byteLength, const SkScalar pos[], - int scalarsPerPosition, const SkPoint& offset) { - SkASSERT(byteLength == 0 || text != nullptr); - SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); - - // nothing to draw - if (text == nullptr || byteLength == 0) { - return; - } - - // Ensure the blob is set for bitmaptext - blob->setHasBitmap(); - - GrAtlasTextStrike* currStrike = nullptr; - - SkGlyphCache* cache = blob->setupCache(runIndex, props, scalerContextFlags, paint, &viewMatrix); - - SkFindAndPlaceGlyph::ProcessPosText( - paint.skPaint().getTextEncoding(), text, byteLength, - offset, viewMatrix, pos, scalarsPerPosition, - paint.skPaint().getTextAlign(), cache, - [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { - position += rounding; - BmpAppendGlyph( - blob, runIndex, fontCache, &currStrike, glyph, - SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), - paint.filteredPremulColor(), cache); - } - ); - - SkGlyphCache::AttachCache(cache); -} - -void GrTextUtils::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, - GrAtlasGlyphCache* fontCache, - GrAtlasTextStrike** strike, const SkGlyph& skGlyph, - int vx, int vy, GrColor color, SkGlyphCache* cache) { - if (!*strike) { - *strike = fontCache->getStrike(cache); - } - - GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), - skGlyph.getSubXFixed(), - skGlyph.getSubYFixed(), - GrGlyph::kCoverage_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, cache); - if (!glyph) { - return; - } - - int x = vx + glyph->fBounds.fLeft; - int y = vy + glyph->fBounds.fTop; - - int width = glyph->fBounds.width(); - int height = glyph->fBounds.height(); - - SkRect r; - r.fLeft = SkIntToScalar(x); - r.fTop = SkIntToScalar(y); - r.fRight = r.fLeft + SkIntToScalar(width); - r.fBottom = r.fTop + SkIntToScalar(height); - - blob->appendGlyph(runIndex, r, color, *strike, glyph, cache, skGlyph, - SkIntToScalar(vx), SkIntToScalar(vy), 1.0f, true); -} - -bool GrTextUtils::CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, const GrShaderCaps& caps) { - if (!viewMatrix.hasPerspective()) { - SkScalar maxScale = viewMatrix.getMaxScale(); - SkScalar scaledTextSize = maxScale * skPaint.getTextSize(); - // Hinted text looks far better at small resolutions - // Scaling up beyond 2x yields undesireable artifacts - if (scaledTextSize < kMinDFFontSize || - scaledTextSize > kLargeDFFontLimit) { - return false; - } - - bool useDFT = props.isUseDeviceIndependentFonts(); -#if SK_FORCE_DISTANCE_FIELD_TEXT - useDFT = true; -#endif - - if (!useDFT && scaledTextSize < kLargeDFFontSize) { - return false; - } - } - - // rasterizers and mask filters modify alpha, which doesn't - // translate well to distance - if (skPaint.getRasterizer() || skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { - return false; - } - - // TODO: add some stroking support - if (skPaint.getStyle() != SkPaint::kFill_Style) { - return false; - } - - return true; -} - -void GrTextUtils::InitDistanceFieldPaint(GrAtlasTextBlob* blob, - SkPaint* skPaint, - SkScalar* textRatio, - const SkMatrix& viewMatrix) { - SkScalar textSize = skPaint->getTextSize(); - SkScalar scaledTextSize = textSize; - - if (viewMatrix.hasPerspective()) { - // for perspective, we simply force to the medium size - // TODO: compute a size based on approximate screen area - scaledTextSize = kMediumDFFontLimit; - } else { - SkScalar maxScale = viewMatrix.getMaxScale(); - // if we have non-unity scale, we need to choose our base text size - // based on the SkPaint's text size multiplied by the max scale factor - // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? - if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { - scaledTextSize *= maxScale; - } - } - - // We have three sizes of distance field text, and within each size 'bucket' there is a floor - // and ceiling. A scale outside of this range would require regenerating the distance fields - SkScalar dfMaskScaleFloor; - SkScalar dfMaskScaleCeil; - if (scaledTextSize <= kSmallDFFontLimit) { - dfMaskScaleFloor = kMinDFFontSize; - dfMaskScaleCeil = kSmallDFFontLimit; - *textRatio = textSize / kSmallDFFontSize; - skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); - } else if (scaledTextSize <= kMediumDFFontLimit) { - dfMaskScaleFloor = kSmallDFFontLimit; - dfMaskScaleCeil = kMediumDFFontLimit; - *textRatio = textSize / kMediumDFFontSize; - skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); - } else { - dfMaskScaleFloor = kMediumDFFontLimit; - dfMaskScaleCeil = kLargeDFFontLimit; - *textRatio = textSize / kLargeDFFontSize; - skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); - } - - // Because there can be multiple runs in the blob, we want the overall maxMinScale, and - // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale - // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can - // tolerate before we'd have to move to a large mip size. When we actually test these values - // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test - // against these values to decide if we can reuse or not(ie, will a given scale change our mip - // level) - SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); - blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); - - skPaint->setAntiAlias(true); - skPaint->setLCDRenderText(false); - skPaint->setAutohinted(false); - skPaint->setHinting(SkPaint::kNormal_Hinting); - skPaint->setSubpixelText(true); -} - -void GrTextUtils::DrawDFText(GrAtlasTextBlob* blob, int runIndex, - GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, - const GrTextUtils::Paint& paint, uint32_t scalerContextFlags, - const SkMatrix& viewMatrix, - const char text[], size_t byteLength, - SkScalar x, SkScalar y) { - SkASSERT(byteLength == 0 || text != nullptr); - - // nothing to draw - if (text == nullptr || byteLength == 0) { - return; - } - - const SkPaint& skPaint = paint.skPaint(); - SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), - skPaint.isDevKernText(), - true); - SkAutoDescriptor desc; - SkScalerContextEffects effects; - // We apply the fake-gamma by altering the distance in the shader, so we ignore the - // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). - skPaint.getScalerContextDescriptor(&effects, &desc, props, SkPaint::kNone_ScalerContextFlags, - nullptr); - SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(skPaint.getTypeface(), effects, - desc.getDesc()); - - SkTArray<SkScalar> positions; - - const char* textPtr = text; - SkScalar stopX = 0; - SkScalar stopY = 0; - SkScalar origin = 0; - switch (skPaint.getTextAlign()) { - case SkPaint::kRight_Align: origin = SK_Scalar1; break; - case SkPaint::kCenter_Align: origin = SK_ScalarHalf; break; - case SkPaint::kLeft_Align: origin = 0; break; - } - - SkAutoKern autokern; - const char* stop = text + byteLength; - while (textPtr < stop) { - // don't need x, y here, since all subpixel variants will have the - // same advance - const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr); - - SkScalar width = SkFloatToScalar(glyph.fAdvanceX) + autokern.adjust(glyph); - positions.push_back(stopX + origin * width); - - SkScalar height = SkFloatToScalar(glyph.fAdvanceY); - positions.push_back(stopY + origin * height); - - stopX += width; - stopY += height; - } - SkASSERT(textPtr == stop); - - SkGlyphCache::AttachCache(origPaintCache); - - // now adjust starting point depending on alignment - SkScalar alignX = stopX; - SkScalar alignY = stopY; - if (skPaint.getTextAlign() == SkPaint::kCenter_Align) { - alignX = SkScalarHalf(alignX); - alignY = SkScalarHalf(alignY); - } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) { - alignX = 0; - alignY = 0; - } - x -= alignX; - y -= alignY; - SkPoint offset = SkPoint::Make(x, y); - - DrawDFPosText(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix, text, - byteLength, positions.begin(), 2, offset); -} - -void GrTextUtils::DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache* fontCache, - const SkSurfaceProps& props, const GrTextUtils::Paint& paint, - uint32_t scalerContextFlags, const SkMatrix& viewMatrix, - const char text[], size_t byteLength, const SkScalar pos[], - int scalarsPerPosition, const SkPoint& offset) { - SkASSERT(byteLength == 0 || text != nullptr); - SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); +uint32_t GrTextUtils::FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint) { + uint32_t flags = paint.getFlags(); - // nothing to draw - if (text == nullptr || byteLength == 0) { - return; + if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { + return flags; } - SkTDArray<char> fallbackTxt; - SkTDArray<SkScalar> fallbackPos; - - // Setup distance field paint and text ratio - SkScalar textRatio; - SkPaint dfPaint(paint); - GrTextUtils::InitDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); - blob->setHasDistanceField(); - blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), - paint.skPaint().isAntiAlias()); - - GrAtlasTextStrike* currStrike = nullptr; - - // We apply the fake-gamma by altering the distance in the shader, so we ignore the - // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). - SkGlyphCache* cache = blob->setupCache(runIndex, props, SkPaint::kNone_ScalerContextFlags, - dfPaint, nullptr); - SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), - dfPaint.isDevKernText(), - true); - - const char* stop = text + byteLength; - - if (SkPaint::kLeft_Align == dfPaint.getTextAlign()) { - while (text < stop) { - const char* lastText = text; - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text); - - if (glyph.fWidth) { - SkScalar x = offset.x() + pos[0]; - SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); - - if (!DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x, y, - paint.filteredPremulColor(), cache, textRatio, viewMatrix)) { - // couldn't append, send to fallback - fallbackTxt.append(SkToInt(text-lastText), lastText); - *fallbackPos.append() = pos[0]; - if (2 == scalarsPerPosition) { - *fallbackPos.append() = pos[1]; - } - } - } - pos += scalarsPerPosition; - } - } else { - SkScalar alignMul = SkPaint::kCenter_Align == dfPaint.getTextAlign() ? SK_ScalarHalf - : SK_Scalar1; - while (text < stop) { - const char* lastText = text; - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text); - - if (glyph.fWidth) { - SkScalar x = offset.x() + pos[0]; - SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); - - SkScalar advanceX = SkFloatToScalar(glyph.fAdvanceX) * alignMul * textRatio; - SkScalar advanceY = SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio; - - if (!DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, x - advanceX, - y - advanceY, paint.filteredPremulColor(), cache, textRatio, - viewMatrix)) { - // couldn't append, send to fallback - fallbackTxt.append(SkToInt(text-lastText), lastText); - *fallbackPos.append() = pos[0]; - if (2 == scalarsPerPosition) { - *fallbackPos.append() = pos[1]; - } - } - } - pos += scalarsPerPosition; - } + if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisableLCD(paint)) { + flags &= ~SkPaint::kLCDRenderText_Flag; + flags |= SkPaint::kGenA8FromLCD_Flag; } - SkGlyphCache::AttachCache(cache); - if (fallbackTxt.count()) { - blob->initOverride(runIndex); - GrTextUtils::DrawBmpPosText(blob, runIndex, fontCache, props, paint, scalerContextFlags, - viewMatrix, fallbackTxt.begin(), fallbackTxt.count(), - fallbackPos.begin(), scalarsPerPosition, offset); - } + return flags; } -bool GrTextUtils::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache* cache, - GrAtlasTextStrike** strike, const SkGlyph& skGlyph, - SkScalar sx, SkScalar sy, GrColor color, - SkGlyphCache* glyphCache, - SkScalar textRatio, const SkMatrix& viewMatrix) { - if (!*strike) { - *strike = cache->getStrike(glyphCache); - } - - GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), - skGlyph.getSubXFixed(), - skGlyph.getSubYFixed(), - GrGlyph::kDistance_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache); - if (!glyph) { - return true; - } - - // fallback to color glyph support - if (kA8_GrMaskFormat != glyph->fMaskFormat) { - return false; - } - - SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); - SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); - SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2 * SK_DistanceFieldInset); - SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2 * SK_DistanceFieldInset); - - SkScalar scale = textRatio; - dx *= scale; - dy *= scale; - width *= scale; - height *= scale; - sx += dx; - sy += dy; - SkRect glyphRect = SkRect::MakeXYWH(sx, sy, width, height); - - blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, - sx - dx, sy - dy, scale, false); - return true; +bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) { + return paint.getMaskFilter() || paint.getRasterizer() || paint.getPathEffect() || + paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style; } void GrTextUtils::DrawTextAsPath(GrContext* context, GrTextUtils::Target* target, @@ -569,26 +156,3 @@ void GrTextUtils::DrawPosTextAsPath(GrContext* context, GrTextUtils::Target* tar pos += scalarsPerPosition; } } - -bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) { - return paint.getMaskFilter() || - paint.getRasterizer() || - paint.getPathEffect() || - paint.isFakeBoldText() || - paint.getStyle() != SkPaint::kFill_Style; -} - -uint32_t GrTextUtils::FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint) { - uint32_t flags = paint.getFlags(); - - if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { - return flags; - } - - if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisableLCD(paint)) { - flags &= ~SkPaint::kLCDRenderText_Flag; - flags |= SkPaint::kGenA8FromLCD_Flag; - } - - return flags; -} diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h index d8d841f051..f72102d6cf 100644 --- a/src/gpu/text/GrTextUtils.h +++ b/src/gpu/text/GrTextUtils.h @@ -124,64 +124,22 @@ public: const SkSurfaceProps& fProps; }; - // Functions for appending BMP text to GrAtlasTextBlob - static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, - const SkSurfaceProps&, const Paint& paint, uint32_t scalerContextFlags, - const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y); - - static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, - const SkSurfaceProps&, const Paint& paint, - uint32_t scalerContextFlags, const SkMatrix& viewMatrix, - const char text[], size_t byteLength, const SkScalar pos[], - int scalarsPerPosition, const SkPoint& offset); - - // functions for appending distance field text - static bool CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, const GrShaderCaps& caps); - - static void DrawDFText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, - const SkSurfaceProps&, const Paint& paint, uint32_t scalerContextFlags, - const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y); - - static void DrawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, - const SkSurfaceProps&, const Paint& paint, - uint32_t scalerContextFlags, const SkMatrix& viewMatrix, - const char text[], size_t byteLength, const SkScalar pos[], - int scalarsPerPosition, const SkPoint& offset); - - // Functions for drawing text as paths - static void DrawTextAsPath(GrContext*, Target*, const GrClip& clip, const SkPaint& paint, - const SkMatrix& viewMatrix, const char text[], size_t byteLength, - SkScalar x, SkScalar y, const SkIRect& clipBounds); - - static void DrawPosTextAsPath(GrContext* context, Target*, const SkSurfaceProps& props, - const GrClip& clip, const SkPaint& paint, - const SkMatrix& viewMatrix, const char text[], size_t byteLength, - const SkScalar pos[], int scalarsPerPosition, - const SkPoint& offset, const SkIRect& clipBounds); - - static bool ShouldDisableLCD(const SkPaint& paint); - - -private: static uint32_t FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint); - static void InitDistanceFieldPaint(GrAtlasTextBlob* blob, - SkPaint* skPaint, - SkScalar* textRatio, - const SkMatrix& viewMatrix); - - static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, - GrAtlasTextStrike**, const SkGlyph&, int left, int top, - GrColor color, SkGlyphCache*); + static bool ShouldDisableLCD(const SkPaint& paint); - static bool DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, - GrAtlasTextStrike**, const SkGlyph&, - SkScalar sx, SkScalar sy, GrColor color, - SkGlyphCache* cache, - SkScalar textRatio, const SkMatrix& viewMatrix); + // Functions for drawing text as paths + static void DrawTextAsPath(GrContext*, GrTextUtils::Target*, const GrClip& clip, + const SkPaint& paint, const SkMatrix& viewMatrix, const char text[], + size_t byteLength, SkScalar x, SkScalar y, + const SkIRect& clipBounds); + + static void DrawPosTextAsPath(GrContext* context, GrTextUtils::Target*, + const SkSurfaceProps& props, const GrClip& clip, + const SkPaint& paint, const SkMatrix& viewMatrix, + const char text[], size_t byteLength, const SkScalar pos[], + int scalarsPerPosition, const SkPoint& offset, + const SkIRect& clipBounds); }; #endif |