Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 759613005: Add color emoji fallback for nvpr text (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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(
24 GrContext* context, const SkDeviceProperties& properties) 24 GrContext* context, const SkDeviceProperties& properties)
25 : GrTextContext(context, properties) 25 : GrTextContext(context, properties)
26 , fPendingGlyphCount(0) { 26 , fStroke(SkStrokeRec::kFill_InitStyle)
27 , fQueuedGlyphCount(0)
28 , fFallbackGlyphsIdx(kGlyphBufferSize) {
27 } 29 }
28 30
29 GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* co ntext, 31 GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* co ntext,
30 const SkDeviceP roperties& props) { 32 const SkDeviceP roperties& props) {
31 GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverText Context, 33 GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverText Context,
32 (context, props)); 34 (context, props));
33 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, pro ps); 35 textContext->fFallbackTextContext = GrBitmapTextContext::Create(context, pro ps);
34 36
35 return textContext; 37 return textContext;
36 } 38 }
(...skipping 19 matching lines...) Expand all
56 return false; 58 return false;
57 } 59 }
58 60
59 // No color bitmap fonts. 61 // No color bitmap fonts.
60 SkScalerContext::Rec rec; 62 SkScalerContext::Rec rec;
61 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); 63 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
62 return rec.getFormat() != SkMask::kARGB32_Format; 64 return rec.getFormat() != SkMask::kARGB32_Format;
63 } 65 }
64 66
65 void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint, 67 void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
66 const SkPaint& skPaint, 68 const SkPaint& skPaint,
67 const char text[], 69 const char text[],
68 size_t byteLength, 70 size_t byteLength,
69 SkScalar x, SkScalar y) { 71 SkScalar x, SkScalar y) {
70 SkASSERT(byteLength == 0 || text != NULL); 72 SkASSERT(byteLength == 0 || text != NULL);
71 73
72 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { 74 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
73 return; 75 return;
74 } 76 }
75 77
76 // This is the slow path, mainly used by Skia unit tests. The other 78 // This is the slow path, mainly used by Skia unit tests. The other
77 // backends (8888, gpu, ...) use device-space dependent glyph caches. In 79 // backends (8888, gpu, ...) use device-space dependent glyph caches. In
78 // order to match the glyph positions that the other code paths produce, we 80 // order to match the glyph positions that the other code paths produce, we
79 // must also use device-space dependent glyph cache. This has the 81 // must also use device-space dependent glyph cache. This has the
80 // side-effect that the glyph shape outline will be in device-space, 82 // side-effect that the glyph shape outline will be in device-space,
81 // too. This in turn has the side-effect that NVPR can not stroke the paths, 83 // too. This in turn has the side-effect that NVPR can not stroke the paths,
82 // as the stroke in NVPR is defined in object-space. 84 // as the stroke in NVPR is defined in object-space.
83 // NOTE: here we have following coincidence that works at the moment: 85 // NOTE: here we have following coincidence that works at the moment:
84 // - When using the device-space glyphs, the transforms we pass to NVPR 86 // - When using the device-space glyphs, the transforms we pass to NVPR
85 // instanced drawing are the global transforms, and the view transform is 87 // instanced drawing are the global transforms, and the view transform is
86 // identity. NVPR can not use non-affine transforms in the instanced 88 // identity. NVPR can not use non-affine transforms in the instanced
87 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it 89 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it
88 // will turn off the use of device-space glyphs when perspective transforms 90 // will turn off the use of device-space glyphs when perspective transforms
89 // are in use. 91 // are in use.
90 92
91 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode); 93 this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode);
92 94
93 // Transform our starting point. 95 // Transform our starting point.
94 if (fNeedsDeviceSpaceGlyphs) { 96 if (fUsingDeviceSpaceGlyphs) {
95 SkPoint loc; 97 SkPoint loc;
96 fContextInitialMatrix.mapXY(x, y, &loc); 98 fContextInitialMatrix.mapXY(x, y, &loc);
97 x = loc.fX; 99 x = loc.fX;
98 y = loc.fY; 100 y = loc.fY;
99 } 101 }
100 102
101 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 103 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
102 104
103 const char* stop = text + byteLength; 105 const char* stop = text + byteLength;
104 106
(...skipping 28 matching lines...) Expand all
133 SkAutoKern autokern; 135 SkAutoKern autokern;
134 136
135 SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio); 137 SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio);
136 138
137 SkFixed fx = SkScalarToFixed(x); 139 SkFixed fx = SkScalarToFixed(x);
138 SkFixed fy = SkScalarToFixed(y); 140 SkFixed fy = SkScalarToFixed(y);
139 while (text < stop) { 141 while (text < stop) {
140 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 142 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
141 fx += SkFixedMul_portable(autokern.adjust(glyph), fixedSizeRatio); 143 fx += SkFixedMul_portable(autokern.adjust(glyph), fixedSizeRatio);
142 if (glyph.fWidth) { 144 if (glyph.fWidth) {
143 this->appendGlyph(glyph.getGlyphID(), SkFixedToScalar(fx), SkFixedTo Scalar(fy)); 145 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT oScalar(fy)));
144 } 146 }
145 147
146 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio); 148 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio);
147 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedSizeRatio); 149 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedSizeRatio);
148 } 150 }
149 151
150 this->finish(); 152 this->finish();
151 } 153 }
152 154
153 void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint, 155 void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint,
154 const SkPaint& skPaint, 156 const SkPaint& skPaint,
155 const char text[], 157 const char text[],
156 size_t byteLength, 158 size_t byteLength,
157 const SkScalar pos[], 159 const SkScalar pos[],
158 int scalarsPerPosition, 160 int scalarsPerPosition,
159 const SkPoint& offset) { 161 const SkPoint& offset) {
160 SkASSERT(byteLength == 0 || text != NULL); 162 SkASSERT(byteLength == 0 || text != NULL);
161 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 163 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
162 164
163 // nothing to draw 165 // nothing to draw
164 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) { 166 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
165 return; 167 return;
166 } 168 }
167 169
168 // This is the fast path. Here we do not bake in the device-transform to 170 // This is the fast path. Here we do not bake in the device-transform to
169 // the glyph outline or the advances. This is because we do not need to 171 // the glyph outline or the advances. This is because we do not need to
(...skipping 12 matching lines...) Expand all
182 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 184 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
183 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); 185 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign());
184 while (text < stop) { 186 while (text < stop) {
185 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 187 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
186 if (glyph.fWidth) { 188 if (glyph.fWidth) {
187 SkPoint tmsLoc; 189 SkPoint tmsLoc;
188 tmsProc(pos, &tmsLoc); 190 tmsProc(pos, &tmsLoc);
189 SkPoint loc; 191 SkPoint loc;
190 alignProc(tmsLoc, glyph, &loc); 192 alignProc(tmsLoc, glyph, &loc);
191 193
192 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); 194 this->appendGlyph(glyph, loc);
193 } 195 }
194 pos += scalarsPerPosition; 196 pos += scalarsPerPosition;
195 } 197 }
196 198
197 this->finish(); 199 this->finish();
198 } 200 }
199 201
200 static GrPathRange* get_gr_glyphs(GrContext* ctx, 202 static GrPathRange* get_gr_glyphs(GrContext* ctx,
201 const SkTypeface* typeface, 203 const SkTypeface* typeface,
202 const SkDescriptor* desc, 204 const SkDescriptor* desc,
(...skipping 22 matching lines...) Expand all
225 const SkPaint& skPaint, 227 const SkPaint& skPaint,
226 size_t textByteLength, 228 size_t textByteLength,
227 RenderMode renderMode) { 229 RenderMode renderMode) {
228 GrTextContext::init(paint, skPaint); 230 GrTextContext::init(paint, skPaint);
229 231
230 fContextInitialMatrix = fContext->getMatrix(); 232 fContextInitialMatrix = fContext->getMatrix();
231 233
232 const bool otherBackendsWillDrawAsPaths = 234 const bool otherBackendsWillDrawAsPaths =
233 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); 235 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
234 236
235 fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && 237 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths &&
236 kMaxAccuracy_RenderMode == renderMode && 238 kMaxAccuracy_RenderMode == renderMode &&
237 SkToBool(fContextInitialMatrix.getType() & 239 SkToBool(fContextInitialMatrix.getType() &
238 (SkMatrix::kScale_Mask | SkMatrix::kAffin e_Mask)); 240 (SkMatrix::kScale_Mask | SkMatrix::kAffin e_Mask));
239 241
240 if (fNeedsDeviceSpaceGlyphs) { 242 if (fUsingDeviceSpaceGlyphs) {
241 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. 243 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms.
242 SkASSERT(!fContextInitialMatrix.hasPerspective()); 244 SkASSERT(!fContextInitialMatrix.hasPerspective());
243 245
246 // The whole shape (including stroke) will be baked into the glyph outli nes. Make
247 // NVPR just fill the baked shapes.
248 fStroke = SkStrokeRec(SkStrokeRec::kFill_InitStyle);
249
244 fTextRatio = fTextInverseRatio = 1.0f; 250 fTextRatio = fTextInverseRatio = 1.0f;
245 251
246 // Glyphs loaded by GPU path rendering have an inverted y-direction. 252 // Glyphs loaded by GPU path rendering have an inverted y-direction.
247 SkMatrix m; 253 SkMatrix m;
248 m.setScale(1, -1); 254 m.setScale(1, -1);
249 fContext->setMatrix(m); 255 fContext->setMatrix(m);
250 256
251 // Post-flip the initial matrix so we're left with just the flip after 257 // Post-flip the initial matrix so we're left with just the flip after
252 // the paint preConcats the inverse. 258 // the paint preConcats the inverse.
253 m = fContextInitialMatrix; 259 m = fContextInitialMatrix;
254 m.postScale(1, -1); 260 m.postScale(1, -1);
255 fPaint.localCoordChangeInverse(m); 261 fPaint.localCoordChangeInverse(m);
256 262
257 // The whole shape (including stroke) will be baked into the glyph outli nes. Make
258 // NVPR just fill the baked shapes.
259 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialM atrix, false); 263 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialM atrix, false);
260 fGlyphs = get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTy peface(), 264 fGlyphs = get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTy peface(),
261 &fGlyphCache->getDescriptor(), 265 &fGlyphCache->getDescriptor(), fStroke);
262 SkStrokeRec(SkStrokeRec::kFill_InitStyle));
263 } else { 266 } else {
264 // Don't bake strokes into the glyph outlines. We will stroke the glyphs 267 // Don't bake strokes into the glyph outlines. We will stroke the glyphs
265 // using the GPU instead. This is the fast path. 268 // using the GPU instead. This is the fast path.
266 SkStrokeRec gpuStroke = SkStrokeRec(fSkPaint); 269 fStroke = SkStrokeRec(fSkPaint);
267 fSkPaint.setStyle(SkPaint::kFill_Style); 270 fSkPaint.setStyle(SkPaint::kFill_Style);
268 271
269 if (gpuStroke.isHairlineStyle()) { 272 if (fStroke.isHairlineStyle()) {
270 // Approximate hairline stroke. 273 // Approximate hairline stroke.
271 SkScalar strokeWidth = SK_Scalar1 / 274 SkScalar strokeWidth = SK_Scalar1 /
272 (SkVector::Make(fContextInitialMatrix.getScaleX(), 275 (SkVector::Make(fContextInitialMatrix.getScaleX(),
273 fContextInitialMatrix.getSkewY()).length()); 276 fContextInitialMatrix.getSkewY()).length());
274 gpuStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/); 277 fStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/);
275 278
276 } else if (fSkPaint.isFakeBoldText() && 279 } else if (fSkPaint.isFakeBoldText() &&
277 #ifdef SK_USE_FREETYPE_EMBOLDEN 280 #ifdef SK_USE_FREETYPE_EMBOLDEN
278 kMaxPerformance_RenderMode == renderMode && 281 kMaxPerformance_RenderMode == renderMode &&
279 #endif 282 #endif
280 SkStrokeRec::kStroke_Style != gpuStroke.getStyle()) { 283 SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
281 284
282 // Instead of baking fake bold into the glyph outlines, do it with t he GPU stroke. 285 // Instead of baking fake bold into the glyph outlines, do it with t he GPU stroke.
283 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(), 286 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
284 kStdFakeBoldInterpKeys, 287 kStdFakeBoldInterpKeys,
285 kStdFakeBoldInterpValues , 288 kStdFakeBoldInterpValues ,
286 kStdFakeBoldInterpLength ); 289 kStdFakeBoldInterpLength );
287 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale); 290 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
288 gpuStroke.setStrokeStyle(gpuStroke.needToApply() ? gpuStroke.getWidt h() + extra : extra, 291 fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
289 true /*strokeAndFill*/); 292 true /*strokeAndFill*/);
290 293
291 fSkPaint.setFakeBoldText(false); 294 fSkPaint.setFakeBoldText(false);
292 } 295 }
293 296
294 bool canUseRawPaths; 297 bool canUseRawPaths;
295 298
296 if (otherBackendsWillDrawAsPaths || kMaxPerformance_RenderMode == render Mode) { 299 if (otherBackendsWillDrawAsPaths || kMaxPerformance_RenderMode == render Mode) {
297 // We can draw the glyphs from canonically sized paths. 300 // We can draw the glyphs from canonically sized paths.
298 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeFor Paths; 301 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeFor Paths;
299 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.g etTextSize(); 302 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.g etTextSize();
300 303
301 // Compensate for the glyphs being scaled by fTextRatio. 304 // Compensate for the glyphs being scaled by fTextRatio.
302 if (!gpuStroke.isFillStyle()) { 305 if (!fStroke.isFillStyle()) {
303 gpuStroke.setStrokeStyle(gpuStroke.getWidth() / fTextRatio, 306 fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
304 SkStrokeRec::kStrokeAndFill_Style == gp uStroke.getStyle()); 307 SkStrokeRec::kStrokeAndFill_Style == fStr oke.getStyle());
305 } 308 }
306 309
307 fSkPaint.setLinearText(true); 310 fSkPaint.setLinearText(true);
308 fSkPaint.setLCDRenderText(false); 311 fSkPaint.setLCDRenderText(false);
309 fSkPaint.setAutohinted(false); 312 fSkPaint.setAutohinted(false);
310 fSkPaint.setHinting(SkPaint::kNo_Hinting); 313 fSkPaint.setHinting(SkPaint::kNo_Hinting);
311 fSkPaint.setSubpixelText(true); 314 fSkPaint.setSubpixelText(true);
312 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPat hs)); 315 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPat hs));
313 316
314 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() && 317 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
315 0 == fSkPaint.getTextSkewX() && 318 0 == fSkPaint.getTextSkewX() &&
316 !fSkPaint.isFakeBoldText() && 319 !fSkPaint.isFakeBoldText() &&
317 !fSkPaint.isVerticalText(); 320 !fSkPaint.isVerticalText();
318 } else { 321 } else {
319 fTextRatio = fTextInverseRatio = 1.0f; 322 fTextRatio = fTextInverseRatio = 1.0f;
320 canUseRawPaths = false; 323 canUseRawPaths = false;
321 } 324 }
322 325
323 SkMatrix textMatrix; 326 SkMatrix textMatrix;
324 // Glyphs loaded by GPU path rendering have an inverted y-direction. 327 // Glyphs loaded by GPU path rendering have an inverted y-direction.
325 textMatrix.setScale(fTextRatio, -fTextRatio); 328 textMatrix.setScale(fTextRatio, -fTextRatio);
326 fPaint.localCoordChange(textMatrix); 329 fPaint.localCoordChange(textMatrix);
327 fContext->concatMatrix(textMatrix); 330 fContext->concatMatrix(textMatrix);
328 331
329 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false); 332 fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false);
330 fGlyphs = canUseRawPaths ? 333 fGlyphs = canUseRawPaths ?
331 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuS troke) : 334 get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, fStr oke) :
332 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g etTypeface(), 335 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g etTypeface(),
333 &fGlyphCache->getDescriptor(), gpuStroke); 336 &fGlyphCache->getDescriptor(), fStroke);
334 } 337 }
335 338
336 fStateRestore.set(&fDrawState); 339 fStateRestore.set(&fDrawState);
337 340
338 fDrawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTa rget()); 341 fDrawState.setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTa rget());
339 342
340 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 343 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
341 kZero_StencilOp, 344 kZero_StencilOp,
342 kZero_StencilOp, 345 kZero_StencilOp,
343 kNotEqual_StencilFunc, 346 kNotEqual_StencilFunc,
344 0xffff, 347 0xffff,
345 0x0000, 348 0x0000,
346 0xffff); 349 0xffff);
347 350
348 *fDrawState.stencil() = kStencilPass; 351 *fDrawState.stencil() = kStencilPass;
349 352
350 SkASSERT(0 == fPendingGlyphCount); 353 SkASSERT(0 == fQueuedGlyphCount);
354 SkASSERT(kGlyphBufferSize == fFallbackGlyphsIdx);
351 } 355 }
352 356
353 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) { 357 bool GrStencilAndCoverTextContext::mapToFallbackContext(GrContext::AutoMatrix& a utoMatrix,
354 if (fPendingGlyphCount >= kGlyphBufferSize) { 358 SkMatrix* inverse) {
359 // The current view matrix is flipped because GPU path rendering glyphs have an
360 // inverted y-direction. Unflip the view matrix for the fallback context. If using
361 // device-space glyphs, we'll also need to restore the original view matrix since
362 // we moved that transfomation into our local glyph cache for this scenario. Also
363 // track the inverse operation so the caller can unmap the paint and glyph p ositions.
364 if (fUsingDeviceSpaceGlyphs) {
365 autoMatrix.set(fContext, fContextInitialMatrix);
366 if (!fContextInitialMatrix.invert(inverse)) {
367 return false;
368 }
369 inverse->preScale(1, -1);
370 } else {
371 inverse->setScale(1, -1);
372 const SkMatrix& unflip = *inverse; // unflip is equal to its own inverse .
373 autoMatrix.setPreConcat(fContext, unflip);
374 }
375 return true;
376 }
377
378 inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, cons t SkPoint& pos) {
379 if (fQueuedGlyphCount >= fFallbackGlyphsIdx) {
380 SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx);
355 this->flush(); 381 this->flush();
356 } 382 }
357 383
358 fIndexBuffer[fPendingGlyphCount] = glyphID; 384 // Stick the glyphs we can't draw at the end of the buffer, growing backward s.
Chris Dalton 2014/11/25 23:13:54 Looking for feedback here. Growing backwards will
jvanverth1 2014/11/26 19:41:35 On one hand, drawing them in reverse order doesn't
359 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x; 385 int index = (SkMask::kARGB32_Format == glyph.fMaskFormat) ?
360 fTransformBuffer[2 * fPendingGlyphCount + 1] = -fTextInverseRatio * y; 386 --fFallbackGlyphsIdx : fQueuedGlyphCount++;
361 387
362 ++fPendingGlyphCount; 388 fGlyphIndices[index] = glyph.getGlyphID();
389 fGlyphPositions[index].set(fTextInverseRatio * pos.x(), -fTextInverseRatio * pos.y());
390 }
391
392 static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) {
393 GR_STATIC_ASSERT(2 * sizeof(SkScalar) == sizeof(SkPoint));
394 GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX));
395
396 return &pointArray[0].fX;
363 } 397 }
364 398
365 void GrStencilAndCoverTextContext::flush() { 399 void GrStencilAndCoverTextContext::flush() {
366 if (0 == fPendingGlyphCount) { 400 if (fQueuedGlyphCount > 0) {
367 return; 401 fDrawTarget->drawPaths(&fDrawState, fGlyphs,
402 fGlyphIndices, GrPathRange::kU16_PathIndexType,
403 get_xy_scalar_array(fGlyphPositions),
404 GrPathRendering::kTranslate_PathTransformType,
405 fQueuedGlyphCount, GrPathRendering::kWinding_Fill Type);
406
407 fQueuedGlyphCount = 0;
368 } 408 }
369 409
370 fDrawTarget->drawPaths(&fDrawState, fGlyphs, fIndexBuffer, GrPathRange::kU16 _PathIndexType, 410 if (fFallbackGlyphsIdx < kGlyphBufferSize) {
371 fTransformBuffer, GrPathRendering::kTranslate_PathTra nsformType, 411 int fallbackGlyphCount = kGlyphBufferSize - fFallbackGlyphsIdx;
372 fPendingGlyphCount, GrPathRendering::kWinding_FillTyp e);
373 412
374 fPendingGlyphCount = 0; 413 GrPaint paintFallback(fPaint);
414
415 SkPaint skPaintFallback(fSkPaint);
416 if (!fUsingDeviceSpaceGlyphs) {
417 fStroke.applyToPaint(&skPaintFallback);
418 }
419 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
420 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
421
422 GrContext::AutoMatrix autoMatrix;
423 SkMatrix inverse;
424 if (this->mapToFallbackContext(autoMatrix, &inverse)) {
425 paintFallback.localCoordChangeInverse(inverse);
426 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp hCount);
427 }
428
429 fFallbackTextContext->drawPosText(paintFallback, skPaintFallback,
430 (char*)&fGlyphIndices[fFallbackGlyphsI dx],
431 2 * fallbackGlyphCount,
432 get_xy_scalar_array(&fGlyphPositions[f FallbackGlyphsIdx]),
433 2, SkPoint::Make(0, 0));
434
435 fFallbackGlyphsIdx = kGlyphBufferSize;
436 }
375 } 437 }
376 438
377 void GrStencilAndCoverTextContext::finish() { 439 void GrStencilAndCoverTextContext::finish() {
378 this->flush(); 440 this->flush();
379 441
380 fGlyphs->unref(); 442 fGlyphs->unref();
381 fGlyphs = NULL; 443 fGlyphs = NULL;
382 444
383 SkGlyphCache::AttachCache(fGlyphCache); 445 SkGlyphCache::AttachCache(fGlyphCache);
384 fGlyphCache = NULL; 446 fGlyphCache = NULL;
385 447
386 fDrawState.stencil()->setDisabled(); 448 fDrawState.stencil()->setDisabled();
387 fStateRestore.set(NULL); 449 fStateRestore.set(NULL);
388 fContext->setMatrix(fContextInitialMatrix); 450 fContext->setMatrix(fContextInitialMatrix);
389 GrTextContext::finish(); 451 GrTextContext::finish();
390 } 452 }
391 453
OLDNEW
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698