Add TextRun object to nvpr text
Adds a TextRun object that defines a resolution-independent, paint-
indepent draw for a string of nvpr text.
BUG=skia:
Review URL: https://codereview.chromium.org/1375353004
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 9c0fc2a..9f394f9 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -25,9 +25,7 @@
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
const SkSurfaceProps& surfaceProps)
- : INHERITED(context, surfaceProps)
- , fDraw(nullptr)
- , fStroke(SkStrokeRec::kFill_InitStyle) {
+ : INHERITED(context, surfaceProps) {
}
GrStencilAndCoverTextContext*
@@ -71,20 +69,103 @@
size_t byteLength,
SkScalar x, SkScalar y,
const SkIRect& regionClipBounds) {
- SkASSERT(byteLength == 0 || text != nullptr);
+ TextRun run(skPaint);
+ run.setText(text, byteLength, x, y, fContext, &fSurfaceProps);
+ run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
+}
- if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) {
- return;
+void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
+ const GrClip& clip,
+ const GrPaint& paint,
+ const SkPaint& skPaint,
+ const SkMatrix& viewMatrix,
+ const char text[],
+ size_t byteLength,
+ const SkScalar pos[],
+ int scalarsPerPosition,
+ const SkPoint& offset,
+ const SkIRect& regionClipBounds) {
+ TextRun run(skPaint);
+ run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps);
+ run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
+ : fStroke(fontAndStroke),
+ fFont(fontAndStroke) {
+ SkASSERT(!fStroke.isHairlineStyle()); // 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()) {
+ // 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*/);
+
+ fFont.setFakeBoldText(false);
}
- this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
+ if (!fFont.getPathEffect() && !fStroke.isDashed()) {
+ // We can draw the glyphs from canonically sized paths.
+ fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
+ fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ // Compensate for the glyphs being scaled by fTextRatio.
+ if (!fStroke.isFillStyle()) {
+ fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
+ SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
+ }
+
+ 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();
+ } else {
+ fTextRatio = fTextInverseRatio = 1.0f;
+ fUsingRawGlyphPaths = false;
+ }
+
+ // When drawing from canonically sized paths, the actual local coords are fTextRatio * coords.
+ fLocalMatrix.setScale(fTextRatio, fTextRatio);
+}
+
+GrStencilAndCoverTextContext::TextRun::~TextRun() {
+}
+
+void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength,
+ SkScalar x, SkScalar y, GrContext* ctx,
+ const SkSurfaceProps* surfaceProps) {
+ SkASSERT(byteLength == 0 || text != nullptr);
+
+ SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
+ SkGlyphCache* glyphCache = autoGlyphCache.getCache();
+
+ fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
+ GrPathRendering::kTranslate_PathTransformType,
+ fFont.countText(text, byteLength)));
+
+ SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
const char* stop = text + byteLength;
// Measure first if needed.
- if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
SkFixed stopX = 0;
SkFixed stopY = 0;
@@ -92,7 +173,7 @@
while (textPtr < stop) {
// We don't need x, y here, since all subpixel variants will have the
// same advance.
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &textPtr, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr, 0, 0);
stopX += glyph.fAdvanceX;
stopY += glyph.fAdvanceY;
@@ -102,7 +183,7 @@
SkScalar alignX = SkFixedToScalar(stopX) * fTextRatio;
SkScalar alignY = SkFixedToScalar(stopY) * fTextRatio;
- if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
alignX = SkScalarHalf(alignX);
alignY = SkScalarHalf(alignY);
}
@@ -118,7 +199,7 @@
SkFixed fx = SkScalarToFixed(x);
SkFixed fy = SkScalarToFixed(y);
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
if (glyph.fWidth) {
this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
@@ -127,39 +208,30 @@
fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
}
-
- this->finish(dc);
}
-void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const char text[],
- size_t byteLength,
- const SkScalar pos[],
- int scalarsPerPosition,
- const SkPoint& offset,
- const SkIRect& regionClipBounds) {
+void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], int scalarsPerPosition,
+ const SkPoint& offset, GrContext* ctx,
+ const SkSurfaceProps* surfaceProps) {
SkASSERT(byteLength == 0 || text != nullptr);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
- // nothing to draw
- if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) {
- return;
- }
+ SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
+ SkGlyphCache* glyphCache = autoGlyphCache.getCache();
- this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
+ fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
+ GrPathRendering::kTranslate_PathTransformType,
+ fFont.countText(text, byteLength)));
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
const char* stop = text + byteLength;
SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
- SkTextAlignProc alignProc(fSkPaint.getTextAlign());
+ SkTextAlignProc alignProc(fFont.getTextAlign());
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
if (glyph.fWidth) {
SkPoint tmsLoc;
tmsProc(pos, &tmsLoc);
@@ -170,23 +242,22 @@
}
pos += scalarsPerPosition;
}
-
- this->finish(dc);
}
-static GrPathRange* get_gr_glyphs(GrContext* ctx,
- const SkTypeface* typeface,
- const SkDescriptor* desc,
- const GrStrokeInfo& stroke) {
+GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx,
+ SkGlyphCache* glyphCache) {
+ SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface()
+ : glyphCache->getScalerContext()->getTypeface();
+ const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getDescriptor();
static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();
- int strokeDataCount = stroke.computeUniqueKeyFragmentData32Cnt();
+ int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt();
GrUniqueKey glyphKey;
GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCount);
reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0;
reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0;
if (strokeDataCount > 0) {
- stroke.asUniqueKeyFragment(&builder[2]);
+ fStroke.asUniqueKeyFragment(&builder[2]);
}
builder.finish();
@@ -194,7 +265,7 @@
static_cast<GrPathRange*>(
ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey)));
if (nullptr == glyphs) {
- glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, stroke));
+ glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStroke));
ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs);
} else {
SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc));
@@ -203,107 +274,32 @@
return glyphs.detach();
}
-void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- size_t textByteLength,
- const SkMatrix& viewMatrix,
- const SkIRect& regionClipBounds) {
- fClip = clip;
-
- fRenderTarget.reset(SkRef(rt));
-
- fRegionClipBounds = regionClipBounds;
- fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
-
- fPaint = paint;
- fSkPaint = skPaint;
-
- // Don't bake strokes into the glyph outlines. We will stroke the glyphs using the GPU instead.
- fStroke = GrStrokeInfo(fSkPaint);
- fSkPaint.setStyle(SkPaint::kFill_Style);
-
- SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
-
- if (fSkPaint.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
- // Instead of baking fake bold into the glyph outlines, do it with the GPU stroke.
- SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
- kStdFakeBoldInterpKeys,
- kStdFakeBoldInterpValues,
- kStdFakeBoldInterpLength);
- SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
- fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
- true /*strokeAndFill*/);
-
- fSkPaint.setFakeBoldText(false);
- }
-
- bool canUseRawPaths;
- if (!fStroke.isDashed()) {
- // We can draw the glyphs from canonically sized paths.
- fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
- fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize();
-
- // Compensate for the glyphs being scaled by fTextRatio.
- if (!fStroke.isFillStyle()) {
- fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
- SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
- }
-
- fSkPaint.setLinearText(true);
- fSkPaint.setLCDRenderText(false);
- fSkPaint.setAutohinted(false);
- fSkPaint.setHinting(SkPaint::kNo_Hinting);
- fSkPaint.setSubpixelText(true);
- fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
-
- canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
- 0 == fSkPaint.getTextSkewX() &&
- !fSkPaint.isFakeBoldText() &&
- !fSkPaint.isVerticalText();
- } else {
- fTextRatio = fTextInverseRatio = 1.0f;
- canUseRawPaths = false;
- }
-
- fViewMatrix = viewMatrix;
- fViewMatrix.preScale(fTextRatio, fTextRatio);
- fLocalMatrix.setScale(fTextRatio, fTextRatio);
-
- fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignoreGamma*/);
- fGlyphs = canUseRawPaths ?
- get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, fStroke) :
- get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
- &fGlyphCache->getDescriptor(), fStroke);
-}
-
-inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
+inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph,
+ const SkPoint& pos) {
// Stick the glyphs we can't draw into the fallback arrays.
if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
fFallbackIndices.push_back(glyph.getGlyphID());
fFallbackPositions.push_back(pos);
} else {
- // TODO: infer the reserve count from the text length.
- if (!fDraw) {
- fDraw = GrPathRangeDraw::Create(fGlyphs,
- GrPathRendering::kTranslate_PathTransformType,
- 64);
- }
float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() };
fDraw->append(glyph.getGlyphID(), translate);
}
}
-void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
- if (fDraw) {
- SkASSERT(fDraw->count());
+void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
+ GrRenderTarget* rt,
+ const GrClip& clip,
+ const GrPaint& paint,
+ const SkMatrix& viewMatrix,
+ const SkIRect& regionClipBounds,
+ GrTextContext* fallbackTextContext,
+ const SkPaint& originalSkPaint) const {
+ SkASSERT(fDraw);
- // We should only be flushing about once every run. However, if this impacts performance
- // we could move the creation of the GrPipelineBuilder earlier.
- GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip);
- SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiAlias());
- pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.isAntiAlias());
+ if (fDraw->count()) {
+ GrPipelineBuilder pipelineBuilder(paint, rt, clip);
+ SkASSERT(rt->isStencilBufferMultisampled() || !paint.isAntiAlias());
+ pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, paint.isAntiAlias());
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
@@ -315,50 +311,38 @@
*pipelineBuilder.stencil() = kStencilPass;
- dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPaint.getColor(),
- fDraw, GrPathRendering::kWinding_FillType);
- fDraw->unref();
- fDraw = nullptr;
+ SkMatrix drawMatrix(viewMatrix);
+ drawMatrix.preScale(fTextRatio, fTextRatio);
+
+ dc->drawPathsFromRange(&pipelineBuilder, drawMatrix, fLocalMatrix, paint.getColor(), fDraw,
+ GrPathRendering::kWinding_FillType);
}
if (fFallbackIndices.count()) {
SkASSERT(fFallbackPositions.count() == fFallbackIndices.count());
- SkPaint fallbackSkPaint(fSkPaint);
+ enum { kPreservedFlags = SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
+ SkPaint::kLCDRenderText_Flag | SkPaint::kAutoHinting_Flag };
+
+ SkPaint fallbackSkPaint(originalSkPaint);
fStroke.applyToPaint(&fallbackSkPaint);
if (!fStroke.isFillStyle()) {
fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
}
fallbackSkPaint.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
fallbackSkPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ fallbackSkPaint.setHinting(fFont.getHinting());
+ fallbackSkPaint.setFlags((fFont.getFlags() & kPreservedFlags) |
+ (originalSkPaint.getFlags() & ~kPreservedFlags));
// 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.
fallbackSkPaint.setSubpixelText(false);
- fallbackSkPaint.setTextSize(fSkPaint.getTextSize() * fTextRatio);
+ fallbackSkPaint.setTextSize(fFont.getTextSize() * fTextRatio);
- SkMatrix fallbackMatrix(fViewMatrix);
- fallbackMatrix.preScale(fTextInverseRatio, fTextInverseRatio);
-
- fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, fPaint, fallbackSkPaint,
- fallbackMatrix, (char*)fFallbackIndices.begin(),
- sizeof(uint16_t) * fFallbackIndices.count(),
- fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
- fRegionClipBounds);
- fFallbackIndices.reset();
- fFallbackPositions.reset();
+ fallbackTextContext->drawPosText(dc, rt, clip, paint, fallbackSkPaint, viewMatrix,
+ (char*)fFallbackIndices.begin(),
+ sizeof(uint16_t) * fFallbackIndices.count(),
+ fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
+ regionClipBounds);
}
}
-
-void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) {
- this->flush(dc);
-
- SkASSERT(!fDraw);
- SkASSERT(!fFallbackIndices.count());
- SkASSERT(!fFallbackPositions.count());
-
- fGlyphs->unref();
- fGlyphs = nullptr;
-
- SkGlyphCache::AttachCache(fGlyphCache);
- fGlyphCache = nullptr;
-}
diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h
index 44b33a5..c5c29ad 100644
--- a/src/gpu/GrStencilAndCoverTextContext.h
+++ b/src/gpu/GrStencilAndCoverTextContext.h
@@ -15,7 +15,6 @@
class GrTextStrike;
class GrPath;
class GrPathRange;
-class GrPathRangeDraw;
class SkSurfaceProps;
/*
@@ -30,25 +29,6 @@
virtual ~GrStencilAndCoverTextContext();
private:
- SkScalar fTextRatio;
- float fTextInverseRatio;
- SkGlyphCache* fGlyphCache;
-
- GrPathRange* fGlyphs;
- GrPathRangeDraw* fDraw;
- GrStrokeInfo fStroke;
- SkSTArray<32, uint16_t, true> fFallbackIndices;
- SkSTArray<32, SkPoint, true> fFallbackPositions;
-
- SkMatrix fViewMatrix;
- SkMatrix fLocalMatrix;
- SkAutoTUnref<GrRenderTarget> fRenderTarget;
- GrClip fClip;
- SkIRect fClipRect;
- SkIRect fRegionClipBounds;
- GrPaint fPaint;
- SkPaint fSkPaint;
-
GrStencilAndCoverTextContext(GrContext*, const SkSurfaceProps&);
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
@@ -65,11 +45,37 @@
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset, const SkIRect& regionClipBounds) override;
- void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, size_t textByteLength,
- const SkMatrix& viewMatrix, const SkIRect& regionClipBounds);
- void appendGlyph(const SkGlyph&, const SkPoint&);
- void flush(GrDrawContext* dc);
- void finish(GrDrawContext* dc);
+ class TextRun {
+ public:
+ TextRun(const SkPaint& fontAndStroke);
+ ~TextRun();
+
+ void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y,
+ GrContext*, const SkSurfaceProps*);
+
+ void setPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset,
+ GrContext*, const SkSurfaceProps*);
+
+ void draw(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkMatrix&,
+ const SkIRect& regionClipBounds, GrTextContext* fallbackTextContext,
+ const SkPaint& originalSkPaint) const;
+
+ private:
+ GrPathRange* createGlyphs(GrContext*, SkGlyphCache*);
+
+ void appendGlyph(const SkGlyph&, const SkPoint&);
+
+ GrStrokeInfo fStroke;
+ SkPaint fFont;
+ SkScalar fTextRatio;
+ float fTextInverseRatio;
+ SkMatrix fLocalMatrix;
+ bool fUsingRawGlyphPaths;
+ SkAutoTUnref<GrPathRangeDraw> fDraw;
+ SkSTArray<32, uint16_t, true> fFallbackIndices;
+ SkSTArray<32, SkPoint, true> fFallbackPositions;
+ };
typedef GrTextContext INHERITED;
};