Index: src/gpu/GrStencilAndCoverTextContext.cpp |
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp |
index 0a09a2fbc249cf43b15a7635d583739621f1db33..d3d711fa020b0d66fc468f164bcd09837eee7cb3 100644 |
--- a/src/gpu/GrStencilAndCoverTextContext.cpp |
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp |
@@ -151,24 +151,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; |
@@ -242,9 +241,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(); |
@@ -253,20 +252,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 { |
+ 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) { |
@@ -310,16 +321,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 |
@@ -328,24 +344,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); |
@@ -353,7 +380,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); |
} |
} |
@@ -380,7 +407,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(); |
} |
@@ -388,12 +432,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; |
} |
@@ -404,8 +444,7 @@ void GrStencilAndCoverTextContext::flush() { |
} |
fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCount, |
- fTransformBuffer, GrDrawTarget::kAffine_PathTransformType, |
- SkPath::kWinding_FillType); |
+ fTransformBuffer, fTransformType, SkPath::kWinding_FillType); |
fPendingGlyphCount = 0; |
} |
@@ -419,9 +458,7 @@ void GrStencilAndCoverTextContext::finish() { |
fDrawTarget->drawState()->stencil()->setDisabled(); |
fStateRestore.set(NULL); |
- if (fNeedsDeviceSpaceGlyphs) { |
- fContext->setMatrix(fGlyphTransform); |
- } |
+ fContext->setMatrix(fContextInitialMatrix); |
GrTextContext::finish(); |
} |