diff options
author | 2014-10-08 09:07:27 -0700 | |
---|---|---|
committer | 2014-10-08 09:07:27 -0700 | |
commit | 0fedb19812f05fcf18d16f0e96000768f4f76b11 (patch) | |
tree | 05282555f6edd1d8ae9957c31769191084a8cdbb /src | |
parent | e97d82b6e58f417546c738edba40e7ede4f41ea3 (diff) |
Rearrange code in TextContexts to be more consistent and match style guide.
Review URL: https://codereview.chromium.org/641613003
Diffstat (limited to 'src')
-rwxr-xr-x | src/gpu/GrBitmapTextContext.cpp | 259 | ||||
-rw-r--r-- | src/gpu/GrBitmapTextContext.h | 18 | ||||
-rwxr-xr-x | src/gpu/GrDistanceFieldTextContext.cpp | 629 | ||||
-rw-r--r-- | src/gpu/GrDistanceFieldTextContext.h | 41 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.cpp | 48 | ||||
-rw-r--r-- | src/gpu/GrStencilAndCoverTextContext.h | 27 | ||||
-rw-r--r-- | src/gpu/GrTextContext.h | 23 |
7 files changed, 521 insertions, 524 deletions
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp index c9cdf2c23f..9478d0436c 100755 --- a/src/gpu/GrBitmapTextContext.cpp +++ b/src/gpu/GrBitmapTextContext.cpp @@ -67,99 +67,13 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context, } GrBitmapTextContext::~GrBitmapTextContext() { - this->flushGlyphs(); + this->flush(); } bool GrBitmapTextContext::canDraw(const SkPaint& paint) { return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); } -static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { - unsigned r = SkColorGetR(c); - unsigned g = SkColorGetG(c); - unsigned b = SkColorGetB(c); - return GrColorPackRGBA(r, g, b, 0xff); -} - -void GrBitmapTextContext::flushGlyphs() { - if (NULL == fDrawTarget) { - return; - } - - GrDrawState* drawState = fDrawTarget->drawState(); - GrDrawState::AutoRestoreEffects are(drawState); - drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); - - if (fCurrVertex > 0) { - // setup our sampler state for our text texture/atlas - SkASSERT(SkIsAlign4(fCurrVertex)); - SkASSERT(fCurrTexture); - GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); - - uint32_t textureUniqueID = fCurrTexture->getUniqueID(); - - if (textureUniqueID != fEffectTextureUniqueID) { - fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, - params)); - fEffectTextureUniqueID = textureUniqueID; - } - - // This effect could be stored with one of the cache objects (atlas?) - drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); - SkASSERT(fStrike); - switch (fStrike->getMaskFormat()) { - // Color bitmap text - case kARGB_GrMaskFormat: - SkASSERT(!drawState->hasColorVertexAttribute()); - drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); - drawState->setColor(0xffffffff); - break; - // LCD text - case kA888_GrMaskFormat: - case kA565_GrMaskFormat: { - if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || - kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || - fPaint.numColorStages()) { - GrPrintf("LCD Text will not draw correctly.\n"); - } - SkASSERT(!drawState->hasColorVertexAttribute()); - // We don't use the GrPaint's color in this case because it's been premultiplied by - // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by - // the mask texture color. The end result is that we get - // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor - int a = SkColorGetA(fSkPaint.getColor()); - // paintAlpha - drawState->setColor(SkColorSetARGB(a, a, a, a)); - // paintColor - drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); - drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); - break; - } - // Grayscale/BW text - case kA8_GrMaskFormat: - // set back to normal in case we took LCD path previously. - drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); - // We're using per-vertex color. - SkASSERT(drawState->hasColorVertexAttribute()); - break; - default: - SkFAIL("Unexepected mask format."); - } - int nGlyphs = fCurrVertex / 4; - fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); - fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, - nGlyphs, - 4, 6, &fVertexBounds); - - fDrawTarget->resetVertexSource(); - fVertices = NULL; - fMaxVertices = 0; - fCurrVertex = 0; - fVertexBounds.setLargestInverted(); - SkSafeSetNull(fCurrTexture); - } -} - inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPaint) { GrTextContext::init(paint, skPaint); @@ -172,12 +86,6 @@ inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai fMaxVertices = 0; } -inline void GrBitmapTextContext::finish() { - this->flushGlyphs(); - - GrTextContext::finish(); -} - void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, const char text[], size_t byteLength, SkScalar x, SkScalar y) { @@ -254,12 +162,12 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, fx += autokern.adjust(glyph); if (glyph.fWidth) { - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkFixedFloorToFixed(fx), - SkFixedFloorToFixed(fy), - fontScaler); + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkFixedFloorToFixed(fx), + SkFixedFloorToFixed(fy), + fontScaler); } fx += glyph.fAdvanceX; @@ -328,12 +236,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai fx & fxMask, fy & fyMask); if (glyph.fWidth) { - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkFixedFloorToFixed(fx), - SkFixedFloorToFixed(fy), - fontScaler); + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkFixedFloorToFixed(fx), + SkFixedFloorToFixed(fy), + fontScaler); } pos += scalarsPerPosition; } @@ -361,12 +269,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai SkASSERT(prevAdvY == glyph.fAdvanceY); SkASSERT(glyph.fWidth); - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkFixedFloorToFixed(fx), - SkFixedFloorToFixed(fy), - fontScaler); + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkFixedFloorToFixed(fx), + SkFixedFloorToFixed(fy), + fontScaler); } pos += scalarsPerPosition; } @@ -384,12 +292,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX; SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY; - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkFixedFloorToFixed(fx), - SkFixedFloorToFixed(fy), - fontScaler); + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkFixedFloorToFixed(fx), + SkFixedFloorToFixed(fy), + fontScaler); } pos += scalarsPerPosition; } @@ -407,12 +315,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX; SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY; - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkFixedFloorToFixed(fx), - SkFixedFloorToFixed(fy), - fontScaler); + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkFixedFloorToFixed(fx), + SkFixedFloorToFixed(fy), + fontScaler); } pos += scalarsPerPosition; } @@ -422,9 +330,9 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai this->finish(); } -void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, - SkFixed vx, SkFixed vy, - GrFontScaler* scaler) { +void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed, + SkFixed vx, SkFixed vy, + GrFontScaler* scaler) { if (NULL == fDrawTarget) { return; } @@ -474,7 +382,7 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, } // flush any accumulated draws to allow us to free up a plot - this->flushGlyphs(); + this->flush(); fContext->flush(); // we should have an unused plot now @@ -518,7 +426,7 @@ HAS_ATLAS: SkASSERT(texture); if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { - this->flushGlyphs(); + this->flush(); fCurrTexture = texture; fCurrTexture->ref(); } @@ -538,7 +446,7 @@ HAS_ATLAS: } bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); if (flush) { - this->flushGlyphs(); + this->flush(); fContext->flush(); if (useColorVerts) { fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>( @@ -607,3 +515,96 @@ HAS_ATLAS: } fCurrVertex += 4; } + +static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { + unsigned r = SkColorGetR(c); + unsigned g = SkColorGetG(c); + unsigned b = SkColorGetB(c); + return GrColorPackRGBA(r, g, b, 0xff); +} + +void GrBitmapTextContext::flush() { + if (NULL == fDrawTarget) { + return; + } + + GrDrawState* drawState = fDrawTarget->drawState(); + GrDrawState::AutoRestoreEffects are(drawState); + drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); + + if (fCurrVertex > 0) { + // setup our sampler state for our text texture/atlas + SkASSERT(SkIsAlign4(fCurrVertex)); + SkASSERT(fCurrTexture); + GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); + + uint32_t textureUniqueID = fCurrTexture->getUniqueID(); + + if (textureUniqueID != fEffectTextureUniqueID) { + fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, + params)); + fEffectTextureUniqueID = textureUniqueID; + } + + // This effect could be stored with one of the cache objects (atlas?) + drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); + SkASSERT(fStrike); + switch (fStrike->getMaskFormat()) { + // Color bitmap text + case kARGB_GrMaskFormat: + SkASSERT(!drawState->hasColorVertexAttribute()); + drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); + drawState->setColor(0xffffffff); + break; + // LCD text + case kA888_GrMaskFormat: + case kA565_GrMaskFormat: { + if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || + kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || + fPaint.numColorStages()) { + GrPrintf("LCD Text will not draw correctly.\n"); + } + SkASSERT(!drawState->hasColorVertexAttribute()); + // We don't use the GrPaint's color in this case because it's been premultiplied by + // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by + // the mask texture color. The end result is that we get + // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor + int a = SkColorGetA(fSkPaint.getColor()); + // paintAlpha + drawState->setColor(SkColorSetARGB(a, a, a, a)); + // paintColor + drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor())); + drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); + break; + } + // Grayscale/BW text + case kA8_GrMaskFormat: + // set back to normal in case we took LCD path previously. + drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); + // We're using per-vertex color. + SkASSERT(drawState->hasColorVertexAttribute()); + break; + default: + SkFAIL("Unexepected mask format."); + } + int nGlyphs = fCurrVertex / 4; + fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); + fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, + nGlyphs, + 4, 6, &fVertexBounds); + + fDrawTarget->resetVertexSource(); + fVertices = NULL; + fMaxVertices = 0; + fCurrVertex = 0; + fVertexBounds.setLargestInverted(); + SkSafeSetNull(fCurrTexture); + } +} + +inline void GrBitmapTextContext::finish() { + this->flush(); + + GrTextContext::finish(); +} + diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h index c136270c65..4bff399ade 100644 --- a/src/gpu/GrBitmapTextContext.h +++ b/src/gpu/GrBitmapTextContext.h @@ -21,6 +21,8 @@ public: GrBitmapTextContext(GrContext*, const SkDeviceProperties&); virtual ~GrBitmapTextContext(); + virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; + virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE; virtual void drawPosText(const GrPaint&, const SkPaint&, @@ -28,16 +30,7 @@ public: const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) SK_OVERRIDE; - virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; - private: - GrTextStrike* fStrike; - - void init(const GrPaint&, const SkPaint&); - void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); - void flushGlyphs(); // automatically called by destructor - void finish(); - enum { kMinRequestedGlyphs = 1, kDefaultRequestedGlyphs = 64, @@ -45,6 +38,7 @@ private: kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, }; + GrTextStrike* fStrike; void* fVertices; int32_t fMaxVertices; GrTexture* fCurrTexture; @@ -53,6 +47,12 @@ private: uint32_t fEffectTextureUniqueID; int fCurrVertex; SkRect fVertexBounds; + + void init(const GrPaint&, const SkPaint&); + void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); + void flush(); // automatically called by destructor + void finish(); + }; #endif diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index b565dd63f8..baba10d570 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -81,7 +81,7 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, } GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { - this->flushGlyphs(); + this->flush(); SkSafeSetNull(fGammaTexture); } @@ -114,6 +114,231 @@ bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { return rec.getFormat() != SkMask::kARGB32_Format; } +inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) { + GrTextContext::init(paint, skPaint); + + fStrike = NULL; + + const SkMatrix& ctm = fContext->getMatrix(); + + // getMaxScale doesn't support perspective, so neither do we at the moment + SkASSERT(!ctm.hasPerspective()); + SkScalar maxScale = ctm.getMaxScale(); + SkScalar textSize = fSkPaint.getTextSize(); + SkScalar scaledTextSize = textSize; + // if we have non-unity scale, we need to choose our base text size + // based on the SkPaint's text size multiplied by the max scale factor + // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? + if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { + scaledTextSize *= maxScale; + } + + fCurrVertex = 0; + + fVertices = NULL; + + if (scaledTextSize <= kSmallDFFontLimit) { + fTextRatio = textSize / kSmallDFFontSize; + fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); + } else if (scaledTextSize <= kMediumDFFontLimit) { + fTextRatio = textSize / kMediumDFFontSize; + fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); + } else { + fTextRatio = textSize / kLargeDFFontSize; + fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); + } + + fUseLCDText = fSkPaint.isLCDRenderText(); + + fSkPaint.setLCDRenderText(false); + fSkPaint.setAutohinted(false); + fSkPaint.setHinting(SkPaint::kNormal_Hinting); + fSkPaint.setSubpixelText(true); + +} + +static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache, + const SkDeviceProperties& deviceProperties, + GrTexture** gammaTexture) { + if (NULL == *gammaTexture) { + int width, height; + size_t size; + +#ifdef SK_GAMMA_CONTRAST + SkScalar contrast = SK_GAMMA_CONTRAST; +#else + SkScalar contrast = 0.5f; +#endif + SkScalar paintGamma = deviceProperties.getGamma(); + SkScalar deviceGamma = deviceProperties.getGamma(); + + size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma, + &width, &height); + + SkAutoTArray<uint8_t> data((int)size); + SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get()); + + // TODO: Update this to use the cache rather than directly creating a texture. + GrTextureDesc desc; + desc.fFlags = kDynamicUpdate_GrTextureFlagBit; + desc.fWidth = width; + desc.fHeight = height; + desc.fConfig = kAlpha_8_GrPixelConfig; + + *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0); + if (NULL == *gammaTexture) { + return; + } + + context->writeTexturePixels(*gammaTexture, + 0, 0, width, height, + (*gammaTexture)->config(), data.get(), 0, + GrContext::kDontFlush_PixelOpsFlag); + } +} + +void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, + const char text[], size_t byteLength, + SkScalar x, SkScalar y) { + SkASSERT(byteLength == 0 || text != NULL); + + // nothing to draw or can't draw + if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/ + || fSkPaint.getRasterizer()) { + return; + } + + this->init(paint, skPaint); + + SkScalar sizeRatio = fTextRatio; + + SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); + + SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); + SkGlyphCache* cache = autoCache.getCache(); + GrFontScaler* fontScaler = GetGrFontScaler(cache); + + setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); + + // need to measure first + // TODO - generate positions and pre-load cache as well? + const char* stop = text + byteLength; + if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { + SkFixed stopX = 0; + SkFixed stopY = 0; + + const char* textPtr = text; + while (textPtr < stop) { + // don't need x, y here, since all subpixel variants will have the + // same advance + const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0); + + stopX += glyph.fAdvanceX; + stopY += glyph.fAdvanceY; + } + SkASSERT(textPtr == stop); + + SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio; + SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio; + + if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { + alignX = SkScalarHalf(alignX); + alignY = SkScalarHalf(alignY); + } + + x -= alignX; + y -= alignY; + } + + SkFixed fx = SkScalarToFixed(x); + SkFixed fy = SkScalarToFixed(y); + SkFixed fixedScale = SkScalarToFixed(sizeRatio); + while (text < stop) { + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); + + if (glyph.fWidth) { + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + fx, + fy, + fontScaler); + } + + fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale); + fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale); + } + + this->finish(); +} + +void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, 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); + + // nothing to draw + if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) { + return; + } + + this->init(paint, skPaint); + + SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); + + SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); + SkGlyphCache* cache = autoCache.getCache(); + GrFontScaler* fontScaler = GetGrFontScaler(cache); + + setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); + + const char* stop = text + byteLength; + + if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { + while (text < stop) { + // the last 2 parameters are ignored + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); + + if (glyph.fWidth) { + SkScalar x = offset.x() + pos[0]; + SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); + + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkScalarToFixed(x), + SkScalarToFixed(y), + fontScaler); + } + pos += scalarsPerPosition; + } + } else { + int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0; + while (text < stop) { + // the last 2 parameters are ignored + const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); + + if (glyph.fWidth) { + SkScalar x = offset.x() + pos[0]; + SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); + + this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(), + glyph.getSubXFixed(), + glyph.getSubYFixed()), + SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift), + SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift), + fontScaler); + } + pos += scalarsPerPosition; + } + } + + this->finish(); +} + static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { unsigned r = SkColorGetR(c); unsigned g = SkColorGetG(c); @@ -143,24 +368,22 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo flags != fEffectFlags) { if (fUseLCDText) { GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); - fCachedGeometryProcessor.reset( - GrDistanceFieldLCDTextureEffect::Create(fCurrTexture, - params, - fGammaTexture, - gammaParams, - colorNoPreMul, - flags)); + fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(fCurrTexture, + params, + fGammaTexture, + gammaParams, + colorNoPreMul, + flags)); } else { #ifdef SK_GAMMA_APPLY_TO_A8 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.getGamma(), filteredColor); - fCachedGeometryProcessor.reset( - GrDistanceFieldTextureEffect::Create(fCurrTexture, - params, - fGammaTexture, - gammaParams, - lum/255.f, - flags)); + fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture, + params, + fGammaTexture, + gammaParams, + lum/255.f, + flags)); #else fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture, params, flags)); @@ -173,83 +396,17 @@ void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo } -void GrDistanceFieldTextContext::flushGlyphs() { +void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed, + SkFixed vx, SkFixed vy, + GrFontScaler* scaler) { if (NULL == fDrawTarget) { return; } - GrDrawState* drawState = fDrawTarget->drawState(); - GrDrawState::AutoRestoreEffects are(drawState); - - drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget()); - - if (fCurrVertex > 0) { - // setup our sampler state for our text texture/atlas - SkASSERT(SkIsAlign4(fCurrVertex)); - - // get our current color - SkColor filteredColor; - SkColorFilter* colorFilter = fSkPaint.getColorFilter(); - if (colorFilter) { - filteredColor = colorFilter->filterColor(fSkPaint.getColor()); - } else { - filteredColor = fSkPaint.getColor(); - } - this->setupCoverageEffect(filteredColor); - - // Effects could be stored with one of the cache objects (atlas?) - drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); - - // Set draw state - if (fUseLCDText) { - GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); - if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || - kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || - fPaint.numColorStages()) { - GrPrintf("LCD Text will not draw correctly.\n"); - } - SkASSERT(!drawState->hasColorVertexAttribute()); - // We don't use the GrPaint's color in this case because it's been premultiplied by - // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by - // the mask texture color. The end result is that we get - // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor - int a = SkColorGetA(fSkPaint.getColor()); - // paintAlpha - drawState->setColor(SkColorSetARGB(a, a, a, a)); - // paintColor - drawState->setBlendConstant(colorNoPreMul); - drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); - } else { - // set back to normal in case we took LCD path previously. - drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); - // We're using per-vertex color. - SkASSERT(drawState->hasColorVertexAttribute()); - } - int nGlyphs = fCurrVertex / 4; - fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); - fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, - nGlyphs, - 4, 6, &fVertexBounds); - fDrawTarget->resetVertexSource(); - fVertices = NULL; - fMaxVertices = 0; - fCurrVertex = 0; - SkSafeSetNull(fCurrTexture); - fVertexBounds.setLargestInverted(); - } -} - -void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, - SkFixed vx, SkFixed vy, - GrFontScaler* scaler) { - if (NULL == fDrawTarget) { - return; - } - if (NULL == fStrike) { fStrike = fContext->getFontCache()->getStrike(scaler, true); } - + GrGlyph* glyph = fStrike->getGlyph(packed, scaler); if (NULL == glyph || glyph->fBounds.isEmpty()) { return; @@ -295,7 +452,7 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed, } // before we purge the cache, we must flush any accumulated draws - this->flushGlyphs(); + this->flush(); fContext->flush(); // we should have an unused plot now @@ -335,38 +492,34 @@ HAS_ATLAS: SkASSERT(texture); if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { - this->flushGlyphs(); + this->flush(); fCurrTexture = texture; fCurrTexture->ref(); } bool useColorVerts = !fUseLCDText; - + if (NULL == fVertices) { // If we need to reserve vertices allow the draw target to suggest // a number of verts to reserve and whether to perform a flush. fMaxVertices = kMinRequestedVerts; if (useColorVerts) { fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>( - SK_ARRAY_COUNT(gTextVertexWithColorAttribs), - kTextVAColorSize); + SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); } else { fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( - SK_ARRAY_COUNT(gTextVertexAttribs), - kTextVASize); + SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); } bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); if (flush) { - this->flushGlyphs(); + this->flush(); fContext->flush(); if (useColorVerts) { fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>( - SK_ARRAY_COUNT(gTextVertexWithColorAttribs), - kTextVAColorSize); + SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize); } else { fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( - SK_ARRAY_COUNT(gTextVertexAttribs), - kTextVASize); + SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize); } } fMaxVertices = kDefaultRequestedVerts; @@ -386,7 +539,7 @@ HAS_ATLAS: NULL); GrAlwaysAssert(success); } - + SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset); @@ -399,7 +552,7 @@ HAS_ATLAS: sy += dy; width *= scale; height *= scale; - + SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset); SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset); SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset); @@ -415,16 +568,16 @@ HAS_ATLAS: size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint)) : (2 * sizeof(SkPoint) + sizeof(GrColor)); - + SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride()); SkPoint* positions = reinterpret_cast<SkPoint*>( - reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); + reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize); // The texture coords are last in both the with and without color vertex layouts. SkPoint* textureCoords = reinterpret_cast<SkPoint*>( - reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint)); + reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint)); textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)), SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)), SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)), @@ -445,233 +598,75 @@ HAS_ATLAS: fCurrVertex += 4; } -inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) { - GrTextContext::init(paint, skPaint); - - fStrike = NULL; - - const SkMatrix& ctm = fContext->getMatrix(); - - // getMaxScale doesn't support perspective, so neither do we at the moment - SkASSERT(!ctm.hasPerspective()); - SkScalar maxScale = ctm.getMaxScale(); - SkScalar textSize = fSkPaint.getTextSize(); - SkScalar scaledTextSize = textSize; - // if we have non-unity scale, we need to choose our base text size - // based on the SkPaint's text size multiplied by the max scale factor - // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)? - if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { - scaledTextSize *= maxScale; - } - - fCurrVertex = 0; - - fVertices = NULL; - - if (scaledTextSize <= kSmallDFFontLimit) { - fTextRatio = textSize / kSmallDFFontSize; - fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); - } else if (scaledTextSize <= kMediumDFFontLimit) { - fTextRatio = textSize / kMediumDFFontSize; - fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); - } else { - fTextRatio = textSize / kLargeDFFontSize; - fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); - } - - fUseLCDText = fSkPaint.isLCDRenderText(); - - fSkPaint.setLCDRenderText(false); - fSkPaint.setAutohinted(false); - fSkPaint.setHinting(SkPaint::kNormal_Hinting); - fSkPaint.setSubpixelText(true); - -} - -inline void GrDistanceFieldTextContext::finish() { - this->flushGlyphs(); - - GrTextContext::finish(); -} - -static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache, - const SkDeviceProperties& deviceProperties, - GrTexture** gammaTexture) { - if (NULL == *gammaTexture) { - int width, height; - size_t size; - -#ifdef SK_GAMMA_CONTRAST - SkScalar contrast = SK_GAMMA_CONTRAST; -#else - SkScalar contrast = 0.5f; -#endif - SkScalar paintGamma = deviceProperties.getGamma(); - SkScalar deviceGamma = deviceProperties.getGamma(); - - size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma, - &width, &height); - - SkAutoTArray<uint8_t> data((int)size); - SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get()); - - // TODO: Update this to use the cache rather than directly creating a texture. - GrTextureDesc desc; - desc.fFlags = kDynamicUpdate_GrTextureFlagBit; - desc.fWidth = width; - desc.fHeight = height; - desc.fConfig = kAlpha_8_GrPixelConfig; - - *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0); - if (NULL == *gammaTexture) { - return; - } - - context->writeTexturePixels(*gammaTexture, - 0, 0, width, height, - (*gammaTexture)->config(), data.get(), 0, - GrContext::kDontFlush_PixelOpsFlag); - } -} - -void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, - const char text[], size_t byteLength, - SkScalar x, SkScalar y) { - SkASSERT(byteLength == 0 || text != NULL); - - // nothing to draw or can't draw - if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/ - || fSkPaint.getRasterizer()) { +void GrDistanceFieldTextContext::flush() { + if (NULL == fDrawTarget) { return; } - this->init(paint, skPaint); - - SkScalar sizeRatio = fTextRatio; - - SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); - - SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); - SkGlyphCache* cache = autoCache.getCache(); - GrFontScaler* fontScaler = GetGrFontScaler(cache); - - setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); - - // need to measure first - // TODO - generate positions and pre-load cache as well? - const char* stop = text + byteLength; - if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { - SkFixed stopX = 0; - SkFixed stopY = 0; - - const char* textPtr = text; - while (textPtr < stop) { - // don't need x, y here, since all subpixel variants will have the - // same advance - const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0); + GrDrawState* drawState = fDrawTarget->drawState(); + GrDrawState::AutoRestoreEffects are(drawState); - stopX += glyph.fAdvanceX; - stopY += glyph.fAdvanceY; - } - SkASSERT(textPtr == stop); + drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget()); - SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio; - SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio; + if (fCurrVertex > 0) { + // setup our sampler state for our text texture/atlas + SkASSERT(SkIsAlign4(fCurrVertex)); - if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { - alignX = SkScalarHalf(alignX); - alignY = SkScalarHalf(alignY); + // get our current color + SkColor filteredColor; + SkColorFilter* colorFilter = fSkPaint.getColorFilter(); + if (colorFilter) { + filteredColor = colorFilter->filterColor(fSkPaint.getColor()); + } else { + filteredColor = fSkPaint.getColor(); } + this->setupCoverageEffect(filteredColor); - x -= alignX; - y -= alignY; - } - - SkFixed fx = SkScalarToFixed(x); - SkFixed fy = SkScalarToFixed(y); - SkFixed fixedScale = SkScalarToFixed(sizeRatio); - while (text < stop) { - const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); + // Effects could be stored with one of the cache objects (atlas?) + drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); - if (glyph.fWidth) { - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - fx, - fy, - fontScaler); + // Set draw state + if (fUseLCDText) { + GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor); + if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || + kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || + fPaint.numColorStages()) { + GrPrintf("LCD Text will not draw correctly.\n"); + } + SkASSERT(!drawState->hasColorVertexAttribute()); + // We don't use the GrPaint's color in this case because it's been premultiplied by + // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by + // the mask texture color. The end result is that we get + // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor + int a = SkColorGetA(fSkPaint.getColor()); + // paintAlpha + drawState->setColor(SkColorSetARGB(a, a, a, a)); + // paintColor + drawState->setBlendConstant(colorNoPreMul); + drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); + } else { + // set back to normal in case we took LCD path previously. + drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); + // We're using per-vertex color. + SkASSERT(drawState->hasColorVertexAttribute()); } - - fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale); - fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale); + int nGlyphs = fCurrVertex / 4; + fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); + fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, + nGlyphs, + 4, 6, &fVertexBounds); + fDrawTarget->resetVertexSource(); + fVertices = NULL; + fMaxVertices = 0; + fCurrVertex = 0; + SkSafeSetNull(fCurrTexture); + fVertexBounds.setLargestInverted(); } - - this->finish(); } -void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, 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); - - // nothing to draw - if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) { - return; - } - - this->init(paint, skPaint); - - SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); - - SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL); - SkGlyphCache* cache = autoCache.getCache(); - GrFontScaler* fontScaler = GetGrFontScaler(cache); - - setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture); - - const char* stop = text + byteLength; - - if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { - while (text < stop) { - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); - - if (glyph.fWidth) { - SkScalar x = offset.x() + pos[0]; - SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); - - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkScalarToFixed(x), - SkScalarToFixed(y), - fontScaler); - } - pos += scalarsPerPosition; - } - } else { - int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0; - while (text < stop) { - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); - - if (glyph.fWidth) { - SkScalar x = offset.x() + pos[0]; - SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0); - - this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), - glyph.getSubXFixed(), - glyph.getSubYFixed()), - SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift), - SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift), - fontScaler); - } - pos += scalarsPerPosition; - } - } +inline void GrDistanceFieldTextContext::finish() { + this->flush(); - this->finish(); + GrTextContext::finish(); } + diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h index 0b08b5986c..d628e3e3bd 100644 --- a/src/gpu/GrDistanceFieldTextContext.h +++ b/src/gpu/GrDistanceFieldTextContext.h @@ -21,6 +21,8 @@ public: GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable); virtual ~GrDistanceFieldTextContext(); + virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; + virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE; virtual void drawPosText(const GrPaint&, const SkPaint&, @@ -28,38 +30,35 @@ public: const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) SK_OVERRIDE; - virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; - private: + enum { + kMinRequestedGlyphs = 1, + kDefaultRequestedGlyphs = 64, + kMinRequestedVerts = kMinRequestedGlyphs * 4, + kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, + }; + GrTextStrike* fStrike; SkScalar fTextRatio; bool fUseLCDText; bool fEnableDFRendering; SkAutoTUnref<GrGeometryProcessor> fCachedGeometryProcessor; // Used to check whether fCachedEffect is still valid. - uint32_t fEffectTextureUniqueID; - SkColor fEffectColor; - uint32_t fEffectFlags; - GrTexture* fGammaTexture; + uint32_t fEffectTextureUniqueID; + SkColor fEffectColor; + uint32_t fEffectFlags; + GrTexture* fGammaTexture; + void* fVertices; + int32_t fMaxVertices; + GrTexture* fCurrTexture; + int fCurrVertex; + SkRect fVertexBounds; void init(const GrPaint&, const SkPaint&); - void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); - void flushGlyphs(); // automatically called by destructor + void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*); void setupCoverageEffect(const SkColor& filteredColor); + void flush(); // automatically called by destructor void finish(); - - enum { - kMinRequestedGlyphs = 1, - kDefaultRequestedGlyphs = 64, - kMinRequestedVerts = kMinRequestedGlyphs * 4, - kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, - }; - - void* fVertices; - int32_t fMaxVertices; - GrTexture* fCurrTexture; - int fCurrVertex; - SkRect fVertexBounds; }; #endif diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp index cfcabe923f..1941fa7afc 100644 --- a/src/gpu/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/GrStencilAndCoverTextContext.cpp @@ -28,6 +28,30 @@ GrStencilAndCoverTextContext::GrStencilAndCoverTextContext( GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() { } +bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) { + if (paint.getRasterizer()) { + return false; + } + if (paint.getMaskFilter()) { + return false; + } + if (paint.getPathEffect()) { + return false; + } + + // No hairlines unless we can map the 1 px width to the object space. + if (paint.getStyle() == SkPaint::kStroke_Style + && paint.getStrokeWidth() == 0 + && fContext->getMatrix().hasPerspective()) { + return false; + } + + // No color bitmap fonts. + SkScalerContext::Rec rec; + SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); + return rec.getFormat() != SkMask::kARGB32_Format; +} + void GrStencilAndCoverTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, const char text[], @@ -189,30 +213,6 @@ void GrStencilAndCoverTextContext::drawPosText(const GrPaint& paint, this->finish(); } -bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) { - if (paint.getRasterizer()) { - return false; - } - if (paint.getMaskFilter()) { - return false; - } - if (paint.getPathEffect()) { - return false; - } - - // No hairlines unless we can map the 1 px width to the object space. - if (paint.getStyle() == SkPaint::kStroke_Style - && paint.getStrokeWidth() == 0 - && fContext->getMatrix().hasPerspective()) { - return false; - } - - // No color bitmap fonts. - SkScalerContext::Rec rec; - SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); - return rec.getFormat() != SkMask::kARGB32_Format; -} - static GrPathRange* get_gr_glyphs(GrContext* ctx, const SkTypeface* typeface, const SkDescriptor* desc, diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h index b6e23bdb3f..dc32025501 100644 --- a/src/gpu/GrStencilAndCoverTextContext.h +++ b/src/gpu/GrStencilAndCoverTextContext.h @@ -27,6 +27,8 @@ public: GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&); virtual ~GrStencilAndCoverTextContext(); + virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; + virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE; @@ -35,8 +37,6 @@ public: const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) SK_OVERRIDE; - virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE; - private: static const int kGlyphBufferSize = 1024; @@ -61,6 +61,18 @@ private: kMaxPerformance_RenderMode, }; + GrDrawState::AutoRestoreEffects fStateRestore; + SkScalar fTextRatio; + float fTextInverseRatio; + SkGlyphCache* fGlyphCache; + GrPathRange* fGlyphs; + uint32_t fIndexBuffer[kGlyphBufferSize]; + float fTransformBuffer[2 * kGlyphBufferSize]; + GrDrawTarget::PathTransformType fTransformType; + int fPendingGlyphCount; + SkMatrix fContextInitialMatrix; + bool fNeedsDeviceSpaceGlyphs; + void init(const GrPaint&, const SkPaint&, size_t textByteLength, RenderMode, const SkPoint& textTranslate); void initGlyphs(SkGlyphCache* cache); @@ -69,17 +81,6 @@ private: void flush(); void finish(); - GrDrawState::AutoRestoreEffects fStateRestore; - SkScalar fTextRatio; - float fTextInverseRatio; - SkGlyphCache* fGlyphCache; - GrPathRange* fGlyphs; - uint32_t fIndexBuffer[kGlyphBufferSize]; - float fTransformBuffer[2 * kGlyphBufferSize]; - GrDrawTarget::PathTransformType fTransformType; - int fPendingGlyphCount; - SkMatrix fContextInitialMatrix; - bool fNeedsDeviceSpaceGlyphs; }; #endif diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h index da41c1bb3c..b82a64840b 100644 --- a/src/gpu/GrTextContext.h +++ b/src/gpu/GrTextContext.h @@ -24,6 +24,9 @@ class GrFontScaler; class GrTextContext { public: virtual ~GrTextContext() {} + + virtual bool canDraw(const SkPaint& paint) = 0; + virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength, SkScalar x, SkScalar y) = 0; virtual void drawPosText(const GrPaint&, const SkPaint&, @@ -31,18 +34,7 @@ public: const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) = 0; - virtual bool canDraw(const SkPaint& paint) = 0; - protected: - GrTextContext(GrContext*, const SkDeviceProperties&); - - static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache); - static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, - const char text[], size_t byteLength, SkVector* stopVector); - - void init(const GrPaint&, const SkPaint&); - void finish() { fDrawTarget = NULL; } - GrContext* fContext; SkDeviceProperties fDeviceProperties; @@ -50,6 +42,15 @@ protected: SkIRect fClipRect; GrPaint fPaint; SkPaint fSkPaint; + + GrTextContext(GrContext*, const SkDeviceProperties&); + + void init(const GrPaint&, const SkPaint&); + void finish() { fDrawTarget = NULL; } + + static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache); + static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, + const char text[], size_t byteLength, SkVector* stopVector); }; #endif |