aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/batches/GrAtlasTextBatch.cpp14
-rw-r--r--src/gpu/batches/GrAtlasTextBatch.h12
-rw-r--r--src/gpu/text/GrAtlasTextBlob.cpp123
-rw-r--r--src/gpu/text/GrAtlasTextBlob.h81
-rw-r--r--src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp8
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp18
6 files changed, 149 insertions, 107 deletions
diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp
index 6fea132969..432322ff7a 100644
--- a/src/gpu/batches/GrAtlasTextBatch.cpp
+++ b/src/gpu/batches/GrAtlasTextBatch.cpp
@@ -34,8 +34,8 @@ SkString GrAtlasTextBatch::dumpInfo() const {
str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n",
i,
fGeoData[i].fColor,
- fGeoData[i].fTransX,
- fGeoData[i].fTransY,
+ fGeoData[i].fX,
+ fGeoData[i].fY,
fGeoData[i].fBlob->runCount());
}
@@ -148,10 +148,10 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const {
Blob* blob = args.fBlob;
size_t byteCount;
void* blobVertices;
- int glyphCount;
+ int subRunGlyphCount;
blob->regenInBatch(target, fFontCache, &helper, args.fRun, args.fSubRun, &cache,
- &typeface, &scaler, &desc, vertexStride, args.fColor, args.fTransX,
- args.fTransY, &blobVertices, &byteCount, &glyphCount);
+ &typeface, &scaler, &desc, vertexStride, args.fViewMatrix, args.fX,
+ args.fY, args.fColor, &blobVertices, &byteCount, &subRunGlyphCount);
// now copy all vertices
memcpy(currVertex, blobVertices, byteCount);
@@ -161,10 +161,10 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const {
SkRect rect;
rect.setLargestInverted();
SkPoint* vertex = (SkPoint*) ((char*)blobVertices);
- rect.growToInclude(vertex, vertexStride, kVerticesPerGlyph * glyphCount);
+ rect.growToInclude(vertex, vertexStride, kVerticesPerGlyph * subRunGlyphCount);
if (this->usesDistanceFields()) {
- fBatch.fViewMatrix.mapRect(&rect);
+ args.fViewMatrix.mapRect(&rect);
}
SkASSERT(fBounds.contains(rect));
#endif
diff --git a/src/gpu/batches/GrAtlasTextBatch.h b/src/gpu/batches/GrAtlasTextBatch.h
index d90aa194c3..435fb59d49 100644
--- a/src/gpu/batches/GrAtlasTextBatch.h
+++ b/src/gpu/batches/GrAtlasTextBatch.h
@@ -22,12 +22,13 @@ public:
typedef GrAtlasTextBlob Blob;
struct Geometry {
+ SkMatrix fViewMatrix;
Blob* fBlob;
+ SkScalar fX;
+ SkScalar fY;
int fRun;
int fSubRun;
GrColor fColor;
- SkScalar fTransX;
- SkScalar fTransY;
};
static GrAtlasTextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount,
@@ -79,9 +80,9 @@ public:
void init() {
const Geometry& geo = fGeoData[0];
fBatch.fColor = geo.fColor;
- fBatch.fViewMatrix = geo.fBlob->viewMatrix();
- geo.fBlob->computeSubRunBounds(&fBounds, geo.fRun, geo.fSubRun);
+ geo.fBlob->computeSubRunBounds(&fBounds, geo.fRun, geo.fSubRun, geo.fViewMatrix, geo.fX,
+ geo.fY);
}
const char* name() const override { return "TextBatch"; }
@@ -141,7 +142,7 @@ private:
inline void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const;
GrColor color() const { return fBatch.fColor; }
- const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
+ const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
int numGlyphs() const { return fBatch.fNumGlyphs; }
@@ -154,7 +155,6 @@ private:
struct BatchTracker {
GrColor fColor;
- SkMatrix fViewMatrix;
bool fUsesLocalCoords;
bool fColorIgnored;
bool fCoverageIgnored;
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index f2ca3d2186..26f6a7c3fe 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -165,8 +165,7 @@ void GrAtlasTextBlob::appendLargeGlyph(GrGlyph* glyph, GrFontScaler* scaler, con
fBigGlyphs.push_back(GrAtlasTextBlob::BigGlyph(*glyph->fPath, x, y, scale, applyVM));
}
-bool GrAtlasTextBlob::mustRegenerate(SkScalar* outTransX, SkScalar* outTransY,
- const SkPaint& paint,
+bool GrAtlasTextBlob::mustRegenerate(const SkPaint& paint,
GrColor color, const SkMaskFilter::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// If we have LCD text then our canonical color will be set to transparent, in this case we have
@@ -177,11 +176,11 @@ bool GrAtlasTextBlob::mustRegenerate(SkScalar* outTransX, SkScalar* outTransY,
return true;
}
- if (fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
+ if (fInitialViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
return true;
}
- if (fViewMatrix.hasPerspective() && !fViewMatrix.cheapEqualTo(viewMatrix)) {
+ if (fInitialViewMatrix.hasPerspective() && !fInitialViewMatrix.cheapEqualTo(viewMatrix)) {
return true;
}
@@ -205,17 +204,17 @@ bool GrAtlasTextBlob::mustRegenerate(SkScalar* outTransX, SkScalar* outTransY,
// for mixed blobs if this becomes an issue.
if (this->hasBitmap() && this->hasDistanceField()) {
// Identical viewmatrices and we can reuse in all cases
- if (fViewMatrix.cheapEqualTo(viewMatrix) && x == fX && y == fY) {
+ if (fInitialViewMatrix.cheapEqualTo(viewMatrix) && x == fInitialX && y == fInitialY) {
return false;
}
return true;
}
if (this->hasBitmap()) {
- if (fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
- fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
- fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
- fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
+ if (fInitialViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
+ fInitialViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
+ fInitialViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
+ fInitialViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
return true;
}
@@ -224,39 +223,27 @@ bool GrAtlasTextBlob::mustRegenerate(SkScalar* outTransX, SkScalar* outTransY,
// This cool bit of math will determine the necessary translation to apply to the already
// generated vertex coordinates to move them to the correct position
SkScalar transX = viewMatrix.getTranslateX() +
- viewMatrix.getScaleX() * (x - fX) +
- viewMatrix.getSkewX() * (y - fY) -
- fViewMatrix.getTranslateX();
+ viewMatrix.getScaleX() * (x - fInitialX) +
+ viewMatrix.getSkewX() * (y - fInitialY) -
+ fInitialViewMatrix.getTranslateX();
SkScalar transY = viewMatrix.getTranslateY() +
- viewMatrix.getSkewY() * (x - fX) +
- viewMatrix.getScaleY() * (y - fY) -
- fViewMatrix.getTranslateY();
- if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY) ) {
+ viewMatrix.getSkewY() * (x - fInitialX) +
+ viewMatrix.getScaleY() * (y - fInitialY) -
+ fInitialViewMatrix.getTranslateY();
+ if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) {
return true;
}
-
- (*outTransX) = transX;
- (*outTransY) = transY;
} else if (this->hasDistanceField()) {
// A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
// distance field being generated, so we have to regenerate in those cases
SkScalar newMaxScale = viewMatrix.getMaxScale();
- SkScalar oldMaxScale = fViewMatrix.getMaxScale();
+ SkScalar oldMaxScale = fInitialViewMatrix.getMaxScale();
SkScalar scaleAdjust = newMaxScale / oldMaxScale;
if (scaleAdjust < fMaxMinScale || scaleAdjust > fMinMaxScale) {
return true;
}
-
- (*outTransX) = x - fX;
- (*outTransY) = y - fY;
}
- // If we can reuse the blob, then make sure we update the blob's viewmatrix, and x/y
- // offsets. Note, we offset the vertex bounds right before flushing
- fViewMatrix = viewMatrix;
- fX = x;
- fY = y;
-
// It is possible that a blob has neither distanceField nor bitmaptext. This is in the case
// when all of the runs inside the blob are drawn as paths. In this case, we always regenerate
// the blob anyways at flush time, so no need to regenerate explicitly
@@ -266,7 +253,8 @@ bool GrAtlasTextBlob::mustRegenerate(SkScalar* outTransX, SkScalar* outTransY,
inline GrDrawBatch* GrAtlasTextBlob::createBatch(
const Run::SubRunInfo& info,
int glyphCount, int run, int subRun,
- GrColor color, SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache) {
@@ -296,12 +284,13 @@ inline GrDrawBatch* GrAtlasTextBlob::createBatch(
batch = GrAtlasTextBatch::CreateBitmap(format, glyphCount, cache);
}
GrAtlasTextBatch::Geometry& geometry = batch->geometry();
+ geometry.fViewMatrix = viewMatrix;
geometry.fBlob = SkRef(this);
geometry.fRun = run;
geometry.fSubRun = subRun;
geometry.fColor = subRunColor;
- geometry.fTransX = transX;
- geometry.fTransY = transY;
+ geometry.fX = x;
+ geometry.fY = y;
batch->init();
return batch;
@@ -309,8 +298,8 @@ inline GrDrawBatch* GrAtlasTextBlob::createBatch(
inline
void GrAtlasTextBlob::flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder,
- int run, GrColor color,
- SkScalar transX, SkScalar transY,
+ int run, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache) {
@@ -322,26 +311,48 @@ void GrAtlasTextBlob::flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBui
}
SkAutoTUnref<GrDrawBatch> batch(this->createBatch(info, glyphCount, run,
- subRun, color, transX, transY,
+ subRun, viewMatrix, x, y, color,
skPaint, props,
distanceAdjustTable, cache));
dc->drawBatch(pipelineBuilder, batch);
}
}
+static void calculate_translation(bool applyVM,
+ const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY,
+ const SkMatrix& currentViewMatrix, SkScalar currentX,
+ SkScalar currentY, SkScalar* transX, SkScalar* transY) {
+ if (applyVM) {
+ *transX = newViewMatrix.getTranslateX() +
+ newViewMatrix.getScaleX() * (newX - currentX) +
+ newViewMatrix.getSkewX() * (newY - currentY) -
+ currentViewMatrix.getTranslateX();
+
+ *transY = newViewMatrix.getTranslateY() +
+ newViewMatrix.getSkewY() * (newX - currentX) +
+ newViewMatrix.getScaleY() * (newY - currentY) -
+ currentViewMatrix.getTranslateY();
+ } else {
+ *transX = newX - currentX;
+ *transY = newY - currentY;
+ }
+}
+
+
void GrAtlasTextBlob::flushBigGlyphs(GrContext* context, GrDrawContext* dc,
const GrClip& clip, const SkPaint& skPaint,
- SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
const SkIRect& clipBounds) {
+ SkScalar transX, transY;
for (int i = 0; i < fBigGlyphs.count(); i++) {
GrAtlasTextBlob::BigGlyph& bigGlyph = fBigGlyphs[i];
- bigGlyph.fVx += transX;
- bigGlyph.fVy += transY;
+ calculate_translation(bigGlyph.fApplyVM, viewMatrix, x, y,
+ fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY);
SkMatrix ctm;
ctm.setScale(bigGlyph.fScale, bigGlyph.fScale);
- ctm.postTranslate(bigGlyph.fVx, bigGlyph.fVy);
+ ctm.postTranslate(bigGlyph.fX + transX, bigGlyph.fY + transY);
if (bigGlyph.fApplyVM) {
- ctm.postConcat(fViewMatrix);
+ ctm.postConcat(viewMatrix);
}
GrBlurUtils::drawPathWithMaskFilter(context, dc, clip, bigGlyph.fPath,
@@ -399,8 +410,7 @@ void GrAtlasTextBlob::flushCached(GrContext* context,
const GrClip& clip,
const SkMatrix& viewMatrix,
const SkIRect& clipBounds,
- SkScalar x, SkScalar y,
- SkScalar transX, SkScalar transY) {
+ SkScalar x, SkScalar y) {
// We loop through the runs of the blob, flushing each. If any run is too large, then we flush
// it as paths
GrPipelineBuilder pipelineBuilder(grPaint, dc->accessRenderTarget(), clip);
@@ -414,13 +424,12 @@ void GrAtlasTextBlob::flushCached(GrContext* context,
drawFilter, viewMatrix, clipBounds, x, y);
continue;
}
- this->flushRun(dc, &pipelineBuilder, run, color,
- transX, transY, skPaint, props,
+ this->flushRun(dc, &pipelineBuilder, run, viewMatrix, x, y, color, skPaint, props,
distanceAdjustTable, context->getBatchFontCache());
}
// Now flush big glyphs
- this->flushBigGlyphs(context, dc, clip, skPaint, transX, transY, clipBounds);
+ this->flushBigGlyphs(context, dc, clip, skPaint, viewMatrix, x, y, clipBounds);
}
void GrAtlasTextBlob::flushThrowaway(GrContext* context,
@@ -430,27 +439,30 @@ void GrAtlasTextBlob::flushThrowaway(GrContext* context,
const SkPaint& skPaint,
const GrPaint& grPaint,
const GrClip& clip,
- const SkIRect& clipBounds) {
+ const SkMatrix& viewMatrix,
+ const SkIRect& clipBounds,
+ SkScalar x, SkScalar y) {
GrPipelineBuilder pipelineBuilder(grPaint, dc->accessRenderTarget(), clip);
GrColor color = grPaint.getColor();
for (int run = 0; run < fRunCount; run++) {
- this->flushRun(dc, &pipelineBuilder, run, color, 0, 0, skPaint, props,
+ this->flushRun(dc, &pipelineBuilder, run, viewMatrix, x, y, color, skPaint, props,
distanceAdjustTable, context->getBatchFontCache());
}
// Now flush big glyphs
- this->flushBigGlyphs(context, dc, clip, skPaint, 0, 0, clipBounds);
+ this->flushBigGlyphs(context, dc, clip, skPaint, viewMatrix, x, y, clipBounds);
}
GrDrawBatch* GrAtlasTextBlob::test_createBatch(
int glyphCount, int run, int subRun,
- GrColor color, SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache) {
const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
- return this->createBatch(info, glyphCount, run, subRun, color, transX, transY, skPaint,
+ return this->createBatch(info, glyphCount, run, subRun, viewMatrix, x, y, color, skPaint,
props, distanceAdjustTable, cache);
}
@@ -476,7 +488,6 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo
}
SkASSERT_RELEASE(l.fKey == r.fKey);
- SkASSERT_RELEASE(l.fViewMatrix.cheapEqualTo(r.fViewMatrix));
//SkASSERT_RELEASE(l.fPaintColor == r.fPaintColor); // Colors might not actually be identical
SkASSERT_RELEASE(l.fMaxMinScale == r.fMaxMinScale);
SkASSERT_RELEASE(l.fMinMaxScale == r.fMinMaxScale);
@@ -540,3 +551,13 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo
}
}
}
+
+void GrAtlasTextBlob::Run::SubRunInfo::computeTranslation(const SkMatrix& viewMatrix,
+ SkScalar x, SkScalar y, SkScalar* transX,
+ SkScalar* transY) {
+ calculate_translation(!this->drawAsDistanceFields(), viewMatrix, x, y,
+ fCurrentViewMatrix, fX, fY, transX, transY);
+ fCurrentViewMatrix = viewMatrix;
+ fX = x;
+ fY = y;
+}
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 8b175c8e96..a026693012 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -173,8 +173,7 @@ public:
}
}
- bool mustRegenerate(SkScalar* outTransX, SkScalar* outTransY, const SkPaint& paint,
- GrColor color, const SkMaskFilter::BlurRec& blurRec,
+ bool mustRegenerate(const SkPaint& paint, GrColor color, const SkMaskFilter::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
// flush a GrAtlasTextBlob associated with a SkTextBlob
@@ -189,8 +188,7 @@ public:
const GrClip& clip,
const SkMatrix& viewMatrix,
const SkIRect& clipBounds,
- SkScalar x, SkScalar y,
- SkScalar transX, SkScalar transY);
+ SkScalar x, SkScalar y);
// flush a throwaway GrAtlasTextBlob *not* associated with an SkTextBlob
void flushThrowaway(GrContext* context,
@@ -200,9 +198,12 @@ public:
const SkPaint& skPaint,
const GrPaint& grPaint,
const GrClip& clip,
- const SkIRect& clipBounds);
+ const SkMatrix& viewMatrix,
+ const SkIRect& clipBounds,
+ SkScalar x, SkScalar y);
- void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex) {
+ void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// We don't yet position distance field text on the cpu, so we have to map the vertex bounds
// into device space.
// We handle vertex bounds differently for distance field text and bitmap text because
@@ -214,8 +215,8 @@ public:
if (subRun.drawAsDistanceFields()) {
// Distance field text is positioned with the (X,Y) as part of the glyph position,
// and currently the view matrix is applied on the GPU
- outBounds->offset(fX - fInitialX, fY - fInitialY);
- fViewMatrix.mapRect(outBounds);
+ outBounds->offset(x - fInitialX, y - fInitialY);
+ viewMatrix.mapRect(outBounds);
} else {
// Bitmap text is fully positioned on the CPU, and offset by an (X,Y) translate in
// device space.
@@ -223,9 +224,9 @@ public:
boundsMatrix.postTranslate(-fInitialX, -fInitialY);
- boundsMatrix.postTranslate(fX, fY);
+ boundsMatrix.postTranslate(x, y);
- boundsMatrix.postConcat(fViewMatrix);
+ boundsMatrix.postConcat(viewMatrix);
boundsMatrix.mapRect(outBounds);
// Due to floating point numerical inaccuracies, we have to round out here
@@ -233,9 +234,6 @@ public:
}
}
- const SkMatrix& viewMatrix() const { return fViewMatrix; }
-
-
// position + local coord
static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
@@ -261,7 +259,8 @@ public:
GrBlobRegenHelper *helper, int run, int subRun, SkGlyphCache** cache,
SkTypeface** typeface, GrFontScaler** scaler,
const SkDescriptor** desc, size_t vertexStride,
- GrColor color, SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
void** vertices, size_t* byteCount, int* glyphCount);
const Key& key() const { return fKey; }
@@ -275,7 +274,7 @@ public:
////////////////////////////////////////////////////////////////////////////////////////////////
// Internal test methods
GrDrawBatch* test_createBatch(int glyphCount, int run, int subRun,
- GrColor color, SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache);
@@ -290,15 +289,14 @@ private:
SkScalar x, SkScalar y, SkScalar scale, bool applyVM);
inline void flushRun(GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder,
- int run, GrColor color,
- SkScalar transX, SkScalar transY,
+ int run, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache);
void flushBigGlyphs(GrContext* context, GrDrawContext* dc,
const GrClip& clip, const SkPaint& skPaint,
- SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
const SkIRect& clipBounds);
void flushRunAsPaths(GrContext* context,
@@ -309,18 +307,23 @@ private:
SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
const SkIRect& clipBounds, SkScalar x, SkScalar y);
- // This function will only be called when we are regenerating a blob from scratch. We record the
+ // This function will only be called when we are generating a blob from scratch. We record the
// initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
// these numbers. When blobs are reused with new matrices, we need to return to model space so
// we can update the vertex bounds appropriately.
void setupViewMatrix(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
- fViewMatrix = viewMatrix;
+ fInitialViewMatrix = viewMatrix;
if (!viewMatrix.invert(&fInitialViewMatrixInverse)) {
fInitialViewMatrixInverse = SkMatrix::I();
SkDebugf("Could not invert viewmatrix\n");
}
- fX = fInitialX = x;
- fY = fInitialY = y;
+ fInitialX = x;
+ fInitialY = y;
+
+ // make sure all initial subruns have the correct VM and X/Y applied
+ for (int i = 0; i < fRunCount; i++) {
+ fRuns[i].fSubRunInfo[0].init(fInitialViewMatrix, x, y);
+ }
}
/*
@@ -369,12 +372,15 @@ private:
SubRunInfo(const SubRunInfo& that)
: fBulkUseToken(that.fBulkUseToken)
, fStrike(SkSafeRef(that.fStrike.get()))
+ , fCurrentViewMatrix(that.fCurrentViewMatrix)
, fVertexBounds(that.fVertexBounds)
, fAtlasGeneration(that.fAtlasGeneration)
, fVertexStartIndex(that.fVertexStartIndex)
, fVertexEndIndex(that.fVertexEndIndex)
, fGlyphStartIndex(that.fGlyphStartIndex)
, fGlyphEndIndex(that.fGlyphEndIndex)
+ , fX(that.fX)
+ , fY(that.fY)
, fColor(that.fColor)
, fMaskFormat(that.fMaskFormat)
, fDrawAsDistanceFields(that.fDrawAsDistanceFields)
@@ -412,6 +418,9 @@ private:
fVertexStartIndex = prev.vertexEndIndex();
fVertexEndIndex = prev.vertexEndIndex();
+
+ // copy over viewmatrix settings
+ this->init(prev.fCurrentViewMatrix, prev.fX, prev.fY);
}
const SkRect& vertexBounds() const { return fVertexBounds; }
@@ -419,6 +428,16 @@ private:
fVertexBounds.joinNonEmptyArg(glyphBounds);
}
+ void init(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
+ fCurrentViewMatrix = viewMatrix;
+ fX = x;
+ fY = y;
+ }
+
+ // This function assumes the translation will be applied before it is called again
+ void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ SkScalar*transX, SkScalar* transY);
+
// df properties
void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; }
bool hasUseLCDText() const { return fUseLCDText; }
@@ -428,12 +447,15 @@ private:
private:
GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken;
SkAutoTUnref<GrBatchTextStrike> fStrike;
+ SkMatrix fCurrentViewMatrix;
SkRect fVertexBounds;
uint64_t fAtlasGeneration;
size_t fVertexStartIndex;
size_t fVertexEndIndex;
uint32_t fGlyphStartIndex;
uint32_t fGlyphEndIndex;
+ SkScalar fX;
+ SkScalar fY;
GrColor fColor;
GrMaskFormat fMaskFormat;
bool fDrawAsDistanceFields; // df property
@@ -475,7 +497,8 @@ private:
inline GrDrawBatch* createBatch(const Run::SubRunInfo& info,
int glyphCount, int run, int subRun,
- GrColor color, SkScalar transX, SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
const SkPaint& skPaint, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
GrBatchFontCache* cache);
@@ -483,14 +506,14 @@ private:
struct BigGlyph {
BigGlyph(const SkPath& path, SkScalar vx, SkScalar vy, SkScalar scale, bool applyVM)
: fPath(path)
- , fVx(vx)
- , fVy(vy)
, fScale(scale)
+ , fX(vx)
+ , fY(vy)
, fApplyVM(applyVM) {}
SkPath fPath;
- SkScalar fVx;
- SkScalar fVy;
SkScalar fScale;
+ SkScalar fX;
+ SkScalar fY;
bool fApplyVM;
};
@@ -514,14 +537,12 @@ private:
StrokeInfo fStrokeInfo;
SkTArray<BigGlyph> fBigGlyphs;
Key fKey;
- SkMatrix fViewMatrix;
+ SkMatrix fInitialViewMatrix;
SkMatrix fInitialViewMatrixInverse;
size_t fSize;
GrColor fPaintColor;
SkScalar fInitialX;
SkScalar fInitialY;
- SkScalar fX;
- SkScalar fY;
// We can reuse distance field text, but only if the new viewmatrix would not result in
// a mip change. Because there can be multiple runs in a blob, we track the overall
diff --git a/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp b/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp
index 14bf4a5d61..00a73641aa 100644
--- a/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp
+++ b/src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp
@@ -235,14 +235,18 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
int runIndex, int subRunIndex, SkGlyphCache** cache,
SkTypeface** typeface, GrFontScaler** scaler,
const SkDescriptor** desc, size_t vertexStride,
- GrColor color, SkScalar transX,
- SkScalar transY,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
+ GrColor color,
void** vertices, size_t* byteCount, int* glyphCount) {
Run& run = fRuns[runIndex];
Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex];
uint64_t currentAtlasGen = fontCache->atlasGeneration(info.maskFormat());
+ // Compute translation if any
+ SkScalar transX, transY;
+ info.computeTranslation(viewMatrix, x, y, &transX, &transY);
+
// 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
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 0f36fe355a..1934a8dc57 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -109,9 +109,6 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
cacheBlob.reset(SkSafeRef(cache->find(key)));
}
- SkScalar transX = 0.f;
- SkScalar transY = 0.f;
-
// Though for the time being runs in the textblob can override the paint, they only touch font
// info.
GrPaint grPaint;
@@ -120,8 +117,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
}
if (cacheBlob) {
- if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColor(), blurRec,
- viewMatrix, x, y)) {
+ if (cacheBlob->mustRegenerate(skPaint, grPaint.getColor(), blurRec, viewMatrix, x, y)) {
// We have to remake the blob because changes may invalidate our masks.
// TODO we could probably get away reuse most of the time if the pointer is unique,
// but we'd have to clear the subrun information
@@ -160,7 +156,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
}
cacheBlob->flushCached(context, dc, blob, props, fDistanceAdjustTable, skPaint,
- grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY);
+ grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y);
}
void GrAtlasTextContext::RegenerateTextBlob(GrAtlasTextBlob* cacheBlob,
@@ -321,7 +317,7 @@ void GrAtlasTextContext::drawText(GrContext* context,
viewMatrix, props,
text, byteLength, x, y));
blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
- clip, regionClipBounds);
+ clip, viewMatrix, regionClipBounds, x, y);
return;
}
@@ -351,7 +347,7 @@ void GrAtlasTextContext::drawPosText(GrContext* context,
pos, scalarsPerPosition,
offset));
blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint,
- clip, regionClipBounds);
+ clip, viewMatrix, regionClipBounds, offset.fX, offset.fY);
return;
}
@@ -408,9 +404,9 @@ DRAW_BATCH_TEST_DEFINE(TextBlobBatch) {
// We'd like to be able to test this with random translations, but currently the vertex
// bounds and vertices will get out of sync
- SkScalar transX = 0.f;//SkIntToScalar(random->nextU());
- SkScalar transY = 0.f;//SkIntToScalar(random->nextU());
- return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint,
+ SkScalar x = 0.f;//SkIntToScalar(random->nextU());
+ SkScalar y = 0.f;//SkIntToScalar(random->nextU());
+ return blob->test_createBatch(textLen, 0, 0, viewMatrix, x, y, color, skPaint,
gSurfaceProps, gTextContext->dfAdjustTable(),
context->getBatchFontCache());
}