| 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 |