Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 759613005: Add color emoji fallback for nvpr text (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrStencilAndCoverTextContext.cpp
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index d6efe9810ce77a97b35aa01984431ec7218e0126..d33bc7a8bfd3395f565af138687e620749a90de5 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -23,7 +23,9 @@
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(
GrContext* context, const SkDeviceProperties& properties)
: GrTextContext(context, properties)
- , fPendingGlyphCount(0) {
+ , fStroke(SkStrokeRec::kFill_InitStyle)
+ , fQueuedGlyphCount(0)
+ , fFallbackGlyphsIdx(kGlyphBufferSize) {
}
GrStencilAndCoverTextContext* GrStencilAndCoverTextContext::Create(GrContext* context,
@@ -63,10 +65,10 @@ bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) {
}
void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
- const SkPaint& skPaint,
- const char text[],
- size_t byteLength,
- SkScalar x, SkScalar y) {
+ const SkPaint& skPaint,
+ const char text[],
+ size_t byteLength,
+ SkScalar x, SkScalar y) {
SkASSERT(byteLength == 0 || text != NULL);
if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
@@ -91,7 +93,7 @@ void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
this->init(paint, skPaint, byteLength, kMaxAccuracy_RenderMode);
// Transform our starting point.
- if (fNeedsDeviceSpaceGlyphs) {
+ if (fUsingDeviceSpaceGlyphs) {
SkPoint loc;
fContextInitialMatrix.mapXY(x, y, &loc);
x = loc.fX;
@@ -140,7 +142,7 @@ void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
fx += SkFixedMul_portable(autokern.adjust(glyph), fixedSizeRatio);
if (glyph.fWidth) {
- this->appendGlyph(glyph.getGlyphID(), SkFixedToScalar(fx), SkFixedToScalar(fy));
+ this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
}
fx += SkFixedMul_portable(glyph.fAdvanceX, fixedSizeRatio);
@@ -151,12 +153,12 @@ void GrStencilAndCoverTextContext::onDrawText(const GrPaint& paint,
}
void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint,
- const SkPaint& skPaint,
- const char text[],
- size_t byteLength,
- const SkScalar pos[],
- int scalarsPerPosition,
- const SkPoint& offset) {
+ const SkPaint& skPaint,
+ const char text[],
+ size_t byteLength,
+ const SkScalar pos[],
+ int scalarsPerPosition,
+ const SkPoint& offset) {
SkASSERT(byteLength == 0 || text != NULL);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
@@ -189,7 +191,7 @@ void GrStencilAndCoverTextContext::onDrawPosText(const GrPaint& paint,
SkPoint loc;
alignProc(tmsLoc, glyph, &loc);
- this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y());
+ this->appendGlyph(glyph, loc);
}
pos += scalarsPerPosition;
}
@@ -232,15 +234,19 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
const bool otherBackendsWillDrawAsPaths =
SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
- fNeedsDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths &&
+ fUsingDeviceSpaceGlyphs = !otherBackendsWillDrawAsPaths &&
kMaxAccuracy_RenderMode == renderMode &&
SkToBool(fContextInitialMatrix.getType() &
(SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask));
- if (fNeedsDeviceSpaceGlyphs) {
+ if (fUsingDeviceSpaceGlyphs) {
// SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms.
SkASSERT(!fContextInitialMatrix.hasPerspective());
+ // The whole shape (including stroke) will be baked into the glyph outlines. Make
+ // NVPR just fill the baked shapes.
+ fStroke = SkStrokeRec(SkStrokeRec::kFill_InitStyle);
+
fTextRatio = fTextInverseRatio = 1.0f;
// Glyphs loaded by GPU path rendering have an inverted y-direction.
@@ -254,30 +260,27 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
m.postScale(1, -1);
fPaint.localCoordChangeInverse(m);
- // The whole shape (including stroke) will be baked into the glyph outlines. Make
- // NVPR just fill the baked shapes.
fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, &fContextInitialMatrix, false);
fGlyphs = get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
- &fGlyphCache->getDescriptor(),
- SkStrokeRec(SkStrokeRec::kFill_InitStyle));
+ &fGlyphCache->getDescriptor(), fStroke);
} else {
// Don't bake strokes into the glyph outlines. We will stroke the glyphs
// using the GPU instead. This is the fast path.
- SkStrokeRec gpuStroke = SkStrokeRec(fSkPaint);
+ fStroke = SkStrokeRec(fSkPaint);
fSkPaint.setStyle(SkPaint::kFill_Style);
- if (gpuStroke.isHairlineStyle()) {
+ if (fStroke.isHairlineStyle()) {
// Approximate hairline stroke.
SkScalar strokeWidth = SK_Scalar1 /
(SkVector::Make(fContextInitialMatrix.getScaleX(),
fContextInitialMatrix.getSkewY()).length());
- gpuStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/);
+ fStroke.setStrokeStyle(strokeWidth, false /*strokeAndFill*/);
} else if (fSkPaint.isFakeBoldText() &&
#ifdef SK_USE_FREETYPE_EMBOLDEN
kMaxPerformance_RenderMode == renderMode &&
#endif
- SkStrokeRec::kStroke_Style != gpuStroke.getStyle()) {
+ SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
// Instead of baking fake bold into the glyph outlines, do it with the GPU stroke.
SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
@@ -285,8 +288,8 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
kStdFakeBoldInterpValues,
kStdFakeBoldInterpLength);
SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
- gpuStroke.setStrokeStyle(gpuStroke.needToApply() ? gpuStroke.getWidth() + extra : extra,
- true /*strokeAndFill*/);
+ fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
+ true /*strokeAndFill*/);
fSkPaint.setFakeBoldText(false);
}
@@ -299,9 +302,9 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize();
// Compensate for the glyphs being scaled by fTextRatio.
- if (!gpuStroke.isFillStyle()) {
- gpuStroke.setStrokeStyle(gpuStroke.getWidth() / fTextRatio,
- SkStrokeRec::kStrokeAndFill_Style == gpuStroke.getStyle());
+ if (!fStroke.isFillStyle()) {
+ fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
+ SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
}
fSkPaint.setLinearText(true);
@@ -328,9 +331,9 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
fGlyphCache = fSkPaint.detachCache(&fDeviceProperties, NULL, false);
fGlyphs = canUseRawPaths ?
- get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, gpuStroke) :
+ get_gr_glyphs(fContext, fSkPaint.getTypeface(), NULL, fStroke) :
get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
- &fGlyphCache->getDescriptor(), gpuStroke);
+ &fGlyphCache->getDescriptor(), fStroke);
}
fStateRestore.set(&fDrawState);
@@ -347,31 +350,90 @@ void GrStencilAndCoverTextContext::init(const GrPaint& paint,
*fDrawState.stencil() = kStencilPass;
- SkASSERT(0 == fPendingGlyphCount);
+ SkASSERT(0 == fQueuedGlyphCount);
+ SkASSERT(kGlyphBufferSize == fFallbackGlyphsIdx);
+}
+
+bool GrStencilAndCoverTextContext::mapToFallbackContext(GrContext::AutoMatrix& autoMatrix,
+ SkMatrix* inverse) {
+ // The current view matrix is flipped because GPU path rendering glyphs have an
+ // inverted y-direction. Unflip the view matrix for the fallback context. If using
+ // device-space glyphs, we'll also need to restore the original view matrix since
+ // we moved that transfomation into our local glyph cache for this scenario. Also
+ // track the inverse operation so the caller can unmap the paint and glyph positions.
+ if (fUsingDeviceSpaceGlyphs) {
+ autoMatrix.set(fContext, fContextInitialMatrix);
+ if (!fContextInitialMatrix.invert(inverse)) {
+ return false;
+ }
+ inverse->preScale(1, -1);
+ } else {
+ inverse->setScale(1, -1);
+ const SkMatrix& unflip = *inverse; // unflip is equal to its own inverse.
+ autoMatrix.setPreConcat(fContext, unflip);
+ }
+ return true;
}
-inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
- if (fPendingGlyphCount >= kGlyphBufferSize) {
+inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
+ if (fQueuedGlyphCount >= fFallbackGlyphsIdx) {
+ SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx);
this->flush();
}
- fIndexBuffer[fPendingGlyphCount] = glyphID;
- fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x;
- fTransformBuffer[2 * fPendingGlyphCount + 1] = -fTextInverseRatio * y;
+ // Stick the glyphs we can't draw at the end of the buffer, growing backwards.
Chris Dalton 2014/11/25 23:13:54 Looking for feedback here. Growing backwards will
jvanverth1 2014/11/26 19:41:35 On one hand, drawing them in reverse order doesn't
+ int index = (SkMask::kARGB32_Format == glyph.fMaskFormat) ?
+ --fFallbackGlyphsIdx : fQueuedGlyphCount++;
- ++fPendingGlyphCount;
+ fGlyphIndices[index] = glyph.getGlyphID();
+ fGlyphPositions[index].set(fTextInverseRatio * pos.x(), -fTextInverseRatio * pos.y());
+}
+
+static const SkScalar* get_xy_scalar_array(const SkPoint* pointArray) {
+ GR_STATIC_ASSERT(2 * sizeof(SkScalar) == sizeof(SkPoint));
+ GR_STATIC_ASSERT(0 == offsetof(SkPoint, fX));
+
+ return &pointArray[0].fX;
}
void GrStencilAndCoverTextContext::flush() {
- if (0 == fPendingGlyphCount) {
- return;
+ if (fQueuedGlyphCount > 0) {
+ fDrawTarget->drawPaths(&fDrawState, fGlyphs,
+ fGlyphIndices, GrPathRange::kU16_PathIndexType,
+ get_xy_scalar_array(fGlyphPositions),
+ GrPathRendering::kTranslate_PathTransformType,
+ fQueuedGlyphCount, GrPathRendering::kWinding_FillType);
+
+ fQueuedGlyphCount = 0;
}
- fDrawTarget->drawPaths(&fDrawState, fGlyphs, fIndexBuffer, GrPathRange::kU16_PathIndexType,
- fTransformBuffer, GrPathRendering::kTranslate_PathTransformType,
- fPendingGlyphCount, GrPathRendering::kWinding_FillType);
+ if (fFallbackGlyphsIdx < kGlyphBufferSize) {
+ int fallbackGlyphCount = kGlyphBufferSize - fFallbackGlyphsIdx;
+
+ GrPaint paintFallback(fPaint);
- fPendingGlyphCount = 0;
+ SkPaint skPaintFallback(fSkPaint);
+ if (!fUsingDeviceSpaceGlyphs) {
+ fStroke.applyToPaint(&skPaintFallback);
+ }
+ skPaintFallback.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
+ skPaintFallback.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+ GrContext::AutoMatrix autoMatrix;
+ SkMatrix inverse;
+ if (this->mapToFallbackContext(autoMatrix, &inverse)) {
+ paintFallback.localCoordChangeInverse(inverse);
+ inverse.mapPoints(&fGlyphPositions[fFallbackGlyphsIdx], fallbackGlyphCount);
+ }
+
+ fFallbackTextContext->drawPosText(paintFallback, skPaintFallback,
+ (char*)&fGlyphIndices[fFallbackGlyphsIdx],
+ 2 * fallbackGlyphCount,
+ get_xy_scalar_array(&fGlyphPositions[fFallbackGlyphsIdx]),
+ 2, SkPoint::Make(0, 0));
+
+ fFallbackGlyphsIdx = kGlyphBufferSize;
+ }
}
void GrStencilAndCoverTextContext::finish() {
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698