OLD | NEW |
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 "GrBitmapTextContext.h" | 9 #include "GrBitmapTextContext.h" |
10 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 && viewMatrix.hasPerspective()) { | 57 && viewMatrix.hasPerspective()) { |
58 return false; | 58 return false; |
59 } | 59 } |
60 | 60 |
61 // No color bitmap fonts. | 61 // No color bitmap fonts. |
62 SkScalerContext::Rec rec; | 62 SkScalerContext::Rec rec; |
63 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); | 63 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); |
64 return rec.getFormat() != SkMask::kARGB32_Format; | 64 return rec.getFormat() != SkMask::kARGB32_Format; |
65 } | 65 } |
66 | 66 |
67 void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint, | 67 void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt, |
| 68 const GrPaint& paint, |
68 const SkPaint& skPaint, | 69 const SkPaint& skPaint, |
69 const SkMatrix& viewMatrix, | 70 const SkMatrix& viewMatrix, |
70 const char text[], | 71 const char text[], |
71 size_t byteLength, | 72 size_t byteLength, |
72 SkScalar x, SkScalar y) { | 73 SkScalar x, SkScalar y) { |
73 SkASSERT(byteLength == 0 || text != NULL); | 74 SkASSERT(byteLength == 0 || text != NULL); |
74 | 75 |
75 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { | 76 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { |
76 return; | 77 return; |
77 } | 78 } |
78 | 79 |
79 // This is the slow path, mainly used by Skia unit tests. The other | 80 // This is the slow path, mainly used by Skia unit tests. The other |
80 // backends (8888, gpu, ...) use device-space dependent glyph caches. In | 81 // backends (8888, gpu, ...) use device-space dependent glyph caches. In |
81 // order to match the glyph positions that the other code paths produce, we | 82 // order to match the glyph positions that the other code paths produce, we |
82 // must also use device-space dependent glyph cache. This has the | 83 // must also use device-space dependent glyph cache. This has the |
83 // side-effect that the glyph shape outline will be in device-space, | 84 // side-effect that the glyph shape outline will be in device-space, |
84 // too. This in turn has the side-effect that NVPR can not stroke the paths, | 85 // too. This in turn has the side-effect that NVPR can not stroke the paths, |
85 // as the stroke in NVPR is defined in object-space. | 86 // as the stroke in NVPR is defined in object-space. |
86 // NOTE: here we have following coincidence that works at the moment: | 87 // NOTE: here we have following coincidence that works at the moment: |
87 // - When using the device-space glyphs, the transforms we pass to NVPR | 88 // - When using the device-space glyphs, the transforms we pass to NVPR |
88 // instanced drawing are the global transforms, and the view transform is | 89 // instanced drawing are the global transforms, and the view transform is |
89 // identity. NVPR can not use non-affine transforms in the instanced | 90 // identity. NVPR can not use non-affine transforms in the instanced |
90 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it | 91 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it |
91 // will turn off the use of device-space glyphs when perspective transforms | 92 // will turn off the use of device-space glyphs when perspective transforms |
92 // are in use. | 93 // are in use. |
93 | 94 |
94 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode, viewMatrix); | 95 this->init(rt, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, viewMatr
ix); |
95 | 96 |
96 // Transform our starting point. | 97 // Transform our starting point. |
97 if (fUsingDeviceSpaceGlyphs) { | 98 if (fUsingDeviceSpaceGlyphs) { |
98 SkPoint loc; | 99 SkPoint loc; |
99 fContextInitialMatrix.mapXY(x, y, &loc); | 100 fContextInitialMatrix.mapXY(x, y, &loc); |
100 x = loc.fX; | 101 x = loc.fX; |
101 y = loc.fY; | 102 y = loc.fY; |
102 } | 103 } |
103 | 104 |
104 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 105 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy))); | 147 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy))); |
147 } | 148 } |
148 | 149 |
149 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio); | 150 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio); |
150 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedSizeRatio); | 151 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedSizeRatio); |
151 } | 152 } |
152 | 153 |
153 this->finish(); | 154 this->finish(); |
154 } | 155 } |
155 | 156 |
156 void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint, | 157 void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt, |
| 158 const GrPaint& paint, |
157 const SkPaint& skPaint, | 159 const SkPaint& skPaint, |
158 const SkMatrix& viewMatrix, | 160 const SkMatrix& viewMatrix, |
159 const char text[], | 161 const char text[], |
160 size_t byteLength, | 162 size_t byteLength, |
161 const SkScalar pos[], | 163 const SkScalar pos[], |
162 int scalarsPerPosition, | 164 int scalarsPerPosition, |
163 const SkPoint& offset) { | 165 const SkPoint& offset) { |
164 SkASSERT(byteLength == 0 || text != NULL); | 166 SkASSERT(byteLength == 0 || text != NULL); |
165 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 167 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
166 | 168 |
167 // nothing to draw | 169 // nothing to draw |
168 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { | 170 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { |
169 return; | 171 return; |
170 } | 172 } |
171 | 173 |
172 // This is the fast path. Here we do not bake in the device-transform to | 174 // This is the fast path. Here we do not bake in the device-transform to |
173 // the glyph outline or the advances. This is because we do not need to | 175 // the glyph outline or the advances. This is because we do not need to |
174 // position the glyphs at all, since the caller has done the positioning. | 176 // position the glyphs at all, since the caller has done the positioning. |
175 // The positioning is based on SkPaint::measureText of individual | 177 // The positioning is based on SkPaint::measureText of individual |
176 // glyphs. That already uses glyph cache without device transforms. Device | 178 // glyphs. That already uses glyph cache without device transforms. Device |
177 // transform is not part of SkPaint::measureText API, and thus we use the | 179 // transform is not part of SkPaint::measureText API, and thus we use the |
178 // same glyphs as what were measured. | 180 // same glyphs as what were measured. |
179 | 181 |
180 this->init(paint, skPaint, byteLength, kMaxPerformance_RenderMode, viewMatri
x); | 182 this->init(rt, paint, skPaint, byteLength, kMaxPerformance_RenderMode, viewM
atrix); |
181 | 183 |
182 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 184 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
183 | 185 |
184 const char* stop = text + byteLength; | 186 const char* stop = text + byteLength; |
185 | 187 |
186 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 188 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
187 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); | 189 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); |
188 while (text < stop) { | 190 while (text < stop) { |
189 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 191 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
190 if (glyph.fWidth) { | 192 if (glyph.fWidth) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 SkAutoTUnref<GrPathRange> glyphs( | 224 SkAutoTUnref<GrPathRange> glyphs( |
223 static_cast<GrPathRange*>(ctx->findAndRefCachedResource(key))); | 225 static_cast<GrPathRange*>(ctx->findAndRefCachedResource(key))); |
224 if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) { | 226 if (NULL == glyphs || (NULL != desc && !glyphs->isEqualTo(*desc))) { |
225 glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc
, stroke)); | 227 glyphs.reset(ctx->getGpu()->pathRendering()->createGlyphs(typeface, desc
, stroke)); |
226 ctx->addResourceToCache(key, glyphs); | 228 ctx->addResourceToCache(key, glyphs); |
227 } | 229 } |
228 | 230 |
229 return glyphs.detach(); | 231 return glyphs.detach(); |
230 } | 232 } |
231 | 233 |
232 void GrStencilAndCoverTextContext::init(const GrPaint& paint, | 234 void GrStencilAndCoverTextContext::init(GrRenderTarget* rt, |
| 235 const GrPaint& paint, |
233 const SkPaint& skPaint, | 236 const SkPaint& skPaint, |
234 size_t textByteLength, | 237 size_t textByteLength, |
235 RenderMode renderMode, | 238 RenderMode renderMode, |
236 const SkMatrix& viewMatrix) { | 239 const SkMatrix& viewMatrix) { |
237 GrTextContext::init(paint, skPaint); | 240 GrTextContext::init(rt, paint, skPaint); |
238 | 241 |
239 fContextInitialMatrix = viewMatrix; | 242 fContextInitialMatrix = viewMatrix; |
240 fViewMatrix = viewMatrix; | 243 fViewMatrix = viewMatrix; |
241 fLocalMatrix = SkMatrix::I(); | 244 fLocalMatrix = SkMatrix::I(); |
242 | 245 |
243 const bool otherBackendsWillDrawAsPaths = | 246 const bool otherBackendsWillDrawAsPaths = |
244 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); | 247 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); |
245 | 248 |
246 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && | 249 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && |
247 kMaxAccuracy_RenderMode == renderMode && | 250 kMaxAccuracy_RenderMode == renderMode && |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 | 347 |
345 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, true /*igno
reGamma*/); | 348 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, true /*igno
reGamma*/); |
346 fGlyphs = canUseRawPaths ? | 349 fGlyphs = canUseRawPaths ? |
347 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, fStr
oke) : | 350 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, fStr
oke) : |
348 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), | 351 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), |
349 &fGlyphCache->getDescriptor(), fStroke); | 352 &fGlyphCache->getDescriptor(), fStroke); |
350 } | 353 } |
351 | 354 |
352 fStateRestore.set(&fPipelineBuilder); | 355 fStateRestore.set(&fPipelineBuilder); |
353 | 356 |
354 fPipelineBuilder.setFromPaint(fPaint, fContext->getRenderTarget()); | 357 fPipelineBuilder.setFromPaint(fPaint, fRenderTarget); |
355 | 358 |
356 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | 359 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, |
357 kZero_StencilOp, | 360 kZero_StencilOp, |
358 kZero_StencilOp, | 361 kZero_StencilOp, |
359 kNotEqual_StencilFunc, | 362 kNotEqual_StencilFunc, |
360 0xffff, | 363 0xffff, |
361 0x0000, | 364 0x0000, |
362 0xffff); | 365 0xffff); |
363 | 366 |
364 *fPipelineBuilder.stencil() = kStencilPass; | 367 *fPipelineBuilder.stencil() = kStencilPass; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 fStroke.applyToPaint(&skPaintFallback); | 435 fStroke.applyToPaint(&skPaintFallback); |
433 } | 436 } |
434 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already
been accounted for. | 437 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already
been accounted for. |
435 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 438 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
436 | 439 |
437 SkMatrix inverse; | 440 SkMatrix inverse; |
438 if (this->mapToFallbackContext(&inverse)) { | 441 if (this->mapToFallbackContext(&inverse)) { |
439 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp
hCount); | 442 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp
hCount); |
440 } | 443 } |
441 | 444 |
442 fFallbackTextContext->drawPosText(paintFallback, skPaintFallback, fViewM
atrix, | 445 fFallbackTextContext->drawPosText(fRenderTarget, paintFallback, skPaintF
allback, |
443 (char*)&fGlyphIndices[fFallbackGlyphsI
dx], | 446 fViewMatrix, (char*)&fGlyphIndices[fFa
llbackGlyphsIdx], |
444 2 * fallbackGlyphCount, | 447 2 * fallbackGlyphCount, |
445 get_xy_scalar_array(&fGlyphPositions[f
FallbackGlyphsIdx]), | 448 get_xy_scalar_array(&fGlyphPositions[f
FallbackGlyphsIdx]), |
446 2, SkPoint::Make(0, 0)); | 449 2, SkPoint::Make(0, 0)); |
447 | 450 |
448 fFallbackGlyphsIdx = kGlyphBufferSize; | 451 fFallbackGlyphsIdx = kGlyphBufferSize; |
449 } | 452 } |
450 } | 453 } |
451 | 454 |
452 void GrStencilAndCoverTextContext::finish() { | 455 void GrStencilAndCoverTextContext::finish() { |
453 this->flush(); | 456 this->flush(); |
454 | 457 |
455 fGlyphs->unref(); | 458 fGlyphs->unref(); |
456 fGlyphs = NULL; | 459 fGlyphs = NULL; |
457 | 460 |
458 SkGlyphCache::AttachCache(fGlyphCache); | 461 SkGlyphCache::AttachCache(fGlyphCache); |
459 fGlyphCache = NULL; | 462 fGlyphCache = NULL; |
460 | 463 |
461 fPipelineBuilder.stencil()->setDisabled(); | 464 fPipelineBuilder.stencil()->setDisabled(); |
462 fStateRestore.set(NULL); | 465 fStateRestore.set(NULL); |
463 fViewMatrix = fContextInitialMatrix; | 466 fViewMatrix = fContextInitialMatrix; |
464 GrTextContext::finish(); | 467 GrTextContext::finish(); |
465 } | 468 } |
466 | 469 |
OLD | NEW |