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 |