| 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 "GrDrawTarget.h" | 9 #include "GrDrawTarget.h" |
| 10 #include "GrGpu.h" | 10 #include "GrGpu.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 // 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, |
| 48 // as the stroke in NVPR is defined in object-space. | 48 // as the stroke in NVPR is defined in object-space. |
| 49 // NOTE: here we have following coincidence that works at the moment: | 49 // NOTE: here we have following coincidence that works at the moment: |
| 50 // - 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 |
| 51 // instanced drawing are the global transforms, and the view transform is | 51 // instanced drawing are the global transforms, and the view transform is |
| 52 // identity. NVPR can not use non-affine transforms in the instanced | 52 // identity. NVPR can not use non-affine transforms in the instanced |
| 53 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it | 53 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it |
| 54 // 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 |
| 55 // are in use. | 55 // are in use. |
| 56 | 56 |
| 57 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode); | 57 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode, SkPoint::Mak
e(0, 0)); |
| 58 | 58 |
| 59 // Transform our starting point. | 59 // Transform our starting point. |
| 60 if (fNeedsDeviceSpaceGlyphs) { | 60 if (fNeedsDeviceSpaceGlyphs) { |
| 61 SkPoint loc; | 61 SkPoint loc; |
| 62 fContextInitialMatrix.mapXY(x, y, &loc); | 62 fContextInitialMatrix.mapXY(x, y, &loc); |
| 63 x = loc.fX; | 63 x = loc.fX; |
| 64 y = loc.fY; | 64 y = loc.fY; |
| 65 } | 65 } |
| 66 | 66 |
| 67 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 67 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 } | 116 } |
| 117 | 117 |
| 118 this->finish(); | 118 this->finish(); |
| 119 } | 119 } |
| 120 | 120 |
| 121 void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint, | 121 void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint, |
| 122 const SkPaint& skPaint, | 122 const SkPaint& skPaint, |
| 123 const char text[], | 123 const char text[], |
| 124 size_t byteLength, | 124 size_t byteLength, |
| 125 const SkScalar pos[], | 125 const SkScalar pos[], |
| 126 SkScalar constY, | 126 int scalarsPerPosition, |
| 127 int scalarsPerPosition) { | 127 const SkPoint& offset) { |
| 128 SkASSERT(byteLength == 0 || text != NULL); | 128 SkASSERT(byteLength == 0 || text != NULL); |
| 129 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 129 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| 130 | 130 |
| 131 // nothing to draw | 131 // nothing to draw |
| 132 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { | 132 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { |
| 133 return; | 133 return; |
| 134 } | 134 } |
| 135 | 135 |
| 136 // 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 |
| 137 // 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 |
| 138 // 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. |
| 139 // The positioning is based on SkPaint::measureText of individual | 139 // The positioning is based on SkPaint::measureText of individual |
| 140 // glyphs. That already uses glyph cache without device transforms. Device | 140 // glyphs. That already uses glyph cache without device transforms. Device |
| 141 // 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 |
| 142 // same glyphs as what were measured. | 142 // same glyphs as what were measured. |
| 143 | 143 |
| 144 const float textTranslateY = (1 == scalarsPerPosition ? constY : 0); | 144 this->init(paint, skPaint, byteLength, kMaxPerformance_RenderMode, offset); |
| 145 this->init(paint, skPaint, byteLength, kMaxPerformance_RenderMode, textTrans
lateY); | |
| 146 | 145 |
| 147 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 146 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 148 | 147 |
| 149 const char* stop = text + byteLength; | 148 const char* stop = text + byteLength; |
| 150 | 149 |
| 151 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 150 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 152 if (1 == scalarsPerPosition) { | 151 if (1 == scalarsPerPosition) { |
| 153 fTransformType = GrPathRendering::kTranslateX_PathTransformType; | 152 fTransformType = GrPathRendering::kTranslateX_PathTransformType; |
| 154 while (text < stop) { | 153 while (text < stop) { |
| 155 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 154 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 156 if (glyph.fWidth) { | 155 if (glyph.fWidth) { |
| 157 this->appendGlyph(glyph.getGlyphID(), *pos); | 156 this->appendGlyph(glyph.getGlyphID(), *pos); |
| 158 } | 157 } |
| 159 pos++; | 158 pos++; |
| 160 } | 159 } |
| 161 } else { | 160 } else { |
| 162 SkASSERT(2 == scalarsPerPosition); | 161 SkASSERT(2 == scalarsPerPosition); |
| 163 fTransformType = GrPathRendering::kTranslate_PathTransformType; | 162 fTransformType = GrPathRendering::kTranslate_PathTransformType; |
| 164 while (text < stop) { | 163 while (text < stop) { |
| 165 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 164 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 166 if (glyph.fWidth) { | 165 if (glyph.fWidth) { |
| 167 this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]); | 166 this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]); |
| 168 } | 167 } |
| 169 pos += 2; | 168 pos += 2; |
| 170 } | 169 } |
| 171 } | 170 } |
| 172 } else { | 171 } else { |
| 173 fTransformType = GrPathRendering::kTranslate_PathTransformType; | 172 fTransformType = GrPathRendering::kTranslate_PathTransformType; |
| 174 SkTextMapStateProc tmsProc(SkMatrix::I(), 0, scalarsPerPosition); | 173 SkTextMapStateProc tmsProc(SkMatrix::I(), SkPoint::Make(0, 0), scalarsPe
rPosition); |
| 175 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); | 174 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); |
| 176 while (text < stop) { | 175 while (text < stop) { |
| 177 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 176 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 178 if (glyph.fWidth) { | 177 if (glyph.fWidth) { |
| 179 SkPoint tmsLoc; | 178 SkPoint tmsLoc; |
| 180 tmsProc(pos, &tmsLoc); | 179 tmsProc(pos, &tmsLoc); |
| 181 SkPoint loc; | 180 SkPoint loc; |
| 182 alignProc(tmsLoc, glyph, &loc); | 181 alignProc(tmsLoc, glyph, &loc); |
| 183 | 182 |
| 184 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); | 183 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 ctx->addResourceToCache(resourceKey, glyphs); | 234 ctx->addResourceToCache(resourceKey, glyphs); |
| 236 } | 235 } |
| 237 | 236 |
| 238 return glyphs.detach(); | 237 return glyphs.detach(); |
| 239 } | 238 } |
| 240 | 239 |
| 241 void GrStencilAndCoverTextContext::init(const GrPaint& paint, | 240 void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| 242 const SkPaint& skPaint, | 241 const SkPaint& skPaint, |
| 243 size_t textByteLength, | 242 size_t textByteLength, |
| 244 RenderMode renderMode, | 243 RenderMode renderMode, |
| 245 SkScalar textTranslateY) { | 244 const SkPoint& textTranslate) { |
| 246 GrTextContext::init(paint, skPaint); | 245 GrTextContext::init(paint, skPaint); |
| 247 | 246 |
| 248 fContextInitialMatrix = fContext->getMatrix(); | 247 fContextInitialMatrix = fContext->getMatrix(); |
| 249 | 248 |
| 250 const bool otherBackendsWillDrawAsPaths = | 249 const bool otherBackendsWillDrawAsPaths = |
| 251 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); | 250 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); |
| 252 | 251 |
| 253 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && | 252 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && |
| 254 kMaxAccuracy_RenderMode == renderMode && | 253 kMaxAccuracy_RenderMode == renderMode && |
| 255 SkToBool(fContextInitialMatrix.getType() & | 254 SkToBool(fContextInitialMatrix.getType() & |
| 256 (SkMatrix::kScale_Mask | SkMatrix::kAffin
e_Mask)); | 255 (SkMatrix::kScale_Mask | SkMatrix::kAffin
e_Mask)); |
| 257 | 256 |
| 258 if (fNeedsDeviceSpaceGlyphs) { | 257 if (fNeedsDeviceSpaceGlyphs) { |
| 259 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. | 258 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. |
| 260 SkASSERT(!fContextInitialMatrix.hasPerspective()); | 259 SkASSERT(!fContextInitialMatrix.hasPerspective()); |
| 261 SkASSERT(0 == textTranslateY); // TODO: Handle textTranslateY in device-
space usecase. | 260 SkASSERT(textTranslate.isZero()); // TODO: Handle textTranslate in devic
e-space usecase. |
| 262 | 261 |
| 263 fTextRatio = fTextInverseRatio = 1.0f; | 262 fTextRatio = fTextInverseRatio = 1.0f; |
| 264 | 263 |
| 265 // Glyphs loaded by GPU path rendering have an inverted y-direction. | 264 // Glyphs loaded by GPU path rendering have an inverted y-direction. |
| 266 SkMatrix m; | 265 SkMatrix m; |
| 267 m.setScale(1, -1); | 266 m.setScale(1, -1); |
| 268 fContext->setMatrix(m); | 267 fContext->setMatrix(m); |
| 269 | 268 |
| 270 // Post-flip the initial matrix so we're left with just the flip after | 269 // Post-flip the initial matrix so we're left with just the flip after |
| 271 // the paint preConcats the inverse. | 270 // the paint preConcats the inverse. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() && | 332 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() && |
| 334 0 == fSkPaint.getTextSkewX() && | 333 0 == fSkPaint.getTextSkewX() && |
| 335 !fSkPaint.isFakeBoldText() && | 334 !fSkPaint.isFakeBoldText() && |
| 336 !fSkPaint.isVerticalText(); | 335 !fSkPaint.isVerticalText(); |
| 337 } else { | 336 } else { |
| 338 fTextRatio = fTextInverseRatio = 1.0f; | 337 fTextRatio = fTextInverseRatio = 1.0f; |
| 339 canUseRawPaths = false; | 338 canUseRawPaths = false; |
| 340 } | 339 } |
| 341 | 340 |
| 342 SkMatrix textMatrix; | 341 SkMatrix textMatrix; |
| 343 textMatrix.setTranslate(0, textTranslateY); | 342 textMatrix.setTranslate(textTranslate.x(), textTranslate.y()); |
| 344 // Glyphs loaded by GPU path rendering have an inverted y-direction. | 343 // Glyphs loaded by GPU path rendering have an inverted y-direction. |
| 345 textMatrix.preScale(fTextRatio, -fTextRatio); | 344 textMatrix.preScale(fTextRatio, -fTextRatio); |
| 346 fPaint.localCoordChange(textMatrix); | 345 fPaint.localCoordChange(textMatrix); |
| 347 fContext->concatMatrix(textMatrix); | 346 fContext->concatMatrix(textMatrix); |
| 348 | 347 |
| 349 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false); | 348 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false); |
| 350 fGlyphs = canUseRawPaths ? | 349 fGlyphs = canUseRawPaths ? |
| 351 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS
troke) : | 350 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS
troke) : |
| 352 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), | 351 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), |
| 353 &fGlyphCache->getDescriptor(), gpuStroke); | 352 &fGlyphCache->getDescriptor(), gpuStroke); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 | 416 |
| 418 SkGlyphCache::AttachCache(fGlyphCache); | 417 SkGlyphCache::AttachCache(fGlyphCache); |
| 419 fGlyphCache = NULL; | 418 fGlyphCache = NULL; |
| 420 | 419 |
| 421 fDrawTarget->drawState()->stencil()->setDisabled(); | 420 fDrawTarget->drawState()->stencil()->setDisabled(); |
| 422 fStateRestore.set(NULL); | 421 fStateRestore.set(NULL); |
| 423 fContext->setMatrix(fContextInitialMatrix); | 422 fContext->setMatrix(fContextInitialMatrix); |
| 424 GrTextContext::finish(); | 423 GrTextContext::finish(); |
| 425 } | 424 } |
| 426 | 425 |
| OLD | NEW |