| Index: src/core/SkPaint.cpp
|
| diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
|
| index 9b6b88386339d24a41d3c2f2bd5a3db4115c0dc5..e781cd45a7893c209336ea49c6beb45c3c831267 100644
|
| --- a/src/core/SkPaint.cpp
|
| +++ b/src/core/SkPaint.cpp
|
| @@ -30,6 +30,7 @@
|
| #include "SkStroke.h"
|
| #include "SkTextFormatParams.h"
|
| #include "SkTextToPathIter.h"
|
| +#include "SkTLazy.h"
|
| #include "SkTypeface.h"
|
| #include "SkXfermode.h"
|
|
|
| @@ -425,6 +426,37 @@ SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| +static SkScalar mag2(SkScalar x, SkScalar y) {
|
| + return x * x + y * y;
|
| +}
|
| +
|
| +static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
|
| + return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
|
| + ||
|
| + mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
|
| +}
|
| +
|
| +bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
|
| + SkASSERT(!ctm.hasPerspective());
|
| + SkASSERT(!textM.hasPerspective());
|
| +
|
| + SkMatrix matrix;
|
| + matrix.setConcat(ctm, textM);
|
| + return tooBig(matrix, MaxCacheSize2());
|
| +}
|
| +
|
| +bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
|
| + SkMatrix textM;
|
| + return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
|
| +}
|
| +
|
| +bool SkPaint::tooBigToUseCache() const {
|
| + SkMatrix textM;
|
| + return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +
|
| #include "SkGlyphCache.h"
|
| #include "SkUtils.h"
|
|
|
| @@ -915,33 +947,51 @@ SkDrawCacheProc SkPaint::getDrawCacheProc() const {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -class SkAutoRestorePaintTextSizeAndFrame {
|
| +#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \
|
| +SkPaint::kDevKernText_Flag | \
|
| +SkPaint::kLinearText_Flag | \
|
| +SkPaint::kLCDRenderText_Flag | \
|
| +SkPaint::kEmbeddedBitmapText_Flag | \
|
| +SkPaint::kAutoHinting_Flag | \
|
| +SkPaint::kGenA8FromLCD_Flag )
|
| +
|
| +SkScalar SkPaint::setupForAsPaths() {
|
| + uint32_t flags = this->getFlags();
|
| + // clear the flags we don't care about
|
| + flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
|
| + // set the flags we do care about
|
| + flags |= SkPaint::kSubpixelText_Flag;
|
| +
|
| + this->setFlags(flags);
|
| + this->setHinting(SkPaint::kNo_Hinting);
|
| +
|
| + SkScalar textSize = fTextSize;
|
| + this->setTextSize(kCanonicalTextSizeForPaths);
|
| + return textSize / kCanonicalTextSizeForPaths;
|
| +}
|
| +
|
| +class SkCanonicalizePaint {
|
| public:
|
| - SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
|
| - : fPaint((SkPaint*)paint) {
|
| -#ifdef SK_BUILD_FOR_ANDROID
|
| - fGenerationID = fPaint->getGenerationID();
|
| -#endif
|
| - fTextSize = paint->getTextSize();
|
| - fStyle = paint->getStyle();
|
| - fPaint->setStyle(SkPaint::kFill_Style);
|
| + SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
|
| + if (paint.isLinearText() || paint.tooBigToUseCache()) {
|
| + SkPaint* p = fLazy.set(paint);
|
| + fScale = p->setupForAsPaths();
|
| + fPaint = p;
|
| + }
|
| }
|
|
|
| - ~SkAutoRestorePaintTextSizeAndFrame() {
|
| - fPaint->setStyle(fStyle);
|
| - fPaint->setTextSize(fTextSize);
|
| -#ifdef SK_BUILD_FOR_ANDROID
|
| - fPaint->setGenerationID(fGenerationID);
|
| -#endif
|
| - }
|
| + const SkPaint& getPaint() const { return *fPaint; }
|
| +
|
| + /**
|
| + * Returns 0 if the paint was unmodified, or the scale factor need to
|
| + * the original textSize
|
| + */
|
| + SkScalar getScale() const { return fScale; }
|
|
|
| private:
|
| - SkPaint* fPaint;
|
| - SkScalar fTextSize;
|
| - SkPaint::Style fStyle;
|
| -#ifdef SK_BUILD_FOR_ANDROID
|
| - uint32_t fGenerationID;
|
| -#endif
|
| + const SkPaint* fPaint;
|
| + SkScalar fScale;
|
| + SkTLazy<SkPaint> fLazy;
|
| };
|
|
|
| static void set_bounds(const SkGlyph& g, SkRect* bounds) {
|
| @@ -1069,14 +1119,9 @@ SkScalar SkPaint::measureText(const void* textData, size_t length,
|
| const char* text = (const char*)textData;
|
| SkASSERT(text != NULL || length == 0);
|
|
|
| - SkScalar scale = 0;
|
| - SkAutoRestorePaintTextSizeAndFrame restore(this);
|
| -
|
| - if (this->isLinearText()) {
|
| - scale = fTextSize / kCanonicalTextSizeForPaths;
|
| - // this gets restored by restore
|
| - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
|
| - }
|
| + SkCanonicalizePaint canon(*this);
|
| + const SkPaint& paint = canon.getPaint();
|
| + SkScalar scale = canon.getScale();
|
|
|
| SkMatrix zoomMatrix, *zoomPtr = NULL;
|
| if (zoom) {
|
| @@ -1084,7 +1129,7 @@ SkScalar SkPaint::measureText(const void* textData, size_t length,
|
| zoomPtr = &zoomMatrix;
|
| }
|
|
|
| - SkAutoGlyphCache autoCache(*this, NULL, zoomPtr);
|
| + SkAutoGlyphCache autoCache(paint, NULL, zoomPtr);
|
| SkGlyphCache* cache = autoCache.getCache();
|
|
|
| SkScalar width = 0;
|
| @@ -1092,7 +1137,7 @@ SkScalar SkPaint::measureText(const void* textData, size_t length,
|
| if (length > 0) {
|
| int tempCount;
|
|
|
| - width = this->measure_text(cache, text, length, &tempCount, bounds);
|
| + width = paint.measure_text(cache, text, length, &tempCount, bounds);
|
| if (scale) {
|
| width = SkScalarMul(width, scale);
|
| if (bounds) {
|
| @@ -1153,23 +1198,22 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
|
| SkASSERT(textD != NULL);
|
| const char* text = (const char*)textD;
|
|
|
| - SkScalar scale = 0;
|
| - SkAutoRestorePaintTextSizeAndFrame restore(this);
|
| + SkCanonicalizePaint canon(*this);
|
| + const SkPaint& paint = canon.getPaint();
|
| + SkScalar scale = canon.getScale();
|
|
|
| - if (this->isLinearText()) {
|
| - scale = fTextSize / kCanonicalTextSizeForPaths;
|
| - maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
|
| - // this gets restored by restore
|
| - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
|
| + // adjust max in case we changed the textSize in paint
|
| + if (scale) {
|
| + maxWidth /= scale;
|
| }
|
|
|
| - SkAutoGlyphCache autoCache(*this, NULL, NULL);
|
| + SkAutoGlyphCache autoCache(paint, NULL, NULL);
|
| SkGlyphCache* cache = autoCache.getCache();
|
|
|
| - SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
|
| + SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
|
| const char* stop;
|
| SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
|
| - const int xyIndex = this->isVerticalText() ? 1 : 0;
|
| + const int xyIndex = paint.isVerticalText() ? 1 : 0;
|
| // use 64bits for our accumulator, to avoid overflowing 16.16
|
| Sk48Dot16 max = SkScalarToFixed(maxWidth);
|
| Sk48Dot16 width = 0;
|
| @@ -1227,15 +1271,10 @@ static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
|
| }
|
|
|
| SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
|
| - SkScalar scale = 0;
|
| - SkAutoRestorePaintTextSizeAndFrame restore(this);
|
| -
|
| - if (this->isLinearText()) {
|
| - scale = fTextSize / kCanonicalTextSizeForPaths;
|
| - // this gets restored by restore
|
| - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
|
| - }
|
| -
|
| + SkCanonicalizePaint canon(*this);
|
| + const SkPaint& paint = canon.getPaint();
|
| + SkScalar scale = canon.getScale();
|
| +
|
| SkMatrix zoomMatrix, *zoomPtr = NULL;
|
| if (zoom) {
|
| zoomMatrix.setScale(zoom, zoom);
|
| @@ -1247,7 +1286,7 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
|
| metrics = &storage;
|
| }
|
|
|
| - this->descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
|
| + paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
|
|
|
| if (scale) {
|
| metrics->fTop = SkScalarMul(metrics->fTop, scale);
|
| @@ -1284,25 +1323,20 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength,
|
| return this->countText(textData, byteLength);
|
| }
|
|
|
| - SkAutoRestorePaintTextSizeAndFrame restore(this);
|
| - SkScalar scale = 0;
|
| -
|
| - if (this->isLinearText()) {
|
| - scale = fTextSize / kCanonicalTextSizeForPaths;
|
| - // this gets restored by restore
|
| - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
|
| - }
|
| + SkCanonicalizePaint canon(*this);
|
| + const SkPaint& paint = canon.getPaint();
|
| + SkScalar scale = canon.getScale();
|
|
|
| - SkAutoGlyphCache autoCache(*this, NULL, NULL);
|
| + SkAutoGlyphCache autoCache(paint, NULL, NULL);
|
| SkGlyphCache* cache = autoCache.getCache();
|
| SkMeasureCacheProc glyphCacheProc;
|
| - glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
|
| + glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
|
| NULL != bounds);
|
|
|
| const char* text = (const char*)textData;
|
| const char* stop = text + byteLength;
|
| int count = 0;
|
| - const int xyIndex = this->isVerticalText() ? 1 : 0;
|
| + const int xyIndex = paint.isVerticalText() ? 1 : 0;
|
|
|
| if (this->isDevKernText()) {
|
| // we adjust the widths returned here through auto-kerning
|
|
|