blob: 9c0fc2a8ec2a2fe10a5bb1e2930224b1dfea736c [file] [log] [blame]
kkinnunenc6cb56f2014-06-24 00:12:27 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrStencilAndCoverTextContext.h"
joshualitt1d89e8d2015-04-01 12:40:54 -07009#include "GrAtlasTextContext.h"
robertphillipsea461502015-05-26 11:38:03 -070010#include "GrDrawContext.h"
kkinnunenc6cb56f2014-06-24 00:12:27 -070011#include "GrDrawTarget.h"
kkinnunenc6cb56f2014-06-24 00:12:27 -070012#include "GrPath.h"
cdaltonb85a0aa2014-07-21 15:32:44 -070013#include "GrPathRange.h"
bsalomond309e7a2015-04-30 14:18:54 -070014#include "GrResourceProvider.h"
jvanverthaab626c2014-10-16 08:04:39 -070015#include "SkAutoKern.h"
kkinnunenc6cb56f2014-06-24 00:12:27 -070016#include "SkDraw.h"
17#include "SkDrawProcs.h"
18#include "SkGlyphCache.h"
19#include "SkGpuDevice.h"
20#include "SkPath.h"
21#include "SkTextMapStateProc.h"
cdalton855d83f2014-09-18 13:51:53 -070022#include "SkTextFormatParams.h"
kkinnunenc6cb56f2014-06-24 00:12:27 -070023
bsalomon1fcc01c2015-09-09 09:48:06 -070024#include "batches/GrDrawPathBatch.h"
25
joshualitt6e8cd962015-03-20 10:30:14 -070026GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
robertphillipsfcf78292015-06-19 11:49:52 -070027 const SkSurfaceProps& surfaceProps)
bsalomon1fcc01c2015-09-09 09:48:06 -070028 : INHERITED(context, surfaceProps)
29 , fDraw(nullptr)
30 , fStroke(SkStrokeRec::kFill_InitStyle) {
kkinnunenc6cb56f2014-06-24 00:12:27 -070031}
32
joshualitt6e8cd962015-03-20 10:30:14 -070033GrStencilAndCoverTextContext*
robertphillipsf6703fa2015-09-01 05:36:47 -070034GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& surfaceProps) {
35 GrStencilAndCoverTextContext* textContext =
36 new GrStencilAndCoverTextContext(context, surfaceProps);
37 textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surfaceProps);
jvanverth8c27a182014-10-14 08:45:50 -070038
39 return textContext;
40}
41
kkinnunenc6cb56f2014-06-24 00:12:27 -070042GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
43}
44
cdaltone68f7362015-03-25 14:02:37 -070045bool GrStencilAndCoverTextContext::canDraw(const GrRenderTarget* rt,
46 const GrClip& clip,
47 const GrPaint& paint,
48 const SkPaint& skPaint,
49 const SkMatrix& viewMatrix) {
50 if (skPaint.getRasterizer()) {
jvanverth0fedb192014-10-08 09:07:27 -070051 return false;
52 }
cdaltone68f7362015-03-25 14:02:37 -070053 if (skPaint.getMaskFilter()) {
jvanverth0fedb192014-10-08 09:07:27 -070054 return false;
55 }
kkinnunen50b58e62015-05-18 23:02:07 -070056 if (SkPathEffect* pe = skPaint.getPathEffect()) {
halcanary96fcdcc2015-08-27 07:41:13 -070057 if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) {
kkinnunen50b58e62015-05-18 23:02:07 -070058 return false;
59 }
jvanverth0fedb192014-10-08 09:07:27 -070060 }
cdalton7d5c9502015-10-03 13:28:35 -070061 // No hairlines. They would require new paths with customized strokes for every new draw matrix.
62 return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth();
jvanverth0fedb192014-10-08 09:07:27 -070063}
64
robertphillipsf6703fa2015-09-01 05:36:47 -070065void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -080066 const GrClip& clip,
joshualitt25d9c152015-02-18 12:29:52 -080067 const GrPaint& paint,
cdalton20b373c2014-12-01 08:38:55 -080068 const SkPaint& skPaint,
joshualitt5531d512014-12-17 15:50:11 -080069 const SkMatrix& viewMatrix,
cdalton20b373c2014-12-01 08:38:55 -080070 const char text[],
71 size_t byteLength,
joshualitt6e8cd962015-03-20 10:30:14 -070072 SkScalar x, SkScalar y,
73 const SkIRect& regionClipBounds) {
halcanary96fcdcc2015-08-27 07:41:13 -070074 SkASSERT(byteLength == 0 || text != nullptr);
jvanverthaab626c2014-10-16 08:04:39 -070075
halcanary96fcdcc2015-08-27 07:41:13 -070076 if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) {
jvanverthaab626c2014-10-16 08:04:39 -070077 return;
78 }
79
cdalton7d5c9502015-10-03 13:28:35 -070080 this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
jvanverthaab626c2014-10-16 08:04:39 -070081
82 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
83
jvanverthaab626c2014-10-16 08:04:39 -070084 const char* stop = text + byteLength;
85
86 // Measure first if needed.
87 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
88 SkFixed stopX = 0;
89 SkFixed stopY = 0;
90
91 const char* textPtr = text;
92 while (textPtr < stop) {
93 // We don't need x, y here, since all subpixel variants will have the
94 // same advance.
95 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &textPtr, 0, 0);
96
97 stopX += glyph.fAdvanceX;
98 stopY += glyph.fAdvanceY;
99 }
100 SkASSERT(textPtr == stop);
101
102 SkScalar alignX = SkFixedToScalar(stopX) * fTextRatio;
103 SkScalar alignY = SkFixedToScalar(stopY) * fTextRatio;
104
105 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
106 alignX = SkScalarHalf(alignX);
107 alignY = SkScalarHalf(alignY);
108 }
109
110 x -= alignX;
111 y -= alignY;
112 }
113
114 SkAutoKern autokern;
115
116 SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio);
117
118 SkFixed fx = SkScalarToFixed(x);
119 SkFixed fy = SkScalarToFixed(y);
120 while (text < stop) {
121 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
bungemand709ea82015-03-17 07:23:39 -0700122 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
jvanverthaab626c2014-10-16 08:04:39 -0700123 if (glyph.fWidth) {
bsalomon1fcc01c2015-09-09 09:48:06 -0700124 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
jvanverthaab626c2014-10-16 08:04:39 -0700125 }
126
bungemand709ea82015-03-17 07:23:39 -0700127 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
128 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
jvanverthaab626c2014-10-16 08:04:39 -0700129 }
130
robertphillipsf6703fa2015-09-01 05:36:47 -0700131 this->finish(dc);
jvanverthaab626c2014-10-16 08:04:39 -0700132}
133
robertphillipsf6703fa2015-09-01 05:36:47 -0700134void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -0800135 const GrClip& clip,
joshualitt25d9c152015-02-18 12:29:52 -0800136 const GrPaint& paint,
cdalton20b373c2014-12-01 08:38:55 -0800137 const SkPaint& skPaint,
joshualitt5531d512014-12-17 15:50:11 -0800138 const SkMatrix& viewMatrix,
cdalton20b373c2014-12-01 08:38:55 -0800139 const char text[],
140 size_t byteLength,
141 const SkScalar pos[],
142 int scalarsPerPosition,
joshualitt6e8cd962015-03-20 10:30:14 -0700143 const SkPoint& offset,
144 const SkIRect& regionClipBounds) {
halcanary96fcdcc2015-08-27 07:41:13 -0700145 SkASSERT(byteLength == 0 || text != nullptr);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700146 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
147
148 // nothing to draw
halcanary96fcdcc2015-08-27 07:41:13 -0700149 if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) {
kkinnunenc6cb56f2014-06-24 00:12:27 -0700150 return;
151 }
152
cdalton7d5c9502015-10-03 13:28:35 -0700153 this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700154
155 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
156
kkinnunenc6cb56f2014-06-24 00:12:27 -0700157 const char* stop = text + byteLength;
kkinnunenc6cb56f2014-06-24 00:12:27 -0700158
cdalton38e13ad2014-11-07 06:02:15 -0800159 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
bungeman79738cc2015-03-11 14:05:29 -0700160 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
cdalton38e13ad2014-11-07 06:02:15 -0800161 while (text < stop) {
162 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
163 if (glyph.fWidth) {
164 SkPoint tmsLoc;
165 tmsProc(pos, &tmsLoc);
166 SkPoint loc;
167 alignProc(tmsLoc, glyph, &loc);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700168
bsalomon1fcc01c2015-09-09 09:48:06 -0700169 this->appendGlyph(glyph, loc);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700170 }
cdalton38e13ad2014-11-07 06:02:15 -0800171 pos += scalarsPerPosition;
kkinnunenc6cb56f2014-06-24 00:12:27 -0700172 }
173
robertphillipsf6703fa2015-09-01 05:36:47 -0700174 this->finish(dc);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700175}
176
cdalton855d83f2014-09-18 13:51:53 -0700177static GrPathRange* get_gr_glyphs(GrContext* ctx,
178 const SkTypeface* typeface,
179 const SkDescriptor* desc,
kkinnunen50b58e62015-05-18 23:02:07 -0700180 const GrStrokeInfo& stroke) {
181
182 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();
183 int strokeDataCount = stroke.computeUniqueKeyFragmentData32Cnt();
184 GrUniqueKey glyphKey;
185 GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCount);
186 reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0;
187 reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0;
188 if (strokeDataCount > 0) {
189 stroke.asUniqueKeyFragment(&builder[2]);
190 }
bsalomon24db3b12015-01-23 04:24:04 -0800191 builder.finish();
cdalton855d83f2014-09-18 13:51:53 -0700192
193 SkAutoTUnref<GrPathRange> glyphs(
kkinnunen50b58e62015-05-18 23:02:07 -0700194 static_cast<GrPathRange*>(
195 ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey)));
halcanary96fcdcc2015-08-27 07:41:13 -0700196 if (nullptr == glyphs) {
bsalomon706f08f2015-05-22 07:35:58 -0700197 glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, stroke));
kkinnunen50b58e62015-05-18 23:02:07 -0700198 ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs);
199 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700200 SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc));
cdalton855d83f2014-09-18 13:51:53 -0700201 }
202
203 return glyphs.detach();
204}
205
joshualitt25d9c152015-02-18 12:29:52 -0800206void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
joshualitt570d2f82015-02-25 13:19:48 -0800207 const GrClip& clip,
joshualitt25d9c152015-02-18 12:29:52 -0800208 const GrPaint& paint,
kkinnunenc6cb56f2014-06-24 00:12:27 -0700209 const SkPaint& skPaint,
cdaltonb2808cd2014-07-25 14:13:57 -0700210 size_t textByteLength,
joshualitt6e8cd962015-03-20 10:30:14 -0700211 const SkMatrix& viewMatrix,
212 const SkIRect& regionClipBounds) {
joshualitt9df46592015-07-09 10:55:28 -0700213 fClip = clip;
214
215 fRenderTarget.reset(SkRef(rt));
216
217 fRegionClipBounds = regionClipBounds;
218 fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
219
220 fPaint = paint;
221 fSkPaint = skPaint;
kkinnunenc6cb56f2014-06-24 00:12:27 -0700222
cdalton7d5c9502015-10-03 13:28:35 -0700223 // Don't bake strokes into the glyph outlines. We will stroke the glyphs using the GPU instead.
224 fStroke = GrStrokeInfo(fSkPaint);
225 fSkPaint.setStyle(SkPaint::kFill_Style);
cdaltonb2808cd2014-07-25 14:13:57 -0700226
cdalton7d5c9502015-10-03 13:28:35 -0700227 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
kkinnunenc6cb56f2014-06-24 00:12:27 -0700228
cdalton7d5c9502015-10-03 13:28:35 -0700229 if (fSkPaint.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
230 // Instead of baking fake bold into the glyph outlines, do it with the GPU stroke.
231 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
232 kStdFakeBoldInterpKeys,
233 kStdFakeBoldInterpValues,
234 kStdFakeBoldInterpLength);
235 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
236 fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
237 true /*strokeAndFill*/);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700238
cdalton7d5c9502015-10-03 13:28:35 -0700239 fSkPaint.setFakeBoldText(false);
240 }
cdaltonb2808cd2014-07-25 14:13:57 -0700241
cdalton7d5c9502015-10-03 13:28:35 -0700242 bool canUseRawPaths;
243 if (!fStroke.isDashed()) {
244 // We can draw the glyphs from canonically sized paths.
245 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
246 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize();
cdalton20b373c2014-12-01 08:38:55 -0800247
cdalton7d5c9502015-10-03 13:28:35 -0700248 // Compensate for the glyphs being scaled by fTextRatio.
249 if (!fStroke.isFillStyle()) {
250 fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
251 SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
252 }
253
254 fSkPaint.setLinearText(true);
255 fSkPaint.setLCDRenderText(false);
256 fSkPaint.setAutohinted(false);
257 fSkPaint.setHinting(SkPaint::kNo_Hinting);
258 fSkPaint.setSubpixelText(true);
259 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
260
261 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
262 0 == fSkPaint.getTextSkewX() &&
263 !fSkPaint.isFakeBoldText() &&
264 !fSkPaint.isVerticalText();
265 } else {
cdalton855d83f2014-09-18 13:51:53 -0700266 fTextRatio = fTextInverseRatio = 1.0f;
cdalton7d5c9502015-10-03 13:28:35 -0700267 canUseRawPaths = false;
268 }
cdalton855d83f2014-09-18 13:51:53 -0700269
cdalton7d5c9502015-10-03 13:28:35 -0700270 fViewMatrix = viewMatrix;
271 fViewMatrix.preScale(fTextRatio, fTextRatio);
272 fLocalMatrix.setScale(fTextRatio, fTextRatio);
cdalton855d83f2014-09-18 13:51:53 -0700273
cdalton7d5c9502015-10-03 13:28:35 -0700274 fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignoreGamma*/);
275 fGlyphs = canUseRawPaths ?
276 get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, fStroke) :
277 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
cdalton20b373c2014-12-01 08:38:55 -0800278 &fGlyphCache->getDescriptor(), fStroke);
cdalton20b373c2014-12-01 08:38:55 -0800279}
280
bsalomon1fcc01c2015-09-09 09:48:06 -0700281inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
282 // Stick the glyphs we can't draw into the fallback arrays.
283 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
284 fFallbackIndices.push_back(glyph.getGlyphID());
cdalton7d5c9502015-10-03 13:28:35 -0700285 fFallbackPositions.push_back(pos);
bsalomon1fcc01c2015-09-09 09:48:06 -0700286 } else {
287 // TODO: infer the reserve count from the text length.
288 if (!fDraw) {
289 fDraw = GrPathRangeDraw::Create(fGlyphs,
290 GrPathRendering::kTranslate_PathTransformType,
291 64);
292 }
cdalton7d5c9502015-10-03 13:28:35 -0700293 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() };
bsalomon1fcc01c2015-09-09 09:48:06 -0700294 fDraw->append(glyph.getGlyphID(), translate);
cdaltonb2808cd2014-07-25 14:13:57 -0700295 }
cdalton20b373c2014-12-01 08:38:55 -0800296}
297
robertphillipsf6703fa2015-09-01 05:36:47 -0700298void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
bsalomon1fcc01c2015-09-09 09:48:06 -0700299 if (fDraw) {
300 SkASSERT(fDraw->count());
robertphillipsea461502015-05-26 11:38:03 -0700301
joshualitt7b670db2015-07-09 13:25:02 -0700302 // We should only be flushing about once every run. However, if this impacts performance
303 // we could move the creation of the GrPipelineBuilder earlier.
304 GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip);
305 SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiAlias());
306 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.isAntiAlias());
307
308 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
309 kZero_StencilOp,
vbuzinovc5d58f02015-08-21 05:24:24 -0700310 kKeep_StencilOp,
joshualitt7b670db2015-07-09 13:25:02 -0700311 kNotEqual_StencilFunc,
312 0xffff,
313 0x0000,
314 0xffff);
315
316 *pipelineBuilder.stencil() = kStencilPass;
317
joshualittf2384692015-09-10 11:00:51 -0700318 dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPaint.getColor(),
319 fDraw, GrPathRendering::kWinding_FillType);
bsalomon1fcc01c2015-09-09 09:48:06 -0700320 fDraw->unref();
321 fDraw = nullptr;
kkinnunenc6cb56f2014-06-24 00:12:27 -0700322 }
323
bsalomon1fcc01c2015-09-09 09:48:06 -0700324 if (fFallbackIndices.count()) {
325 SkASSERT(fFallbackPositions.count() == fFallbackIndices.count());
cdalton20b373c2014-12-01 08:38:55 -0800326
cdalton7d5c9502015-10-03 13:28:35 -0700327 SkPaint fallbackSkPaint(fSkPaint);
328 fStroke.applyToPaint(&fallbackSkPaint);
329 if (!fStroke.isFillStyle()) {
330 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
cdalton20b373c2014-12-01 08:38:55 -0800331 }
cdalton7d5c9502015-10-03 13:28:35 -0700332 fallbackSkPaint.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
333 fallbackSkPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
334 // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color
335 // glyphs show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
336 fallbackSkPaint.setSubpixelText(false);
337 fallbackSkPaint.setTextSize(fSkPaint.getTextSize() * fTextRatio);
cdalton20b373c2014-12-01 08:38:55 -0800338
cdalton7d5c9502015-10-03 13:28:35 -0700339 SkMatrix fallbackMatrix(fViewMatrix);
340 fallbackMatrix.preScale(fTextInverseRatio, fTextInverseRatio);
cdalton20b373c2014-12-01 08:38:55 -0800341
cdalton7d5c9502015-10-03 13:28:35 -0700342 fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, fPaint, fallbackSkPaint,
343 fallbackMatrix, (char*)fFallbackIndices.begin(),
bsalomon1fcc01c2015-09-09 09:48:06 -0700344 sizeof(uint16_t) * fFallbackIndices.count(),
cdalton7d5c9502015-10-03 13:28:35 -0700345 fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
346 fRegionClipBounds);
bsalomon1fcc01c2015-09-09 09:48:06 -0700347 fFallbackIndices.reset();
348 fFallbackPositions.reset();
cdalton20b373c2014-12-01 08:38:55 -0800349 }
kkinnunenc6cb56f2014-06-24 00:12:27 -0700350}
351
robertphillipsf6703fa2015-09-01 05:36:47 -0700352void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) {
353 this->flush(dc);
kkinnunenc6cb56f2014-06-24 00:12:27 -0700354
bsalomon1fcc01c2015-09-09 09:48:06 -0700355 SkASSERT(!fDraw);
356 SkASSERT(!fFallbackIndices.count());
357 SkASSERT(!fFallbackPositions.count());
358
cdalton855d83f2014-09-18 13:51:53 -0700359 fGlyphs->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700360 fGlyphs = nullptr;
cdalton855d83f2014-09-18 13:51:53 -0700361
362 SkGlyphCache::AttachCache(fGlyphCache);
halcanary96fcdcc2015-08-27 07:41:13 -0700363 fGlyphCache = nullptr;
kkinnunenc6cb56f2014-06-24 00:12:27 -0700364}