Chromium Code Reviews| Index: src/gpu/GrAtlasTextContext.cpp |
| diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp |
| index 72650770a6075ab046daf6407cfd9b7573368856..fff51ceb040a37821c75ab078f7e3d21ac7e10a9 100644 |
| --- a/src/gpu/GrAtlasTextContext.cpp |
| +++ b/src/gpu/GrAtlasTextContext.cpp |
| @@ -282,20 +282,18 @@ bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr |
| } |
| // Mixed blobs can't be regenerated at this point |
| - SkASSERT(blob.fHasBitmap || blob.fHasDistanceField); |
| if (blob.fHasBitmap && blob.fHasDistanceField) { |
| 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.fHasBitmap) { |
| + 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 |
| @@ -329,8 +327,17 @@ bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr |
| (*outTransY) = transY; |
| } else { |
| // blob.fHasDistanceFields |
| - // TODO figure out the regen formula |
| - return true; |
| + // 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 +510,7 @@ void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, |
| cacheBlob->fHasDistanceField = true; |
| 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 +588,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 +604,32 @@ 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 |
|
jvanverth1
2015/04/21 15:29:47
A little more detail in a comment on how this work
|
| + 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 +669,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(); |