| 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, SkPoint::Mak
e(0, 0)); | 57 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode); |
| 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 int scalarsPerPosition, | 126 SkScalar constY, |
| 127 const SkPoint& offset) { | 127 int scalarsPerPosition) { |
| 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 this->init(paint, skPaint, byteLength, kMaxPerformance_RenderMode, offset); | 144 const float textTranslateY = (1 == scalarsPerPosition ? constY : 0); |
| 145 this->init(paint, skPaint, byteLength, kMaxPerformance_RenderMode, textTrans
lateY); |
| 145 | 146 |
| 146 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); | 147 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| 147 | 148 |
| 148 const char* stop = text + byteLength; | 149 const char* stop = text + byteLength; |
| 149 | 150 |
| 150 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { | 151 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| 151 if (1 == scalarsPerPosition) { | 152 if (1 == scalarsPerPosition) { |
| 152 fTransformType = GrPathRendering::kTranslateX_PathTransformType; | 153 fTransformType = GrPathRendering::kTranslateX_PathTransformType; |
| 153 while (text < stop) { | 154 while (text < stop) { |
| 154 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 155 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 155 if (glyph.fWidth) { | 156 if (glyph.fWidth) { |
| 156 this->appendGlyph(glyph.getGlyphID(), *pos); | 157 this->appendGlyph(glyph.getGlyphID(), *pos); |
| 157 } | 158 } |
| 158 pos++; | 159 pos++; |
| 159 } | 160 } |
| 160 } else { | 161 } else { |
| 161 SkASSERT(2 == scalarsPerPosition); | 162 SkASSERT(2 == scalarsPerPosition); |
| 162 fTransformType = GrPathRendering::kTranslate_PathTransformType; | 163 fTransformType = GrPathRendering::kTranslate_PathTransformType; |
| 163 while (text < stop) { | 164 while (text < stop) { |
| 164 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 165 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 165 if (glyph.fWidth) { | 166 if (glyph.fWidth) { |
| 166 this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]); | 167 this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]); |
| 167 } | 168 } |
| 168 pos += 2; | 169 pos += 2; |
| 169 } | 170 } |
| 170 } | 171 } |
| 171 } else { | 172 } else { |
| 172 fTransformType = GrPathRendering::kTranslate_PathTransformType; | 173 fTransformType = GrPathRendering::kTranslate_PathTransformType; |
| 173 SkTextMapStateProc tmsProc(SkMatrix::I(), SkPoint::Make(0, 0), scalarsPe
rPosition); | 174 SkTextMapStateProc tmsProc(SkMatrix::I(), 0, scalarsPerPosition); |
| 174 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); | 175 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); |
| 175 while (text < stop) { | 176 while (text < stop) { |
| 176 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 177 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| 177 if (glyph.fWidth) { | 178 if (glyph.fWidth) { |
| 178 SkPoint tmsLoc; | 179 SkPoint tmsLoc; |
| 179 tmsProc(pos, &tmsLoc); | 180 tmsProc(pos, &tmsLoc); |
| 180 SkPoint loc; | 181 SkPoint loc; |
| 181 alignProc(tmsLoc, glyph, &loc); | 182 alignProc(tmsLoc, glyph, &loc); |
| 182 | 183 |
| 183 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); | 184 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 ctx->addResourceToCache(resourceKey, glyphs); | 235 ctx->addResourceToCache(resourceKey, glyphs); |
| 235 } | 236 } |
| 236 | 237 |
| 237 return glyphs.detach(); | 238 return glyphs.detach(); |
| 238 } | 239 } |
| 239 | 240 |
| 240 void GrStencilAndCoverTextContext::init(const GrPaint& paint, | 241 void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| 241 const SkPaint& skPaint, | 242 const SkPaint& skPaint, |
| 242 size_t textByteLength, | 243 size_t textByteLength, |
| 243 RenderMode renderMode, | 244 RenderMode renderMode, |
| 244 const SkPoint& textTranslate) { | 245 SkScalar textTranslateY) { |
| 245 GrTextContext::init(paint, skPaint); | 246 GrTextContext::init(paint, skPaint); |
| 246 | 247 |
| 247 fContextInitialMatrix = fContext->getMatrix(); | 248 fContextInitialMatrix = fContext->getMatrix(); |
| 248 | 249 |
| 249 const bool otherBackendsWillDrawAsPaths = | 250 const bool otherBackendsWillDrawAsPaths = |
| 250 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); | 251 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); |
| 251 | 252 |
| 252 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && | 253 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && |
| 253 kMaxAccuracy_RenderMode == renderMode && | 254 kMaxAccuracy_RenderMode == renderMode && |
| 254 SkToBool(fContextInitialMatrix.getType() & | 255 SkToBool(fContextInitialMatrix.getType() & |
| 255 (SkMatrix::kScale_Mask | SkMatrix::kAffin
e_Mask)); | 256 (SkMatrix::kScale_Mask | SkMatrix::kAffin
e_Mask)); |
| 256 | 257 |
| 257 if (fNeedsDeviceSpaceGlyphs) { | 258 if (fNeedsDeviceSpaceGlyphs) { |
| 258 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. | 259 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. |
| 259 SkASSERT(!fContextInitialMatrix.hasPerspective()); | 260 SkASSERT(!fContextInitialMatrix.hasPerspective()); |
| 260 SkASSERT(textTranslate.isZero()); // TODO: Handle textTranslate in devic
e-space usecase. | 261 SkASSERT(0 == textTranslateY); // TODO: Handle textTranslateY in device-
space usecase. |
| 261 | 262 |
| 262 fTextRatio = fTextInverseRatio = 1.0f; | 263 fTextRatio = fTextInverseRatio = 1.0f; |
| 263 | 264 |
| 264 // Glyphs loaded by GPU path rendering have an inverted y-direction. | 265 // Glyphs loaded by GPU path rendering have an inverted y-direction. |
| 265 SkMatrix m; | 266 SkMatrix m; |
| 266 m.setScale(1, -1); | 267 m.setScale(1, -1); |
| 267 fContext->setMatrix(m); | 268 fContext->setMatrix(m); |
| 268 | 269 |
| 269 // Post-flip the initial matrix so we're left with just the flip after | 270 // Post-flip the initial matrix so we're left with just the flip after |
| 270 // the paint preConcats the inverse. | 271 // the paint preConcats the inverse. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() && | 333 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() && |
| 333 0 == fSkPaint.getTextSkewX() && | 334 0 == fSkPaint.getTextSkewX() && |
| 334 !fSkPaint.isFakeBoldText() && | 335 !fSkPaint.isFakeBoldText() && |
| 335 !fSkPaint.isVerticalText(); | 336 !fSkPaint.isVerticalText(); |
| 336 } else { | 337 } else { |
| 337 fTextRatio = fTextInverseRatio = 1.0f; | 338 fTextRatio = fTextInverseRatio = 1.0f; |
| 338 canUseRawPaths = false; | 339 canUseRawPaths = false; |
| 339 } | 340 } |
| 340 | 341 |
| 341 SkMatrix textMatrix; | 342 SkMatrix textMatrix; |
| 342 textMatrix.setTranslate(textTranslate.x(), textTranslate.y()); | 343 textMatrix.setTranslate(0, textTranslateY); |
| 343 // Glyphs loaded by GPU path rendering have an inverted y-direction. | 344 // Glyphs loaded by GPU path rendering have an inverted y-direction. |
| 344 textMatrix.preScale(fTextRatio, -fTextRatio); | 345 textMatrix.preScale(fTextRatio, -fTextRatio); |
| 345 fPaint.localCoordChange(textMatrix); | 346 fPaint.localCoordChange(textMatrix); |
| 346 fContext->concatMatrix(textMatrix); | 347 fContext->concatMatrix(textMatrix); |
| 347 | 348 |
| 348 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false); | 349 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false); |
| 349 fGlyphs = canUseRawPaths ? | 350 fGlyphs = canUseRawPaths ? |
| 350 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS
troke) : | 351 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS
troke) : |
| 351 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), | 352 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g
etTypeface(), |
| 352 &fGlyphCache->getDescriptor(), gpuStroke); | 353 &fGlyphCache->getDescriptor(), gpuStroke); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 | 417 |
| 417 SkGlyphCache::AttachCache(fGlyphCache); | 418 SkGlyphCache::AttachCache(fGlyphCache); |
| 418 fGlyphCache = NULL; | 419 fGlyphCache = NULL; |
| 419 | 420 |
| 420 fDrawTarget->drawState()->stencil()->setDisabled(); | 421 fDrawTarget->drawState()->stencil()->setDisabled(); |
| 421 fStateRestore.set(NULL); | 422 fStateRestore.set(NULL); |
| 422 fContext->setMatrix(fContextInitialMatrix); | 423 fContext->setMatrix(fContextInitialMatrix); |
| 423 GrTextContext::finish(); | 424 GrTextContext::finish(); |
| 424 } | 425 } |
| 425 | 426 |
| OLD | NEW |