summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp')
-rwxr-xr-xchromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp490
1 files changed, 412 insertions, 78 deletions
diff --git a/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
index a43c4a28746..25c13ec8d1a 100755
--- a/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
@@ -10,6 +10,7 @@
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
#include "GrIndexBuffer.h"
+#include "GrStrokeInfo.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
#include "SkColorPriv.h"
@@ -18,31 +19,59 @@
#include "SkStrokeRec.h"
#include "effects/GrCustomCoordsTextureEffect.h"
-static const int kGlyphCoordsAttributeIndex = 1;
+#include "SkAutoKern.h"
+#include "SkDraw.h"
+#include "SkDrawProcs.h"
+#include "SkGlyphCache.h"
+#include "SkGpuDevice.h"
+#include "SkGr.h"
+#include "SkTextMapStateProc.h"
SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
"Dump the contents of the font cache before every purge.");
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint,
- SkColor color) :
- GrTextContext(context, paint) {
- fAutoMatrix.setIdentity(fContext, &fPaint);
+static const int kGlyphCoordsNoColorAttributeIndex = 1;
+static const int kGlyphCoordsWithColorAttributeIndex = 2;
- fSkPaintColor = color;
+namespace {
+// position + texture coord
+extern const GrVertexAttrib gTextVertexAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding}
+};
+
+// position + color + texture coord
+extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVertexAttribBinding}
+};
+};
+
+GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
+ const SkDeviceProperties& properties)
+ : GrTextContext(context, properties) {
fStrike = NULL;
fCurrTexture = NULL;
fCurrVertex = 0;
+ fEffectTextureGenID = 0;
fVertices = NULL;
fMaxVertices = 0;
+
+ fVertexBounds.setLargestInverted();
}
GrBitmapTextContext::~GrBitmapTextContext() {
this->flushGlyphs();
}
+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);
@@ -61,76 +90,348 @@ void GrBitmapTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
// setup our sampler state for our text texture/atlas
- SkASSERT(GrIsALIGN4(fCurrVertex));
+ SkASSERT(SkIsAlign4(fCurrVertex));
SkASSERT(fCurrTexture);
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
+ uint32_t textureGenID = fCurrTexture->getGenerationID();
+
+ if (textureGenID != fEffectTextureGenID) {
+ fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, params));
+ fEffectTextureGenID = textureGenID;
+ }
+
// This effect could be stored with one of the cache objects (atlas?)
- drawState->addCoverageEffect(
- GrCustomCoordsTextureEffect::Create(fCurrTexture, params),
- kGlyphCoordsAttributeIndex)->unref();
-
- if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) {
- drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
- drawState->setColor(0xffffffff);
- } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
- if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
- kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
- fPaint.numColorStages()) {
- GrPrintf("LCD Text will not draw correctly.\n");
+ int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
+ kGlyphCoordsNoColorAttributeIndex;
+ drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
+ SkASSERT(NULL != 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;
}
- // 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(fSkPaintColor);
- // paintAlpha
- drawState->setColor(SkColorSetARGB(a, a, a, a));
- // paintColor
- drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaintColor));
- drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
- } else {
- // set back to normal in case we took LCD path previously.
- drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
- drawState->setColor(fPaint.getColor());
+ // Grayscale/BW text
+ case kA8_GrMaskFormat:
+ // set back to normal in case we took LCD path previously.
+ drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+ //drawState->setColor(fPaint.getColor());
+ // We're using per-vertex color.
+ SkASSERT(drawState->hasColorVertexAttribute());
+ drawState->setColor(0xFFFFFFFF);
+ break;
+ default:
+ SkFAIL("Unexepected mask format.");
}
-
int nGlyphs = fCurrVertex / 4;
fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
nGlyphs,
- 4, 6);
+ 4, 6, &fVertexBounds);
fDrawTarget->resetVertexSource();
fVertices = NULL;
fMaxVertices = 0;
fCurrVertex = 0;
+ fVertexBounds.setLargestInverted();
SkSafeSetNull(fCurrTexture);
}
}
-namespace {
+inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
+ GrTextContext::init(paint, skPaint);
-// position + texture coord
-extern const GrVertexAttrib gTextVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
-};
+ fStrike = NULL;
-};
+ fCurrTexture = NULL;
+ fCurrVertex = 0;
+
+ fVertices = NULL;
+ 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) {
+ SkASSERT(byteLength == 0 || text != NULL);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // transform our starting point
+ {
+ SkPoint loc;
+ fContext->getMatrix().mapXY(x, y, &loc);
+ x = loc.fX;
+ y = loc.fY;
+ }
+
+ // need to measure first
+ if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ SkVector stop;
+
+ MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+
+ SkScalar stopX = stop.fX;
+ SkScalar stopY = stop.fY;
+
+ if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ stopX = SkScalarHalf(stopX);
+ stopY = SkScalarHalf(stopY);
+ }
+ x -= stopX;
+ y -= stopY;
+ }
+
+ const char* stop = text + byteLength;
+
+ SkAutoKern autokern;
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ SkFixed halfSampleX, halfSampleY;
+ if (cache->isSubpixel()) {
+ halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+ halfSampleY = SK_FixedHalf;
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+ halfSampleX = SK_FixedHalf;
+ }
+ } else {
+ halfSampleX = halfSampleY = SK_FixedHalf;
+ }
+
+ SkFixed fx = SkScalarToFixed(x) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(y) + halfSampleY;
+
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
+
+ fx += autokern.adjust(glyph);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+
+ fx += glyph.fAdvanceX;
+ fy += glyph.fAdvanceY;
+ }
+
+ this->finish();
+}
+
+void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) {
+ SkASSERT(byteLength == 0 || text != NULL);
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // store original matrix before we reset, so we can use it to transform positions
+ SkMatrix ctm = fContext->getMatrix();
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ const char* stop = text + byteLength;
+ SkTextAlignProc alignProc(fSkPaint.getTextAlign());
+ SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
+ SkFixed halfSampleX = 0, halfSampleY = 0;
+
+ if (cache->isSubpixel()) {
+ // maybe we should skip the rounding if linearText is set
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleY = SK_FixedHalf;
+#endif
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleX = SK_FixedHalf;
+#endif
+ }
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
+
+ const SkGlyph& glyph = glyphCacheProc(cache, &text,
+ fx & fxMask, fy & fyMask);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ const char* currentText = text;
+ const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (metricGlyph.fWidth) {
+ SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
+ SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkIPoint fixedLoc;
+ alignProc(tmsLoc, metricGlyph, &fixedLoc);
+
+ SkFixed fx = fixedLoc.fX + halfSampleX;
+ SkFixed fy = fixedLoc.fY + halfSampleY;
+
+ // have to call again, now that we've been "aligned"
+ const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
+ fx & fxMask, fy & fyMask);
+ // the assumption is that the metrics haven't changed
+ SkASSERT(prevAdvX == glyph.fAdvanceX);
+ SkASSERT(prevAdvY == glyph.fAdvanceY);
+ SkASSERT(glyph.fWidth);
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ } else { // not subpixel
+
+ 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) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+
+ 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);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+
+ SkIPoint fixedLoc;
+ alignProc(tmsLoc, glyph, &fixedLoc);
+
+ 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);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ }
+
+ this->finish();
+}
void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
- GrFixed vx, GrFixed vy,
+ SkFixed vx, SkFixed vy,
GrFontScaler* scaler) {
if (NULL == fDrawTarget) {
return;
}
+
if (NULL == fStrike) {
-#if SK_DISTANCEFIELD_FONTS
fStrike = fContext->getFontCache()->getStrike(scaler, false);
-#else
- fStrike = fContext->getFontCache()->getStrike(scaler);
-#endif
}
GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
@@ -142,8 +443,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
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();
+ SkFixed width = glyph->fBounds.width();
+ SkFixed height = glyph->fBounds.height();
// check if we clipped out
if (true || NULL == glyph->fPlot) {
@@ -156,13 +457,13 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
if (NULL == glyph->fPlot) {
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
// try to clear out an unused plot before we flush
- fContext->getFontCache()->freePlotExceptFor(fStrike);
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -172,14 +473,13 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
#endif
}
- // before we purge the cache, we must flush any accumulated draws
+ // flush any accumulated draws to allow us to free up a plot
this->flushGlyphs();
fContext->flush();
- // try to purge
- fContext->getFontCache()->purgeExceptFor(fStrike);
- // need to use new flush count here
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ // we should have an unused plot now
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -199,8 +499,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
GrPaint tmpPaint(fPaint);
am.setPreConcat(fContext, translate, &tmpPaint);
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
+ GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
+ fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
return;
}
@@ -222,18 +522,30 @@ HAS_ATLAS:
fCurrTexture->ref();
}
+ bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
+
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;
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs));
+ if (useColorVerts) {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+ } else {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs));
+ }
bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
if (flush) {
this->flushGlyphs();
fContext->flush();
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs));
+ if (useColorVerts) {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+ } else {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs));
+ }
}
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
@@ -248,24 +560,46 @@ HAS_ATLAS:
}
bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
0,
- GrTCast<void**>(&fVertices),
+ &fVertices,
NULL);
GrAlwaysAssert(success);
- SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize());
}
- GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
- GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
-
- fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx),
- SkFixedToFloat(vy),
- SkFixedToFloat(vx + width),
- SkFixedToFloat(vy + height),
- 2 * sizeof(SkPoint));
- fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
- SkFixedToFloat(texture->normalizeFixedY(ty)),
- SkFixedToFloat(texture->normalizeFixedX(tx + width)),
- SkFixedToFloat(texture->normalizeFixedY(ty + height)),
- 2 * sizeof(SkPoint));
+ SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
+ SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
+
+ SkRect r;
+ r.fLeft = SkFixedToFloat(vx);
+ r.fTop = SkFixedToFloat(vy);
+ r.fRight = SkFixedToFloat(vx + width);
+ r.fBottom = SkFixedToFloat(vy + height);
+
+ fVertexBounds.growToInclude(r);
+
+ size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
+ (2 * sizeof(SkPoint));
+
+ SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize());
+
+ 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->normalizeFixedX(tx)),
+ SkFixedToFloat(texture->normalizeFixedY(ty)),
+ SkFixedToFloat(texture->normalizeFixedX(tx + width)),
+ SkFixedToFloat(texture->normalizeFixedY(ty + height)),
+ vertSize);
+ if (useColorVerts) {
+ // 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;
}