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 |