Chromium Code Reviews| Index: src/gpu/GrStencilAndCoverTextContext.cpp |
| diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp |
| index 1d20a49eb02a416aaa2e43e8a6ab0daa4bcfecb2..df46ec80a92866918efeadc9258485fe1c64bb11 100644 |
| --- a/src/gpu/GrStencilAndCoverTextContext.cpp |
| +++ b/src/gpu/GrStencilAndCoverTextContext.cpp |
| @@ -140,24 +140,23 @@ void GrStencilAndCoverTextContext::drawText(const GrPaint& paint, |
| // will turn off the use of device-space glyphs when perspective transforms |
| // are in use. |
| - fGlyphTransform = fContext->getMatrix(); |
| - |
| - this->init(paint, skPaint, byteLength); |
| + this->init(paint, skPaint, byteLength, kUseIfNeeded_DeviceSpaceGlyphsBehavior); |
| SkMatrix* glyphCacheTransform = NULL; |
| // Transform our starting point. |
| if (fNeedsDeviceSpaceGlyphs) { |
| SkPoint loc; |
| - fGlyphTransform.mapXY(x, y, &loc); |
| + fContextInitialMatrix.mapXY(x, y, &loc); |
| x = loc.fX; |
| y = loc.fY; |
| - glyphCacheTransform = &fGlyphTransform; |
| + glyphCacheTransform = &fContextInitialMatrix; |
| } |
| SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform); |
| fGlyphCache = autoCache.getCache(); |
| fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke); |
| + fTransformType = GrDrawTarget::kTranslate_PathTransformType; |
| const char* stop = text + byteLength; |
| @@ -231,9 +230,9 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint, |
| // glyphs. That already uses glyph cache without device transforms. Device |
| // transform is not part of SkPaint::measureText API, and thus we use the |
| // same glyphs as what were measured. |
| - fGlyphTransform.reset(); |
| - this->init(paint, skPaint, byteLength); |
| + const float textTranslateY = (1 == scalarsPerPosition ? constY : 0); |
| + this->init(paint, skPaint, byteLength, kDoNotUse_DeviceSpaceGlyphsBehavior, textTranslateY); |
| SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); |
| @@ -242,20 +241,32 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint, |
| fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke); |
| const char* stop = text + byteLength; |
| - SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); |
| - SkTextMapStateProc tmsProc(SkMatrix::I(), constY, scalarsPerPosition); |
| if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { |
| - while (text < stop) { |
| - SkPoint loc; |
| - tmsProc(pos, &loc); |
| - const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| - if (glyph.fWidth) { |
| - this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); |
| + if (1 == scalarsPerPosition) { |
| + fTransformType = GrDrawTarget::kTranslateX_PathTransformType; |
| + while (text < stop) { |
| + const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| + if (glyph.fWidth) { |
| + this->appendGlyph(glyph.getGlyphID(), *pos); |
| + } |
| + pos++; |
| + } |
| + } else { |
| + SkASSERT(2 == scalarsPerPosition); |
| + fTransformType = GrDrawTarget::kTranslate_PathTransformType; |
| + while (text < stop) { |
| + const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| + if (glyph.fWidth) { |
| + this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]); |
| + } |
| + pos += 2; |
| } |
| - pos += scalarsPerPosition; |
| } |
| } else { |
|
Chris Dalton
2014/07/18 22:23:30
We could do a translate-x here too if we could ver
jvanverth1
2014/07/21 17:23:13
Not sure -- adding bungeman to see if he knows.
bungeman-skia
2014/07/21 17:51:27
I'm not sure I understand. You've used scalersPerP
|
| + fTransformType = GrDrawTarget::kTranslate_PathTransformType; |
| + SkTextMapStateProc tmsProc(SkMatrix::I(), 0, scalarsPerPosition); |
| + SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign()); |
| while (text < stop) { |
| const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); |
| if (glyph.fWidth) { |
| @@ -299,16 +310,21 @@ bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) { |
| void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| const SkPaint& skPaint, |
| - size_t textByteLength) { |
| + size_t textByteLength, |
| + DeviceSpaceGlyphsBehavior deviceSpaceGlyphsBehavior, |
| + SkScalar textTranslateY) { |
| GrTextContext::init(paint, skPaint); |
| + fContextInitialMatrix = fContext->getMatrix(); |
| + |
| bool otherBackendsWillDrawAsPaths = |
| - SkDraw::ShouldDrawTextAsPaths(skPaint, fContext->getMatrix()); |
| + SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix); |
| if (otherBackendsWillDrawAsPaths) { |
| // This is to reproduce SkDraw::drawText_asPaths glyph positions. |
| fSkPaint.setLinearText(true); |
| fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; |
| + fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize(); |
| fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); |
| if (fSkPaint.getStyle() != SkPaint::kFill_Style) { |
| // Compensate the glyphs being scaled up by fTextRatio by scaling the |
| @@ -317,24 +333,35 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| } |
| fNeedsDeviceSpaceGlyphs = false; |
| } else { |
| - fTextRatio = 1.0f; |
| - fNeedsDeviceSpaceGlyphs = (fGlyphTransform.getType() & |
| - (SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) != 0; |
| + fTextRatio = fTextInverseRatio = 1.0f; |
| + fNeedsDeviceSpaceGlyphs = |
| + kUseIfNeeded_DeviceSpaceGlyphsBehavior == deviceSpaceGlyphsBehavior && |
| + (fContextInitialMatrix.getType() & |
| + (SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) != 0; |
| // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. |
| - SkASSERT(!fGlyphTransform.hasPerspective()); |
| - if (fNeedsDeviceSpaceGlyphs) { |
| - fPaint.localCoordChangeInverse(fGlyphTransform); |
| - fContext->setIdentityMatrix(); |
| - } |
| + SkASSERT(!fContextInitialMatrix.hasPerspective()); |
| } |
| fStroke = SkStrokeRec(fSkPaint); |
| if (fNeedsDeviceSpaceGlyphs) { |
| + SkASSERT(1.0f == fTextRatio); |
| + SkASSERT(0.0f == textTranslateY); |
| + fPaint.localCoordChangeInverse(fContextInitialMatrix); |
| + fContext->setIdentityMatrix(); |
| + |
| // The whole shape is baked into the glyph. Make NVPR just fill the |
| // baked shape. |
| fStroke.setStrokeStyle(-1, false); |
| } else { |
| + if (1.0f != fTextRatio || 0.0f != textTranslateY) { |
| + SkMatrix textMatrix; |
| + textMatrix.setTranslate(0, textTranslateY); |
| + textMatrix.preScale(fTextRatio, fTextRatio); |
| + fPaint.localCoordChange(textMatrix); |
| + fContext->concatMatrix(textMatrix); |
| + } |
| + |
| if (fSkPaint.getStrokeWidth() == 0.0f) { |
| if (fSkPaint.getStyle() == SkPaint::kStrokeAndFill_Style) { |
| fStroke.setStrokeStyle(-1, false); |
| @@ -342,7 +369,7 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| // Approximate hairline stroke. |
| const SkMatrix& ctm = fContext->getMatrix(); |
| SkScalar strokeWidth = SK_Scalar1 / |
| - (fTextRatio * SkVector::Make(ctm.getScaleX(), ctm.getSkewY()).length()); |
| + (SkVector::Make(ctm.getScaleX(), ctm.getSkewY()).length()); |
| fStroke.setStrokeStyle(strokeWidth, false); |
| } |
| } |
| @@ -369,7 +396,24 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint, |
| SkASSERT(0 == fPendingGlyphCount); |
| } |
| +inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) { |
| + SkASSERT(GrDrawTarget::kTranslateX_PathTransformType == fTransformType); |
| + |
| + if (fPendingGlyphCount >= kGlyphBufferSize) { |
| + this->flush(); |
| + } |
| + |
| + fGlyphs->preloadGlyph(glyphID, fGlyphCache); |
| + |
| + fIndexBuffer[fPendingGlyphCount] = glyphID; |
| + fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x; |
| + |
| + ++fPendingGlyphCount; |
| +} |
| + |
| inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) { |
| + SkASSERT(GrDrawTarget::kTranslate_PathTransformType == fTransformType); |
| + |
| if (fPendingGlyphCount >= kGlyphBufferSize) { |
| this->flush(); |
| } |
| @@ -377,12 +421,8 @@ inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, |
| fGlyphs->preloadGlyph(glyphID, fGlyphCache); |
| fIndexBuffer[fPendingGlyphCount] = glyphID; |
| - fTransformBuffer[6 * fPendingGlyphCount + 0] = fTextRatio; |
| - fTransformBuffer[6 * fPendingGlyphCount + 1] = 0; |
| - fTransformBuffer[6 * fPendingGlyphCount + 2] = x; |
| - fTransformBuffer[6 * fPendingGlyphCount + 3] = 0; |
| - fTransformBuffer[6 * fPendingGlyphCount + 4] = fTextRatio; |
| - fTransformBuffer[6 * fPendingGlyphCount + 5] = y; |
| + fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x; |
| + fTransformBuffer[2 * fPendingGlyphCount + 1] = fTextInverseRatio * y; |
| ++fPendingGlyphCount; |
| } |
| @@ -393,8 +433,7 @@ void GrStencilAndCoverTextContext::flush() { |
| } |
| fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCount, |
| - fTransformBuffer, GrDrawTarget::kAffine_PathTransformType, |
| - SkPath::kWinding_FillType); |
| + fTransformBuffer, fTransformType, SkPath::kWinding_FillType); |
| fPendingGlyphCount = 0; |
| } |
| @@ -408,9 +447,7 @@ void GrStencilAndCoverTextContext::finish() { |
| fDrawTarget->drawState()->stencil()->setDisabled(); |
| fStateRestore.set(NULL); |
| - if (fNeedsDeviceSpaceGlyphs) { |
| - fContext->setMatrix(fGlyphTransform); |
| - } |
| + fContext->setMatrix(fContextInitialMatrix); |
| GrTextContext::finish(); |
| } |