| 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" |
| 11 #include "GrGpu.h" | 11 #include "GrGpu.h" |
| 12 #include "GrPath.h" | 12 #include "GrPath.h" |
| 13 #include "GrPathRange.h" | 13 #include "GrPathRange.h" |
| 14 #include "SkAutoKern.h" | 14 #include "SkAutoKern.h" |
| 15 #include "SkDraw.h" | 15 #include "SkDraw.h" |
| 16 #include "SkDrawProcs.h" | 16 #include "SkDrawProcs.h" |
| 17 #include "SkGlyphCache.h" | 17 #include "SkGlyphCache.h" |
| 18 #include "SkGpuDevice.h" | 18 #include "SkGpuDevice.h" |
| 19 #include "SkPath.h" | 19 #include "SkPath.h" |
| 20 #include "SkTextMapStateProc.h" | 20 #include "SkTextMapStateProc.h" |
| 21 #include "SkTextFormatParams.h" | 21 #include "SkTextFormatParams.h" |
| 22 | 22 |
| 23 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext( | 23 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, |
| 24 GrContext* context, const SkDeviceProperties& properties) | 24 SkGpuDevice* gpuDevic
e, |
| 25 : GrTextContext(context, properties) | 25 const SkDevicePropert
ies& properties) |
| 26 : GrTextContext(context, gpuDevice, properties) |
| 26 , fStroke(SkStrokeRec::kFill_InitStyle) | 27 , fStroke(SkStrokeRec::kFill_InitStyle) |
| 27 , fQueuedGlyphCount(0) | 28 , fQueuedGlyphCount(0) |
| 28 , fFallbackGlyphsIdx(kGlyphBufferSize) { | 29 , fFallbackGlyphsIdx(kGlyphBufferSize) { |
| 29 } | 30 } |
| 30 | 31 |
| 31 GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* co
ntext, | 32 GrStencilAndCoverTextContext* |
| 32 const SkDeviceP
roperties& props) { | 33 GrStencilAndCoverTextContext::Create(GrContext* context, SkGpuDevice* gpuDevice, |
| 34 const SkDeviceProperties& props) { |
| 33 GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverText
Context, | 35 GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverText
Context, |
| 34 (context, props)); | 36 (context, gpuDevice,
props)); |
| 35 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, pro
ps); | 37 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, gpu
Device, props); |
| 36 | 38 |
| 37 return textContext; | 39 return textContext; |
| 38 } | 40 } |
| 39 | 41 |
| 40 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { | 42 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { |
| 41 } | 43 } |
| 42 | 44 |
| 43 bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint, const SkMatrix&
viewMatrix) { | 45 bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint, const SkMatrix&
viewMatrix) { |
| 44 if (paint.getRasterizer()) { | 46 if (paint.getRasterizer()) { |
| 45 return false; | 47 return false; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 64 return rec.getFormat() != SkMask::kARGB32_Format; | 66 return rec.getFormat() != SkMask::kARGB32_Format; |
| 65 } | 67 } |
| 66 | 68 |
| 67 void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt, | 69 void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt, |
| 68 const GrClip& clip, | 70 const GrClip& clip, |
| 69 const GrPaint& paint, | 71 const GrPaint& paint, |
| 70 const SkPaint& skPaint, | 72 const SkPaint& skPaint, |
| 71 const SkMatrix& viewMatrix, | 73 const SkMatrix& viewMatrix, |
| 72 const char text[], | 74 const char text[], |
| 73 size_t byteLength, | 75 size_t byteLength, |
| 74 SkScalar x, SkScalar y) { | 76 SkScalar x, SkScalar y, |
| 77 const SkIRect& regionClipBounds) { |
| 75 SkASSERT(byteLength == 0 || text != NULL); | 78 SkASSERT(byteLength == 0 || text != NULL); |
| 76 | 79 |
| 77 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { | 80 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { |
| 78 return; | 81 return; |
| 79 } | 82 } |
| 80 | 83 |
| 81 // This is the slow path, mainly used by Skia unit tests. The other | 84 // This is the slow path, mainly used by Skia unit tests. The other |
| 82 // backends (8888, gpu, ...) use device-space dependent glyph caches. In | 85 // backends (8888, gpu, ...) use device-space dependent glyph caches. In |
| 83 // order to match the glyph positions that the other code paths produce, we | 86 // order to match the glyph positions that the other code paths produce, we |
| 84 // must also use device-space dependent glyph cache. This has the | 87 // must also use device-space dependent glyph cache. This has the |
| 85 // side-effect that the glyph shape outline will be in device-space, | 88 // side-effect that the glyph shape outline will be in device-space, |
| 86 // too. This in turn has the side-effect that NVPR can not stroke the paths, | 89 // too. This in turn has the side-effect that NVPR can not stroke the paths, |
| 87 // as the stroke in NVPR is defined in object-space. | 90 // as the stroke in NVPR is defined in object-space. |
| 88 // NOTE: here we have following coincidence that works at the moment: | 91 // NOTE: here we have following coincidence that works at the moment: |
| 89 // - When using the device-space glyphs, the transforms we pass to NVPR | 92 // - When using the device-space glyphs, the transforms we pass to NVPR |
| 90 // instanced drawing are the global transforms, and the view transform is | 93 // instanced drawing are the global transforms, and the view transform is |
| 91 // identity. NVPR can not use non-affine transforms in the instanced | 94 // identity. NVPR can not use non-affine transforms in the instanced |
| 92 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it | 95 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it |
| 93 // will turn off the use of device-space glyphs when perspective transforms | 96 // will turn off the use of device-space glyphs when perspective transforms |
| 94 // are in use. | 97 // are in use. |
| 95 | 98 |
| 96 this->init(rt, clip, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, vi
ewMatrix); | 99 this->init(rt, clip, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, vi
ewMatrix, |
| 100 regionClipBounds); |
| 97 | 101 |
| 98 // Transform our starting point. | 102 // Transform our starting point. |
| 99 if (fUsingDeviceSpaceGlyphs) { | 103 if (fUsingDeviceSpaceGlyphs) { |
| 100 SkPoint loc; | 104 SkPoint loc; |
| 101 fContextInitialMatrix.mapXY(x, y, &loc); | 105 fContextInitialMatrix.mapXY(x, y, &loc); |
| 102 x = loc.fX; | 106 x = loc.fX; |
| 103 y = loc.fY; | 107 y = loc.fY; |
| 104 } | 108 } |
| 105 | 109 |
| 106 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 110 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 | 161 |
| 158 void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt, | 162 void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt, |
| 159 const GrClip& clip, | 163 const GrClip& clip, |
| 160 const GrPaint& paint, | 164 const GrPaint& paint, |
| 161 const SkPaint& skPaint, | 165 const SkPaint& skPaint, |
| 162 const SkMatrix& viewMatrix, | 166 const SkMatrix& viewMatrix, |
| 163 const char text[], | 167 const char text[], |
| 164 size_t byteLength, | 168 size_t byteLength, |
| 165 const SkScalar pos[], | 169 const SkScalar pos[], |
| 166 int scalarsPerPosition, | 170 int scalarsPerPosition, |
| 167 const SkPoint& offset) { | 171 const SkPoint& offset, |
| 172 const SkIRect& regionClipBounds
) { |
| 168 SkASSERT(byteLength == 0 || text != NULL); | 173 SkASSERT(byteLength == 0 || text != NULL); |
| 169 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 174 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| 170 | 175 |
| 171 // nothing to draw | 176 // nothing to draw |
| 172 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { | 177 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { |
| 173 return; | 178 return; |
| 174 } | 179 } |
| 175 | 180 |
| 176 // This is the fast path. Here we do not bake in the device-transform to | 181 // This is the fast path. Here we do not bake in the device-transform to |
| 177 // the glyph outline or the advances. This is because we do not need to | 182 // the glyph outline or the advances. This is because we do not need to |
| 178 // position the glyphs at all, since the caller has done the positioning. | 183 // position the glyphs at all, since the caller has done the positioning. |
| 179 // The positioning is based on SkPaint::measureText of individual | 184 // The positioning is based on SkPaint::measureText of individual |
| 180 // glyphs. That already uses glyph cache without device transforms. Device | 185 // glyphs. That already uses glyph cache without device transforms. Device |
| 181 // transform is not part of SkPaint::measureText API, and thus we use the | 186 // transform is not part of SkPaint::measureText API, and thus we use the |
| 182 // same glyphs as what were measured. | 187 // same glyphs as what were measured. |
| 183 | 188 |
| 184 this->init(rt, clip, paint, skPaint, byteLength, kMaxPerformance_RenderMode,
viewMatrix); | 189 this->init(rt, clip, paint, skPaint, byteLength, kMaxPerformance_RenderMode,
viewMatrix, |
| 190 regionClipBounds); |
| 185 | 191 |
| 186 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 192 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 187 | 193 |
| 188 const char* stop = text + byteLength; | 194 const char* stop = text + byteLength; |
| 189 | 195 |
| 190 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 196 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
| 191 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); | 197 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); |
| 192 while (text < stop) { | 198 while (text < stop) { |
| 193 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 199 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 194 if (glyph.fWidth) { | 200 if (glyph.fWidth) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 | 238 |
| 233 return glyphs.detach(); | 239 return glyphs.detach(); |
| 234 } | 240 } |
| 235 | 241 |
| 236 void GrStencilAndCoverTextContext::init(GrRenderTarget* rt, | 242 void GrStencilAndCoverTextContext::init(GrRenderTarget* rt, |
| 237 const GrClip& clip, | 243 const GrClip& clip, |
| 238 const GrPaint& paint, | 244 const GrPaint& paint, |
| 239 const SkPaint& skPaint, | 245 const SkPaint& skPaint, |
| 240 size_t textByteLength, | 246 size_t textByteLength, |
| 241 RenderMode renderMode, | 247 RenderMode renderMode, |
| 242 const SkMatrix& viewMatrix) { | 248 const SkMatrix& viewMatrix, |
| 243 GrTextContext::init(rt, clip, paint, skPaint); | 249 const SkIRect& regionClipBounds) { |
| 250 GrTextContext::init(rt, clip, paint, skPaint, regionClipBounds); |
| 244 | 251 |
| 245 fContextInitialMatrix = viewMatrix; | 252 fContextInitialMatrix = viewMatrix; |
| 246 fViewMatrix = viewMatrix; | 253 fViewMatrix = viewMatrix; |
| 247 fLocalMatrix = SkMatrix::I(); | 254 fLocalMatrix = SkMatrix::I(); |
| 248 | 255 |
| 249 const bool otherBackendsWillDrawAsPaths = | 256 const bool otherBackendsWillDrawAsPaths = |
| 250 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); | 257 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); |
| 251 | 258 |
| 252 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && | 259 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && |
| 253 kMaxAccuracy_RenderMode == renderMode && | 260 kMaxAccuracy_RenderMode == renderMode && |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 | 449 |
| 443 SkMatrix inverse; | 450 SkMatrix inverse; |
| 444 if (this->mapToFallbackContext(&inverse)) { | 451 if (this->mapToFallbackContext(&inverse)) { |
| 445 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp
hCount); | 452 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp
hCount); |
| 446 } | 453 } |
| 447 | 454 |
| 448 fFallbackTextContext->drawPosText(fRenderTarget, fClip, paintFallback, s
kPaintFallback, | 455 fFallbackTextContext->drawPosText(fRenderTarget, fClip, paintFallback, s
kPaintFallback, |
| 449 fViewMatrix, (char*)&fGlyphIndices[fFa
llbackGlyphsIdx], | 456 fViewMatrix, (char*)&fGlyphIndices[fFa
llbackGlyphsIdx], |
| 450 2 * fallbackGlyphCount, | 457 2 * fallbackGlyphCount, |
| 451 get_xy_scalar_array(&fGlyphPositions[f
FallbackGlyphsIdx]), | 458 get_xy_scalar_array(&fGlyphPositions[f
FallbackGlyphsIdx]), |
| 452 2, SkPoint::Make(0, 0)); | 459 2, SkPoint::Make(0, 0), fRegionClipBou
nds); |
| 453 | 460 |
| 454 fFallbackGlyphsIdx = kGlyphBufferSize; | 461 fFallbackGlyphsIdx = kGlyphBufferSize; |
| 455 } | 462 } |
| 456 } | 463 } |
| 457 | 464 |
| 458 void GrStencilAndCoverTextContext::finish() { | 465 void GrStencilAndCoverTextContext::finish() { |
| 459 this->flush(); | 466 this->flush(); |
| 460 | 467 |
| 461 fGlyphs->unref(); | 468 fGlyphs->unref(); |
| 462 fGlyphs = NULL; | 469 fGlyphs = NULL; |
| 463 | 470 |
| 464 SkGlyphCache::AttachCache(fGlyphCache); | 471 SkGlyphCache::AttachCache(fGlyphCache); |
| 465 fGlyphCache = NULL; | 472 fGlyphCache = NULL; |
| 466 | 473 |
| 467 fPipelineBuilder.stencil()->setDisabled(); | 474 fPipelineBuilder.stencil()->setDisabled(); |
| 468 fStateRestore.set(NULL); | 475 fStateRestore.set(NULL); |
| 469 fViewMatrix = fContextInitialMatrix; | 476 fViewMatrix = fContextInitialMatrix; |
| 470 GrTextContext::finish(); | 477 GrTextContext::finish(); |
| 471 } | 478 } |
| 472 | 479 |
| OLD | NEW |