| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
| 8 | 8 |
| 9 #include "GrAtlas.h" | 9 #include "GrAtlas.h" |
| 10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); | 44 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); |
| 45 | 45 |
| 46 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof
(SkIPoint16); | 46 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof
(SkIPoint16); |
| 47 | 47 |
| 48 static const int kMinDFFontSize = 18; | 48 static const int kMinDFFontSize = 18; |
| 49 static const int kSmallDFFontSize = 32; | 49 static const int kSmallDFFontSize = 32; |
| 50 static const int kSmallDFFontLimit = 32; | 50 static const int kSmallDFFontLimit = 32; |
| 51 static const int kMediumDFFontSize = 72; | 51 static const int kMediumDFFontSize = 72; |
| 52 static const int kMediumDFFontLimit = 72; | 52 static const int kMediumDFFontLimit = 72; |
| 53 static const int kLargeDFFontSize = 162; | 53 static const int kLargeDFFontSize = 162; |
| 54 static const int kLargeDFFontLimit = 2 * kLargeDFFontSize; |
| 54 | 55 |
| 55 SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;) | 56 SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;) |
| 56 static const int kDistanceAdjustLumShift = 5; | 57 static const int kDistanceAdjustLumShift = 5; |
| 57 | 58 |
| 58 static const int kVerticesPerGlyph = 4; | 59 static const int kVerticesPerGlyph = 4; |
| 59 static const int kIndicesPerGlyph = 6; | 60 static const int kIndicesPerGlyph = 6; |
| 60 | 61 |
| 61 static size_t get_vertex_stride(GrMaskFormat maskFormat) { | 62 static size_t get_vertex_stride(GrMaskFormat maskFormat) { |
| 62 switch (maskFormat) { | 63 switch (maskFormat) { |
| 63 case kA8_GrMaskFormat: | 64 case kA8_GrMaskFormat: |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 // bounds above on translation | 320 // bounds above on translation |
| 320 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX)); | 321 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX)); |
| 321 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY)); | 322 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY)); |
| 322 if (blob.fTotalXError > kMinDiscernableTranslation || | 323 if (blob.fTotalXError > kMinDiscernableTranslation || |
| 323 blob.fTotalYError > kMinDiscernableTranslation) { | 324 blob.fTotalYError > kMinDiscernableTranslation) { |
| 324 SkDebugf("Exceeding error threshold for bitmap text translation"); | 325 SkDebugf("Exceeding error threshold for bitmap text translation"); |
| 325 } | 326 } |
| 326 #endif | 327 #endif |
| 327 (*outTransX) = transX; | 328 (*outTransX) = transX; |
| 328 (*outTransY) = transY; | 329 (*outTransY) = transY; |
| 329 } else { | 330 } else if (blob.hasDistanceField()) { |
| 330 SkASSERT(blob.hasDistanceField()); | |
| 331 // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would resul
t in a different | 331 // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would resul
t in a different |
| 332 // distance field being generated, so we have to regenerate in those cas
es | 332 // distance field being generated, so we have to regenerate in those cas
es |
| 333 SkScalar newMaxScale = viewMatrix.getMaxScale(); | 333 SkScalar newMaxScale = viewMatrix.getMaxScale(); |
| 334 SkScalar oldMaxScale = blob.fViewMatrix.getMaxScale(); | 334 SkScalar oldMaxScale = blob.fViewMatrix.getMaxScale(); |
| 335 SkScalar scaleAdjust = newMaxScale / oldMaxScale; | 335 SkScalar scaleAdjust = newMaxScale / oldMaxScale; |
| 336 if (scaleAdjust < blob.fMaxMinScale || scaleAdjust > blob.fMinMaxScale)
{ | 336 if (scaleAdjust < blob.fMaxMinScale || scaleAdjust > blob.fMinMaxScale)
{ |
| 337 return true; | 337 return true; |
| 338 } | 338 } |
| 339 | 339 |
| 340 (*outTransX) = x - blob.fX; | 340 (*outTransX) = x - blob.fX; |
| 341 (*outTransY) = y - blob.fY; | 341 (*outTransY) = y - blob.fY; |
| 342 } | 342 } |
| 343 // It is possible that a blob has neither distanceField nor bitmaptext. Thi
s is in the case |
| 344 // when all of the runs inside the blob are drawn as paths. In this case, w
e always regenerate |
| 345 // the blob anyways at flush time, so no need to regenerate explicitly |
| 343 | 346 |
| 344 return false; | 347 return false; |
| 345 } | 348 } |
| 346 | 349 |
| 347 | 350 |
| 348 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, | 351 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, |
| 349 const SkPaint& skPaint, | 352 const SkPaint& skPaint, |
| 350 const SkMatrix* viewMatrix, | 353 const SkMatrix* viewMatrix, |
| 351 bool noGamma) { | 354 bool noGamma) { |
| 352 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, vi
ewMatrix, noGamma); | 355 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, vi
ewMatrix, noGamma); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 const SkMatrix& viewMatr
ix) { | 437 const SkMatrix& viewMatr
ix) { |
| 435 // TODO: support perspective (need getMaxScale replacement) | 438 // TODO: support perspective (need getMaxScale replacement) |
| 436 if (viewMatrix.hasPerspective()) { | 439 if (viewMatrix.hasPerspective()) { |
| 437 return false; | 440 return false; |
| 438 } | 441 } |
| 439 | 442 |
| 440 SkScalar maxScale = viewMatrix.getMaxScale(); | 443 SkScalar maxScale = viewMatrix.getMaxScale(); |
| 441 SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); | 444 SkScalar scaledTextSize = maxScale*skPaint.getTextSize(); |
| 442 // Hinted text looks far better at small resolutions | 445 // Hinted text looks far better at small resolutions |
| 443 // Scaling up beyond 2x yields undesireable artifacts | 446 // Scaling up beyond 2x yields undesireable artifacts |
| 444 if (scaledTextSize < kMinDFFontSize || scaledTextSize > 2 * kLargeDFFontSize
) { | 447 if (scaledTextSize < kMinDFFontSize || scaledTextSize > kLargeDFFontLimit) { |
| 445 return false; | 448 return false; |
| 446 } | 449 } |
| 447 | 450 |
| 448 if (!fEnableDFRendering && !skPaint.isDistanceFieldTextTEMP() && | 451 if (!fEnableDFRendering && !skPaint.isDistanceFieldTextTEMP() && |
| 449 scaledTextSize < kLargeDFFontSize) { | 452 scaledTextSize < kLargeDFFontSize) { |
| 450 return false; | 453 return false; |
| 451 } | 454 } |
| 452 | 455 |
| 453 // rasterizers and mask filters modify alpha, which doesn't | 456 // rasterizers and mask filters modify alpha, which doesn't |
| 454 // translate well to distance | 457 // translate well to distance |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { | 607 if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) { |
| 605 scaledTextSize *= maxScale; | 608 scaledTextSize *= maxScale; |
| 606 } | 609 } |
| 607 | 610 |
| 608 // We have three sizes of distance field text, and within each size 'bucket'
there is a floor | 611 // We have three sizes of distance field text, and within each size 'bucket'
there is a floor |
| 609 // and ceiling. A scale outside of this range would require regenerating th
e distance fields | 612 // and ceiling. A scale outside of this range would require regenerating th
e distance fields |
| 610 SkScalar dfMaskScaleFloor; | 613 SkScalar dfMaskScaleFloor; |
| 611 SkScalar dfMaskScaleCeil; | 614 SkScalar dfMaskScaleCeil; |
| 612 if (scaledTextSize <= kSmallDFFontLimit) { | 615 if (scaledTextSize <= kSmallDFFontLimit) { |
| 613 dfMaskScaleFloor = kMinDFFontSize; | 616 dfMaskScaleFloor = kMinDFFontSize; |
| 614 dfMaskScaleCeil = kMediumDFFontLimit; | 617 dfMaskScaleCeil = kSmallDFFontLimit; |
| 615 *textRatio = textSize / kSmallDFFontSize; | 618 *textRatio = textSize / kSmallDFFontSize; |
| 616 skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); | 619 skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); |
| 617 } else if (scaledTextSize <= kMediumDFFontLimit) { | 620 } else if (scaledTextSize <= kMediumDFFontLimit) { |
| 618 dfMaskScaleFloor = kMediumDFFontLimit; | 621 dfMaskScaleFloor = kSmallDFFontLimit; |
| 619 dfMaskScaleCeil = kLargeDFFontSize; | 622 dfMaskScaleCeil = kMediumDFFontLimit; |
| 620 *textRatio = textSize / kMediumDFFontSize; | 623 *textRatio = textSize / kMediumDFFontSize; |
| 621 skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); | 624 skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); |
| 622 } else { | 625 } else { |
| 623 dfMaskScaleFloor = kLargeDFFontSize; | 626 dfMaskScaleFloor = kMediumDFFontLimit; |
| 624 dfMaskScaleCeil = 2 * kLargeDFFontSize; | 627 dfMaskScaleCeil = kLargeDFFontLimit; |
| 625 *textRatio = textSize / kLargeDFFontSize; | 628 *textRatio = textSize / kLargeDFFontSize; |
| 626 skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); | 629 skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); |
| 627 } | 630 } |
| 628 | 631 |
| 629 // Because there can be multiple runs in the blob, we want the overall maxMi
nScale, and | 632 // Because there can be multiple runs in the blob, we want the overall maxMi
nScale, and |
| 630 // minMaxScale to make regeneration decisions. Specifically, we want the ma
ximum minimum scale | 633 // minMaxScale to make regeneration decisions. Specifically, we want the ma
ximum minimum scale |
| 631 // we can tolerate before we'd drop to a lower mip size, and the minimum max
imum scale we can | 634 // we can tolerate before we'd drop to a lower mip size, and the minimum max
imum scale we can |
| 632 // tolerate before we'd have to move to a large mip size. When we actually
test these values | 635 // tolerate before we'd have to move to a large mip size. When we actually
test these values |
| 633 // we look at the delta in scale between the new viewmatrix and the old view
matrix, and test | 636 // we look at the delta in scale between the new viewmatrix and the old view
matrix, and test |
| 634 // against these values to decide if we can reuse or not(ie, will a given sc
ale change our mip | 637 // against these values to decide if we can reuse or not(ie, will a given sc
ale change our mip |
| 635 // level) | 638 // level) |
| 639 SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScale
Ceil); |
| 636 blob->fMaxMinScale = SkMaxScalar(dfMaskScaleFloor / scaledTextSize, blob->fM
axMinScale); | 640 blob->fMaxMinScale = SkMaxScalar(dfMaskScaleFloor / scaledTextSize, blob->fM
axMinScale); |
| 637 blob->fMinMaxScale = SkMinScalar(dfMaskScaleCeil / scaledTextSize, blob->fMi
nMaxScale); | 641 blob->fMinMaxScale = SkMinScalar(dfMaskScaleCeil / scaledTextSize, blob->fMi
nMaxScale); |
| 638 | 642 |
| 639 skPaint->setLCDRenderText(false); | 643 skPaint->setLCDRenderText(false); |
| 640 skPaint->setAutohinted(false); | 644 skPaint->setAutohinted(false); |
| 641 skPaint->setHinting(SkPaint::kNormal_Hinting); | 645 skPaint->setHinting(SkPaint::kNormal_Hinting); |
| 642 skPaint->setSubpixelText(true); | 646 skPaint->setSubpixelText(true); |
| 643 } | 647 } |
| 644 | 648 |
| 645 inline void GrAtlasTextContext::fallbackDrawPosText(BitmapTextBlob* blob, | 649 inline void GrAtlasTextContext::fallbackDrawPosText(BitmapTextBlob* blob, |
| (...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2160 pipelineBuilder.setFromPaint(grPaint, rt, clip); | 2164 pipelineBuilder.setFromPaint(grPaint, rt, clip); |
| 2161 | 2165 |
| 2162 GrColor color = grPaint.getColor(); | 2166 GrColor color = grPaint.getColor(); |
| 2163 for (int run = 0; run < cacheBlob->fRunCount; run++) { | 2167 for (int run = 0; run < cacheBlob->fRunCount; run++) { |
| 2164 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, sk
Paint); | 2168 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, 0, 0, sk
Paint); |
| 2165 } | 2169 } |
| 2166 | 2170 |
| 2167 // Now flush big glyphs | 2171 // Now flush big glyphs |
| 2168 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); | 2172 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); |
| 2169 } | 2173 } |
| OLD | NEW |