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

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: Fix builds 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
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | src/gpu/gl/GrGLPath.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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()->pathRendering()->createPathRange(kMaxGly phCount, 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 12 matching lines...) Expand all
133 // too. This in turn has the side-effect that NVPR can not stroke the paths, 47 // too. This in turn has the side-effect that NVPR can not stroke the paths,
134 // as the stroke in NVPR is defined in object-space. 48 // as the stroke in NVPR is defined in object-space.
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, kMaxAccuracy_RenderMode);
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 135
226 // This is the fast path. Here we do not bake in the device-transform to 136 // This is the fast path. Here we do not bake in the device-transform to
227 // the glyph outline or the advances. This is because we do not need to 137 // the glyph outline or the advances. This is because we do not need to
228 // position the glyphs at all, since the caller has done the positioning. 138 // position the glyphs at all, since the caller has done the positioning.
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, kMaxPerformance_RenderMode, textTrans lateY);
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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 && fContext->getMatrix().hasPerspective()) { 207 && fContext->getMatrix().hasPerspective()) {
302 return false; 208 return false;
303 } 209 }
304 210
305 // No color bitmap fonts. 211 // No color bitmap fonts.
306 SkScalerContext::Rec rec; 212 SkScalerContext::Rec rec;
307 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); 213 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
308 return rec.getFormat() != SkMask::kARGB32_Format; 214 return rec.getFormat() != SkMask::kARGB32_Format;
309 } 215 }
310 216
217 static GrPathRange* get_gr_glyphs(GrContext* ctx,
218 const SkTypeface* typeface,
219 const SkDescriptor* desc,
220 const SkStrokeRec& stroke) {
221 static const GrCacheID::Domain gGlyphsDomain = GrCacheID::GenerateDomain();
222
223 GrCacheID::Key key;
224 uint64_t* keyData = key.fData64;
225 keyData[0] = desc ? desc->getChecksum() : 0;
226 keyData[0] = (keyData[0] << 32) | (typeface ? typeface->uniqueID() : 0);
227 keyData[1] = GrPath::ComputeStrokeKey(stroke);
228 GrResourceKey resourceKey = GrResourceKey(GrCacheID(gGlyphsDomain, key),
229 GrPathRange::resourceType(), 0);
230
231 SkAutoTUnref<GrPathRange> glyphs(
232 static_cast<GrPathRange*>(ctx->findAndRefCachedResource(resourceKey)));
233 if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) {
234 glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc , stroke));
235 ctx->addResourceToCache(resourceKey, glyphs);
236 }
237
238 return glyphs.detach();
239 }
240
311 void GrStencilAndCoverTextContext::init(const GrPaint& paint, 241 void GrStencilAndCoverTextContext::init(const GrPaint& paint,
312 const SkPaint& skPaint, 242 const SkPaint& skPaint,
313 size_t textByteLength, 243 size_t textByteLength,
314 DeviceSpaceGlyphsBehavior deviceSpaceGly phsBehavior, 244 RenderMode renderMode,
315 SkScalar textTranslateY) { 245 SkScalar textTranslateY) {
316 GrTextContext::init(paint, skPaint); 246 GrTextContext::init(paint, skPaint);
317 247
318 fContextInitialMatrix = fContext->getMatrix(); 248 fContextInitialMatrix = fContext->getMatrix();
319 249
320 bool otherBackendsWillDrawAsPaths = 250 const bool otherBackendsWillDrawAsPaths =
321 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); 251 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
322 252
323 if (otherBackendsWillDrawAsPaths) { 253 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths &&
324 // This is to reproduce SkDraw::drawText_asPaths glyph positions. 254 kMaxAccuracy_RenderMode == renderMode &&
325 fSkPaint.setLinearText(true); 255 SkToBool(fContextInitialMatrix.getType() &
326 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPath s; 256 (SkMatrix::kScale_Mask | SkMatrix::kAffin e_Mask));
327 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTe xtSize(); 257
328 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)) ; 258 if (fNeedsDeviceSpaceGlyphs) {
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. 259 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms.
342 SkASSERT(!fContextInitialMatrix.hasPerspective()); 260 SkASSERT(!fContextInitialMatrix.hasPerspective());
261 SkASSERT(0 == textTranslateY); // TODO: Handle textTranslateY in device- space usecase.
262
263 fTextRatio = fTextInverseRatio = 1.0f;
264
265 // Glyphs loaded by GPU path rendering have an inverted y-direction.
266 SkMatrix m;
267 m.setScale(1, -1);
268 fContext->setMatrix(m);
269
270 // Post-flip the initial matrix so we're left with just the flip after
271 // the paint preConcats the inverse.
272 m = fContextInitialMatrix;
273 m.postScale(1, -1);
274 fPaint.localCoordChangeInverse(m);
275
276 // The whole shape (including stroke) will be baked into the glyph outli nes. Make
277 // NVPR just fill the baked shapes.
278 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialM atrix, false);
279 fGlyphs = get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTy peface(),
280 &fGlyphCache->getDescriptor(),
281 SkStrokeRec(SkStrokeRec::kFill_InitStyle));
282 } else {
283 // Don't bake strokes into the glyph outlines. We will stroke the glyphs
284 // using the GPU instead. This is the fast path.
285 SkStrokeRec gpuStroke = SkStrokeRec(fSkPaint);
286 fSkPaint.setStyle(SkPaint::kFill_Style);
287
288 if (gpuStroke.isHairlineStyle()) {
289 // Approximate hairline stroke.
290 SkScalar strokeWidth = SK_Scalar1 /
291 (SkVector::Make(fContextInitialMatrix.getScaleX(),
292 fContextInitialMatrix.getSkewY()).length());
293 gpuStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/);
294
295 } else if (fSkPaint.isFakeBoldText() &&
296 #ifdef SK_USE_FREETYPE_EMBOLDEN
297 kMaxPerformance_RenderMode == renderMode &&
298 #endif
299 SkStrokeRec::kStroke_Style != gpuStroke.getStyle()) {
300
301 // Instead of baking fake bold into the glyph outlines, do it with t he GPU stroke.
302 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
303 kStdFakeBoldInterpKeys,
304 kStdFakeBoldInterpValues ,
305 kStdFakeBoldInterpLength );
306 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
307 gpuStroke.setStrokeStyle(gpuStroke.needToApply() ? gpuStroke.getWidt h() + extra : extra,
308 true /*strokeAndFill*/);
309
310 fSkPaint.setFakeBoldText(false);
311 }
312
313 bool canUseRawPaths;
314
315 if (otherBackendsWillDrawAsPaths || kMaxPerformance_RenderMode == render Mode) {
316 // We can draw the glyphs from canonically sized paths.
317 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeFor Paths;
318 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.g etTextSize();
319
320 // Compensate for the glyphs being scaled by fTextRatio.
321 if (!gpuStroke.isFillStyle()) {
322 gpuStroke.setStrokeStyle(gpuStroke.getWidth() / fTextRatio,
323 SkStrokeRec::kStrokeAndFill_Style == gp uStroke.getStyle());
324 }
325
326 fSkPaint.setLinearText(true);
327 fSkPaint.setLCDRenderText(false);
328 fSkPaint.setAutohinted(false);
329 fSkPaint.setHinting(SkPaint::kNo_Hinting);
330 fSkPaint.setSubpixelText(true);
331 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPat hs));
332
333 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
334 0 == fSkPaint.getTextSkewX() &&
335 !fSkPaint.isFakeBoldText() &&
336 !fSkPaint.isVerticalText();
337 } else {
338 fTextRatio = fTextInverseRatio = 1.0f;
339 canUseRawPaths = false;
340 }
341
342 SkMatrix textMatrix;
343 textMatrix.setTranslate(0, textTranslateY);
344 // Glyphs loaded by GPU path rendering have an inverted y-direction.
345 textMatrix.preScale(fTextRatio, -fTextRatio);
346 fPaint.localCoordChange(textMatrix);
347 fContext->concatMatrix(textMatrix);
348
349 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false);
350 fGlyphs = canUseRawPaths ?
351 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS troke) :
352 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g etTypeface(),
353 &fGlyphCache->getDescriptor(), gpuStroke);
343 } 354 }
344 355
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()); 356 fStateRestore.set(fDrawTarget->drawState());
382 357
383 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(), 358 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(),
384 fContext->getRenderTarget()); 359 fContext->getRenderTarget());
385 360
386 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 361 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
387 kZero_StencilOp, 362 kZero_StencilOp,
388 kZero_StencilOp, 363 kZero_StencilOp,
389 kNotEqual_StencilFunc, 364 kNotEqual_StencilFunc,
390 0xffff, 365 0xffff,
391 0x0000, 366 0x0000,
392 0xffff); 367 0xffff);
393 368
394 *fDrawTarget->drawState()->stencil() = kStencilPass; 369 *fDrawTarget->drawState()->stencil() = kStencilPass;
395 370
396 SkASSERT(0 == fPendingGlyphCount); 371 SkASSERT(0 == fPendingGlyphCount);
397 } 372 }
398 373
399 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) { 374 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) {
400 SkASSERT(GrPathRendering::kTranslateX_PathTransformType == fTransformType); 375 SkASSERT(GrPathRendering::kTranslateX_PathTransformType == fTransformType);
401 376
402 if (fPendingGlyphCount >= kGlyphBufferSize) { 377 if (fPendingGlyphCount >= kGlyphBufferSize) {
403 this->flush(); 378 this->flush();
404 } 379 }
405 380
406 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
407
408 fIndexBuffer[fPendingGlyphCount] = glyphID; 381 fIndexBuffer[fPendingGlyphCount] = glyphID;
409 fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x; 382 fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x;
410 383
411 ++fPendingGlyphCount; 384 ++fPendingGlyphCount;
412 } 385 }
413 386
414 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) { 387 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
415 SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType); 388 SkASSERT(GrPathRendering::kTranslate_PathTransformType == fTransformType);
416 389
417 if (fPendingGlyphCount >= kGlyphBufferSize) { 390 if (fPendingGlyphCount >= kGlyphBufferSize) {
418 this->flush(); 391 this->flush();
419 } 392 }
420 393
421 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
422
423 fIndexBuffer[fPendingGlyphCount] = glyphID; 394 fIndexBuffer[fPendingGlyphCount] = glyphID;
424 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x; 395 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x;
425 fTransformBuffer[2 * fPendingGlyphCount + 1] = fTextInverseRatio * y; 396 fTransformBuffer[2 * fPendingGlyphCount + 1] = -fTextInverseRatio * y;
426 397
427 ++fPendingGlyphCount; 398 ++fPendingGlyphCount;
428 } 399 }
429 400
430 void GrStencilAndCoverTextContext::flush() { 401 void GrStencilAndCoverTextContext::flush() {
431 if (0 == fPendingGlyphCount) { 402 if (0 == fPendingGlyphCount) {
432 return; 403 return;
433 } 404 }
434 405
435 fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCoun t, 406 fDrawTarget->drawPaths(fGlyphs, fIndexBuffer, fPendingGlyphCount,
436 fTransformBuffer, fTransformType, SkPath::kWinding_Fi llType); 407 fTransformBuffer, fTransformType, SkPath::kWinding_Fi llType);
437 408
438 fPendingGlyphCount = 0; 409 fPendingGlyphCount = 0;
439 } 410 }
440 411
441 void GrStencilAndCoverTextContext::finish() { 412 void GrStencilAndCoverTextContext::finish() {
442 this->flush(); 413 this->flush();
443 414
444 SkSafeUnref(fGlyphs); 415 fGlyphs->unref();
445 fGlyphs = NULL; 416 fGlyphs = NULL;
417
418 SkGlyphCache::AttachCache(fGlyphCache);
446 fGlyphCache = NULL; 419 fGlyphCache = NULL;
447 420
448 fDrawTarget->drawState()->stencil()->setDisabled(); 421 fDrawTarget->drawState()->stencil()->setDisabled();
449 fStateRestore.set(NULL); 422 fStateRestore.set(NULL);
450 fContext->setMatrix(fContextInitialMatrix); 423 fContext->setMatrix(fContextInitialMatrix);
451 GrTextContext::finish(); 424 GrTextContext::finish();
452 } 425 }
453 426
OLDNEW
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | src/gpu/gl/GrGLPath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698