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 "GrAtlasTextContext.h" | 9 #include "GrAtlasTextContext.h" |
10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
11 #include "GrDrawTarget.h" | 11 #include "GrDrawTarget.h" |
12 #include "GrPath.h" | 12 #include "GrPath.h" |
13 #include "GrPathRange.h" | 13 #include "GrPathRange.h" |
14 #include "GrResourceProvider.h" | 14 #include "GrResourceProvider.h" |
15 #include "SkAutoKern.h" | 15 #include "SkAutoKern.h" |
16 #include "SkDraw.h" | 16 #include "SkDraw.h" |
17 #include "SkDrawProcs.h" | 17 #include "SkDrawProcs.h" |
18 #include "SkGlyphCache.h" | 18 #include "SkGlyphCache.h" |
19 #include "SkGpuDevice.h" | 19 #include "SkGpuDevice.h" |
20 #include "SkPath.h" | 20 #include "SkPath.h" |
21 #include "SkTextMapStateProc.h" | 21 #include "SkTextMapStateProc.h" |
22 #include "SkTextFormatParams.h" | 22 #include "SkTextFormatParams.h" |
23 | 23 |
| 24 #include "batches/GrDrawPathBatch.h" |
| 25 |
24 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, | 26 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context, |
25 const SkSurfaceProps&
surfaceProps) | 27 const SkSurfaceProps&
surfaceProps) |
26 : GrTextContext(context, surfaceProps) | 28 : INHERITED(context, surfaceProps) |
27 , fStroke(SkStrokeRec::kFill_InitStyle) | 29 , fDraw(nullptr) |
28 , fQueuedGlyphCount(0) | 30 , fStroke(SkStrokeRec::kFill_InitStyle) { |
29 , fFallbackGlyphsIdx(kGlyphBufferSize) { | |
30 } | 31 } |
31 | 32 |
32 GrStencilAndCoverTextContext* | 33 GrStencilAndCoverTextContext* |
33 GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s
urfaceProps) { | 34 GrStencilAndCoverTextContext::Create(GrContext* context, const SkSurfaceProps& s
urfaceProps) { |
34 GrStencilAndCoverTextContext* textContext = | 35 GrStencilAndCoverTextContext* textContext = |
35 new GrStencilAndCoverTextContext(context, surfaceProps); | 36 new GrStencilAndCoverTextContext(context, surfaceProps); |
36 textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surf
aceProps); | 37 textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, surf
aceProps); |
37 | 38 |
38 return textContext; | 39 return textContext; |
39 } | 40 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 SkAutoKern autokern; | 148 SkAutoKern autokern; |
148 | 149 |
149 SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio); | 150 SkFixed fixedSizeRatio = SkScalarToFixed(fTextRatio); |
150 | 151 |
151 SkFixed fx = SkScalarToFixed(x); | 152 SkFixed fx = SkScalarToFixed(x); |
152 SkFixed fy = SkScalarToFixed(y); | 153 SkFixed fy = SkScalarToFixed(y); |
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 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); | 156 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); |
156 if (glyph.fWidth) { | 157 if (glyph.fWidth) { |
157 this->appendGlyph(dc, glyph, SkPoint::Make(SkFixedToScalar(fx), SkFi
xedToScalar(fy))); | 158 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy))); |
158 } | 159 } |
159 | 160 |
160 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); | 161 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); |
161 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); | 162 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); |
162 } | 163 } |
163 | 164 |
164 this->finish(dc); | 165 this->finish(dc); |
165 } | 166 } |
166 | 167 |
167 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
et* rt, | 168 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
et* rt, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 202 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
202 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); | 203 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); |
203 while (text < stop) { | 204 while (text < stop) { |
204 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); | 205 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
205 if (glyph.fWidth) { | 206 if (glyph.fWidth) { |
206 SkPoint tmsLoc; | 207 SkPoint tmsLoc; |
207 tmsProc(pos, &tmsLoc); | 208 tmsProc(pos, &tmsLoc); |
208 SkPoint loc; | 209 SkPoint loc; |
209 alignProc(tmsLoc, glyph, &loc); | 210 alignProc(tmsLoc, glyph, &loc); |
210 | 211 |
211 this->appendGlyph(dc, glyph, loc); | 212 this->appendGlyph(glyph, loc); |
212 } | 213 } |
213 pos += scalarsPerPosition; | 214 pos += scalarsPerPosition; |
214 } | 215 } |
215 | 216 |
216 this->finish(dc); | 217 this->finish(dc); |
217 } | 218 } |
218 | 219 |
219 static GrPathRange* get_gr_glyphs(GrContext* ctx, | 220 static GrPathRange* get_gr_glyphs(GrContext* ctx, |
220 const SkTypeface* typeface, | 221 const SkTypeface* typeface, |
221 const SkDescriptor* desc, | 222 const SkDescriptor* desc, |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 } | 392 } |
392 inverse->preScale(1, -1); | 393 inverse->preScale(1, -1); |
393 } else { | 394 } else { |
394 inverse->setScale(1, -1); | 395 inverse->setScale(1, -1); |
395 const SkMatrix& unflip = *inverse; // unflip is equal to its own inverse
. | 396 const SkMatrix& unflip = *inverse; // unflip is equal to its own inverse
. |
396 fViewMatrix.preConcat(unflip); | 397 fViewMatrix.preConcat(unflip); |
397 } | 398 } |
398 return true; | 399 return true; |
399 } | 400 } |
400 | 401 |
401 inline void GrStencilAndCoverTextContext::appendGlyph(GrDrawContext* dc, | 402 inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, cons
t SkPoint& pos) { |
402 const SkGlyph& glyph, | 403 // Stick the glyphs we can't draw into the fallback arrays. |
403 const SkPoint& pos) { | 404 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
404 if (fQueuedGlyphCount >= fFallbackGlyphsIdx) { | 405 fFallbackIndices.push_back(glyph.getGlyphID()); |
405 SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx); | 406 fFallbackPositions.push_back().set(fTextInverseRatio * pos.x(), |
406 this->flush(dc); | 407 -fTextInverseRatio * pos.y()); |
| 408 } else { |
| 409 // TODO: infer the reserve count from the text length. |
| 410 if (!fDraw) { |
| 411 fDraw = GrPathRangeDraw::Create(fGlyphs, |
| 412 GrPathRendering::kTranslate_PathTran
sformType, |
| 413 64); |
| 414 } |
| 415 float translate[] = { fTextInverseRatio * pos.x(), -fTextInverseRatio *
pos.y() }; |
| 416 fDraw->append(glyph.getGlyphID(), translate); |
407 } | 417 } |
408 | |
409 // Stick the glyphs we can't draw at the end of the buffer, growing backward
s. | |
410 int index = (SkMask::kARGB32_Format == glyph.fMaskFormat) ? | |
411 --fFallbackGlyphsIdx : fQueuedGlyphCount++; | |
412 | |
413 fGlyphIndices[index] = glyph.getGlyphID(); | |
414 fGlyphPositions[index].set(fTextInverseRatio * pos.x(), -fTextInverseRatio *
pos.y()); | |
415 } | 418 } |
416 | 419 |
417 static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) { | 420 static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) { |
418 GR_STATIC_ASSERT(2 * sizeof(SkScalar) == sizeof(SkPoint)); | 421 GR_STATIC_ASSERT(2 * sizeof(SkScalar) == sizeof(SkPoint)); |
419 GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX)); | 422 GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX)); |
420 | 423 |
421 return &pointArray[0].fX; | 424 return &pointArray[0].fX; |
422 } | 425 } |
423 | 426 |
424 void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) { | 427 void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) { |
425 if (fQueuedGlyphCount > 0) { | 428 if (fDraw) { |
| 429 SkASSERT(fDraw->count()); |
426 SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor
(), | 430 SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor
(), |
427 fViewMatrix, | 431 fViewMatrix, |
428 fLocalMatrix)); | 432 fLocalMatrix)); |
429 | 433 |
430 // We should only be flushing about once every run. However, if this im
pacts performance | 434 // We should only be flushing about once every run. However, if this im
pacts performance |
431 // we could move the creation of the GrPipelineBuilder earlier. | 435 // we could move the creation of the GrPipelineBuilder earlier. |
432 GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip); | 436 GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip); |
433 SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiA
lias()); | 437 SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiA
lias()); |
434 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.is
AntiAlias()); | 438 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.is
AntiAlias()); |
435 | 439 |
436 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | 440 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, |
437 kZero_StencilOp, | 441 kZero_StencilOp, |
438 kKeep_StencilOp, | 442 kKeep_StencilOp, |
439 kNotEqual_StencilFunc, | 443 kNotEqual_StencilFunc, |
440 0xffff, | 444 0xffff, |
441 0x0000, | 445 0x0000, |
442 0xffff); | 446 0xffff); |
443 | 447 |
444 *pipelineBuilder.stencil() = kStencilPass; | 448 *pipelineBuilder.stencil() = kStencilPass; |
445 | 449 |
446 SkASSERT(kGlyphBufferSize == fFallbackGlyphsIdx); | 450 dc->drawPathsFromRange(&pipelineBuilder, pp, fDraw, GrPathRendering::kWi
nding_FillType); |
447 | 451 fDraw->unref(); |
448 dc->drawPaths(&pipelineBuilder, pp, fGlyphs, | 452 fDraw = nullptr; |
449 fGlyphIndices, GrPathRange::kU16_PathIndexType, | |
450 get_xy_scalar_array(fGlyphPositions), | |
451 GrPathRendering::kTranslate_PathTransformType, | |
452 fQueuedGlyphCount, GrPathRendering::kWinding_FillType); | |
453 | |
454 fQueuedGlyphCount = 0; | |
455 } | 453 } |
456 | 454 |
457 if (fFallbackGlyphsIdx < kGlyphBufferSize) { | 455 if (fFallbackIndices.count()) { |
458 int fallbackGlyphCount = kGlyphBufferSize - fFallbackGlyphsIdx; | 456 SkASSERT(fFallbackPositions.count() == fFallbackIndices.count()); |
459 | |
460 GrPaint paintFallback(fPaint); | 457 GrPaint paintFallback(fPaint); |
461 | 458 |
462 SkPaint skPaintFallback(fSkPaint); | 459 SkPaint skPaintFallback(fSkPaint); |
463 if (!fUsingDeviceSpaceGlyphs) { | 460 if (!fUsingDeviceSpaceGlyphs) { |
464 fStroke.applyToPaint(&skPaintFallback); | 461 fStroke.applyToPaint(&skPaintFallback); |
465 } | 462 } |
466 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already
been accounted for. | 463 skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already
been accounted for. |
467 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 464 skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
468 | 465 |
469 SkMatrix inverse; | 466 SkMatrix inverse; |
470 if (this->mapToFallbackContext(&inverse)) { | 467 if (this->mapToFallbackContext(&inverse)) { |
471 inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyp
hCount); | 468 inverse.mapPoints(fFallbackPositions.begin(), fFallbackPositions.cou
nt()); |
472 } | 469 } |
473 | 470 |
474 fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, paintFallbac
k, skPaintFallback, | 471 fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, paintFallbac
k, skPaintFallback, |
475 fViewMatrix, (char*)&fGlyphIndices[fFa
llbackGlyphsIdx], | 472 fViewMatrix, (char*)fFallbackIndices.b
egin(), |
476 2 * fallbackGlyphCount, | 473 sizeof(uint16_t) * fFallbackIndices.co
unt(), |
477 get_xy_scalar_array(&fGlyphPositions[f
FallbackGlyphsIdx]), | 474 get_xy_scalar_array(fFallbackPositions
.begin()), |
478 2, SkPoint::Make(0, 0), fRegionClipBou
nds); | 475 2, SkPoint::Make(0, 0), fRegionClipBou
nds); |
479 | 476 fFallbackIndices.reset(); |
480 fFallbackGlyphsIdx = kGlyphBufferSize; | 477 fFallbackPositions.reset(); |
481 } | 478 } |
482 } | 479 } |
483 | 480 |
484 void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) { | 481 void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) { |
485 this->flush(dc); | 482 this->flush(dc); |
486 | 483 |
| 484 SkASSERT(!fDraw); |
| 485 SkASSERT(!fFallbackIndices.count()); |
| 486 SkASSERT(!fFallbackPositions.count()); |
| 487 |
487 fGlyphs->unref(); | 488 fGlyphs->unref(); |
488 fGlyphs = nullptr; | 489 fGlyphs = nullptr; |
489 | 490 |
490 SkGlyphCache::AttachCache(fGlyphCache); | 491 SkGlyphCache::AttachCache(fGlyphCache); |
491 fGlyphCache = nullptr; | 492 fGlyphCache = nullptr; |
492 | 493 |
493 fViewMatrix = fContextInitialMatrix; | 494 fViewMatrix = fContextInitialMatrix; |
494 } | 495 } |
495 | |
OLD | NEW |