| Index: src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| index 381aa302824c0897c2cd9764113ae1ab99e53044..18843e563f1de4df50c225cd66eb79a2c88e2b72 100644
|
| --- a/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| +++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp
|
| @@ -342,7 +342,7 @@ public:
|
|
|
| bool isInitialized() const { return fBuilder != nullptr; }
|
|
|
| - void init(const SkPaint& font, SkScalar textRatio);
|
| + void init(sk_sp<SkFont> font, SkScalar textRatio);
|
|
|
| void appendGlyph(uint16_t glyphId, const SkPoint& pos);
|
|
|
| @@ -363,42 +363,103 @@ private:
|
|
|
| ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| +
|
| +static sk_sp<SkFont> make_font_from_paint(const SkPaint& paint) {
|
| + uint32_t flags = 0;
|
| + if (paint.isVerticalText()) {
|
| + flags |= SkFont::kVertical_Flag;
|
| + }
|
| + if (paint.isEmbeddedBitmapText()) {
|
| + flags |= SkFont::kEmbeddedBitmaps_Flag;
|
| + }
|
| + if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
|
| + flags |= SkFont::kGenA8FromLCD_Flag;
|
| + }
|
| + if (paint.isFakeBoldText()) {
|
| + flags |= SkFont::kEmbolden_Flag;
|
| + }
|
| + if (SkPaint::kFull_Hinting == paint.getHinting()) {
|
| + flags |= SkFont::kEnableByteCodeHints_Flag;
|
| + }
|
| + if (paint.isAutohinted()) {
|
| + flags |= SkFont::kEnableAutoHints_Flag;
|
| + }
|
| + if (paint.isSubpixelText() || paint.isLinearText()) {
|
| + // this is our default
|
| + } else {
|
| + flags |= SkFont::kUseNonlinearMetrics_Flag;
|
| + }
|
| + if (paint.isDevKernText()) {
|
| + flags |= SkFont::kDevKern_Flag;
|
| + }
|
| +
|
| + SkFont::MaskType maskType = SkFont::kBW_MaskType;
|
| + if (paint.isAntiAlias()) {
|
| + maskType = paint.isLCDRenderText() ? SkFont::kLCD_MaskType : SkFont::kA8_MaskType;
|
| + }
|
| +
|
| + return SkFont::Make(sk_ref_sp(paint.getTypeface()),
|
| + paint.getTextSize(),
|
| + paint.getTextScaleX(),
|
| + paint.getTextSkewX(),
|
| + maskType,
|
| + flags);
|
| +}
|
| +
|
| +static SkTextEncoding from_paint_encoding(SkPaint::TextEncoding encoding) {
|
| + static_assert(kUTF8_SkTextEncoding == SkPaint::kUTF8_TextEncoding, "enum mismatch");
|
| + static_assert(kUTF16_SkTextEncoding == SkPaint::kUTF16_TextEncoding, "enum mismatch");
|
| + static_assert(kUTF32_SkTextEncoding == SkPaint::kUTF32_TextEncoding, "enum mismatch");
|
| + static_assert(kGlyphID_SkTextEncoding == SkPaint::kGlyphID_TextEncoding, "enum mismatch");
|
| + return (SkTextEncoding) encoding;
|
| +}
|
| +
|
| +static SkPaint::TextEncoding from_font_encoding(SkTextEncoding encoding) {
|
| + static_assert(kUTF8_SkTextEncoding == SkPaint::kUTF8_TextEncoding, "enum mismatch");
|
| + static_assert(kUTF16_SkTextEncoding == SkPaint::kUTF16_TextEncoding, "enum mismatch");
|
| + static_assert(kUTF32_SkTextEncoding == SkPaint::kUTF32_TextEncoding, "enum mismatch");
|
| + static_assert(kGlyphID_SkTextEncoding == SkPaint::kGlyphID_TextEncoding, "enum mismatch");
|
| + return (SkPaint::TextEncoding) encoding;
|
| +}
|
| +
|
| GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
| : fStyle(fontAndStroke)
|
| - , fFont(fontAndStroke)
|
| , fTotalGlyphCount(0)
|
| , fFallbackGlyphCount(0)
|
| , fDetachedGlyphCache(nullptr)
|
| , fLastDrawnGlyphsID(SK_InvalidUniqueID) {
|
| - SkASSERT(fFont.getTextSize() > 0);
|
| SkASSERT(!fStyle.hasNonDashPathEffect()); // Arbitrary path effects not supported.
|
| SkASSERT(!fStyle.isSimpleHairline()); // Hairlines are not supported.
|
|
|
| - // Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
|
| - // rendering API for stroking).
|
| - fFont.setStyle(SkPaint::kFill_Style);
|
|
|
| - if (fFont.isFakeBoldText() && fStyle.isSimpleFill()) {
|
| + fFont = make_font_from_paint(fontAndStroke);
|
| + SkASSERT(fFont->getSize() > 0);
|
| + fTextEncoding = from_paint_encoding(fontAndStroke.getTextEncoding());
|
| + fTextAlign = fontAndStroke.getTextAlign();
|
| +
|
| + if (fFont->isEmbolden() && fStyle.isSimpleFill()) {
|
| const SkStrokeRec& stroke = fStyle.strokeRec();
|
| // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
|
| - SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
|
| + SkScalar fakeBoldScale = SkScalarInterpFunc(fFont->getSize(),
|
| kStdFakeBoldInterpKeys,
|
| kStdFakeBoldInterpValues,
|
| kStdFakeBoldInterpLength);
|
| - SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale);
|
| + SkScalar extra = SkScalarMul(fFont->getSize(), fakeBoldScale);
|
|
|
| SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle);
|
| strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extra : extra,
|
| true /*strokeAndFill*/);
|
| fStyle = GrStyle(strokeRec, fStyle.pathEffect());
|
| - fFont.setFakeBoldText(false);
|
| +
|
| + uint32_t newFlags = fFont->getFlags() & ~SkFont::kEmbolden_Flag;
|
| + fFont = fFont->makeWithFlags(newFlags);
|
| }
|
|
|
| - if (!fFont.getPathEffect() && !fStyle.isDashed()) {
|
| + if (!fStyle.pathEffect() && !fStyle.isDashed()) {
|
| const SkStrokeRec& stroke = fStyle.strokeRec();
|
| // We can draw the glyphs from canonically sized paths.
|
| - fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
|
| - fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();
|
| + fTextRatio = fFont->getSize() / SkPaint::kCanonicalTextSizeForPaths;
|
| + fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont->getSize();
|
|
|
| // Compensate for the glyphs being scaled by fTextRatio.
|
| if (!fStyle.isSimpleFill()) {
|
| @@ -408,17 +469,23 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
| fStyle = GrStyle(strokeRec, fStyle.pathEffect());
|
| }
|
|
|
| - fFont.setLinearText(true);
|
| - fFont.setLCDRenderText(false);
|
| - fFont.setAutohinted(false);
|
| - fFont.setHinting(SkPaint::kNo_Hinting);
|
| - fFont.setSubpixelText(true);
|
| - fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
|
| -
|
| - fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
|
| - 0 == fFont.getTextSkewX() &&
|
| - !fFont.isFakeBoldText() &&
|
| - !fFont.isVerticalText();
|
| + uint32_t newFlags = fFont->getFlags();
|
| + newFlags |= 0;
|
| + newFlags &= ~(SkFont::kEnableAutoHints_Flag|SkFont::kEnableByteCodeHints_Flag|
|
| + SkFont::kUseNonlinearMetrics_Flag);
|
| +
|
| + fFont = SkFont::Make(sk_ref_sp(fFont->getTypeface()),
|
| + SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths),
|
| + fFont->getScaleX(),
|
| + fFont->getSkewX(),
|
| + fFont->getMaskType() == SkFont::kLCD_MaskType ? SkFont::kA8_MaskType
|
| + : SkFont::kBW_MaskType,
|
| + newFlags);
|
| +
|
| + fUsingRawGlyphPaths = SK_Scalar1 == fFont->getScaleX() &&
|
| + 0 == fFont->getSkewX() &&
|
| + !fFont->isEmbolden() &&
|
| + !fFont->isVertical();
|
| } else {
|
| fTextRatio = fTextInverseRatio = 1.0f;
|
| fUsingRawGlyphPaths = false;
|
| @@ -428,7 +495,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
| if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) {
|
| static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::GenerateDomain();
|
|
|
| - const SkTypeface* typeface = fFont.getTypeface();
|
| + const SkTypeface* typeface = fFont->getTypeface();
|
| GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1);
|
| reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
|
| } else {
|
| @@ -438,7 +505,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
| // Key should be valid since we opted out of drawing arbitrary path effects.
|
| SkASSERT(styleDataCount >= 0);
|
| if (fUsingRawGlyphPaths) {
|
| - const SkTypeface* typeface = fFont.getTypeface();
|
| + const SkTypeface* typeface = fFont->getTypeface();
|
| GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + styleDataCount);
|
| reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
|
| reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount;
|
| @@ -471,18 +538,18 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
|
| SkASSERT(byteLength == 0 || text != nullptr);
|
|
|
| SkGlyphCache* glyphCache = this->getGlyphCache();
|
| - SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(),
|
| - fFont.isDevKernText(),
|
| + SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(from_font_encoding(fTextEncoding),
|
| + fFont->isDevKern(),
|
| true);
|
|
|
| - fTotalGlyphCount = fFont.countText(text, byteLength);
|
| + fTotalGlyphCount = fFont->countText(text, byteLength, fTextEncoding);
|
| fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
|
| fTotalGlyphCount));
|
|
|
| const char* stop = text + byteLength;
|
|
|
| // Measure first if needed.
|
| - if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
|
| + if (SkPaint::kLeft_Align != fTextAlign) {
|
| SkScalar stopX = 0;
|
| SkScalar stopY = 0;
|
|
|
| @@ -500,7 +567,7 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
|
| SkScalar alignX = stopX * fTextRatio;
|
| SkScalar alignY = stopY * fTextRatio;
|
|
|
| - if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
|
| + if (SkPaint::kCenter_Align == fTextAlign) {
|
| alignX = SkScalarHalf(alignX);
|
| alignY = SkScalarHalf(alignY);
|
| }
|
| @@ -533,18 +600,18 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
|
| SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
|
|
|
| SkGlyphCache* glyphCache = this->getGlyphCache();
|
| - SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(),
|
| - fFont.isDevKernText(),
|
| + SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(from_font_encoding(fTextEncoding),
|
| + fFont->isDevKern(),
|
| true);
|
|
|
| - fTotalGlyphCount = fFont.countText(text, byteLength);
|
| + fTotalGlyphCount = fFont->countText(text, byteLength, fTextEncoding);
|
| fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
|
| fTotalGlyphCount));
|
|
|
| const char* stop = text + byteLength;
|
|
|
| SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
|
| - SkTextAlignProc alignProc(fFont.getTextAlign());
|
| + SkTextAlignProc alignProc(fTextAlign);
|
| FallbackBlobBuilder fallback;
|
| while (text < stop) {
|
| const SkGlyph& glyph = glyphCacheProc(glyphCache, &text);
|
| @@ -568,7 +635,7 @@ GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
|
| if (nullptr == glyphs) {
|
| if (fUsingRawGlyphPaths) {
|
| SkScalerContextEffects noeffects;
|
| - glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(), noeffects,
|
| + glyphs = ctx->resourceProvider()->createGlyphs(fFont->getTypeface(), noeffects,
|
| nullptr, fStyle);
|
| } else {
|
| SkGlyphCache* cache = this->getGlyphCache();
|
| @@ -635,9 +702,11 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
|
| // hurt batching.
|
| const SkRect bounds = SkRect::MakeIWH(drawContext->width(), drawContext->height());
|
|
|
| + GrColor color = grPaint.getColor();
|
| +
|
| SkAutoTUnref<GrDrawBatch> batch(
|
| GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x,
|
| - fTextInverseRatio * y, grPaint.getColor(),
|
| + fTextInverseRatio * y, color,
|
| GrPathRendering::kWinding_FillType, glyphs, fInstanceData,
|
| bounds));
|
|
|
| @@ -691,17 +760,24 @@ size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const {
|
|
|
| ////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| -void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font,
|
| +void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(sk_sp<SkFont> font,
|
| SkScalar textRatio) {
|
| SkASSERT(!this->isInitialized());
|
| fBuilder.reset(new SkTextBlobBuilder);
|
| - fFont = font;
|
| - fFont.setTextAlign(SkPaint::kLeft_Align); // The glyph positions will already account for align.
|
| - fFont.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
| +
|
| + // The Fallback path still uses a full SkPaint!
|
| +// fTextAlign = SkPaint::kLeft_Align; // The glyph positions will already account for align.
|
| +// fTextEncoding = SkPaint::kGlyphID_TextEncoding;
|
| // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color glyphs
|
| // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
|
| - fFont.setSubpixelText(false);
|
| - fFont.setTextSize(fFont.getTextSize() * textRatio);
|
| +#if 0
|
| + fFont = SkFont::Make(sk_ref_sp(font->getTypeface()),
|
| + font->getSize() * textRatio,
|
| + font->getScaleX(),
|
| + font->getSkewX(),
|
| + font->getMaskType(),
|
| + font->getFlags() & ~SkFont::kUseNonlinearMetrics_Flag);
|
| +#endif
|
| fBuffIdx = 0;
|
| }
|
|
|
|
|