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

Unified Diff: src/gpu/GrStencilAndCoverTextContext.cpp

Issue 1375353004: Add TextRun object to nvpr text (Closed) Base URL: https://skia.googlesource.com/skia.git@upload1_simplify
Patch Set: Created 5 years, 3 months 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 9c0fc2a8ec2a2fe10a5bb1e2930224b1dfea736c..9f394f901875364ff3fc59570716a215410f86f1 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -25,9 +25,7 @@
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
const SkSurfaceProps& surfaceProps)
- : INHERITED(context, surfaceProps)
- , fDraw(nullptr)
- , fStroke(SkStrokeRec::kFill_InitStyle) {
+ : INHERITED(context, surfaceProps) {
}
GrStencilAndCoverTextContext*
@@ -71,20 +69,103 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
size_t byteLength,
SkScalar x, SkScalar y,
const SkIRect& regionClipBounds) {
- SkASSERT(byteLength == 0 || text != nullptr);
+ TextRun run(skPaint);
+ run.setText(text, byteLength, x, y, fContext, &fSurfaceProps);
+ run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
+}
+
+void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
+ const GrClip& clip,
+ const GrPaint& paint,
+ const SkPaint& skPaint,
+ const SkMatrix& viewMatrix,
+ const char text[],
+ size_t byteLength,
+ const SkScalar pos[],
+ int scalarsPerPosition,
+ const SkPoint& offset,
+ const SkIRect& regionClipBounds) {
+ TextRun run(skPaint);
+ run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps);
+ run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
+}
- if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) {
- return;
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
+ : fStroke(fontAndStroke),
+ fFont(fontAndStroke) {
+ SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
+
+ // Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
+ // rendering API for stroking).
+ fFont.setStyle(SkPaint::kFill_Style);
+
+ if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
+ // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
+ SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
+ kStdFakeBoldInterpKeys,
+ kStdFakeBoldInterpValues,
+ kStdFakeBoldInterpLength);
+ SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale);
+ fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
+ true /*strokeAndFill*/);
+
+ fFont.setFakeBoldText(false);
}
- this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
+ if (!fFont.getPathEffect() && !fStroke.isDashed()) {
+ // We can draw the glyphs from canonically sized paths.
+ fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
+ fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ // Compensate for the glyphs being scaled by fTextRatio.
+ if (!fStroke.isFillStyle()) {
+ fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
+ SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
+ }
+
+ fFont.setLinearText(true);
+ fFont.setLCDRenderText(false);
+ fFont.setAutohinted(false);
+ fFont.setHinting(SkPaint::kNo_Hinting);
+ fFont.setSubpixelText(true);
+ fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
+
+ fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
+ 0 == fFont.getTextSkewX() &&
+ !fFont.isFakeBoldText() &&
+ !fFont.isVerticalText();
+ } else {
+ fTextRatio = fTextInverseRatio = 1.0f;
+ fUsingRawGlyphPaths = false;
+ }
+
+ // When drawing from canonically sized paths, the actual local coords are fTextRatio * coords.
+ fLocalMatrix.setScale(fTextRatio, fTextRatio);
+}
+
+GrStencilAndCoverTextContext::TextRun::~TextRun() {
+}
+
+void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength,
+ SkScalar x, SkScalar y, GrContext* ctx,
+ const SkSurfaceProps* surfaceProps) {
+ SkASSERT(byteLength == 0 || text != nullptr);
+
+ SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
+ SkGlyphCache* glyphCache = autoGlyphCache.getCache();
+
+ fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
+ GrPathRendering::kTranslate_PathTransformType,
+ fFont.countText(text, byteLength)));
+
+ SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
const char* stop = text + byteLength;
// Measure first if needed.
- if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
SkFixed stopX = 0;
SkFixed stopY = 0;
@@ -92,7 +173,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
while (textPtr < stop) {
// We don't need x, y here, since all subpixel variants will have the
// same advance.
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &textPtr, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr, 0, 0);
stopX += glyph.fAdvanceX;
stopY += glyph.fAdvanceY;
@@ -102,7 +183,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
SkScalar alignX = SkFixedToScalar(stopX) * fTextRatio;
SkScalar alignY = SkFixedToScalar(stopY) * fTextRatio;
- if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
alignX = SkScalarHalf(alignX);
alignY = SkScalarHalf(alignY);
}
@@ -118,7 +199,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
SkFixed fx = SkScalarToFixed(x);
SkFixed fy = SkScalarToFixed(y);
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
if (glyph.fWidth) {
this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
@@ -127,39 +208,30 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
}
-
- this->finish(dc);
}
-void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- const SkMatrix& viewMatrix,
- const char text[],
- size_t byteLength,
- const SkScalar pos[],
- int scalarsPerPosition,
- const SkPoint& offset,
- const SkIRect& regionClipBounds) {
+void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
+ const SkScalar pos[], int scalarsPerPosition,
+ const SkPoint& offset, GrContext* ctx,
+ const SkSurfaceProps* surfaceProps) {
SkASSERT(byteLength == 0 || text != nullptr);
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
- // nothing to draw
- if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) {
- return;
- }
+ SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
+ SkGlyphCache* glyphCache = autoGlyphCache.getCache();
- this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
+ fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
+ GrPathRendering::kTranslate_PathTransformType,
+ fFont.countText(text, byteLength)));
- SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+ SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
const char* stop = text + byteLength;
SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
- SkTextAlignProc alignProc(fSkPaint.getTextAlign());
+ SkTextAlignProc alignProc(fFont.getTextAlign());
while (text < stop) {
- const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
+ const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
if (glyph.fWidth) {
SkPoint tmsLoc;
tmsProc(pos, &tmsLoc);
@@ -170,23 +242,22 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
}
pos += scalarsPerPosition;
}
-
- this->finish(dc);
}
-static GrPathRange* get_gr_glyphs(GrContext* ctx,
- const SkTypeface* typeface,
- const SkDescriptor* desc,
- const GrStrokeInfo& stroke) {
+GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx,
+ SkGlyphCache* glyphCache) {
+ SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface()
+ : glyphCache->getScalerContext()->getTypeface();
+ const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getDescriptor();
static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();
- int strokeDataCount = stroke.computeUniqueKeyFragmentData32Cnt();
+ int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt();
GrUniqueKey glyphKey;
GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCount);
reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0;
reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0;
if (strokeDataCount > 0) {
- stroke.asUniqueKeyFragment(&builder[2]);
+ fStroke.asUniqueKeyFragment(&builder[2]);
}
builder.finish();
@@ -194,7 +265,7 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx,
static_cast<GrPathRange*>(
ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey)));
if (nullptr == glyphs) {
- glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, stroke));
+ glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStroke));
ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs);
} else {
SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc));
@@ -203,107 +274,32 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx,
return glyphs.detach();
}
-void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
- const GrClip& clip,
- const GrPaint& paint,
- const SkPaint& skPaint,
- size_t textByteLength,
- const SkMatrix& viewMatrix,
- const SkIRect& regionClipBounds) {
- fClip = clip;
-
- fRenderTarget.reset(SkRef(rt));
-
- fRegionClipBounds = regionClipBounds;
- fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
-
- fPaint = paint;
- fSkPaint = skPaint;
-
- // Don't bake strokes into the glyph outlines. We will stroke the glyphs using the GPU instead.
- fStroke = GrStrokeInfo(fSkPaint);
- fSkPaint.setStyle(SkPaint::kFill_Style);
-
- SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
-
- if (fSkPaint.isFakeBoldText() && 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(),
- kStdFakeBoldInterpKeys,
- kStdFakeBoldInterpValues,
- kStdFakeBoldInterpLength);
- SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
- fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
- true /*strokeAndFill*/);
-
- fSkPaint.setFakeBoldText(false);
- }
-
- bool canUseRawPaths;
- if (!fStroke.isDashed()) {
- // We can draw the glyphs from canonically sized paths.
- fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
- fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize();
-
- // Compensate for the glyphs being scaled by fTextRatio.
- if (!fStroke.isFillStyle()) {
- fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
- SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
- }
-
- fSkPaint.setLinearText(true);
- fSkPaint.setLCDRenderText(false);
- fSkPaint.setAutohinted(false);
- fSkPaint.setHinting(SkPaint::kNo_Hinting);
- fSkPaint.setSubpixelText(true);
- fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
-
- canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
- 0 == fSkPaint.getTextSkewX() &&
- !fSkPaint.isFakeBoldText() &&
- !fSkPaint.isVerticalText();
- } else {
- fTextRatio = fTextInverseRatio = 1.0f;
- canUseRawPaths = false;
- }
-
- fViewMatrix = viewMatrix;
- fViewMatrix.preScale(fTextRatio, fTextRatio);
- fLocalMatrix.setScale(fTextRatio, fTextRatio);
-
- fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignoreGamma*/);
- fGlyphs = canUseRawPaths ?
- get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, fStroke) :
- get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
- &fGlyphCache->getDescriptor(), fStroke);
-}
-
-inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
+inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph,
+ const SkPoint& pos) {
// Stick the glyphs we can't draw into the fallback arrays.
if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
fFallbackIndices.push_back(glyph.getGlyphID());
fFallbackPositions.push_back(pos);
} else {
- // TODO: infer the reserve count from the text length.
- if (!fDraw) {
- fDraw = GrPathRangeDraw::Create(fGlyphs,
- GrPathRendering::kTranslate_PathTransformType,
- 64);
- }
float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() };
fDraw->append(glyph.getGlyphID(), translate);
}
}
-void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
- if (fDraw) {
- SkASSERT(fDraw->count());
+void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
+ GrRenderTarget* rt,
+ const GrClip& clip,
+ const GrPaint& paint,
+ const SkMatrix& viewMatrix,
+ const SkIRect& regionClipBounds,
+ GrTextContext* fallbackTextContext,
+ const SkPaint& originalSkPaint) const {
+ SkASSERT(fDraw);
- // We should only be flushing about once every run. However, if this impacts performance
- // we could move the creation of the GrPipelineBuilder earlier.
- GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip);
- SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiAlias());
- pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.isAntiAlias());
+ if (fDraw->count()) {
+ GrPipelineBuilder pipelineBuilder(paint, rt, clip);
+ SkASSERT(rt->isStencilBufferMultisampled() || !paint.isAntiAlias());
+ pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, paint.isAntiAlias());
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
kZero_StencilOp,
@@ -315,50 +311,38 @@ void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
*pipelineBuilder.stencil() = kStencilPass;
- dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPaint.getColor(),
- fDraw, GrPathRendering::kWinding_FillType);
- fDraw->unref();
- fDraw = nullptr;
+ SkMatrix drawMatrix(viewMatrix);
+ drawMatrix.preScale(fTextRatio, fTextRatio);
+
+ dc->drawPathsFromRange(&pipelineBuilder, drawMatrix, fLocalMatrix, paint.getColor(), fDraw,
+ GrPathRendering::kWinding_FillType);
}
if (fFallbackIndices.count()) {
SkASSERT(fFallbackPositions.count() == fFallbackIndices.count());
- SkPaint fallbackSkPaint(fSkPaint);
+ enum { kPreservedFlags = SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
+ SkPaint::kLCDRenderText_Flag | SkPaint::kAutoHinting_Flag };
+
+ SkPaint fallbackSkPaint(originalSkPaint);
fStroke.applyToPaint(&fallbackSkPaint);
if (!fStroke.isFillStyle()) {
fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
}
fallbackSkPaint.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
fallbackSkPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ fallbackSkPaint.setHinting(fFont.getHinting());
+ fallbackSkPaint.setFlags((fFont.getFlags() & kPreservedFlags) |
+ (originalSkPaint.getFlags() & ~kPreservedFlags));
// No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color
// glyphs show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
fallbackSkPaint.setSubpixelText(false);
- fallbackSkPaint.setTextSize(fSkPaint.getTextSize() * fTextRatio);
-
- SkMatrix fallbackMatrix(fViewMatrix);
- fallbackMatrix.preScale(fTextInverseRatio, fTextInverseRatio);
-
- fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, fPaint, fallbackSkPaint,
- fallbackMatrix, (char*)fFallbackIndices.begin(),
- sizeof(uint16_t) * fFallbackIndices.count(),
- fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
- fRegionClipBounds);
- fFallbackIndices.reset();
- fFallbackPositions.reset();
- }
-}
-
-void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) {
- this->flush(dc);
+ fallbackSkPaint.setTextSize(fFont.getTextSize() * fTextRatio);
- SkASSERT(!fDraw);
- SkASSERT(!fFallbackIndices.count());
- SkASSERT(!fFallbackPositions.count());
-
- fGlyphs->unref();
- fGlyphs = nullptr;
-
- SkGlyphCache::AttachCache(fGlyphCache);
- fGlyphCache = nullptr;
+ fallbackTextContext->drawPosText(dc, rt, clip, paint, fallbackSkPaint, viewMatrix,
+ (char*)fFallbackIndices.begin(),
+ sizeof(uint16_t) * fFallbackIndices.count(),
+ fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
+ regionClipBounds);
+ }
}
« 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