| Index: src/gpu/GrAtlasTextContext.cpp
|
| diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
|
| index b5e8693e8db2e44f2191528f02da09d035500529..8c162220f9e2ec98d31e50e2a8c83cd6c57cc976 100644
|
| --- a/src/gpu/GrAtlasTextContext.cpp
|
| +++ b/src/gpu/GrAtlasTextContext.cpp
|
| @@ -287,15 +287,14 @@ bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr
|
| return true;
|
| }
|
|
|
| - // TODO distance fields can handle many of these conditions
|
| - if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
|
| - blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
|
| - blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
|
| - blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
|
| - return true;
|
| - }
|
| -
|
| if (blob.hasBitmap()) {
|
| + if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
|
| + blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
|
| + blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
|
| + blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
|
| + return true;
|
| + }
|
| +
|
| // We can update the positions in the cachedtextblobs without regenerating the whole blob,
|
| // but only for integer translations.
|
| // This cool bit of math will determine the necessary translation to apply to the already
|
| @@ -328,9 +327,18 @@ bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr
|
| (*outTransX) = transX;
|
| (*outTransY) = transY;
|
| } else {
|
| - // blob.hasDistanceField()
|
| - // TODO figure out the regen formula
|
| - return true;
|
| + SkASSERT(blob.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 = blob.fViewMatrix.getMaxScale();
|
| + SkScalar scaleAdjust = newMaxScale / oldMaxScale;
|
| + if (scaleAdjust < blob.fMaxMinScale || scaleAdjust > blob.fMinMaxScale) {
|
| + return true;
|
| + }
|
| +
|
| + (*outTransX) = x - blob.fX;
|
| + (*outTransY) = y - blob.fY;
|
| }
|
|
|
| return false;
|
| @@ -503,7 +511,7 @@ void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
|
| cacheBlob->setHasDistanceField();
|
| SkPaint dfPaint = runPaint;
|
| SkScalar textRatio;
|
| - this->initDistanceFieldPaint(&dfPaint, &textRatio, viewMatrix);
|
| + this->initDistanceFieldPaint(cacheBlob, &dfPaint, &textRatio, viewMatrix);
|
| Run& runIdx = cacheBlob->fRuns[run];
|
| PerSubRunInfo& subRun = runIdx.fSubRunInfo.back();
|
| subRun.fUseLCDText = runPaint.isLCDRenderText();
|
| @@ -581,7 +589,9 @@ void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
|
| }
|
| }
|
|
|
| -inline void GrAtlasTextContext::initDistanceFieldPaint(SkPaint* skPaint, SkScalar* textRatio,
|
| +inline void GrAtlasTextContext::initDistanceFieldPaint(BitmapTextBlob* blob,
|
| + SkPaint* skPaint,
|
| + SkScalar* textRatio,
|
| const SkMatrix& viewMatrix) {
|
| // getMaxScale doesn't support perspective, so neither do we at the moment
|
| SkASSERT(!viewMatrix.hasPerspective());
|
| @@ -595,17 +605,37 @@ inline void GrAtlasTextContext::initDistanceFieldPaint(SkPaint* skPaint, SkScala
|
| scaledTextSize *= maxScale;
|
| }
|
|
|
| + // We have three sizes of distance field text, and within each size 'bucket' there is a floor
|
| + // and ceiling. A scale outside of this range would require regenerating the distance fields
|
| + SkScalar dfMaskScaleFloor;
|
| + SkScalar dfMaskScaleCeil;
|
| if (scaledTextSize <= kSmallDFFontLimit) {
|
| + dfMaskScaleFloor = kMinDFFontSize;
|
| + dfMaskScaleCeil = kMediumDFFontLimit;
|
| *textRatio = textSize / kSmallDFFontSize;
|
| skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize));
|
| } else if (scaledTextSize <= kMediumDFFontLimit) {
|
| + dfMaskScaleFloor = kMediumDFFontLimit;
|
| + dfMaskScaleCeil = kLargeDFFontSize;
|
| *textRatio = textSize / kMediumDFFontSize;
|
| skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize));
|
| } else {
|
| + dfMaskScaleFloor = kLargeDFFontSize;
|
| + dfMaskScaleCeil = 2 * kLargeDFFontSize;
|
| *textRatio = textSize / kLargeDFFontSize;
|
| skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize));
|
| }
|
|
|
| + // Because there can be multiple runs in the blob, we want the overall maxMinScale, and
|
| + // minMaxScale to make regeneration decisions. Specifically, we want the maximum minimum scale
|
| + // we can tolerate before we'd drop to a lower mip size, and the minimum maximum scale we can
|
| + // tolerate before we'd have to move to a large mip size. When we actually test these values
|
| + // we look at the delta in scale between the new viewmatrix and the old viewmatrix, and test
|
| + // against these values to decide if we can reuse or not(ie, will a given scale change our mip
|
| + // level)
|
| + blob->fMaxMinScale = SkMaxScalar(dfMaskScaleFloor / scaledTextSize, blob->fMaxMinScale);
|
| + blob->fMinMaxScale = SkMinScalar(dfMaskScaleCeil / scaledTextSize, blob->fMinMaxScale);
|
| +
|
| skPaint->setLCDRenderText(false);
|
| skPaint->setAutohinted(false);
|
| skPaint->setHinting(SkPaint::kNormal_Hinting);
|
| @@ -645,7 +675,7 @@ GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint,
|
| BitmapTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize);
|
|
|
| *dfPaint = origPaint;
|
| - this->initDistanceFieldPaint(dfPaint, textRatio, viewMatrix);
|
| + this->initDistanceFieldPaint(blob, dfPaint, textRatio, viewMatrix);
|
| blob->fViewMatrix = viewMatrix;
|
| Run& run = blob->fRuns[0];
|
| PerSubRunInfo& subRun = run.fSubRunInfo.back();
|
|
|