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; |
} |