Rearrange code in TextContexts to be more consistent and match style guide.

Review URL: https://codereview.chromium.org/641613003
This commit is contained in:
jvanverth 2014-10-08 09:07:27 -07:00 committed by Commit bot
parent e97d82b6e5
commit 0fedb19812
7 changed files with 563 additions and 566 deletions

View File

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

View File

@ -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

View File

@ -81,7 +81,7 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
}
GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
this->flushGlyphs();
this->flush();
SkSafeSetNull(fGammaTexture);
}
@ -114,337 +114,6 @@ bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
return rec.getFormat() != SkMask::kARGB32_Format;
}
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 GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
uint32_t textureUniqueID = fCurrTexture->getUniqueID();
const SkMatrix& ctm = fContext->getMatrix();
// set up any flags
uint32_t flags = 0;
flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
flags |= fUseLCDText && ctm.rectStaysRect() ?
kRectToRect_DistanceFieldEffectFlag : 0;
bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry);
flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
// see if we need to create a new effect
if (textureUniqueID != fEffectTextureUniqueID ||
filteredColor != fEffectColor ||
flags != fEffectFlags) {
if (fUseLCDText) {
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
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));
#else
fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture,
params, flags));
#endif
}
fEffectTextureUniqueID = textureUniqueID;
fEffectColor = filteredColor;
fEffectFlags = flags;
}
}
void GrDistanceFieldTextContext::flushGlyphs() {
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;
}
SkScalar sx = SkFixedToScalar(vx);
SkScalar sy = SkFixedToScalar(vy);
/*
// not valid, need to find a different solution for this
vx += SkIntToFixed(glyph->fBounds.fLeft);
vy += SkIntToFixed(glyph->fBounds.fTop);
// keep them as ints until we've done the clip-test
GrFixed width = glyph->fBounds.width();
GrFixed height = glyph->fBounds.height();
// check if we clipped out
if (true || NULL == glyph->fPlot) {
int x = vx >> 16;
int y = vy >> 16;
if (fClipRect.quickReject(x, y, x + width, y + height)) {
// SkCLZ(3); // so we can set a break-point in the debugger
return;
}
}
*/
if (NULL == glyph->fPlot) {
if (!fStrike->glyphTooLargeForAtlas(glyph)) {
if (fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
// try to clear out an unused plot before we flush
if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
if (c_DumpFontCache) {
#ifdef SK_DEVELOPER
fContext->getFontCache()->dump();
#endif
}
// before we purge the cache, we must flush any accumulated draws
this->flushGlyphs();
fContext->flush();
// we should have an unused plot now
if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
}
if (NULL == glyph->fPath) {
SkPath* path = SkNEW(SkPath);
if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
// flag the glyph as being dead?
delete path;
return;
}
glyph->fPath = path;
}
GrContext::AutoMatrix am;
SkMatrix ctm;
ctm.setScale(fTextRatio, fTextRatio);
ctm.postTranslate(sx, sy);
GrPaint tmpPaint(fPaint);
am.setPreConcat(fContext, ctm, &tmpPaint);
GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
return;
}
HAS_ATLAS:
SkASSERT(glyph->fPlot);
GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
glyph->fPlot->setDrawToken(drawToken);
GrTexture* texture = glyph->fPlot->texture();
SkASSERT(texture);
if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
this->flushGlyphs();
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);
} else {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
SK_ARRAY_COUNT(gTextVertexAttribs),
kTextVASize);
}
bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
if (flush) {
this->flushGlyphs();
fContext->flush();
if (useColorVerts) {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
SK_ARRAY_COUNT(gTextVertexWithColorAttribs),
kTextVAColorSize);
} else {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
SK_ARRAY_COUNT(gTextVertexAttribs),
kTextVASize);
}
}
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
fDrawTarget->geometryHints(&fMaxVertices, NULL);
int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
if (fMaxVertices < kMinRequestedVerts) {
fMaxVertices = kDefaultRequestedVerts;
} else if (fMaxVertices > maxQuadVertices) {
// don't exceed the limit of the index buffer
fMaxVertices = maxQuadVertices;
}
bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
0,
&fVertices,
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);
SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
SkScalar scale = fTextRatio;
dx *= scale;
dy *= scale;
sx += dx;
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);
SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
SkRect r;
r.fLeft = sx;
r.fTop = sy;
r.fRight = sx + width;
r.fBottom = sy + height;
fVertexBounds.joinNonEmptyArg(r);
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);
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));
textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
vertSize);
if (useColorVerts) {
if (0xFF == GrColorUnpackA(fPaint.getColor())) {
fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
}
// color comes after position.
GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
for (int i = 0; i < 4; ++i) {
*colors = fPaint.getColor();
colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
}
}
fCurrVertex += 4;
}
inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
GrTextContext::init(paint, skPaint);
@ -488,12 +157,6 @@ inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
}
inline void GrDistanceFieldTextContext::finish() {
this->flushGlyphs();
GrTextContext::finish();
}
static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
const SkDeviceProperties& deviceProperties,
GrTexture** gammaTexture) {
@ -594,12 +257,12 @@ void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& s
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
if (glyph.fWidth) {
this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
glyph.getSubXFixed(),
glyph.getSubYFixed()),
fx,
fy,
fontScaler);
this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
glyph.getSubXFixed(),
glyph.getSubYFixed()),
fx,
fy,
fontScaler);
}
fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
@ -643,12 +306,12 @@ void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint
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);
this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
glyph.getSubXFixed(),
glyph.getSubYFixed()),
SkScalarToFixed(x),
SkScalarToFixed(y),
fontScaler);
}
pos += scalarsPerPosition;
}
@ -662,12 +325,12 @@ void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint
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);
this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
glyph.getSubXFixed(),
glyph.getSubYFixed()),
SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift),
SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift),
fontScaler);
}
pos += scalarsPerPosition;
}
@ -675,3 +338,335 @@ void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint
this->finish();
}
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 GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
uint32_t textureUniqueID = fCurrTexture->getUniqueID();
const SkMatrix& ctm = fContext->getMatrix();
// set up any flags
uint32_t flags = 0;
flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
flags |= fUseLCDText && ctm.rectStaysRect() ?
kRectToRect_DistanceFieldEffectFlag : 0;
bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry);
flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
// see if we need to create a new effect
if (textureUniqueID != fEffectTextureUniqueID ||
filteredColor != fEffectColor ||
flags != fEffectFlags) {
if (fUseLCDText) {
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
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));
#else
fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture,
params, flags));
#endif
}
fEffectTextureUniqueID = textureUniqueID;
fEffectColor = filteredColor;
fEffectFlags = flags;
}
}
void GrDistanceFieldTextContext::appendGlyph(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;
}
SkScalar sx = SkFixedToScalar(vx);
SkScalar sy = SkFixedToScalar(vy);
/*
// not valid, need to find a different solution for this
vx += SkIntToFixed(glyph->fBounds.fLeft);
vy += SkIntToFixed(glyph->fBounds.fTop);
// keep them as ints until we've done the clip-test
GrFixed width = glyph->fBounds.width();
GrFixed height = glyph->fBounds.height();
// check if we clipped out
if (true || NULL == glyph->fPlot) {
int x = vx >> 16;
int y = vy >> 16;
if (fClipRect.quickReject(x, y, x + width, y + height)) {
// SkCLZ(3); // so we can set a break-point in the debugger
return;
}
}
*/
if (NULL == glyph->fPlot) {
if (!fStrike->glyphTooLargeForAtlas(glyph)) {
if (fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
// try to clear out an unused plot before we flush
if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
if (c_DumpFontCache) {
#ifdef SK_DEVELOPER
fContext->getFontCache()->dump();
#endif
}
// before we purge the cache, we must flush any accumulated draws
this->flush();
fContext->flush();
// we should have an unused plot now
if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
}
if (NULL == glyph->fPath) {
SkPath* path = SkNEW(SkPath);
if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
// flag the glyph as being dead?
delete path;
return;
}
glyph->fPath = path;
}
GrContext::AutoMatrix am;
SkMatrix ctm;
ctm.setScale(fTextRatio, fTextRatio);
ctm.postTranslate(sx, sy);
GrPaint tmpPaint(fPaint);
am.setPreConcat(fContext, ctm, &tmpPaint);
GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
return;
}
HAS_ATLAS:
SkASSERT(glyph->fPlot);
GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
glyph->fPlot->setDrawToken(drawToken);
GrTexture* texture = glyph->fPlot->texture();
SkASSERT(texture);
if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
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);
} else {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
}
bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
if (flush) {
this->flush();
fContext->flush();
if (useColorVerts) {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
} else {
fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
}
}
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
fDrawTarget->geometryHints(&fMaxVertices, NULL);
int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
if (fMaxVertices < kMinRequestedVerts) {
fMaxVertices = kDefaultRequestedVerts;
} else if (fMaxVertices > maxQuadVertices) {
// don't exceed the limit of the index buffer
fMaxVertices = maxQuadVertices;
}
bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
0,
&fVertices,
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);
SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
SkScalar scale = fTextRatio;
dx *= scale;
dy *= scale;
sx += dx;
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);
SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
SkRect r;
r.fLeft = sx;
r.fTop = sy;
r.fRight = sx + width;
r.fBottom = sy + height;
fVertexBounds.joinNonEmptyArg(r);
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);
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));
textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
vertSize);
if (useColorVerts) {
if (0xFF == GrColorUnpackA(fPaint.getColor())) {
fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
}
// color comes after position.
GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
for (int i = 0; i < 4; ++i) {
*colors = fPaint.getColor();
colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
}
}
fCurrVertex += 4;
}
void GrDistanceFieldTextContext::flush() {
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();
}
}
inline void GrDistanceFieldTextContext::finish() {
this->flush();
GrTextContext::finish();
}

View File

@ -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,26 +30,7 @@ public:
const SkScalar pos[], int scalarsPerPosition,
const SkPoint& offset) SK_OVERRIDE;
virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
private:
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;
void init(const GrPaint&, const SkPaint&);
void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
void flushGlyphs(); // automatically called by destructor
void setupCoverageEffect(const SkColor& filteredColor);
void finish();
enum {
kMinRequestedGlyphs = 1,
kDefaultRequestedGlyphs = 64,
@ -55,11 +38,27 @@ private:
kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
};
void* fVertices;
int32_t fMaxVertices;
GrTexture* fCurrTexture;
int fCurrVertex;
SkRect fVertexBounds;
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;
void* fVertices;
int32_t fMaxVertices;
GrTexture* fCurrTexture;
int fCurrVertex;
SkRect fVertexBounds;
void init(const GrPaint&, const SkPaint&);
void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
void setupCoverageEffect(const SkColor& filteredColor);
void flush(); // automatically called by destructor
void finish();
};
#endif

View File

@ -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,

View File

@ -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

View File

@ -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