Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 563283004: Use per-typeface sets of glyphs for nvpr text (Closed) Base URL: https://skia.googlesource.com/skia.git@upload_glyphmemorypath
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrStencilAndCoverTextContext.h" 8 #include "GrStencilAndCoverTextContext.h"
9 #include "GrDrawTarget.h" 9 #include "GrDrawTarget.h"
10 #include "GrGpu.h" 10 #include "GrGpu.h"
11 #include "GrPath.h" 11 #include "GrPath.h"
12 #include "GrPathRange.h" 12 #include "GrPathRange.h"
13 #include "SkAutoKern.h" 13 #include "SkAutoKern.h"
14 #include "SkDraw.h" 14 #include "SkDraw.h"
15 #include "SkDrawProcs.h" 15 #include "SkDrawProcs.h"
16 #include "SkGlyphCache.h" 16 #include "SkGlyphCache.h"
17 #include "SkGpuDevice.h" 17 #include "SkGpuDevice.h"
18 #include "SkPath.h" 18 #include "SkPath.h"
19 #include "SkTextMapStateProc.h" 19 #include "SkTextMapStateProc.h"
20 20 #include "SkTextFormatParams.h"
21 class GrStencilAndCoverTextContext::GlyphPathRange : public GrGpuResource {
22 static const int kMaxGlyphCount = 1 << 16; // Glyph IDs are uint16_t's
23 static const int kGlyphGroupSize = 16; // Glyphs get tracked in groups of 16
24
25 public:
26 static GlyphPathRange* Create(GrContext* context,
27 SkGlyphCache* cache,
28 const SkStrokeRec& stroke) {
29 static const GrCacheID::Domain gGlyphPathRangeDomain = GrCacheID::Genera teDomain();
30
31 GrCacheID::Key key;
32 key.fData32[0] = cache->getDescriptor().getChecksum();
33 key.fData32[1] = cache->getScalerContext()->getTypeface()->uniqueID();
34 key.fData64[1] = GrPath::ComputeStrokeKey(stroke);
35
36 GrResourceKey resourceKey(GrCacheID(gGlyphPathRangeDomain, key),
37 GrPathRange::resourceType(), 0);
38 SkAutoTUnref<GlyphPathRange> glyphs(
39 static_cast<GlyphPathRange*>(context->findAndRefCachedResource(resou rceKey)));
40
41 if (NULL == glyphs ||
42 !glyphs->fDesc->equals(cache->getDescriptor() /*checksum collision*/ )) {
43 glyphs.reset(SkNEW_ARGS(GlyphPathRange, (context, cache->getDescript or(), stroke)));
44 glyphs->registerWithCache();
45 context->addResourceToCache(resourceKey, glyphs);
46 }
47
48 return glyphs.detach();
49 }
50
51 const GrPathRange* pathRange() const { return fPathRange.get(); }
52
53 void preloadGlyph(uint16_t glyphID, SkGlyphCache* cache) {
54 const uint16_t groupIndex = glyphID / kGlyphGroupSize;
55 const uint16_t groupByte = groupIndex >> 3;
56 const uint8_t groupBit = 1 << (groupIndex & 7);
57
58 const bool hasGlyph = 0 != (fLoadedGlyphs[groupByte] & groupBit);
59 if (hasGlyph) {
60 return;
61 }
62
63 // We track which glyphs are loaded in groups of kGlyphGroupSize. To
64 // mark a glyph loaded we need to load the entire group.
65 const uint16_t groupFirstID = groupIndex * kGlyphGroupSize;
66 const uint16_t groupLastID = groupFirstID + kGlyphGroupSize - 1;
67 SkPath skPath;
68 for (int id = groupFirstID; id <= groupLastID; ++id) {
69 const SkGlyph& skGlyph = cache->getGlyphIDMetrics(id);
70 if (const SkPath* skPath = cache->findPath(skGlyph)) {
71 fPathRange->initAt(id, *skPath);
72 } // GrGpu::drawPaths will silently ignore undefined paths.
73 }
74
75 fLoadedGlyphs[groupByte] |= groupBit;
76 this->didChangeGpuMemorySize();
77 }
78
79 // GrGpuResource overrides
80 virtual size_t gpuMemorySize() const SK_OVERRIDE { return fPathRange->gpuMem orySize(); }
81
82 private:
83 GlyphPathRange(GrContext* context, const SkDescriptor& desc, const SkStrokeR ec& stroke)
84 : INHERITED(context->getGpu(), false)
85 , fDesc(desc.copy())
86 // We reserve a range of kMaxGlyphCount paths because of fallbacks fonts . We
87 // can't know exactly how many glyphs we might need without preloading e very
88 // fallback, which we don't want to do at this point.
89 , fPathRange(context->getGpu()->createPathRange(kMaxGlyphCount, stroke)) {
90 memset(fLoadedGlyphs, 0, sizeof(fLoadedGlyphs));
91 }
92
93 ~GlyphPathRange() {
94 this->release();
95 SkDescriptor::Free(fDesc);
96 }
97
98 static const int kMaxGroupCount = (kMaxGlyphCount + (kGlyphGroupSize - 1)) / kGlyphGroupSize;
99 SkDescriptor* const fDesc;
100 uint8_t fLoadedGlyphs[(kMaxGroupCount + 7) >> 3]; // One bit per glyph group
101 SkAutoTUnref<GrPathRange> fPathRange;
102
103 typedef GrGpuResource INHERITED;
104 };
105
106 21
107 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext( 22 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(
108 GrContext* context, const SkDeviceProperties& properties) 23 GrContext* context, const SkDeviceProperties& properties)
109 : GrTextContext(context, properties) 24 : GrTextContext(context, properties)
110 , fStroke(SkStrokeRec::kFill_InitStyle)
111 , fPendingGlyphCount(0) { 25 , fPendingGlyphCount(0) {
112 } 26 }
113 27
114 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { 28 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
115 } 29 }
116 30
117 void GrStencilAndCoverTextContext::drawText(const GrPaint& paint, 31 void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
118 const SkPaint& skPaint, 32 const SkPaint& skPaint,
119 const char text[], 33 const char text[],
120 size_t byteLength, 34 size_t byteLength,
(...skipping 14 matching lines...) Expand all
135 // NOTE: here we have following coincidence that works at the moment: 49 // NOTE: here we have following coincidence that works at the moment:
136 // - When using the device-space glyphs, the transforms we pass to NVPR 50 // - When using the device-space glyphs, the transforms we pass to NVPR
137 // instanced drawing are the global transforms, and the view transform is 51 // instanced drawing are the global transforms, and the view transform is
138 // identity. NVPR can not use non-affine transforms in the instanced 52 // identity. NVPR can not use non-affine transforms in the instanced
139 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it 53 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it
140 // will turn off the use of device-space glyphs when perspective transforms 54 // will turn off the use of device-space glyphs when perspective transforms
141 // are in use. 55 // are in use.
142 56
143 this->init(paint, skPaint, byteLength, kUseIfNeeded_DeviceSpaceGlyphsBehavio r); 57 this->init(paint, skPaint, byteLength, kUseIfNeeded_DeviceSpaceGlyphsBehavio r);
144 58
145 SkMatrix* glyphCacheTransform = NULL;
146 // Transform our starting point. 59 // Transform our starting point.
147 if (fNeedsDeviceSpaceGlyphs) { 60 if (fNeedsDeviceSpaceGlyphs) {
148 SkPoint loc; 61 SkPoint loc;
149 fContextInitialMatrix.mapXY(x, y, &loc); 62 fContextInitialMatrix.mapXY(x, y, &loc);
150 x = loc.fX; 63 x = loc.fX;
151 y = loc.fY; 64 y = loc.fY;
152 glyphCacheTransform = &fContextInitialMatrix;
153 } 65 }
154 66
155 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 67 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
156 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform ); 68
157 fGlyphCache = autoCache.getCache();
158 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
159 fTransformType = GrPathRendering::kTranslate_PathTransformType; 69 fTransformType = GrPathRendering::kTranslate_PathTransformType;
160 70
161 const char* stop = text + byteLength; 71 const char* stop = text + byteLength;
162 72
163 // Measure first if needed. 73 // Measure first if needed.
164 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { 74 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
165 SkFixed stopX = 0; 75 SkFixed stopX = 0;
166 SkFixed stopY = 0; 76 SkFixed stopY = 0;
167 77
168 const char* textPtr = text; 78 const char* textPtr = text;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 // The positioning is based on SkPaint::measureText of individual 139 // The positioning is based on SkPaint::measureText of individual
230 // glyphs. That already uses glyph cache without device transforms. Device 140 // glyphs. That already uses glyph cache without device transforms. Device
231 // transform is not part of SkPaint::measureText API, and thus we use the 141 // transform is not part of SkPaint::measureText API, and thus we use the
232 // same glyphs as what were measured. 142 // same glyphs as what were measured.
233 143
234 const float textTranslateY = (1 == scalarsPerPosition ? constY : 0); 144 const float textTranslateY = (1 == scalarsPerPosition ? constY : 0);
235 this->init(paint, skPaint, byteLength, kDoNotUse_DeviceSpaceGlyphsBehavior, textTranslateY); 145 this->init(paint, skPaint, byteLength, kDoNotUse_DeviceSpaceGlyphsBehavior, textTranslateY);
236 146
237 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 147 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
238 148
239 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
240 fGlyphCache = autoCache.getCache();
241 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
242
243 const char* stop = text + byteLength; 149 const char* stop = text + byteLength;
244 150
245 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { 151 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
246 if (1 == scalarsPerPosition) { 152 if (1 == scalarsPerPosition) {
247 fTransformType = GrPathRendering::kTranslateX_PathTransformType; 153 fTransformType = GrPathRendering::kTranslateX_PathTransformType;
248 while (text < stop) { 154 while (text < stop) {
249 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 155 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
250 if (glyph.fWidth) { 156 if (glyph.fWidth) {
251 this->appendGlyph(glyph.getGlyphID(), *pos); 157 this->appendGlyph(glyph.getGlyphID(), *pos);
252 } 158 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 216
311 void GrStencilAndCoverTextContext::init(const GrPaint& paint, 217 void GrStencilAndCoverTextContext::init(const GrPaint& paint,
312 const SkPaint& skPaint, 218 const SkPaint& skPaint,
313 size_t textByteLength, 219 size_t textByteLength,
314 DeviceSpaceGlyphsBehavior deviceSpaceGly phsBehavior, 220 DeviceSpaceGlyphsBehavior deviceSpaceGly phsBehavior,
315 SkScalar textTranslateY) { 221 SkScalar textTranslateY) {
316 GrTextContext::init(paint, skPaint); 222 GrTextContext::init(paint, skPaint);
317 223
318 fContextInitialMatrix = fContext->getMatrix(); 224 fContextInitialMatrix = fContext->getMatrix();
319 225
320 bool otherBackendsWillDrawAsPaths = 226 const bool otherBackendsWillDrawAsPaths =
321 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); 227 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
322 228
323 if (otherBackendsWillDrawAsPaths) { 229 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths &&
324 // This is to reproduce SkDraw::drawText_asPaths glyph positions. 230 kUseIfNeeded_DeviceSpaceGlyphsBehavior == deviceSp aceGlyphsBehavior;
325 fSkPaint.setLinearText(true); 231
326 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPath s; 232 if (fNeedsDeviceSpaceGlyphs) {
327 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTe xtSize();
328 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)) ;
329 if (fSkPaint.getStyle() != SkPaint::kFill_Style) {
330 // Compensate the glyphs being scaled up by fTextRatio by scaling th e
331 // stroke down.
332 fSkPaint.setStrokeWidth(fSkPaint.getStrokeWidth() / fTextRatio);
333 }
334 fNeedsDeviceSpaceGlyphs = false;
335 } else {
336 fTextRatio = fTextInverseRatio = 1.0f;
337 fNeedsDeviceSpaceGlyphs =
338 kUseIfNeeded_DeviceSpaceGlyphsBehavior == deviceSpaceGlyphsBehavior &&
339 (fContextInitialMatrix.getType() &
340 (SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) != 0;
341 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. 233 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms.
342 SkASSERT(!fContextInitialMatrix.hasPerspective()); 234 SkASSERT(!fContextInitialMatrix.hasPerspective());
235 SkASSERT(0 == textTranslateY);
236
237 fTextRatio = fTextInverseRatio = 1.0f;
238
239 // The whole shape (including stroke) will be baked into the glyph outli nes. Make
240 // NVPR just fill the baked shapes.
241 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialM atrix, false);
242 fGlyphs = fContext->createGlyphs(fGlyphCache->getScalerContext()->getTyp eface(),
243 &fGlyphCache->getDescriptor(),
244 SkStrokeRec(SkStrokeRec::kFill_InitStyl e));
245
246 // Glyphs loaded by GPU path rendering have an inverted y-direction.
247 SkMatrix m;
248 m.setScale(1, -1);
249 fContext->setMatrix(m);
250
251 // Post-flip the initial matrix so we're left with just the flip after
252 // the paint preConcats the inverse.
253 m = fContextInitialMatrix;
254 m.postScale(1, -1);
255 fPaint.localCoordChangeInverse(m);
256 } else {
257 // Don't bake strokes into the glyph outlines. We will stroke the glyphs
258 // using the GPU instead. This is the fast path.
259 SkStrokeRec gpuStroke = SkStrokeRec(fSkPaint);
260 fSkPaint.setStyle(SkPaint::kFill_Style);
261
262 #ifndef SK_USE_FREETYPE_EMBOLDEN
263 if (fSkPaint.isFakeBoldText()) {
264 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
265 kStdFakeBoldInterpKeys,
266 kStdFakeBoldInterpValues ,
267 kStdFakeBoldInterpLength );
268 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
269
270 if (gpuStroke.isFillStyle()) {
271 gpuStroke.setStrokeStyle(extra, true /*strokeAndFill*/);
272 } else {
273 gpuStroke.setStrokeStyle(gpuStroke.getWidth() + extra,
274 SkStrokeRec::kStrokeAndFill_Style == gp uStroke.getStyle());
275 }
276
277 fSkPaint.setFakeBoldText(false);
278 }
279 #endif
280
281 if (gpuStroke.isHairlineStyle()) {
282 // Approximate hairline stroke.
283 SkScalar strokeWidth = SK_Scalar1 /
284 (SkVector::Make(fContextInitialMatrix.getScaleX(),
285 fContextInitialMatrix.getSkewY()).length());
286 gpuStroke.setStrokeStyle(strokeWidth, false);
287 }
288
289 if (otherBackendsWillDrawAsPaths || (SK_Scalar1 == fSkPaint.getTextScale X() &&
290 0 == fSkPaint.getTextSkewX() &&
291 #ifdef SK_USE_FREETYPE_EMBOLDEN
292 !fSkPaint.isFakeBoldText() &&
293 #endif
294 !fSkPaint.isVerticalText())) {
295 // We can draw the glyphs from their generic raw paths.
296 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeFor Paths;
297 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.g etTextSize();
298
299 if (!gpuStroke.isFillStyle()) {
300 // Compensate for the glyphs being scaled by fTextRatio.
301 gpuStroke.setStrokeStyle(gpuStroke.getWidth() / fTextRatio,
302 SkStrokeRec::kStrokeAndFill_Style == gp uStroke.getStyle());
303 }
304
305 fSkPaint.setLinearText(true);
306 fSkPaint.setLCDRenderText(false);
307 fSkPaint.setAutohinted(false);
308 fSkPaint.setHinting(SkPaint::kNo_Hinting);
309 fSkPaint.setSubpixelText(true);
310 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPat hs));
311
312 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false);
313 fGlyphs = fContext->createGlyphs(fSkPaint.getTypeface(), NULL, gpuSt roke);
314 } else {
315 fTextRatio = fTextInverseRatio = 1.0f;
316
317 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false);
318 fGlyphs = fContext->createGlyphs(fGlyphCache->getScalerContext()->ge tTypeface(),
319 &fGlyphCache->getDescriptor(),
320 gpuStroke);
321 }
322
323 SkMatrix textMatrix;
324 textMatrix.setTranslate(0, textTranslateY);
325 // Glyphs loaded by GPU path rendering have an inverted y-direction.
326 textMatrix.preScale(fTextRatio, -fTextRatio);
327 fPaint.localCoordChange(textMatrix);
328 fContext->concatMatrix(textMatrix);
343 } 329 }
344 330
345 fStroke = SkStrokeRec(fSkPaint);
346
347 if (fNeedsDeviceSpaceGlyphs) {
348 SkASSERT(1.0f == fTextRatio);
349 SkASSERT(0.0f == textTranslateY);
350 fPaint.localCoordChangeInverse(fContextInitialMatrix);
351 fContext->setIdentityMatrix();
352
353 // The whole shape is baked into the glyph. Make NVPR just fill the
354 // baked shape.
355 fStroke.setStrokeStyle(-1, false);
356 } else {
357 if (1.0f != fTextRatio || 0.0f != textTranslateY) {
358 SkMatrix textMatrix;
359 textMatrix.setTranslate(0, textTranslateY);
360 textMatrix.preScale(fTextRatio, fTextRatio);
361 fPaint.localCoordChange(textMatrix);
362 fContext->concatMatrix(textMatrix);
363 }
364
365 if (fSkPaint.getStrokeWidth() == 0.0f) {
366 if (fSkPaint.getStyle() == SkPaint::kStrokeAndFill_Style) {
367 fStroke.setStrokeStyle(-1, false);
368 } else if (fSkPaint.getStyle() == SkPaint::kStroke_Style) {
369 // Approximate hairline stroke.
370 const SkMatrix& ctm = fContext->getMatrix();
371 SkScalar strokeWidth = SK_Scalar1 /
372 (SkVector::Make(ctm.getScaleX(), ctm.getSkewY()).length());
373 fStroke.setStrokeStyle(strokeWidth, false);
374 }
375 }
376
377 // Make glyph cache produce paths geometry for fill. We will stroke them
378 // by passing fStroke to drawPath. This is the fast path.
379 fSkPaint.setStyle(SkPaint::kFill_Style);
380 }
381 fStateRestore.set(fDrawTarget->drawState()); 331 fStateRestore.set(fDrawTarget->drawState());
382 332
383 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(), 333 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(),
384 fContext->getRenderTarget()); 334 fContext->getRenderTarget());
385 335
386 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 336 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
387 kZero_StencilOp, 337 kZero_StencilOp,
388 kZero_StencilOp, 338 kZero_StencilOp,
389 kNotEqual_StencilFunc, 339 kNotEqual_StencilFunc,
390 0xffff, 340 0xffff,
391 0x0000, 341 0x0000,
392 0xffff); 342 0xffff);
393 343
394 *fDrawTarget->drawState()->stencil() = kStencilPass; 344 *fDrawTarget->drawState()->stencil() = kStencilPass;
395 345
396 SkASSERT(0 == fPendingGlyphCount); 346 SkASSERT(0 == fPendingGlyphCount);
397 } 347 }
398 348
399 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) { 349 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) {
400 SkASSERT(GrPathRendering::kTranslateX_PathTransformType == fTransformType); 350 SkASSERT(GrPathRendering::kTranslateX_PathTransformType == fTransformType);
401 351
402 if (fPendingGlyphCount >= kGlyphBufferSize) { 352 if (fPendingGlyphCount >= kGlyphBufferSize) {
403 this->flush(); 353 this->flush();
404 } 354 }
405 355
406 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
407
408 fIndexBuffer[fPendingGlyphCount] = glyphID; 356 fIndexBuffer[fPendingGlyphCount] = glyphID;
409 fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x; 357 fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x;
410 358
411 ++fPendingGlyphCount; 359 ++fPendingGlyphCount;
412 } 360 }
413 361
414 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) { 362 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
415 SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType); 363 SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType);
416 364
417 if (fPendingGlyphCount >= kGlyphBufferSize) { 365 if (fPendingGlyphCount >= kGlyphBufferSize) {
418 this->flush(); 366 this->flush();
419 } 367 }
420 368
421 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
422
423 fIndexBuffer[fPendingGlyphCount] = glyphID; 369 fIndexBuffer[fPendingGlyphCount] = glyphID;
424 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x; 370 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x;
425 fTransformBuffer[2 * fPendingGlyphCount + 1] = fTextInverseRatio * y; 371 fTransformBuffer[2 * fPendingGlyphCount + 1] = -fTextInverseRatio * y;
426 372
427 ++fPendingGlyphCount; 373 ++fPendingGlyphCount;
428 } 374 }
429 375
430 void GrStencilAndCoverTextContext::flush() { 376 void GrStencilAndCoverTextContext::flush() {
431 if (0 == fPendingGlyphCount) { 377 if (0 == fPendingGlyphCount) {
432 return; 378 return;
433 } 379 }
434 380
435 fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCoun t, 381 fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount,
436 fTransformBuffer, fTransformType, SkPath::kWinding_Fi llType); 382 fTransformBuffer, fTransformType, SkPath::kWinding_Fi llType);
437 383
438 fPendingGlyphCount = 0; 384 fPendingGlyphCount = 0;
439 } 385 }
440 386
441 void GrStencilAndCoverTextContext::finish() { 387 void GrStencilAndCoverTextContext::finish() {
442 this->flush(); 388 this->flush();
443 389
444 SkSafeUnref(fGlyphs); 390 fGlyphs->unref();
445 fGlyphs = NULL; 391 fGlyphs = NULL;
392
393 SkGlyphCache::AttachCache(fGlyphCache);
446 fGlyphCache = NULL; 394 fGlyphCache = NULL;
447 395
448 fDrawTarget->drawState()->stencil()->setDisabled(); 396 fDrawTarget->drawState()->stencil()->setDisabled();
449 fStateRestore.set(NULL); 397 fStateRestore.set(NULL);
450 fContext->setMatrix(fContextInitialMatrix); 398 fContext->setMatrix(fContextInitialMatrix);
451 GrTextContext::finish(); 399 GrTextContext::finish();
452 } 400 }
453 401
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698