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

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

Issue 1380973002: Simplify nvpr text (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove accidental SampleApp hack Created 5 years, 2 months 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 "GrAtlasTextContext.h" 9 #include "GrAtlasTextContext.h"
10 #include "GrDrawContext.h" 10 #include "GrDrawContext.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 return false; 51 return false;
52 } 52 }
53 if (skPaint.getMaskFilter()) { 53 if (skPaint.getMaskFilter()) {
54 return false; 54 return false;
55 } 55 }
56 if (SkPathEffect* pe = skPaint.getPathEffect()) { 56 if (SkPathEffect* pe = skPaint.getPathEffect()) {
57 if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) { 57 if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) {
58 return false; 58 return false;
59 } 59 }
60 } 60 }
61 61 // No hairlines. They would require new paths with customized strokes for ev ery new draw matrix.
62 // No hairlines unless we can map the 1 px width to the object space. 62 return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrok eWidth();
63 if (skPaint.getStyle() == SkPaint::kStroke_Style
64 && skPaint.getStrokeWidth() == 0
65 && viewMatrix.hasPerspective()) {
66 return false;
67 }
68
69 // No color bitmap fonts.
70 SkScalerContext::Rec rec;
71 SkScalerContext::MakeRec(skPaint, &fSurfaceProps, nullptr, &rec);
72 return rec.getFormat() != SkMask::kARGB32_Format;
73 } 63 }
74 64
75 void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt, 65 void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt,
76 const GrClip& clip, 66 const GrClip& clip,
77 const GrPaint& paint, 67 const GrPaint& paint,
78 const SkPaint& skPaint, 68 const SkPaint& skPaint,
79 const SkMatrix& viewMatrix, 69 const SkMatrix& viewMatrix,
80 const char text[], 70 const char text[],
81 size_t byteLength, 71 size_t byteLength,
82 SkScalar x, SkScalar y, 72 SkScalar x, SkScalar y,
83 const SkIRect& regionClipBounds) { 73 const SkIRect& regionClipBounds) {
84 SkASSERT(byteLength == 0 || text != nullptr); 74 SkASSERT(byteLength == 0 || text != nullptr);
85 75
86 if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) { 76 if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) {
87 return; 77 return;
88 } 78 }
89 79
90 // This is the slow path, mainly used by Skia unit tests. The other 80 this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBound s);
91 // backends (8888, gpu, ...) use device-space dependent glyph caches. In
92 // order to match the glyph positions that the other code paths produce, we
93 // must also use device-space dependent glyph cache. This has the
94 // side-effect that the glyph shape outline will be in device-space,
95 // too. This in turn has the side-effect that NVPR can not stroke the paths,
96 // as the stroke in NVPR is defined in object-space.
97 // NOTE: here we have following coincidence that works at the moment:
98 // - When using the device-space glyphs, the transforms we pass to NVPR
99 // instanced drawing are the global transforms, and the view transform is
100 // identity. NVPR can not use non-affine transforms in the instanced
101 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it
102 // will turn off the use of device-space glyphs when perspective transforms
103 // are in use.
104
105 this->init(rt, clip, paint, skPaint, byteLength, kMaxAccuracy_RenderMode, vi ewMatrix,
106 regionClipBounds);
107
108 // Transform our starting point.
109 if (fUsingDeviceSpaceGlyphs) {
110 SkPoint loc;
111 fContextInitialMatrix.mapXY(x, y, &loc);
112 x = loc.fX;
113 y = loc.fY;
114 }
115 81
116 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 82 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
117 83
118 const char* stop = text + byteLength; 84 const char* stop = text + byteLength;
119 85
120 // Measure first if needed. 86 // Measure first if needed.
121 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { 87 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
122 SkFixed stopX = 0; 88 SkFixed stopX = 0;
123 SkFixed stopY = 0; 89 SkFixed stopY = 0;
124 90
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 const SkPoint& offset, 143 const SkPoint& offset,
178 const SkIRect& regionClipBounds ) { 144 const SkIRect& regionClipBounds ) {
179 SkASSERT(byteLength == 0 || text != nullptr); 145 SkASSERT(byteLength == 0 || text != nullptr);
180 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 146 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
181 147
182 // nothing to draw 148 // nothing to draw
183 if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) { 149 if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) {
184 return; 150 return;
185 } 151 }
186 152
187 // This is the fast path. Here we do not bake in the device-transform to 153 this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBound s);
188 // the glyph outline or the advances. This is because we do not need to
189 // position the glyphs at all, since the caller has done the positioning.
190 // The positioning is based on SkPaint::measureText of individual
191 // glyphs. That already uses glyph cache without device transforms. Device
192 // transform is not part of SkPaint::measureText API, and thus we use the
193 // same glyphs as what were measured.
194
195 this->init(rt, clip, paint, skPaint, byteLength, kMaxPerformance_RenderMode, viewMatrix,
196 regionClipBounds);
197 154
198 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 155 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
199 156
200 const char* stop = text + byteLength; 157 const char* stop = text + byteLength;
201 158
202 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 159 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
203 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); 160 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
204 while (text < stop) { 161 while (text < stop) {
205 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 162 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
206 if (glyph.fWidth) { 163 if (glyph.fWidth) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 } 201 }
245 202
246 return glyphs.detach(); 203 return glyphs.detach();
247 } 204 }
248 205
249 void GrStencilAndCoverTextContext::init(GrRenderTarget* rt, 206 void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
250 const GrClip& clip, 207 const GrClip& clip,
251 const GrPaint& paint, 208 const GrPaint& paint,
252 const SkPaint& skPaint, 209 const SkPaint& skPaint,
253 size_t textByteLength, 210 size_t textByteLength,
254 RenderMode renderMode,
255 const SkMatrix& viewMatrix, 211 const SkMatrix& viewMatrix,
256 const SkIRect& regionClipBounds) { 212 const SkIRect& regionClipBounds) {
257 fClip = clip; 213 fClip = clip;
258 214
259 fRenderTarget.reset(SkRef(rt)); 215 fRenderTarget.reset(SkRef(rt));
260 216
261 fRegionClipBounds = regionClipBounds; 217 fRegionClipBounds = regionClipBounds;
262 fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect); 218 fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
263 219
264 fPaint = paint; 220 fPaint = paint;
265 fSkPaint = skPaint; 221 fSkPaint = skPaint;
266 222
267 fContextInitialMatrix = viewMatrix; 223 // Don't bake strokes into the glyph outlines. We will stroke the glyphs usi ng the GPU instead.
268 fViewMatrix = viewMatrix; 224 fStroke = GrStrokeInfo(fSkPaint);
269 fLocalMatrix = SkMatrix::I(); 225 fSkPaint.setStyle(SkPaint::kFill_Style);
270 226
271 const bool otherBackendsWillDrawAsPaths = 227 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
272 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
273 228
274 fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths && 229 if (fSkPaint.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getSt yle()) {
275 kMaxAccuracy_RenderMode == renderMode && 230 // Instead of baking fake bold into the glyph outlines, do it with the G PU stroke.
276 SkToBool(fContextInitialMatrix.getType() & 231 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
277 (SkMatrix::kScale_Mask | SkMatrix::kAffin e_Mask)); 232 kStdFakeBoldInterpKeys,
233 kStdFakeBoldInterpValues,
234 kStdFakeBoldInterpLength);
235 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
236 fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extr a : extra,
237 true /*strokeAndFill*/);
278 238
279 if (fUsingDeviceSpaceGlyphs) { 239 fSkPaint.setFakeBoldText(false);
280 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. 240 }
281 SkASSERT(!fContextInitialMatrix.hasPerspective());
282 241
283 // The whole shape (including stroke) will be baked into the glyph outli nes. Make 242 bool canUseRawPaths;
284 // NVPR just fill the baked shapes. 243 if (!fStroke.isDashed()) {
285 fStroke = GrStrokeInfo(SkStrokeRec::kFill_InitStyle); 244 // We can draw the glyphs from canonically sized paths.
245 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPath s;
246 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTe xtSize();
286 247
287 fTextRatio = fTextInverseRatio = 1.0f; 248 // Compensate for the glyphs being scaled by fTextRatio.
288 249 if (!fStroke.isFillStyle()) {
289 // Glyphs loaded by GPU path rendering have an inverted y-direction. 250 fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
290 SkMatrix m; 251 SkStrokeRec::kStrokeAndFill_Style == fStroke. getStyle());
291 m.setScale(1, -1);
292 fViewMatrix = m;
293
294 // Post-flip the initial matrix so we're left with just the flip after
295 // the paint preConcats the inverse.
296 m = fContextInitialMatrix;
297 m.postScale(1, -1);
298 if (!m.invert(&fLocalMatrix)) {
299 SkDebugf("Not invertible!\n");
300 return;
301 } 252 }
302 253
303 fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, &fContextInitialMatri x, 254 fSkPaint.setLinearText(true);
304 true /*ignoreGamma*/); 255 fSkPaint.setLCDRenderText(false);
305 fGlyphs = get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTy peface(), 256 fSkPaint.setAutohinted(false);
306 &fGlyphCache->getDescriptor(), fStroke); 257 fSkPaint.setHinting(SkPaint::kNo_Hinting);
258 fSkPaint.setSubpixelText(true);
259 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)) ;
260
261 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
262 0 == fSkPaint.getTextSkewX() &&
263 !fSkPaint.isFakeBoldText() &&
264 !fSkPaint.isVerticalText();
307 } else { 265 } else {
308 // Don't bake strokes into the glyph outlines. We will stroke the glyphs 266 fTextRatio = fTextInverseRatio = 1.0f;
309 // using the GPU instead. This is the fast path. 267 canUseRawPaths = false;
310 fStroke = GrStrokeInfo(fSkPaint);
311 fSkPaint.setStyle(SkPaint::kFill_Style);
312
313 if (fStroke.isHairlineStyle()) {
314 // Approximate hairline stroke.
315 SkScalar strokeWidth = SK_Scalar1 /
316 (SkVector::Make(fContextInitialMatrix.getScaleX(),
317 fContextInitialMatrix.getSkewY()).length());
318 fStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/);
319
320 } else if (fSkPaint.isFakeBoldText() &&
321 #ifdef SK_USE_FREETYPE_EMBOLDEN
322 kMaxPerformance_RenderMode == renderMode &&
323 #endif
324 SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
325
326 // Instead of baking fake bold into the glyph outlines, do it with t he GPU stroke.
327 SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
328 kStdFakeBoldInterpKeys,
329 kStdFakeBoldInterpValues ,
330 kStdFakeBoldInterpLength );
331 SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
332 fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
333 true /*strokeAndFill*/);
334
335 fSkPaint.setFakeBoldText(false);
336 }
337
338 bool canUseRawPaths;
339 if (!fStroke.isDashed() && (otherBackendsWillDrawAsPaths ||
340 kMaxPerformance_RenderMode == renderMode)) {
341 // We can draw the glyphs from canonically sized paths.
342 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeFor Paths;
343 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.g etTextSize();
344
345 // Compensate for the glyphs being scaled by fTextRatio.
346 if (!fStroke.isFillStyle()) {
347 fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
348 SkStrokeRec::kStrokeAndFill_Style == fStr oke.getStyle());
349 }
350
351 fSkPaint.setLinearText(true);
352 fSkPaint.setLCDRenderText(false);
353 fSkPaint.setAutohinted(false);
354 fSkPaint.setHinting(SkPaint::kNo_Hinting);
355 fSkPaint.setSubpixelText(true);
356 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPat hs));
357
358 canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
359 0 == fSkPaint.getTextSkewX() &&
360 !fSkPaint.isFakeBoldText() &&
361 !fSkPaint.isVerticalText();
362 } else {
363 fTextRatio = fTextInverseRatio = 1.0f;
364 canUseRawPaths = false;
365 }
366
367 SkMatrix textMatrix;
368 // Glyphs loaded by GPU path rendering have an inverted y-direction.
369 textMatrix.setScale(fTextRatio, -fTextRatio);
370 fViewMatrix.preConcat(textMatrix);
371 fLocalMatrix = textMatrix;
372
373 fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignor eGamma*/);
374 fGlyphs = canUseRawPaths ?
375 get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, f Stroke) :
376 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->g etTypeface(),
377 &fGlyphCache->getDescriptor(), fStroke);
378 } 268 }
379 269
380 } 270 fViewMatrix = viewMatrix;
271 fViewMatrix.preScale(fTextRatio, fTextRatio);
272 fLocalMatrix.setScale(fTextRatio, fTextRatio);
381 273
382 bool GrStencilAndCoverTextContext::mapToFallbackContext(SkMatrix* inverse) { 274 fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignoreGam ma*/);
383 // The current view matrix is flipped because GPU path rendering glyphs have an 275 fGlyphs = canUseRawPaths ?
384 // inverted y-direction. Unflip the view matrix for the fallback context. If using 276 get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, fStro ke) :
385 // device-space glyphs, we'll also need to restore the original view matrix since 277 get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTy peface(),
386 // we moved that transfomation into our local glyph cache for this scenario. Also 278 &fGlyphCache->getDescriptor(), fStroke);
387 // track the inverse operation so the caller can unmap the paint and glyph p ositions.
388 if (fUsingDeviceSpaceGlyphs) {
389 fViewMatrix = fContextInitialMatrix;
390 if (!fContextInitialMatrix.invert(inverse)) {
391 return false;
392 }
393 inverse->preScale(1, -1);
394 } else {
395 inverse->setScale(1, -1);
396 const SkMatrix& unflip = *inverse; // unflip is equal to its own inverse .
397 fViewMatrix.preConcat(unflip);
398 }
399 return true;
400 } 279 }
401 280
402 inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, cons t SkPoint& pos) { 281 inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, cons t SkPoint& pos) {
403 // Stick the glyphs we can't draw into the fallback arrays. 282 // Stick the glyphs we can't draw into the fallback arrays.
404 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 283 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
405 fFallbackIndices.push_back(glyph.getGlyphID()); 284 fFallbackIndices.push_back(glyph.getGlyphID());
406 fFallbackPositions.push_back().set(fTextInverseRatio * pos.x(), 285 fFallbackPositions.push_back(pos);
407 -fTextInverseRatio * pos.y());
408 } else { 286 } else {
409 // TODO: infer the reserve count from the text length. 287 // TODO: infer the reserve count from the text length.
410 if (!fDraw) { 288 if (!fDraw) {
411 fDraw = GrPathRangeDraw::Create(fGlyphs, 289 fDraw = GrPathRangeDraw::Create(fGlyphs,
412 GrPathRendering::kTranslate_PathTran sformType, 290 GrPathRendering::kTranslate_PathTran sformType,
413 64); 291 64);
414 } 292 }
415 float translate[] = { fTextInverseRatio * pos.x(), -fTextInverseRatio * pos.y() }; 293 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p os.y() };
416 fDraw->append(glyph.getGlyphID(), translate); 294 fDraw->append(glyph.getGlyphID(), translate);
417 } 295 }
418 } 296 }
419 297
420 static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) {
421 GR_STATIC_ASSERT(2 * sizeof(SkScalar) == sizeof(SkPoint));
422 GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX));
423
424 return &pointArray[0].fX;
425 }
426
427 void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) { 298 void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
428 if (fDraw) { 299 if (fDraw) {
429 SkASSERT(fDraw->count()); 300 SkASSERT(fDraw->count());
430 301
431 // We should only be flushing about once every run. However, if this im pacts performance 302 // We should only be flushing about once every run. However, if this im pacts performance
432 // we could move the creation of the GrPipelineBuilder earlier. 303 // we could move the creation of the GrPipelineBuilder earlier.
433 GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip); 304 GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip);
434 SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiA lias()); 305 SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiA lias());
435 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.is AntiAlias()); 306 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.is AntiAlias());
436 307
437 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 308 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
438 kZero_StencilOp, 309 kZero_StencilOp,
439 kKeep_StencilOp, 310 kKeep_StencilOp,
440 kNotEqual_StencilFunc, 311 kNotEqual_StencilFunc,
441 0xffff, 312 0xffff,
442 0x0000, 313 0x0000,
443 0xffff); 314 0xffff);
444 315
445 *pipelineBuilder.stencil() = kStencilPass; 316 *pipelineBuilder.stencil() = kStencilPass;
446 317
447 dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPai nt.getColor(), 318 dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPai nt.getColor(),
448 fDraw, GrPathRendering::kWinding_FillType); 319 fDraw, GrPathRendering::kWinding_FillType);
449 fDraw->unref(); 320 fDraw->unref();
450 fDraw = nullptr; 321 fDraw = nullptr;
451 } 322 }
452 323
453 if (fFallbackIndices.count()) { 324 if (fFallbackIndices.count()) {
454 SkASSERT(fFallbackPositions.count() == fFallbackIndices.count()); 325 SkASSERT(fFallbackPositions.count() == fFallbackIndices.count());
455 GrPaint paintFallback(fPaint);
456 326
457 SkPaint skPaintFallback(fSkPaint); 327 SkPaint fallbackSkPaint(fSkPaint);
458 if (!fUsingDeviceSpaceGlyphs) { 328 fStroke.applyToPaint(&fallbackSkPaint);
459 fStroke.applyToPaint(&skPaintFallback); 329 if (!fStroke.isFillStyle()) {
330 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
460 } 331 }
461 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for. 332 fallbackSkPaint.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
462 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 333 fallbackSkPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
334 // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color
335 // glyphs show up and https://code.google.com/p/skia/issues/detail?id=44 08 gets resolved.
336 fallbackSkPaint.setSubpixelText(false);
337 fallbackSkPaint.setTextSize(fSkPaint.getTextSize() * fTextRatio);
463 338
464 SkMatrix inverse; 339 SkMatrix fallbackMatrix(fViewMatrix);
465 if (this->mapToFallbackContext(&inverse)) { 340 fallbackMatrix.preScale(fTextInverseRatio, fTextInverseRatio);
466 inverse.mapPoints(fFallbackPositions.begin(), fFallbackPositions.cou nt());
467 }
468 341
469 fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, paintFallbac k, skPaintFallback, 342 fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, fPaint, fall backSkPaint,
470 fViewMatrix, (char*)fFallbackIndices.b egin(), 343 fallbackMatrix, (char*)fFallbackIndice s.begin(),
471 sizeof(uint16_t) * fFallbackIndices.co unt(), 344 sizeof(uint16_t) * fFallbackIndices.co unt(),
472 get_xy_scalar_array(fFallbackPositions .begin()), 345 fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
473 2, SkPoint::Make(0, 0), fRegionClipBou nds); 346 fRegionClipBounds);
474 fFallbackIndices.reset(); 347 fFallbackIndices.reset();
475 fFallbackPositions.reset(); 348 fFallbackPositions.reset();
476 } 349 }
477 } 350 }
478 351
479 void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) { 352 void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) {
480 this->flush(dc); 353 this->flush(dc);
481 354
482 SkASSERT(!fDraw); 355 SkASSERT(!fDraw);
483 SkASSERT(!fFallbackIndices.count()); 356 SkASSERT(!fFallbackIndices.count());
484 SkASSERT(!fFallbackPositions.count()); 357 SkASSERT(!fFallbackPositions.count());
485 358
486 fGlyphs->unref(); 359 fGlyphs->unref();
487 fGlyphs = nullptr; 360 fGlyphs = nullptr;
488 361
489 SkGlyphCache::AttachCache(fGlyphCache); 362 SkGlyphCache::AttachCache(fGlyphCache);
490 fGlyphCache = nullptr; 363 fGlyphCache = nullptr;
491
492 fViewMatrix = fContextInitialMatrix;
493 } 364 }
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