| Index: src/gpu/batches/GrAtlasTextBatch.cpp
|
| diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp
|
| index 91088c0c59068811a94fea0a48c9ba6dca51d39a..9d408f997ab7e24c749d1406a09e196d1640065d 100644
|
| --- a/src/gpu/batches/GrAtlasTextBatch.cpp
|
| +++ b/src/gpu/batches/GrAtlasTextBatch.cpp
|
| @@ -18,6 +18,210 @@
|
| #include "effects/GrBitmapTextGeoProc.h"
|
| #include "effects/GrDistanceFieldGeoProc.h"
|
|
|
| +////////////////////////////////////////////////////////////////////////////////////////////////////
|
| +// A large template to handle regenerating the vertices of a textblob with as few branches as
|
| +// possible
|
| +template <bool regenPos, bool regenCol, bool regenTexCoords>
|
| +inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexStride,
|
| + bool useDistanceFields, SkScalar transX, SkScalar transY,
|
| + GrColor color) {
|
| + int u0, v0, u1, v1;
|
| + if (regenTexCoords) {
|
| + SkASSERT(glyph);
|
| + int width = glyph->fBounds.width();
|
| + int height = glyph->fBounds.height();
|
| +
|
| + if (useDistanceFields) {
|
| + u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
|
| + v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
|
| + u1 = u0 + width - 2 * SK_DistanceFieldInset;
|
| + v1 = v0 + height - 2 * SK_DistanceFieldInset;
|
| + } else {
|
| + u0 = glyph->fAtlasLocation.fX;
|
| + v0 = glyph->fAtlasLocation.fY;
|
| + u1 = u0 + width;
|
| + v1 = v0 + height;
|
| + }
|
| + }
|
| +
|
| + // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
|
| + // vertices, hence vertexStride - sizeof(SkIPoint16)
|
| + intptr_t colorOffset = sizeof(SkPoint);
|
| + intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
|
| +
|
| + // V0
|
| + if (regenPos) {
|
| + SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
|
| + point->fX += transX;
|
| + point->fY += transY;
|
| + }
|
| +
|
| + if (regenCol) {
|
| + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
|
| + *vcolor = color;
|
| + }
|
| +
|
| + if (regenTexCoords) {
|
| + SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
|
| + textureCoords->set(u0, v0);
|
| + }
|
| + vertex += vertexStride;
|
| +
|
| + // V1
|
| + if (regenPos) {
|
| + SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
|
| + point->fX += transX;
|
| + point->fY += transY;
|
| + }
|
| +
|
| + if (regenCol) {
|
| + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
|
| + *vcolor = color;
|
| + }
|
| +
|
| + if (regenTexCoords) {
|
| + SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
|
| + textureCoords->set(u0, v1);
|
| + }
|
| + vertex += vertexStride;
|
| +
|
| + // V2
|
| + if (regenPos) {
|
| + SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
|
| + point->fX += transX;
|
| + point->fY += transY;
|
| + }
|
| +
|
| + if (regenCol) {
|
| + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
|
| + *vcolor = color;
|
| + }
|
| +
|
| + if (regenTexCoords) {
|
| + SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
|
| + textureCoords->set(u1, v1);
|
| + }
|
| + vertex += vertexStride;
|
| +
|
| + // V3
|
| + if (regenPos) {
|
| + SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
|
| + point->fX += transX;
|
| + point->fY += transY;
|
| + }
|
| +
|
| + if (regenCol) {
|
| + SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
|
| + *vcolor = color;
|
| + }
|
| +
|
| + if (regenTexCoords) {
|
| + SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
|
| + textureCoords->set(u1, v0);
|
| + }
|
| +}
|
| +
|
| +typedef GrAtlasTextBlob Blob;
|
| +typedef Blob::Run Run;
|
| +typedef Run::SubRunInfo TextInfo;
|
| +
|
| +template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
|
| +inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Blob* blob, Run* run,
|
| + TextInfo* info, SkGlyphCache** cache,
|
| + SkTypeface** typeface, GrFontScaler** scaler,
|
| + const SkDescriptor** desc, const GrGeometryProcessor* gp,
|
| + int glyphCount, size_t vertexStride,
|
| + GrColor color, SkScalar transX, SkScalar transY) {
|
| + static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs");
|
| + GrBatchTextStrike* strike = nullptr;
|
| + if (regenTexCoords) {
|
| + info->fBulkUseToken.reset();
|
| +
|
| + // We can reuse if we have a valid strike and our descriptors / typeface are the
|
| + // same. The override descriptor is only for the non distance field text within
|
| + // a run
|
| + const SkDescriptor* newDesc = (run->fOverrideDescriptor && !this->usesDistanceFields()) ?
|
| + run->fOverrideDescriptor->getDesc() :
|
| + run->fDescriptor.getDesc();
|
| + if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) ||
|
| + !((*desc)->equals(*newDesc))) {
|
| + if (*cache) {
|
| + SkGlyphCache::AttachCache(*cache);
|
| + }
|
| + *desc = newDesc;
|
| + *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc);
|
| + *scaler = GrTextContext::GetGrFontScaler(*cache);
|
| + strike = info->fStrike;
|
| + *typeface = run->fTypeface;
|
| + }
|
| +
|
| + if (regenGlyphs) {
|
| + strike = fFontCache->getStrike(*scaler);
|
| + } else {
|
| + strike = info->fStrike;
|
| + }
|
| + }
|
| +
|
| + bool brokenRun = false;
|
| + for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
|
| + GrGlyph* glyph = nullptr;
|
| + if (regenTexCoords) {
|
| + size_t glyphOffset = glyphIdx + info->fGlyphStartIndex;
|
| +
|
| + glyph = blob->fGlyphs[glyphOffset];
|
| + GrGlyph::PackedID id = glyph->fPackedID;
|
| + const SkGlyph& skGlyph = (*scaler)->grToSkGlyph(id);
|
| + if (regenGlyphs) {
|
| + // Get the id from the old glyph, and use the new strike to lookup
|
| + // the glyph.
|
| + blob->fGlyphs[glyphOffset] = strike->getGlyph(skGlyph, id, this->maskFormat(),
|
| + *scaler);
|
| + }
|
| + glyph = blob->fGlyphs[glyphOffset];
|
| + SkASSERT(glyph);
|
| + SkASSERT(id == glyph->fPackedID);
|
| + // We want to be able to assert this but cannot for testing purposes.
|
| + // once skbug:4143 has landed we can revist this assert
|
| + //SkASSERT(glyph->fMaskFormat == this->maskFormat());
|
| +
|
| + if (!fFontCache->hasGlyph(glyph) &&
|
| + !strike->addGlyphToAtlas(target, glyph, *scaler, skGlyph, this->maskFormat())) {
|
| + this->flush(target, flushInfo);
|
| + target->initDraw(gp, this->pipeline());
|
| + brokenRun = glyphIdx > 0;
|
| +
|
| + SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
|
| + glyph,
|
| + *scaler,
|
| + skGlyph,
|
| + this->maskFormat());
|
| + SkASSERT(success);
|
| + }
|
| + fFontCache->addGlyphToBulkAndSetUseToken(&info->fBulkUseToken, glyph,
|
| + target->currentToken());
|
| + }
|
| +
|
| + intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
|
| + vertex += info->fVertexStartIndex;
|
| + vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph;
|
| + regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride,
|
| + this->usesDistanceFields(), transX,
|
| + transY, color);
|
| + flushInfo->fGlyphsToFlush++;
|
| + }
|
| +
|
| + // We my have changed the color so update it here
|
| + run->fColor = color;
|
| + if (regenTexCoords) {
|
| + if (regenGlyphs) {
|
| + info->fStrike.reset(SkRef(strike));
|
| + }
|
| + info->fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration :
|
| + fFontCache->atlasGeneration(this->maskFormat());
|
| + }
|
| +}
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
|
| unsigned r = SkColorGetR(c);
|
| unsigned g = SkColorGetG(c);
|
| @@ -81,6 +285,26 @@ void GrAtlasTextBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
|
| fBatch.fCoverageIgnored = !opt.readsCoverage();
|
| }
|
|
|
| +enum RegenMask {
|
| + kNoRegen = 0x0,
|
| + kRegenPos = 0x1,
|
| + kRegenCol = 0x2,
|
| + kRegenTex = 0x4,
|
| + kRegenGlyph = 0x8 | kRegenTex, // we have to regenerate the texture coords when we regen glyphs
|
| +
|
| + // combinations
|
| + kRegenPosCol = kRegenPos | kRegenCol,
|
| + kRegenPosTex = kRegenPos | kRegenTex,
|
| + kRegenPosTexGlyph = kRegenPos | kRegenGlyph,
|
| + kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex,
|
| + kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph,
|
| + kRegenColTex = kRegenCol | kRegenTex,
|
| + kRegenColTexGlyph = kRegenCol | kRegenGlyph,
|
| +};
|
| +
|
| +#define REGEN_ARGS target, &flushInfo, blob, &run, &info, &cache, &typeface, &scaler, &desc, gp, \
|
| + glyphCount, vertexStride, args.fColor, args.fTransX, args.fTransY
|
| +
|
| void GrAtlasTextBatch::onPrepareDraws(Target* target) {
|
| // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
|
| // TODO actually only invert if we don't have RGBA
|
| @@ -153,8 +377,18 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) {
|
| TextInfo& info = run.fSubRunInfo[args.fSubRun];
|
|
|
| uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat);
|
| +
|
| + // Because the GrBatchFontCache may evict the strike a blob depends on using for
|
| + // generating its texture coords, we have to track whether or not the strike has
|
| + // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is
|
| + // otherwise we have to get the new strike, and use that to get the correct glyphs.
|
| + // Because we do not have the packed ids, and thus can't look up our glyphs in the
|
| + // new strike, we instead keep our ref to the old strike and use the packed ids from
|
| + // it. These ids will still be valid as long as we hold the ref. When we are done
|
| + // updating our cache of the GrGlyph*s, we drop our ref on the old strike
|
| + bool regenerateGlyphs = info.fStrike->isAbandoned();
|
| bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen ||
|
| - info.fStrike->isAbandoned();
|
| + regenerateGlyphs;
|
| bool regenerateColors;
|
| if (usesDistanceFields) {
|
| regenerateColors = !isLCD && run.fColor != args.fColor;
|
| @@ -164,136 +398,34 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) {
|
| bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f;
|
| int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
|
|
|
| - // We regenerate both texture coords and colors in the blob itself, and update the
|
| - // atlas generation. If we don't end up purging any unused plots, we can avoid
|
| - // regenerating the coords. We could take a finer grained approach to updating texture
|
| - // coords but its not clear if the extra bookkeeping would offset any gains.
|
| - // To avoid looping over the glyphs twice, we do one loop and conditionally update color
|
| - // or coords as needed. One final note, if we have to break a run for an atlas eviction
|
| - // then we can't really trust the atlas has all of the correct data. Atlas evictions
|
| - // should be pretty rare, so we just always regenerate in those cases
|
| - if (regenerateTextureCoords || regenerateColors || regeneratePositions) {
|
| - // first regenerate texture coordinates / colors if need be
|
| - bool brokenRun = false;
|
| -
|
| - // Because the GrBatchFontCache may evict the strike a blob depends on using for
|
| - // generating its texture coords, we have to track whether or not the strike has
|
| - // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is
|
| - // otherwise we have to get the new strike, and use that to get the correct glyphs.
|
| - // Because we do not have the packed ids, and thus can't look up our glyphs in the
|
| - // new strike, we instead keep our ref to the old strike and use the packed ids from
|
| - // it. These ids will still be valid as long as we hold the ref. When we are done
|
| - // updating our cache of the GrGlyph*s, we drop our ref on the old strike
|
| - bool regenerateGlyphs = false;
|
| - GrBatchTextStrike* strike = nullptr;
|
| - if (regenerateTextureCoords) {
|
| - info.fBulkUseToken.reset();
|
| -
|
| - // We can reuse if we have a valid strike and our descriptors / typeface are the
|
| - // same. The override descriptor is only for the non distance field text within
|
| - // a run
|
| - const SkDescriptor* newDesc = (run.fOverrideDescriptor && !usesDistanceFields) ?
|
| - run.fOverrideDescriptor->getDesc() :
|
| - run.fDescriptor.getDesc();
|
| - if (!cache || !SkTypeface::Equal(typeface, run.fTypeface) ||
|
| - !(desc->equals(*newDesc))) {
|
| - if (cache) {
|
| - SkGlyphCache::AttachCache(cache);
|
| - }
|
| - desc = newDesc;
|
| - cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
|
| - scaler = GrTextContext::GetGrFontScaler(cache);
|
| - strike = info.fStrike;
|
| - typeface = run.fTypeface;
|
| - }
|
| -
|
| - if (info.fStrike->isAbandoned()) {
|
| - regenerateGlyphs = true;
|
| - strike = fFontCache->getStrike(scaler);
|
| - } else {
|
| - strike = info.fStrike;
|
| - }
|
| - }
|
| -
|
| - for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
|
| - if (regenerateTextureCoords) {
|
| - size_t glyphOffset = glyphIdx + info.fGlyphStartIndex;
|
| -
|
| - GrGlyph* glyph = blob->fGlyphs[glyphOffset];
|
| - GrGlyph::PackedID id = glyph->fPackedID;
|
| - const SkGlyph& skGlyph = scaler->grToSkGlyph(id);
|
| - if (regenerateGlyphs) {
|
| - // Get the id from the old glyph, and use the new strike to lookup
|
| - // the glyph.
|
| - blob->fGlyphs[glyphOffset] = strike->getGlyph(skGlyph, id, maskFormat,
|
| - scaler);
|
| - }
|
| - glyph = blob->fGlyphs[glyphOffset];
|
| - SkASSERT(glyph);
|
| - SkASSERT(id == glyph->fPackedID);
|
| - // We want to be able to assert this but cannot for testing purposes.
|
| - // once skbug:4143 has landed we can revist this assert
|
| - //SkASSERT(glyph->fMaskFormat == this->maskFormat());
|
| -
|
| - if (!fFontCache->hasGlyph(glyph) &&
|
| - !strike->addGlyphToAtlas(target, glyph, scaler, skGlyph, maskFormat)) {
|
| - this->flush(target, &flushInfo);
|
| - target->initDraw(gp, this->pipeline());
|
| - brokenRun = glyphIdx > 0;
|
| -
|
| - SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
|
| - glyph,
|
| - scaler,
|
| - skGlyph,
|
| - maskFormat);
|
| - SkASSERT(success);
|
| - }
|
| - fFontCache->addGlyphToBulkAndSetUseToken(&info.fBulkUseToken, glyph,
|
| - target->currentToken());
|
| -
|
| - // Texture coords are the last vertex attribute so we get a pointer to the
|
| - // first one and then map with stride in regenerateTextureCoords
|
| - intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
|
| - vertex += info.fVertexStartIndex;
|
| - vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
|
| - vertex += vertexStride - sizeof(SkIPoint16);
|
| -
|
| - this->regenerateTextureCoords(glyph, vertex, vertexStride);
|
| - }
|
| -
|
| - if (regenerateColors) {
|
| - intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
|
| - vertex += info.fVertexStartIndex;
|
| - vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
|
| - this->regenerateColors(vertex, vertexStride, args.fColor);
|
| - }
|
| -
|
| - if (regeneratePositions) {
|
| - intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices);
|
| - vertex += info.fVertexStartIndex;
|
| - vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
|
| - SkScalar transX = args.fTransX;
|
| - SkScalar transY = args.fTransY;
|
| - this->regeneratePositions(vertex, vertexStride, transX, transY);
|
| - }
|
| - flushInfo.fGlyphsToFlush++;
|
| - }
|
| -
|
| - // We my have changed the color so update it here
|
| - run.fColor = args.fColor;
|
| - if (regenerateTextureCoords) {
|
| - if (regenerateGlyphs) {
|
| - info.fStrike.reset(SkRef(strike));
|
| - }
|
| - info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration :
|
| - fFontCache->atlasGeneration(maskFormat);
|
| - }
|
| - } else {
|
| - flushInfo.fGlyphsToFlush += glyphCount;
|
| -
|
| - // set use tokens for all of the glyphs in our subrun. This is only valid if we
|
| - // have a valid atlas generation
|
| - fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentToken(), maskFormat);
|
| + uint32_t regenMaskBits = kNoRegen;
|
| + regenMaskBits |= regeneratePositions ? kRegenPos : 0;
|
| + regenMaskBits |= regenerateColors ? kRegenCol : 0;
|
| + regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0;
|
| + regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0;
|
| + RegenMask regenMask = (RegenMask)regenMaskBits;
|
| +
|
| + switch (regenMask) {
|
| + case kRegenPos: this->regenBlob<true, false, false, false>(REGEN_ARGS); break;
|
| + case kRegenCol: this->regenBlob<false, true, false, false>(REGEN_ARGS); break;
|
| + case kRegenTex: this->regenBlob<false, false, true, false>(REGEN_ARGS); break;
|
| + case kRegenGlyph: this->regenBlob<false, false, true, true>(REGEN_ARGS); break;
|
| +
|
| + // combinations
|
| + case kRegenPosCol: this->regenBlob<true, true, false, false>(REGEN_ARGS); break;
|
| + case kRegenPosTex: this->regenBlob<true, false, true, false>(REGEN_ARGS); break;
|
| + case kRegenPosTexGlyph: this->regenBlob<true, false, true, true>(REGEN_ARGS); break;
|
| + case kRegenPosColTex: this->regenBlob<true, true, true, false>(REGEN_ARGS); break;
|
| + case kRegenPosColTexGlyph: this->regenBlob<true, true, true, true>(REGEN_ARGS); break;
|
| + case kRegenColTex: this->regenBlob<false, true, true, false>(REGEN_ARGS); break;
|
| + case kRegenColTexGlyph: this->regenBlob<false, true, true, true>(REGEN_ARGS); break;
|
| + case kNoRegen:
|
| + flushInfo.fGlyphsToFlush += glyphCount;
|
| +
|
| + // set use tokens for all of the glyphs in our subrun. This is only valid if we
|
| + // have a valid atlas generation
|
| + fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentToken(), maskFormat);
|
| + break;
|
| }
|
|
|
| // now copy all vertices
|
| @@ -302,6 +434,7 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) {
|
|
|
| currVertex += byteCount;
|
| }
|
| +
|
| // Make sure to attach the last cache if applicable
|
| if (cache) {
|
| SkGlyphCache::AttachCache(cache);
|
| @@ -309,63 +442,6 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) {
|
| this->flush(target, &flushInfo);
|
| }
|
|
|
| -void GrAtlasTextBatch::regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex,
|
| - size_t vertexStride) {
|
| - int width = glyph->fBounds.width();
|
| - int height = glyph->fBounds.height();
|
| -
|
| - int u0, v0, u1, v1;
|
| - if (this->usesDistanceFields()) {
|
| - u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
|
| - v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
|
| - u1 = u0 + width - 2 * SK_DistanceFieldInset;
|
| - v1 = v0 + height - 2 * SK_DistanceFieldInset;
|
| - } else {
|
| - u0 = glyph->fAtlasLocation.fX;
|
| - v0 = glyph->fAtlasLocation.fY;
|
| - u1 = u0 + width;
|
| - v1 = v0 + height;
|
| - }
|
| -
|
| - SkIPoint16* textureCoords;
|
| - // V0
|
| - textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
|
| - textureCoords->set(u0, v0);
|
| - vertex += vertexStride;
|
| -
|
| - // V1
|
| - textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
|
| - textureCoords->set(u0, v1);
|
| - vertex += vertexStride;
|
| -
|
| - // V2
|
| - textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
|
| - textureCoords->set(u1, v1);
|
| - vertex += vertexStride;
|
| -
|
| - // V3
|
| - textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
|
| - textureCoords->set(u1, v0);
|
| -}
|
| -
|
| -void GrAtlasTextBatch::regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
|
| - for (int i = 0; i < kVerticesPerGlyph; i++) {
|
| - SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
|
| - *vcolor = color;
|
| - vertex += vertexStride;
|
| - }
|
| -}
|
| -
|
| -void GrAtlasTextBatch::regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar transX,
|
| - SkScalar transY) {
|
| - for (int i = 0; i < kVerticesPerGlyph; i++) {
|
| - SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
|
| - point->fX += transX;
|
| - point->fY += transY;
|
| - vertex += vertexStride;
|
| - }
|
| -}
|
| -
|
| void GrAtlasTextBatch::flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) {
|
| GrVertices vertices;
|
| int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads();
|
|
|