Index: src/gpu/text/GrStencilAndCoverTextContext.cpp |
diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp |
index c2c1c569e8eb915b1a77693aab6cde3b19ba58f8..cc018845f66eda1b5160267d4d4180159e5ed183 100644 |
--- a/src/gpu/text/GrStencilAndCoverTextContext.cpp |
+++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp |
@@ -235,6 +235,18 @@ void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContex |
} |
} |
+static inline int style_key_cnt(const GrStyle& style) { |
+ int cnt = GrStyle::KeySize(style, GrStyle::Apply::kPathEffectAndStrokeRec); |
+ // We should be able to make a key because we filtered out arbitrary path effects. |
+ SkASSERT(cnt > 0); |
+ return cnt; |
+} |
+ |
+static inline void write_style_key(uint32_t* dst, const GrStyle& style) { |
+ // Pass 1 for the scale since the GPU will apply the style not GrStyle::applyToPath(). |
+ GrStyle::WriteKey(dst, style, GrStyle::Apply::kPathEffectAndStrokeRec, SK_Scalar1); |
+} |
+ |
const GrStencilAndCoverTextContext::TextBlob& |
GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, |
const SkPaint& skPaint) { |
@@ -253,11 +265,11 @@ GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, |
fCacheSize += blob->cpuMemorySize(); |
return *blob; |
} else { |
- GrStrokeInfo stroke(skPaint); |
+ GrStyle style(skPaint); |
SkSTArray<4, uint32_t, true> key; |
- key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt()); |
+ key.reset(1 + style_key_cnt(style)); |
key[0] = skBlob->uniqueID(); |
- stroke.asUniqueKeyFragment(&key[1]); |
+ write_style_key(&key[1], style); |
if (TextBlob** found = fBlobKeyCache.find(key)) { |
fLRUList.remove(*found); |
fLRUList.addToTail(*found); |
@@ -353,41 +365,48 @@ private: |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
- : fStroke(fontAndStroke), |
+ : fStyle(fontAndStroke), |
fFont(fontAndStroke), |
fTotalGlyphCount(0), |
fFallbackGlyphCount(0), |
fDetachedGlyphCache(nullptr), |
fLastDrawnGlyphsID(SK_InvalidUniqueID) { |
SkASSERT(fFont.getTextSize() > 0); |
- SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. |
+ 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() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) { |
+ if (fFont.isFakeBoldText() && 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(), |
kStdFakeBoldInterpKeys, |
kStdFakeBoldInterpValues, |
kStdFakeBoldInterpLength); |
SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale); |
- fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra, |
- true /*strokeAndFill*/); |
+ SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); |
+ strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extra : extra, |
+ true /*strokeAndFill*/); |
+ fStyle = GrStyle(strokeRec, fStyle.pathEffect()); |
fFont.setFakeBoldText(false); |
} |
- if (!fFont.getPathEffect() && !fStroke.isDashed()) { |
+ if (!fFont.getPathEffect() && !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(); |
// Compensate for the glyphs being scaled by fTextRatio. |
- if (!fStroke.isFillStyle()) { |
- fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio, |
- SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle()); |
+ if (!fStyle.isSimpleFill()) { |
+ SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle); |
+ strokeRec.setStrokeStyle(stroke.getWidth() / fTextRatio, |
+ SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()); |
+ fStyle = GrStyle(strokeRec, fStyle.pathEffect()); |
} |
fFont.setLinearText(true); |
@@ -407,7 +426,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
} |
// Generate the key that will be used to cache the GPU glyph path objects. |
- if (fUsingRawGlyphPaths && fStroke.isFillStyle()) { |
+ if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) { |
static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::GenerateDomain(); |
const SkTypeface* typeface = fFont.getTypeface(); |
@@ -416,24 +435,30 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
} else { |
static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain(); |
- int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt(); |
+ int styleDataCount = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec); |
+ // Key should be valid since we opted out of drawing arbitrary path effects. |
+ SkASSERT(styleDataCount >= 0); |
if (fUsingRawGlyphPaths) { |
const SkTypeface* typeface = fFont.getTypeface(); |
- GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + strokeDataCount); |
+ GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + styleDataCount); |
reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0; |
- reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount; |
- fStroke.asUniqueKeyFragment(&builder[2]); |
+ reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount; |
+ if (styleDataCount) { |
+ write_style_key(&builder[2], fStyle); |
+ } |
} else { |
SkGlyphCache* glyphCache = this->getGlyphCache(); |
const SkTypeface* typeface = glyphCache->getScalerContext()->getTypeface(); |
const SkDescriptor* desc = &glyphCache->getDescriptor(); |
int descDataCount = (desc->getLength() + 3) / 4; |
GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, |
- 2 + strokeDataCount + descDataCount); |
+ 2 + styleDataCount + descDataCount); |
reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0; |
- reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDataCount << 16); |
- fStroke.asUniqueKeyFragment(&builder[2]); |
- memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); |
+ reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount | (descDataCount << 16); |
+ if (styleDataCount) { |
+ write_style_key(&builder[2], fStyle); |
+ } |
+ memcpy(&builder[2 + styleDataCount], desc, desc->getLength()); |
} |
} |
} |
@@ -541,13 +566,13 @@ GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx) |
if (fUsingRawGlyphPaths) { |
SkScalerContextEffects noeffects; |
glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(), noeffects, |
- nullptr, fStroke); |
+ nullptr, fStyle); |
} else { |
SkGlyphCache* cache = this->getGlyphCache(); |
glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerContext()->getTypeface(), |
cache->getScalerContext()->getEffects(), |
&cache->getDescriptor(), |
- fStroke); |
+ fStyle); |
} |
ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyphs); |
} |
@@ -621,9 +646,9 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, |
if (fFallbackTextBlob) { |
SkPaint fallbackSkPaint(originalSkPaint); |
- fStroke.applyToPaint(&fallbackSkPaint); |
- if (!fStroke.isFillStyle()) { |
- fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); |
+ fStyle.strokeRec().applyToPaint(&fallbackSkPaint); |
+ if (!fStyle.isSimpleFill()) { |
+ fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio); |
} |
fallbackTextContext->drawTextBlob(ctx, dc, pipelineBuilder->clip(), fallbackSkPaint, |