| 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();
|
| }
|
|
|
|
|