gfx/skia/trunk/src/core/SkPaint.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     2 /*
     3  * Copyright 2006 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 #include "SkPaint.h"
    10 #include "SkAnnotation.h"
    11 #include "SkAutoKern.h"
    12 #include "SkColorFilter.h"
    13 #include "SkData.h"
    14 #include "SkDeviceProperties.h"
    15 #include "SkFontDescriptor.h"
    16 #include "SkFontHost.h"
    17 #include "SkGlyphCache.h"
    18 #include "SkImageFilter.h"
    19 #include "SkMaskFilter.h"
    20 #include "SkMaskGamma.h"
    21 #include "SkReadBuffer.h"
    22 #include "SkWriteBuffer.h"
    23 #include "SkPaintDefaults.h"
    24 #include "SkPaintOptionsAndroid.h"
    25 #include "SkPathEffect.h"
    26 #include "SkRasterizer.h"
    27 #include "SkScalar.h"
    28 #include "SkScalerContext.h"
    29 #include "SkShader.h"
    30 #include "SkStringUtils.h"
    31 #include "SkStroke.h"
    32 #include "SkTextFormatParams.h"
    33 #include "SkTextToPathIter.h"
    34 #include "SkTLazy.h"
    35 #include "SkTypeface.h"
    36 #include "SkXfermode.h"
    38 enum {
    39     kColor_DirtyBit               = 1 <<  0,
    40     kBitfields_DirtyBit           = 1 <<  1,
    41     kTextSize_DirtyBit            = 1 <<  2,
    42     kTextScaleX_DirtyBit          = 1 <<  3,
    43     kTextSkewX_DirtyBit           = 1 <<  4,
    44     kStrokeWidth_DirtyBit         = 1 <<  5,
    45     kStrokeMiter_DirtyBit         = 1 <<  6,
    46     kPathEffect_DirtyBit          = 1 <<  7,
    47     kShader_DirtyBit              = 1 <<  8,
    48     kXfermode_DirtyBit            = 1 <<  9,
    49     kMaskFilter_DirtyBit          = 1 << 10,
    50     kColorFilter_DirtyBit         = 1 << 11,
    51     kRasterizer_DirtyBit          = 1 << 12,
    52     kLooper_DirtyBit              = 1 << 13,
    53     kImageFilter_DirtyBit         = 1 << 14,
    54     kTypeface_DirtyBit            = 1 << 15,
    55     kAnnotation_DirtyBit          = 1 << 16,
    56     kPaintOptionsAndroid_DirtyBit = 1 << 17,
    57 };
    59 // define this to get a printf for out-of-range parameter in setters
    60 // e.g. setTextSize(-1)
    61 //#define SK_REPORT_API_RANGE_CHECK
    63 #ifdef SK_BUILD_FOR_ANDROID
    64 #define GEN_ID_INC                  fGenerationID++
    65 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
    66 #else
    67 #define GEN_ID_INC
    68 #define GEN_ID_INC_EVAL(expression)
    69 #endif
    71 SkPaint::SkPaint() {
    72     // since we may have padding, we zero everything so that our memcmp() call
    73     // in operator== will work correctly.
    74     // with this, we can skip 0 and null individual initializations
    75     sk_bzero(this, sizeof(*this));
    77 #if 0   // not needed with the bzero call above
    78     fTypeface    = NULL;
    79     fTextSkewX   = 0;
    80     fPathEffect  = NULL;
    81     fShader      = NULL;
    82     fXfermode    = NULL;
    83     fMaskFilter  = NULL;
    84     fColorFilter = NULL;
    85     fRasterizer  = NULL;
    86     fLooper      = NULL;
    87     fImageFilter = NULL;
    88     fAnnotation  = NULL;
    89     fWidth       = 0;
    90     fDirtyBits   = 0;
    91 #endif
    93     fTextSize   = SkPaintDefaults_TextSize;
    94     fTextScaleX = SK_Scalar1;
    95     fColor      = SK_ColorBLACK;
    96     fMiterLimit = SkPaintDefaults_MiterLimit;
    97     fFlags      = SkPaintDefaults_Flags;
    98     fCapType    = kDefault_Cap;
    99     fJoinType   = kDefault_Join;
   100     fTextAlign  = kLeft_Align;
   101     fStyle      = kFill_Style;
   102     fTextEncoding = kUTF8_TextEncoding;
   103     fHinting    = SkPaintDefaults_Hinting;
   104 #ifdef SK_BUILD_FOR_ANDROID
   105     new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
   106     fGenerationID = 0;
   107 #endif
   108 }
   110 SkPaint::SkPaint(const SkPaint& src) {
   111     memcpy(this, &src, sizeof(src));
   113     SkSafeRef(fTypeface);
   114     SkSafeRef(fPathEffect);
   115     SkSafeRef(fShader);
   116     SkSafeRef(fXfermode);
   117     SkSafeRef(fMaskFilter);
   118     SkSafeRef(fColorFilter);
   119     SkSafeRef(fRasterizer);
   120     SkSafeRef(fLooper);
   121     SkSafeRef(fImageFilter);
   122     SkSafeRef(fAnnotation);
   124 #ifdef SK_BUILD_FOR_ANDROID
   125     new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
   126 #endif
   127 }
   129 SkPaint::~SkPaint() {
   130     SkSafeUnref(fTypeface);
   131     SkSafeUnref(fPathEffect);
   132     SkSafeUnref(fShader);
   133     SkSafeUnref(fXfermode);
   134     SkSafeUnref(fMaskFilter);
   135     SkSafeUnref(fColorFilter);
   136     SkSafeUnref(fRasterizer);
   137     SkSafeUnref(fLooper);
   138     SkSafeUnref(fImageFilter);
   139     SkSafeUnref(fAnnotation);
   140 }
   142 SkPaint& SkPaint::operator=(const SkPaint& src) {
   143     SkASSERT(&src);
   145     SkSafeRef(src.fTypeface);
   146     SkSafeRef(src.fPathEffect);
   147     SkSafeRef(src.fShader);
   148     SkSafeRef(src.fXfermode);
   149     SkSafeRef(src.fMaskFilter);
   150     SkSafeRef(src.fColorFilter);
   151     SkSafeRef(src.fRasterizer);
   152     SkSafeRef(src.fLooper);
   153     SkSafeRef(src.fImageFilter);
   154     SkSafeRef(src.fAnnotation);
   156     SkSafeUnref(fTypeface);
   157     SkSafeUnref(fPathEffect);
   158     SkSafeUnref(fShader);
   159     SkSafeUnref(fXfermode);
   160     SkSafeUnref(fMaskFilter);
   161     SkSafeUnref(fColorFilter);
   162     SkSafeUnref(fRasterizer);
   163     SkSafeUnref(fLooper);
   164     SkSafeUnref(fImageFilter);
   165     SkSafeUnref(fAnnotation);
   167 #ifdef SK_BUILD_FOR_ANDROID
   168     fPaintOptionsAndroid.~SkPaintOptionsAndroid();
   170     uint32_t oldGenerationID = fGenerationID;
   171 #endif
   172     memcpy(this, &src, sizeof(src));
   173 #ifdef SK_BUILD_FOR_ANDROID
   174     fGenerationID = oldGenerationID + 1;
   176     new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
   177 #endif
   179     return *this;
   180 }
   182 bool operator==(const SkPaint& a, const SkPaint& b) {
   183 #ifdef SK_BUILD_FOR_ANDROID
   184     //assumes that fGenerationID is the last field in the struct
   185     return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
   186 #else
   187     return !memcmp(&a, &b, sizeof(a));
   188 #endif
   189 }
   191 void SkPaint::reset() {
   192     SkPaint init;
   194 #ifdef SK_BUILD_FOR_ANDROID
   195     uint32_t oldGenerationID = fGenerationID;
   196 #endif
   197     *this = init;
   198 #ifdef SK_BUILD_FOR_ANDROID
   199     fGenerationID = oldGenerationID + 1;
   200 #endif
   201 }
   203 #ifdef SK_BUILD_FOR_ANDROID
   204 uint32_t SkPaint::getGenerationID() const {
   205     return fGenerationID;
   206 }
   208 void SkPaint::setGenerationID(uint32_t generationID) {
   209     fGenerationID = generationID;
   210 }
   212 unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
   213     SkAutoGlyphCache autoCache(*this, NULL, NULL);
   214     SkGlyphCache* cache = autoCache.getCache();
   215     return cache->getBaseGlyphCount(text);
   216 }
   218 void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
   219     if (options != fPaintOptionsAndroid) {
   220         fPaintOptionsAndroid = options;
   221         GEN_ID_INC;
   222         fDirtyBits |= kPaintOptionsAndroid_DirtyBit;
   223     }
   224 }
   225 #endif
   227 SkPaint::FilterLevel SkPaint::getFilterLevel() const {
   228     int level = 0;
   229     if (fFlags & kFilterBitmap_Flag) {
   230         level |= 1;
   231     }
   232     if (fFlags & kHighQualityFilterBitmap_Flag) {
   233         level |= 2;
   234     }
   235     return (FilterLevel)level;
   236 }
   238 void SkPaint::setFilterLevel(FilterLevel level) {
   239     unsigned mask = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag;
   240     unsigned flags = 0;
   241     if (level & 1) {
   242         flags |= kFilterBitmap_Flag;
   243     }
   244     if (level & 2) {
   245         flags |= kHighQualityFilterBitmap_Flag;
   246     }
   247     this->setFlags((fFlags & ~mask) | flags);
   248 }
   250 void SkPaint::setHinting(Hinting hintingLevel) {
   251     GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
   252     fHinting = hintingLevel;
   253     fDirtyBits |= kBitfields_DirtyBit;
   254 }
   256 void SkPaint::setFlags(uint32_t flags) {
   257     GEN_ID_INC_EVAL(fFlags != flags);
   258     fFlags = flags;
   259     fDirtyBits |= kBitfields_DirtyBit;
   260 }
   262 void SkPaint::setAntiAlias(bool doAA) {
   263     this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
   264 }
   266 void SkPaint::setDither(bool doDither) {
   267     this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
   268 }
   270 void SkPaint::setSubpixelText(bool doSubpixel) {
   271     this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
   272 }
   274 void SkPaint::setLCDRenderText(bool doLCDRender) {
   275     this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
   276 }
   278 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
   279     this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
   280 }
   282 void SkPaint::setAutohinted(bool useAutohinter) {
   283     this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
   284 }
   286 void SkPaint::setLinearText(bool doLinearText) {
   287     this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
   288 }
   290 void SkPaint::setVerticalText(bool doVertical) {
   291     this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
   292 }
   294 void SkPaint::setUnderlineText(bool doUnderline) {
   295     this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
   296 }
   298 void SkPaint::setStrikeThruText(bool doStrikeThru) {
   299     this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
   300 }
   302 void SkPaint::setFakeBoldText(bool doFakeBold) {
   303     this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
   304 }
   306 void SkPaint::setDevKernText(bool doDevKern) {
   307     this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
   308 }
   310 void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
   311     this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
   312 }
   314 void SkPaint::setStyle(Style style) {
   315     if ((unsigned)style < kStyleCount) {
   316         GEN_ID_INC_EVAL((unsigned)style != fStyle);
   317         fStyle = style;
   318         fDirtyBits |= kBitfields_DirtyBit;
   319     } else {
   320 #ifdef SK_REPORT_API_RANGE_CHECK
   321         SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
   322 #endif
   323     }
   324 }
   326 void SkPaint::setColor(SkColor color) {
   327     GEN_ID_INC_EVAL(color != fColor);
   328     fColor = color;
   329     fDirtyBits |= kColor_DirtyBit;
   330 }
   332 void SkPaint::setAlpha(U8CPU a) {
   333     this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
   334                                   SkColorGetG(fColor), SkColorGetB(fColor)));
   335 }
   337 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
   338     this->setColor(SkColorSetARGB(a, r, g, b));
   339 }
   341 void SkPaint::setStrokeWidth(SkScalar width) {
   342     if (width >= 0) {
   343         GEN_ID_INC_EVAL(width != fWidth);
   344         fWidth = width;
   345         fDirtyBits |= kStrokeWidth_DirtyBit;
   346     } else {
   347 #ifdef SK_REPORT_API_RANGE_CHECK
   348         SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
   349 #endif
   350     }
   351 }
   353 void SkPaint::setStrokeMiter(SkScalar limit) {
   354     if (limit >= 0) {
   355         GEN_ID_INC_EVAL(limit != fMiterLimit);
   356         fMiterLimit = limit;
   357         fDirtyBits |= kStrokeMiter_DirtyBit;
   358     } else {
   359 #ifdef SK_REPORT_API_RANGE_CHECK
   360         SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
   361 #endif
   362     }
   363 }
   365 void SkPaint::setStrokeCap(Cap ct) {
   366     if ((unsigned)ct < kCapCount) {
   367         GEN_ID_INC_EVAL((unsigned)ct != fCapType);
   368         fCapType = SkToU8(ct);
   369         fDirtyBits |= kBitfields_DirtyBit;
   370     } else {
   371 #ifdef SK_REPORT_API_RANGE_CHECK
   372         SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
   373 #endif
   374     }
   375 }
   377 void SkPaint::setStrokeJoin(Join jt) {
   378     if ((unsigned)jt < kJoinCount) {
   379         GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
   380         fJoinType = SkToU8(jt);
   381         fDirtyBits |= kBitfields_DirtyBit;
   382     } else {
   383 #ifdef SK_REPORT_API_RANGE_CHECK
   384         SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
   385 #endif
   386     }
   387 }
   389 ///////////////////////////////////////////////////////////////////////////////
   391 void SkPaint::setTextAlign(Align align) {
   392     if ((unsigned)align < kAlignCount) {
   393         GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
   394         fTextAlign = SkToU8(align);
   395         fDirtyBits |= kBitfields_DirtyBit;
   396     } else {
   397 #ifdef SK_REPORT_API_RANGE_CHECK
   398         SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
   399 #endif
   400     }
   401 }
   403 void SkPaint::setTextSize(SkScalar ts) {
   404     if (ts >= 0) {
   405         GEN_ID_INC_EVAL(ts != fTextSize);
   406         fTextSize = ts;
   407         fDirtyBits |= kTextSize_DirtyBit;
   408     } else {
   409 #ifdef SK_REPORT_API_RANGE_CHECK
   410         SkDebugf("SkPaint::setTextSize() called with negative value\n");
   411 #endif
   412     }
   413 }
   415 void SkPaint::setTextScaleX(SkScalar scaleX) {
   416     GEN_ID_INC_EVAL(scaleX != fTextScaleX);
   417     fTextScaleX = scaleX;
   418     fDirtyBits |= kTextScaleX_DirtyBit;
   419 }
   421 void SkPaint::setTextSkewX(SkScalar skewX) {
   422     GEN_ID_INC_EVAL(skewX != fTextSkewX);
   423     fTextSkewX = skewX;
   424     fDirtyBits |= kTextSkewX_DirtyBit;
   425 }
   427 void SkPaint::setTextEncoding(TextEncoding encoding) {
   428     if ((unsigned)encoding <= kGlyphID_TextEncoding) {
   429         GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
   430         fTextEncoding = encoding;
   431         fDirtyBits |= kBitfields_DirtyBit;
   432     } else {
   433 #ifdef SK_REPORT_API_RANGE_CHECK
   434         SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
   435 #endif
   436     }
   437 }
   439 ///////////////////////////////////////////////////////////////////////////////
   441 // Returns dst with the given bitmask enabled or disabled, depending on value.
   442 inline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
   443     return value ? (dst | bitmask) : (dst & ~bitmask);
   444 }
   446 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
   447     SkRefCnt_SafeAssign(fTypeface, font);
   448     GEN_ID_INC;
   449     fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
   450     return font;
   451 }
   453 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
   454     SkRefCnt_SafeAssign(fRasterizer, r);
   455     GEN_ID_INC;
   456     fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
   457     return r;
   458 }
   460 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
   461     SkRefCnt_SafeAssign(fLooper, looper);
   462     GEN_ID_INC;
   463     fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
   464     return looper;
   465 }
   467 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
   468     SkRefCnt_SafeAssign(fImageFilter, imageFilter);
   469     GEN_ID_INC;
   470     fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
   471     return imageFilter;
   472 }
   474 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
   475     SkRefCnt_SafeAssign(fAnnotation, annotation);
   476     GEN_ID_INC;
   477     fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
   478     return annotation;
   479 }
   481 ///////////////////////////////////////////////////////////////////////////////
   483 static SkScalar mag2(SkScalar x, SkScalar y) {
   484     return x * x + y * y;
   485 }
   487 static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
   488     return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
   489             ||
   490             mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
   491 }
   493 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
   494     SkASSERT(!ctm.hasPerspective());
   495     SkASSERT(!textM.hasPerspective());
   497     SkMatrix matrix;
   498     matrix.setConcat(ctm, textM);
   499     return tooBig(matrix, MaxCacheSize2());
   500 }
   502 bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
   503     SkMatrix textM;
   504     return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
   505 }
   507 bool SkPaint::tooBigToUseCache() const {
   508     SkMatrix textM;
   509     return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
   510 }
   512 ///////////////////////////////////////////////////////////////////////////////
   514 #include "SkGlyphCache.h"
   515 #include "SkUtils.h"
   517 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
   518                            void* context) {
   519     *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
   520 }
   522 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
   523                           uint16_t glyphs[]) const {
   524     if (byteLength == 0) {
   525         return 0;
   526     }
   528     SkASSERT(textData != NULL);
   530     if (NULL == glyphs) {
   531         switch (this->getTextEncoding()) {
   532         case kUTF8_TextEncoding:
   533             return SkUTF8_CountUnichars((const char*)textData, byteLength);
   534         case kUTF16_TextEncoding:
   535             return SkUTF16_CountUnichars((const uint16_t*)textData,
   536                                          byteLength >> 1);
   537         case kUTF32_TextEncoding:
   538             return byteLength >> 2;
   539         case kGlyphID_TextEncoding:
   540             return byteLength >> 1;
   541         default:
   542             SkDEBUGFAIL("unknown text encoding");
   543         }
   544         return 0;
   545     }
   547     // if we get here, we have a valid glyphs[] array, so time to fill it in
   549     // handle this encoding before the setup for the glyphcache
   550     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
   551         // we want to ignore the low bit of byteLength
   552         memcpy(glyphs, textData, byteLength >> 1 << 1);
   553         return byteLength >> 1;
   554     }
   556     SkAutoGlyphCache autoCache(*this, NULL, NULL);
   557     SkGlyphCache*    cache = autoCache.getCache();
   559     const char* text = (const char*)textData;
   560     const char* stop = text + byteLength;
   561     uint16_t*   gptr = glyphs;
   563     switch (this->getTextEncoding()) {
   564         case SkPaint::kUTF8_TextEncoding:
   565             while (text < stop) {
   566                 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
   567             }
   568             break;
   569         case SkPaint::kUTF16_TextEncoding: {
   570             const uint16_t* text16 = (const uint16_t*)text;
   571             const uint16_t* stop16 = (const uint16_t*)stop;
   572             while (text16 < stop16) {
   573                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
   574             }
   575             break;
   576         }
   577         case kUTF32_TextEncoding: {
   578             const int32_t* text32 = (const int32_t*)text;
   579             const int32_t* stop32 = (const int32_t*)stop;
   580             while (text32 < stop32) {
   581                 *gptr++ = cache->unicharToGlyph(*text32++);
   582             }
   583             break;
   584         }
   585         default:
   586             SkDEBUGFAIL("unknown text encoding");
   587     }
   588     return gptr - glyphs;
   589 }
   591 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
   592     if (0 == byteLength) {
   593         return true;
   594     }
   596     SkASSERT(textData != NULL);
   598     // handle this encoding before the setup for the glyphcache
   599     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
   600         const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
   601         size_t count = byteLength >> 1;
   602         for (size_t i = 0; i < count; i++) {
   603             if (0 == glyphID[i]) {
   604                 return false;
   605             }
   606         }
   607         return true;
   608     }
   610     SkAutoGlyphCache autoCache(*this, NULL, NULL);
   611     SkGlyphCache*    cache = autoCache.getCache();
   613     switch (this->getTextEncoding()) {
   614         case SkPaint::kUTF8_TextEncoding: {
   615             const char* text = static_cast<const char*>(textData);
   616             const char* stop = text + byteLength;
   617             while (text < stop) {
   618                 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
   619                     return false;
   620                 }
   621             }
   622             break;
   623         }
   624         case SkPaint::kUTF16_TextEncoding: {
   625             const uint16_t* text = static_cast<const uint16_t*>(textData);
   626             const uint16_t* stop = text + (byteLength >> 1);
   627             while (text < stop) {
   628                 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
   629                     return false;
   630                 }
   631             }
   632             break;
   633         }
   634         case SkPaint::kUTF32_TextEncoding: {
   635             const int32_t* text = static_cast<const int32_t*>(textData);
   636             const int32_t* stop = text + (byteLength >> 2);
   637             while (text < stop) {
   638                 if (0 == cache->unicharToGlyph(*text++)) {
   639                     return false;
   640                 }
   641             }
   642             break;
   643         }
   644         default:
   645             SkDEBUGFAIL("unknown text encoding");
   646             return false;
   647     }
   648     return true;
   649 }
   651 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
   652                                SkUnichar textData[]) const {
   653     if (count <= 0) {
   654         return;
   655     }
   657     SkASSERT(glyphs != NULL);
   658     SkASSERT(textData != NULL);
   660     SkAutoGlyphCache autoCache(*this, NULL, NULL);
   661     SkGlyphCache*    cache = autoCache.getCache();
   663     for (int index = 0; index < count; index++) {
   664         textData[index] = cache->glyphToUnichar(glyphs[index]);
   665     }
   666 }
   668 ///////////////////////////////////////////////////////////////////////////////
   670 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
   671                                               const char** text) {
   672     SkASSERT(cache != NULL);
   673     SkASSERT(text != NULL);
   675     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
   676 }
   678 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
   679                                               const char** text) {
   680     SkASSERT(cache != NULL);
   681     SkASSERT(text != NULL);
   683     return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
   684 }
   686 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
   687                                                const char** text) {
   688     SkASSERT(cache != NULL);
   689     SkASSERT(text != NULL);
   691     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
   692 }
   694 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
   695                                                const char** text) {
   696     SkASSERT(cache != NULL);
   697     SkASSERT(text != NULL);
   699     return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
   700 }
   702 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
   703                                                const char** text) {
   704     SkASSERT(cache != NULL);
   705     SkASSERT(text != NULL);
   707     const int32_t* ptr = *(const int32_t**)text;
   708     SkUnichar uni = *ptr++;
   709     *text = (const char*)ptr;
   710     return cache->getUnicharMetrics(uni);
   711 }
   713 static const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
   714                                                const char** text) {
   715     SkASSERT(cache != NULL);
   716     SkASSERT(text != NULL);
   718     const int32_t* ptr = *(const int32_t**)text;
   719     SkUnichar uni = *--ptr;
   720     *text = (const char*)ptr;
   721     return cache->getUnicharMetrics(uni);
   722 }
   724 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
   725                                                const char** text) {
   726     SkASSERT(cache != NULL);
   727     SkASSERT(text != NULL);
   729     const uint16_t* ptr = *(const uint16_t**)text;
   730     unsigned glyphID = *ptr;
   731     ptr += 1;
   732     *text = (const char*)ptr;
   733     return cache->getGlyphIDMetrics(glyphID);
   734 }
   736 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
   737                                                const char** text) {
   738     SkASSERT(cache != NULL);
   739     SkASSERT(text != NULL);
   741     const uint16_t* ptr = *(const uint16_t**)text;
   742     ptr -= 1;
   743     unsigned glyphID = *ptr;
   744     *text = (const char*)ptr;
   745     return cache->getGlyphIDMetrics(glyphID);
   746 }
   748 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
   749                                               const char** text) {
   750     SkASSERT(cache != NULL);
   751     SkASSERT(text != NULL);
   753     return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
   754 }
   756 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
   757                                               const char** text) {
   758     SkASSERT(cache != NULL);
   759     SkASSERT(text != NULL);
   761     return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
   762 }
   764 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
   765                                                const char** text) {
   766     SkASSERT(cache != NULL);
   767     SkASSERT(text != NULL);
   769     return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
   770 }
   772 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
   773                                                const char** text) {
   774     SkASSERT(cache != NULL);
   775     SkASSERT(text != NULL);
   777     return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
   778 }
   780 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
   781                                                const char** text) {
   782     SkASSERT(cache != NULL);
   783     SkASSERT(text != NULL);
   785     const int32_t* ptr = *(const int32_t**)text;
   786     SkUnichar uni = *ptr++;
   787     *text = (const char*)ptr;
   788     return cache->getUnicharAdvance(uni);
   789 }
   791 static const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
   792                                                const char** text) {
   793     SkASSERT(cache != NULL);
   794     SkASSERT(text != NULL);
   796     const int32_t* ptr = *(const int32_t**)text;
   797     SkUnichar uni = *--ptr;
   798     *text = (const char*)ptr;
   799     return cache->getUnicharAdvance(uni);
   800 }
   802 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
   803                                                const char** text) {
   804     SkASSERT(cache != NULL);
   805     SkASSERT(text != NULL);
   807     const uint16_t* ptr = *(const uint16_t**)text;
   808     unsigned glyphID = *ptr;
   809     ptr += 1;
   810     *text = (const char*)ptr;
   811     return cache->getGlyphIDAdvance(glyphID);
   812 }
   814 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
   815                                                const char** text) {
   816     SkASSERT(cache != NULL);
   817     SkASSERT(text != NULL);
   819     const uint16_t* ptr = *(const uint16_t**)text;
   820     ptr -= 1;
   821     unsigned glyphID = *ptr;
   822     *text = (const char*)ptr;
   823     return cache->getGlyphIDAdvance(glyphID);
   824 }
   826 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
   827                                                 bool needFullMetrics) const {
   828     static const SkMeasureCacheProc gMeasureCacheProcs[] = {
   829         sk_getMetrics_utf8_next,
   830         sk_getMetrics_utf16_next,
   831         sk_getMetrics_utf32_next,
   832         sk_getMetrics_glyph_next,
   834         sk_getMetrics_utf8_prev,
   835         sk_getMetrics_utf16_prev,
   836         sk_getMetrics_utf32_prev,
   837         sk_getMetrics_glyph_prev,
   839         sk_getAdvance_utf8_next,
   840         sk_getAdvance_utf16_next,
   841         sk_getAdvance_utf32_next,
   842         sk_getAdvance_glyph_next,
   844         sk_getAdvance_utf8_prev,
   845         sk_getAdvance_utf16_prev,
   846         sk_getAdvance_utf32_prev,
   847         sk_getAdvance_glyph_prev
   848     };
   850     unsigned index = this->getTextEncoding();
   852     if (kBackward_TextBufferDirection == tbd) {
   853         index += 4;
   854     }
   855     if (!needFullMetrics && !this->isDevKernText()) {
   856         index += 8;
   857     }
   859     SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
   860     return gMeasureCacheProcs[index];
   861 }
   863 ///////////////////////////////////////////////////////////////////////////////
   865 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
   866                                         const char** text, SkFixed, SkFixed) {
   867     SkASSERT(cache != NULL);
   868     SkASSERT(text != NULL);
   870     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
   871 }
   873 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
   874                                     const char** text, SkFixed x, SkFixed y) {
   875     SkASSERT(cache != NULL);
   876     SkASSERT(text != NULL);
   878     return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
   879 }
   881 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
   882                                         const char** text, SkFixed, SkFixed) {
   883     SkASSERT(cache != NULL);
   884     SkASSERT(text != NULL);
   886     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
   887 }
   889 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
   890                                      const char** text, SkFixed x, SkFixed y) {
   891     SkASSERT(cache != NULL);
   892     SkASSERT(text != NULL);
   894     return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
   895                                     x, y);
   896 }
   898 static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
   899                                     const char** text, SkFixed, SkFixed) {
   900     SkASSERT(cache != NULL);
   901     SkASSERT(text != NULL);
   903     const int32_t* ptr = *(const int32_t**)text;
   904     SkUnichar uni = *ptr++;
   905     *text = (const char*)ptr;
   906     return cache->getUnicharMetrics(uni);
   907 }
   909 static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
   910                                     const char** text, SkFixed x, SkFixed y) {
   911     SkASSERT(cache != NULL);
   912     SkASSERT(text != NULL);
   914     const int32_t* ptr = *(const int32_t**)text;
   915     SkUnichar uni = *--ptr;
   916     *text = (const char*)ptr;
   917     return cache->getUnicharMetrics(uni, x, y);
   918 }
   920 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
   921                                          const char** text, SkFixed, SkFixed) {
   922     SkASSERT(cache != NULL);
   923     SkASSERT(text != NULL);
   925     const uint16_t* ptr = *(const uint16_t**)text;
   926     unsigned glyphID = *ptr;
   927     ptr += 1;
   928     *text = (const char*)ptr;
   929     return cache->getGlyphIDMetrics(glyphID);
   930 }
   932 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
   933                                      const char** text, SkFixed x, SkFixed y) {
   934     SkASSERT(cache != NULL);
   935     SkASSERT(text != NULL);
   937     const uint16_t* ptr = *(const uint16_t**)text;
   938     unsigned glyphID = *ptr;
   939     ptr += 1;
   940     *text = (const char*)ptr;
   941     return cache->getGlyphIDMetrics(glyphID, x, y);
   942 }
   944 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
   945     static const SkDrawCacheProc gDrawCacheProcs[] = {
   946         sk_getMetrics_utf8_00,
   947         sk_getMetrics_utf16_00,
   948         sk_getMetrics_utf32_00,
   949         sk_getMetrics_glyph_00,
   951         sk_getMetrics_utf8_xy,
   952         sk_getMetrics_utf16_xy,
   953         sk_getMetrics_utf32_xy,
   954         sk_getMetrics_glyph_xy
   955     };
   957     unsigned index = this->getTextEncoding();
   958     if (fFlags & kSubpixelText_Flag) {
   959         index += 4;
   960     }
   962     SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
   963     return gDrawCacheProcs[index];
   964 }
   966 ///////////////////////////////////////////////////////////////////////////////
   968 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
   969 SkPaint::kDevKernText_Flag          |       \
   970 SkPaint::kLinearText_Flag           |       \
   971 SkPaint::kLCDRenderText_Flag        |       \
   972 SkPaint::kEmbeddedBitmapText_Flag   |       \
   973 SkPaint::kAutoHinting_Flag          |       \
   974 SkPaint::kGenA8FromLCD_Flag )
   976 SkScalar SkPaint::setupForAsPaths() {
   977     uint32_t flags = this->getFlags();
   978     // clear the flags we don't care about
   979     flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
   980     // set the flags we do care about
   981     flags |= SkPaint::kSubpixelText_Flag;
   983     this->setFlags(flags);
   984     this->setHinting(SkPaint::kNo_Hinting);
   986     SkScalar textSize = fTextSize;
   987     this->setTextSize(kCanonicalTextSizeForPaths);
   988     return textSize / kCanonicalTextSizeForPaths;
   989 }
   991 class SkCanonicalizePaint {
   992 public:
   993     SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
   994         if (paint.isLinearText() || paint.tooBigToUseCache()) {
   995             SkPaint* p = fLazy.set(paint);
   996             fScale = p->setupForAsPaths();
   997             fPaint = p;
   998         }
   999     }
  1001     const SkPaint& getPaint() const { return *fPaint; }
  1003     /**
  1004      *  Returns 0 if the paint was unmodified, or the scale factor need to
  1005      *  the original textSize
  1006      */
  1007     SkScalar getScale() const { return fScale; }
  1009 private:
  1010     const SkPaint*   fPaint;
  1011     SkScalar         fScale;
  1012     SkTLazy<SkPaint> fLazy;
  1013 };
  1015 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
  1016     bounds->set(SkIntToScalar(g.fLeft),
  1017                 SkIntToScalar(g.fTop),
  1018                 SkIntToScalar(g.fLeft + g.fWidth),
  1019                 SkIntToScalar(g.fTop + g.fHeight));
  1022 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
  1023 // we don't overflow along the way
  1024 typedef int64_t Sk48Dot16;
  1026 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
  1027     return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
  1030 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
  1031     SkScalar sx = Sk48Dot16ToScalar(dx);
  1032     bounds->join(SkIntToScalar(g.fLeft) + sx,
  1033                  SkIntToScalar(g.fTop),
  1034                  SkIntToScalar(g.fLeft + g.fWidth) + sx,
  1035                  SkIntToScalar(g.fTop + g.fHeight));
  1038 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
  1039     SkScalar sy = Sk48Dot16ToScalar(dy);
  1040     bounds->join(SkIntToScalar(g.fLeft),
  1041                  SkIntToScalar(g.fTop) + sy,
  1042                  SkIntToScalar(g.fLeft + g.fWidth),
  1043                  SkIntToScalar(g.fTop + g.fHeight) + sy);
  1046 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
  1048 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
  1049 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
  1050     SkASSERT(0 == xyIndex || 1 == xyIndex);
  1051     return (&glyph.fAdvanceX)[xyIndex];
  1054 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
  1055                                const char* text, size_t byteLength,
  1056                                int* count, SkRect* bounds) const {
  1057     SkASSERT(count);
  1058     if (byteLength == 0) {
  1059         *count = 0;
  1060         if (bounds) {
  1061             bounds->setEmpty();
  1063         return 0;
  1066     SkMeasureCacheProc glyphCacheProc;
  1067     glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
  1068                                                NULL != bounds);
  1070     int xyIndex;
  1071     JoinBoundsProc joinBoundsProc;
  1072     if (this->isVerticalText()) {
  1073         xyIndex = 1;
  1074         joinBoundsProc = join_bounds_y;
  1075     } else {
  1076         xyIndex = 0;
  1077         joinBoundsProc = join_bounds_x;
  1080     int         n = 1;
  1081     const char* stop = (const char*)text + byteLength;
  1082     const SkGlyph* g = &glyphCacheProc(cache, &text);
  1083     // our accumulated fixed-point advances might overflow 16.16, so we use
  1084     // a 48.16 (64bit) accumulator, and then convert that to scalar at the
  1085     // very end.
  1086     Sk48Dot16 x = advance(*g, xyIndex);
  1088     SkAutoKern  autokern;
  1090     if (NULL == bounds) {
  1091         if (this->isDevKernText()) {
  1092             int rsb;
  1093             for (; text < stop; n++) {
  1094                 rsb = g->fRsbDelta;
  1095                 g = &glyphCacheProc(cache, &text);
  1096                 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
  1098         } else {
  1099             for (; text < stop; n++) {
  1100                 x += advance(glyphCacheProc(cache, &text), xyIndex);
  1103     } else {
  1104         set_bounds(*g, bounds);
  1105         if (this->isDevKernText()) {
  1106             int rsb;
  1107             for (; text < stop; n++) {
  1108                 rsb = g->fRsbDelta;
  1109                 g = &glyphCacheProc(cache, &text);
  1110                 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
  1111                 joinBoundsProc(*g, bounds, x);
  1112                 x += advance(*g, xyIndex);
  1114         } else {
  1115             for (; text < stop; n++) {
  1116                 g = &glyphCacheProc(cache, &text);
  1117                 joinBoundsProc(*g, bounds, x);
  1118                 x += advance(*g, xyIndex);
  1122     SkASSERT(text == stop);
  1124     *count = n;
  1125     return Sk48Dot16ToScalar(x);
  1128 SkScalar SkPaint::measureText(const void* textData, size_t length,
  1129                               SkRect* bounds, SkScalar zoom) const {
  1130     const char* text = (const char*)textData;
  1131     SkASSERT(text != NULL || length == 0);
  1133     SkCanonicalizePaint canon(*this);
  1134     const SkPaint& paint = canon.getPaint();
  1135     SkScalar scale = canon.getScale();
  1137     SkMatrix zoomMatrix, *zoomPtr = NULL;
  1138     if (zoom) {
  1139         zoomMatrix.setScale(zoom, zoom);
  1140         zoomPtr = &zoomMatrix;
  1143     SkAutoGlyphCache    autoCache(paint, NULL, zoomPtr);
  1144     SkGlyphCache*       cache = autoCache.getCache();
  1146     SkScalar width = 0;
  1148     if (length > 0) {
  1149         int tempCount;
  1151         width = paint.measure_text(cache, text, length, &tempCount, bounds);
  1152         if (scale) {
  1153             width = SkScalarMul(width, scale);
  1154             if (bounds) {
  1155                 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
  1156                 bounds->fTop = SkScalarMul(bounds->fTop, scale);
  1157                 bounds->fRight = SkScalarMul(bounds->fRight, scale);
  1158                 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
  1161     } else if (bounds) {
  1162         // ensure that even if we don't measure_text we still update the bounds
  1163         bounds->setEmpty();
  1165     return width;
  1168 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
  1170 static bool forward_textBufferPred(const char* text, const char* stop) {
  1171     return text < stop;
  1174 static bool backward_textBufferPred(const char* text, const char* stop) {
  1175     return text > stop;
  1178 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
  1179                                              const char** text, size_t length,
  1180                                              const char** stop) {
  1181     if (SkPaint::kForward_TextBufferDirection == tbd) {
  1182         *stop = *text + length;
  1183         return forward_textBufferPred;
  1184     } else {
  1185         // text should point to the end of the buffer, and stop to the beginning
  1186         *stop = *text;
  1187         *text += length;
  1188         return backward_textBufferPred;
  1192 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
  1193                           SkScalar* measuredWidth,
  1194                           TextBufferDirection tbd) const {
  1195     if (0 == length || 0 >= maxWidth) {
  1196         if (measuredWidth) {
  1197             *measuredWidth = 0;
  1199         return 0;
  1202     if (0 == fTextSize) {
  1203         if (measuredWidth) {
  1204             *measuredWidth = 0;
  1206         return length;
  1209     SkASSERT(textD != NULL);
  1210     const char* text = (const char*)textD;
  1212     SkCanonicalizePaint canon(*this);
  1213     const SkPaint& paint = canon.getPaint();
  1214     SkScalar scale = canon.getScale();
  1216     // adjust max in case we changed the textSize in paint
  1217     if (scale) {
  1218         maxWidth /= scale;
  1221     SkAutoGlyphCache    autoCache(paint, NULL, NULL);
  1222     SkGlyphCache*       cache = autoCache.getCache();
  1224     SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
  1225     const char*      stop;
  1226     SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
  1227     const int        xyIndex = paint.isVerticalText() ? 1 : 0;
  1228     // use 64bits for our accumulator, to avoid overflowing 16.16
  1229     Sk48Dot16        max = SkScalarToFixed(maxWidth);
  1230     Sk48Dot16        width = 0;
  1232     SkAutoKern  autokern;
  1234     if (this->isDevKernText()) {
  1235         int rsb = 0;
  1236         while (pred(text, stop)) {
  1237             const char* curr = text;
  1238             const SkGlyph& g = glyphCacheProc(cache, &text);
  1239             SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
  1240             if ((width += x) > max) {
  1241                 width -= x;
  1242                 text = curr;
  1243                 break;
  1245             rsb = g.fRsbDelta;
  1247     } else {
  1248         while (pred(text, stop)) {
  1249             const char* curr = text;
  1250             SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
  1251             if ((width += x) > max) {
  1252                 width -= x;
  1253                 text = curr;
  1254                 break;
  1259     if (measuredWidth) {
  1260         SkScalar scalarWidth = Sk48Dot16ToScalar(width);
  1261         if (scale) {
  1262             scalarWidth = SkScalarMul(scalarWidth, scale);
  1264         *measuredWidth = scalarWidth;
  1267     // return the number of bytes measured
  1268     return (kForward_TextBufferDirection == tbd) ?
  1269                 text - stop + length : stop - text + length;
  1272 ///////////////////////////////////////////////////////////////////////////////
  1274 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
  1275     *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
  1276     return false;   // don't detach the cache
  1279 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
  1280                                 void* context) {
  1281     SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
  1284 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
  1285     SkCanonicalizePaint canon(*this);
  1286     const SkPaint& paint = canon.getPaint();
  1287     SkScalar scale = canon.getScale();
  1289     SkMatrix zoomMatrix, *zoomPtr = NULL;
  1290     if (zoom) {
  1291         zoomMatrix.setScale(zoom, zoom);
  1292         zoomPtr = &zoomMatrix;
  1295     FontMetrics storage;
  1296     if (NULL == metrics) {
  1297         metrics = &storage;
  1300     paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
  1302     if (scale) {
  1303         metrics->fTop = SkScalarMul(metrics->fTop, scale);
  1304         metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
  1305         metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
  1306         metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
  1307         metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
  1308         metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
  1309         metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
  1310         metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
  1311         metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
  1312         metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
  1313         metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
  1315     return metrics->fDescent - metrics->fAscent + metrics->fLeading;
  1318 ///////////////////////////////////////////////////////////////////////////////
  1320 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
  1321     bounds->set(g.fLeft * scale,
  1322                 g.fTop * scale,
  1323                 (g.fLeft + g.fWidth) * scale,
  1324                 (g.fTop + g.fHeight) * scale);
  1327 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
  1328                            SkScalar widths[], SkRect bounds[]) const {
  1329     if (0 == byteLength) {
  1330         return 0;
  1333     SkASSERT(NULL != textData);
  1335     if (NULL == widths && NULL == bounds) {
  1336         return this->countText(textData, byteLength);
  1339     SkCanonicalizePaint canon(*this);
  1340     const SkPaint& paint = canon.getPaint();
  1341     SkScalar scale = canon.getScale();
  1343     SkAutoGlyphCache    autoCache(paint, NULL, NULL);
  1344     SkGlyphCache*       cache = autoCache.getCache();
  1345     SkMeasureCacheProc  glyphCacheProc;
  1346     glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
  1347                                                NULL != bounds);
  1349     const char* text = (const char*)textData;
  1350     const char* stop = text + byteLength;
  1351     int         count = 0;
  1352     const int   xyIndex = paint.isVerticalText() ? 1 : 0;
  1354     if (this->isDevKernText()) {
  1355         // we adjust the widths returned here through auto-kerning
  1356         SkAutoKern  autokern;
  1357         SkFixed     prevWidth = 0;
  1359         if (scale) {
  1360             while (text < stop) {
  1361                 const SkGlyph& g = glyphCacheProc(cache, &text);
  1362                 if (widths) {
  1363                     SkFixed  adjust = autokern.adjust(g);
  1365                     if (count > 0) {
  1366                         SkScalar w = SkFixedToScalar(prevWidth + adjust);
  1367                         *widths++ = SkScalarMul(w, scale);
  1369                     prevWidth = advance(g, xyIndex);
  1371                 if (bounds) {
  1372                     set_bounds(g, bounds++, scale);
  1374                 ++count;
  1376             if (count > 0 && widths) {
  1377                 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
  1379         } else {
  1380             while (text < stop) {
  1381                 const SkGlyph& g = glyphCacheProc(cache, &text);
  1382                 if (widths) {
  1383                     SkFixed  adjust = autokern.adjust(g);
  1385                     if (count > 0) {
  1386                         *widths++ = SkFixedToScalar(prevWidth + adjust);
  1388                     prevWidth = advance(g, xyIndex);
  1390                 if (bounds) {
  1391                     set_bounds(g, bounds++);
  1393                 ++count;
  1395             if (count > 0 && widths) {
  1396                 *widths = SkFixedToScalar(prevWidth);
  1399     } else {    // no devkern
  1400         if (scale) {
  1401             while (text < stop) {
  1402                 const SkGlyph& g = glyphCacheProc(cache, &text);
  1403                 if (widths) {
  1404                     *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
  1405                                             scale);
  1407                 if (bounds) {
  1408                     set_bounds(g, bounds++, scale);
  1410                 ++count;
  1412         } else {
  1413             while (text < stop) {
  1414                 const SkGlyph& g = glyphCacheProc(cache, &text);
  1415                 if (widths) {
  1416                     *widths++ = SkFixedToScalar(advance(g, xyIndex));
  1418                 if (bounds) {
  1419                     set_bounds(g, bounds++);
  1421                 ++count;
  1426     SkASSERT(text == stop);
  1427     return count;
  1430 ///////////////////////////////////////////////////////////////////////////////
  1432 #include "SkDraw.h"
  1434 void SkPaint::getTextPath(const void* textData, size_t length,
  1435                           SkScalar x, SkScalar y, SkPath* path) const {
  1436     SkASSERT(length == 0 || textData != NULL);
  1438     const char* text = (const char*)textData;
  1439     if (text == NULL || length == 0 || path == NULL) {
  1440         return;
  1443     SkTextToPathIter    iter(text, length, *this, false);
  1444     SkMatrix            matrix;
  1445     SkScalar            prevXPos = 0;
  1447     matrix.setScale(iter.getPathScale(), iter.getPathScale());
  1448     matrix.postTranslate(x, y);
  1449     path->reset();
  1451     SkScalar        xpos;
  1452     const SkPath*   iterPath;
  1453     while (iter.next(&iterPath, &xpos)) {
  1454         matrix.postTranslate(xpos - prevXPos, 0);
  1455         if (iterPath) {
  1456             path->addPath(*iterPath, matrix);
  1458         prevXPos = xpos;
  1462 void SkPaint::getPosTextPath(const void* textData, size_t length,
  1463                              const SkPoint pos[], SkPath* path) const {
  1464     SkASSERT(length == 0 || textData != NULL);
  1466     const char* text = (const char*)textData;
  1467     if (text == NULL || length == 0 || path == NULL) {
  1468         return;
  1471     SkTextToPathIter    iter(text, length, *this, false);
  1472     SkMatrix            matrix;
  1473     SkPoint             prevPos;
  1474     prevPos.set(0, 0);
  1476     matrix.setScale(iter.getPathScale(), iter.getPathScale());
  1477     path->reset();
  1479     unsigned int    i = 0;
  1480     const SkPath*   iterPath;
  1481     while (iter.next(&iterPath, NULL)) {
  1482         matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
  1483         if (iterPath) {
  1484             path->addPath(*iterPath, matrix);
  1486         prevPos = pos[i];
  1487         i++;
  1491 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
  1492                             SkWriteBuffer* buffer) {
  1493     buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
  1496 // SkFontHost can override this choice in FilterRec()
  1497 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
  1498     uint32_t flags = paint.getFlags();
  1500     // Antialiasing being disabled trumps all other settings.
  1501     if (!(flags & SkPaint::kAntiAlias_Flag)) {
  1502         return SkMask::kBW_Format;
  1505     if (flags & SkPaint::kLCDRenderText_Flag) {
  1506         return SkMask::kLCD16_Format;
  1509     return SkMask::kA8_Format;
  1512 // if linear-text is on, then we force hinting to be off (since that's sort of
  1513 // the point of linear-text.
  1514 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
  1515     SkPaint::Hinting h = paint.getHinting();
  1516     if (paint.isLinearText()) {
  1517         h = SkPaint::kNo_Hinting;
  1519     return h;
  1522 // return true if the paint is just a single color (i.e. not a shader). If its
  1523 // a shader, then we can't compute a const luminance for it :(
  1524 static bool justAColor(const SkPaint& paint, SkColor* color) {
  1525     if (paint.getShader()) {
  1526         return false;
  1528     SkColor c = paint.getColor();
  1529     if (paint.getColorFilter()) {
  1530         c = paint.getColorFilter()->filterColor(c);
  1532     if (color) {
  1533         *color = c;
  1535     return true;
  1538 static SkColor computeLuminanceColor(const SkPaint& paint) {
  1539     SkColor c;
  1540     if (!justAColor(paint, &c)) {
  1541         c = SkColorSetRGB(0x7F, 0x80, 0x7F);
  1543     return c;
  1546 #define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
  1548 // Beyond this size, LCD doesn't appreciably improve quality, but it always
  1549 // cost more RAM and draws slower, so we set a cap.
  1550 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
  1551     #define SK_MAX_SIZE_FOR_LCDTEXT    48
  1552 #endif
  1554 static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
  1555     SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
  1556                     rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
  1557     SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
  1558     return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
  1561 /*
  1562  *  Return the scalar with only limited fractional precision. Used to consolidate matrices
  1563  *  that vary only slightly when we create our key into the font cache, since the font scaler
  1564  *  typically returns the same looking resuts for tiny changes in the matrix.
  1565  */
  1566 static SkScalar sk_relax(SkScalar x) {
  1567     int n = sk_float_round2int(x * 1024);
  1568     return n / 1024.0f;
  1571 void SkScalerContext::MakeRec(const SkPaint& paint,
  1572                               const SkDeviceProperties* deviceProperties,
  1573                               const SkMatrix* deviceMatrix,
  1574                               Rec* rec) {
  1575     SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
  1577     SkTypeface* typeface = paint.getTypeface();
  1578     if (NULL == typeface) {
  1579         typeface = SkTypeface::GetDefaultTypeface();
  1581     rec->fOrigFontID = typeface->uniqueID();
  1582     rec->fFontID = rec->fOrigFontID;
  1583     rec->fTextSize = paint.getTextSize();
  1584     rec->fPreScaleX = paint.getTextScaleX();
  1585     rec->fPreSkewX  = paint.getTextSkewX();
  1587     if (deviceMatrix) {
  1588         rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
  1589         rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
  1590         rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
  1591         rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
  1592     } else {
  1593         rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
  1594         rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
  1597     SkPaint::Style  style = paint.getStyle();
  1598     SkScalar        strokeWidth = paint.getStrokeWidth();
  1600     unsigned flags = 0;
  1602     if (paint.isFakeBoldText()) {
  1603 #ifdef SK_USE_FREETYPE_EMBOLDEN
  1604         flags |= SkScalerContext::kEmbolden_Flag;
  1605 #else
  1606         SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
  1607                                                     kStdFakeBoldInterpKeys,
  1608                                                     kStdFakeBoldInterpValues,
  1609                                                     kStdFakeBoldInterpLength);
  1610         SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
  1612         if (style == SkPaint::kFill_Style) {
  1613             style = SkPaint::kStrokeAndFill_Style;
  1614             strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
  1615         } else {
  1616             strokeWidth += extra;
  1618 #endif
  1621     if (paint.isDevKernText()) {
  1622         flags |= SkScalerContext::kDevKernText_Flag;
  1625     if (style != SkPaint::kFill_Style && strokeWidth > 0) {
  1626         rec->fFrameWidth = strokeWidth;
  1627         rec->fMiterLimit = paint.getStrokeMiter();
  1628         rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
  1630         if (style == SkPaint::kStrokeAndFill_Style) {
  1631             flags |= SkScalerContext::kFrameAndFill_Flag;
  1633     } else {
  1634         rec->fFrameWidth = 0;
  1635         rec->fMiterLimit = 0;
  1636         rec->fStrokeJoin = 0;
  1639     rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
  1641     SkDeviceProperties::Geometry geometry = deviceProperties
  1642                                           ? deviceProperties->fGeometry
  1643                                           : SkDeviceProperties::Geometry::MakeDefault();
  1644     if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
  1645         if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) {
  1646             // eeek, can't support LCD
  1647             rec->fMaskFormat = SkMask::kA8_Format;
  1648         } else {
  1649             if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) {
  1650                 flags |= SkScalerContext::kLCD_Vertical_Flag;
  1652             if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) {
  1653                 flags |= SkScalerContext::kLCD_BGROrder_Flag;
  1658     if (paint.isEmbeddedBitmapText()) {
  1659         flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
  1661     if (paint.isSubpixelText()) {
  1662         flags |= SkScalerContext::kSubpixelPositioning_Flag;
  1664     if (paint.isAutohinted()) {
  1665         flags |= SkScalerContext::kForceAutohinting_Flag;
  1667     if (paint.isVerticalText()) {
  1668         flags |= SkScalerContext::kVertical_Flag;
  1670     if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
  1671         flags |= SkScalerContext::kGenA8FromLCD_Flag;
  1673     rec->fFlags = SkToU16(flags);
  1675     // these modify fFlags, so do them after assigning fFlags
  1676     rec->setHinting(computeHinting(paint));
  1678     rec->setLuminanceColor(computeLuminanceColor(paint));
  1680     if (NULL == deviceProperties) {
  1681         rec->setDeviceGamma(SK_GAMMA_EXPONENT);
  1682         rec->setPaintGamma(SK_GAMMA_EXPONENT);
  1683     } else {
  1684         rec->setDeviceGamma(deviceProperties->fGamma);
  1686         //For now always set the paint gamma equal to the device gamma.
  1687         //The math in SkMaskGamma can handle them being different,
  1688         //but it requires superluminous masks when
  1689         //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
  1690         rec->setPaintGamma(deviceProperties->fGamma);
  1693 #ifdef SK_GAMMA_CONTRAST
  1694     rec->setContrast(SK_GAMMA_CONTRAST);
  1695 #else
  1696     /**
  1697      * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
  1698      * With lower values small text appears washed out (though correctly so).
  1699      * With higher values lcd fringing is worse and the smoothing effect of
  1700      * partial coverage is diminished.
  1701      */
  1702     rec->setContrast(0.5f);
  1703 #endif
  1705     rec->fReservedAlign = 0;
  1707     /*  Allow the fonthost to modify our rec before we use it as a key into the
  1708         cache. This way if we're asking for something that they will ignore,
  1709         they can modify our rec up front, so we don't create duplicate cache
  1710         entries.
  1711      */
  1712     typeface->onFilterRec(rec);
  1714     // be sure to call PostMakeRec(rec) before you actually use it!
  1717 /**
  1718  * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
  1719  * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
  1720  * to hold it until the returned pointer is refed or forgotten.
  1721  */
  1722 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
  1724 static SkMaskGamma* gLinearMaskGamma = NULL;
  1725 static SkMaskGamma* gMaskGamma = NULL;
  1726 static SkScalar gContrast = SK_ScalarMin;
  1727 static SkScalar gPaintGamma = SK_ScalarMin;
  1728 static SkScalar gDeviceGamma = SK_ScalarMin;
  1729 /**
  1730  * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
  1731  * the returned SkMaskGamma pointer is refed or forgotten.
  1732  */
  1733 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
  1734     if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
  1735         if (NULL == gLinearMaskGamma) {
  1736             gLinearMaskGamma = SkNEW(SkMaskGamma);
  1738         return *gLinearMaskGamma;
  1740     if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
  1741         SkSafeUnref(gMaskGamma);
  1742         gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
  1743         gContrast = contrast;
  1744         gPaintGamma = paintGamma;
  1745         gDeviceGamma = deviceGamma;
  1747     return *gMaskGamma;
  1750 /*static*/ void SkPaint::Term() {
  1751     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
  1753     SkSafeUnref(gLinearMaskGamma);
  1754     gLinearMaskGamma = NULL;
  1755     SkSafeUnref(gMaskGamma);
  1756     gMaskGamma = NULL;
  1757     SkDEBUGCODE(gContrast = SK_ScalarMin;)
  1758     SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
  1759     SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
  1762 /**
  1763  *  We ensure that the rec is self-consistent and efficient (where possible)
  1764  */
  1765 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
  1766     /**
  1767      *  If we're asking for A8, we force the colorlum to be gray, since that
  1768      *  limits the number of unique entries, and the scaler will only look at
  1769      *  the lum of one of them.
  1770      */
  1771     switch (rec->fMaskFormat) {
  1772         case SkMask::kLCD16_Format:
  1773         case SkMask::kLCD32_Format: {
  1774             // filter down the luminance color to a finite number of bits
  1775             SkColor color = rec->getLuminanceColor();
  1776             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
  1777             break;
  1779         case SkMask::kA8_Format: {
  1780             // filter down the luminance to a single component, since A8 can't
  1781             // use per-component information
  1783             SkColor color = rec->getLuminanceColor();
  1784             U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color);
  1785             //If we are asked to look like LCD, look like LCD.
  1786             if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
  1787                 // HACK: Prevents green from being pre-blended as white.
  1788                 lum -= ((255 - lum) * lum) / 255;
  1791             // reduce to our finite number of bits
  1792             color = SkColorSetRGB(lum, lum, lum);
  1793             rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
  1794             break;
  1796         case SkMask::kBW_Format:
  1797             // No need to differentiate gamma if we're BW
  1798             rec->ignorePreBlend();
  1799             break;
  1803 #define MIN_SIZE_FOR_EFFECT_BUFFER  1024
  1805 #ifdef SK_DEBUG
  1806     #define TEST_DESC
  1807 #endif
  1809 /*
  1810  *  ignoreGamma tells us that the caller just wants metrics that are unaffected
  1811  *  by gamma correction, so we jam the luminance field to 0 (most common value
  1812  *  for black text) in hopes that we get a cache hit easier. A better solution
  1813  *  would be for the fontcache lookup to know to ignore the luminance field
  1814  *  entirely, but not sure how to do that and keep it fast.
  1815  */
  1816 void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
  1817                              const SkMatrix* deviceMatrix,
  1818                              void (*proc)(SkTypeface*, const SkDescriptor*, void*),
  1819                              void* context, bool ignoreGamma) const {
  1820     SkScalerContext::Rec    rec;
  1822     SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
  1823     if (ignoreGamma) {
  1824         rec.setLuminanceColor(0);
  1827     size_t          descSize = sizeof(rec);
  1828     int             entryCount = 1;
  1829     SkPathEffect*   pe = this->getPathEffect();
  1830     SkMaskFilter*   mf = this->getMaskFilter();
  1831     SkRasterizer*   ra = this->getRasterizer();
  1833     SkWriteBuffer    peBuffer, mfBuffer, raBuffer;
  1835     if (pe) {
  1836         peBuffer.writeFlattenable(pe);
  1837         descSize += peBuffer.bytesWritten();
  1838         entryCount += 1;
  1839         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
  1840         // seems like we could support kLCD as well at this point...
  1842     if (mf) {
  1843         mfBuffer.writeFlattenable(mf);
  1844         descSize += mfBuffer.bytesWritten();
  1845         entryCount += 1;
  1846         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
  1847         /* Pre-blend is not currently applied to filtered text.
  1848            The primary filter is blur, for which contrast makes no sense,
  1849            and for which the destination guess error is more visible.
  1850            Also, all existing users of blur have calibrated for linear. */
  1851         rec.ignorePreBlend();
  1853     if (ra) {
  1854         raBuffer.writeFlattenable(ra);
  1855         descSize += raBuffer.bytesWritten();
  1856         entryCount += 1;
  1857         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
  1860 #ifdef SK_BUILD_FOR_ANDROID
  1861     SkWriteBuffer androidBuffer;
  1862     fPaintOptionsAndroid.flatten(androidBuffer);
  1863     descSize += androidBuffer.bytesWritten();
  1864     entryCount += 1;
  1865 #endif
  1867     ///////////////////////////////////////////////////////////////////////////
  1868     // Now that we're done tweaking the rec, call the PostMakeRec cleanup
  1869     SkScalerContext::PostMakeRec(*this, &rec);
  1871     descSize += SkDescriptor::ComputeOverhead(entryCount);
  1873     SkAutoDescriptor    ad(descSize);
  1874     SkDescriptor*       desc = ad.getDesc();
  1876     desc->init();
  1877     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1879 #ifdef SK_BUILD_FOR_ANDROID
  1880     add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1881 #endif
  1883     if (pe) {
  1884         add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
  1886     if (mf) {
  1887         add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1889     if (ra) {
  1890         add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
  1893     SkASSERT(descSize == desc->getLength());
  1894     desc->computeChecksum();
  1896 #ifdef TEST_DESC
  1898         // Check that we completely write the bytes in desc (our key), and that
  1899         // there are no uninitialized bytes. If there were, then we would get
  1900         // false-misses (or worse, false-hits) in our fontcache.
  1901         //
  1902         // We do this buy filling 2 others, one with 0s and the other with 1s
  1903         // and create those, and then check that all 3 are identical.
  1904         SkAutoDescriptor    ad1(descSize);
  1905         SkAutoDescriptor    ad2(descSize);
  1906         SkDescriptor*       desc1 = ad1.getDesc();
  1907         SkDescriptor*       desc2 = ad2.getDesc();
  1909         memset(desc1, 0x00, descSize);
  1910         memset(desc2, 0xFF, descSize);
  1912         desc1->init();
  1913         desc2->init();
  1914         desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1915         desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1917 #ifdef SK_BUILD_FOR_ANDROID
  1918         add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1919         add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1920 #endif
  1922         if (pe) {
  1923             add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
  1924             add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
  1926         if (mf) {
  1927             add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1928             add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1930         if (ra) {
  1931             add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
  1932             add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
  1935         SkASSERT(descSize == desc1->getLength());
  1936         SkASSERT(descSize == desc2->getLength());
  1937         desc1->computeChecksum();
  1938         desc2->computeChecksum();
  1939         SkASSERT(!memcmp(desc, desc1, descSize));
  1940         SkASSERT(!memcmp(desc, desc2, descSize));
  1942 #endif
  1944     proc(fTypeface, desc, context);
  1947 SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
  1948                                    const SkMatrix* deviceMatrix) const {
  1949     SkGlyphCache* cache;
  1950     this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false);
  1951     return cache;
  1954 /**
  1955  * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
  1956  */
  1957 //static
  1958 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
  1959     SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
  1960     const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
  1961                                                    rec.getPaintGamma(),
  1962                                                    rec.getDeviceGamma());
  1963     return maskGamma.preBlend(rec.getLuminanceColor());
  1966 ///////////////////////////////////////////////////////////////////////////////
  1968 #include "SkStream.h"
  1970 static uintptr_t asint(const void* p) {
  1971     return reinterpret_cast<uintptr_t>(p);
  1974 union Scalar32 {
  1975     SkScalar    fScalar;
  1976     uint32_t    f32;
  1977 };
  1979 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
  1980     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
  1981     Scalar32 tmp;
  1982     tmp.fScalar = value;
  1983     *ptr = tmp.f32;
  1984     return ptr + 1;
  1987 static SkScalar read_scalar(const uint32_t*& ptr) {
  1988     SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
  1989     Scalar32 tmp;
  1990     tmp.f32 = *ptr++;
  1991     return tmp.fScalar;
  1994 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
  1995     SkASSERT(a == (uint8_t)a);
  1996     SkASSERT(b == (uint8_t)b);
  1997     SkASSERT(c == (uint8_t)c);
  1998     SkASSERT(d == (uint8_t)d);
  1999     return (a << 24) | (b << 16) | (c << 8) | d;
  2002 enum FlatFlags {
  2003     kHasTypeface_FlatFlag                      = 0x01,
  2004     kHasEffects_FlatFlag                       = 0x02,
  2005     kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
  2006 };
  2008 // The size of a flat paint's POD fields
  2009 static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
  2010                                         1 * sizeof(SkColor) +
  2011                                         1 * sizeof(uint16_t) +
  2012                                         6 * sizeof(uint8_t);
  2014 /*  To save space/time, we analyze the paint, and write a truncated version of
  2015     it if there are not tricky elements like shaders, etc.
  2016  */
  2017 void SkPaint::flatten(SkWriteBuffer& buffer) const {
  2018     uint8_t flatFlags = 0;
  2019     if (this->getTypeface()) {
  2020         flatFlags |= kHasTypeface_FlatFlag;
  2022     if (asint(this->getPathEffect()) |
  2023         asint(this->getShader()) |
  2024         asint(this->getXfermode()) |
  2025         asint(this->getMaskFilter()) |
  2026         asint(this->getColorFilter()) |
  2027         asint(this->getRasterizer()) |
  2028         asint(this->getLooper()) |
  2029         asint(this->getAnnotation()) |
  2030         asint(this->getImageFilter())) {
  2031         flatFlags |= kHasEffects_FlatFlag;
  2033 #ifdef SK_BUILD_FOR_ANDROID
  2034     if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) {
  2035         flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag;
  2037 #endif
  2039     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
  2040     uint32_t* ptr = buffer.reserve(kPODPaintSize);
  2042     ptr = write_scalar(ptr, this->getTextSize());
  2043     ptr = write_scalar(ptr, this->getTextScaleX());
  2044     ptr = write_scalar(ptr, this->getTextSkewX());
  2045     ptr = write_scalar(ptr, this->getStrokeWidth());
  2046     ptr = write_scalar(ptr, this->getStrokeMiter());
  2047     *ptr++ = this->getColor();
  2048     // previously flags:16, textAlign:8, flatFlags:8
  2049     // now flags:16, hinting:4, textAlign:4, flatFlags:8
  2050     *ptr++ = (this->getFlags() << 16) |
  2051         // hinting added later. 0 in this nibble means use the default.
  2052         ((this->getHinting()+1) << 12) |
  2053         (this->getTextAlign() << 8) |
  2054         flatFlags;
  2055     *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
  2056                     this->getStyle(), this->getTextEncoding());
  2058     // now we're done with ptr and the (pre)reserved space. If we need to write
  2059     // additional fields, use the buffer directly
  2060     if (flatFlags & kHasTypeface_FlatFlag) {
  2061         buffer.writeTypeface(this->getTypeface());
  2063     if (flatFlags & kHasEffects_FlatFlag) {
  2064         buffer.writeFlattenable(this->getPathEffect());
  2065         buffer.writeFlattenable(this->getShader());
  2066         buffer.writeFlattenable(this->getXfermode());
  2067         buffer.writeFlattenable(this->getMaskFilter());
  2068         buffer.writeFlattenable(this->getColorFilter());
  2069         buffer.writeFlattenable(this->getRasterizer());
  2070         buffer.writeFlattenable(this->getLooper());
  2071         buffer.writeFlattenable(this->getImageFilter());
  2073         if (fAnnotation) {
  2074             buffer.writeBool(true);
  2075             fAnnotation->writeToBuffer(buffer);
  2076         } else {
  2077             buffer.writeBool(false);
  2080 #ifdef SK_BUILD_FOR_ANDROID
  2081     if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
  2082         this->getPaintOptionsAndroid().flatten(buffer);
  2084 #endif
  2087 void SkPaint::unflatten(SkReadBuffer& buffer) {
  2088     uint8_t flatFlags = 0;
  2089     SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
  2090     const void* podData = buffer.skip(kPODPaintSize);
  2091     const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
  2093     // the order we read must match the order we wrote in flatten()
  2094     this->setTextSize(read_scalar(pod));
  2095     this->setTextScaleX(read_scalar(pod));
  2096     this->setTextSkewX(read_scalar(pod));
  2097     this->setStrokeWidth(read_scalar(pod));
  2098     this->setStrokeMiter(read_scalar(pod));
  2099     this->setColor(*pod++);
  2101     // previously flags:16, textAlign:8, flatFlags:8
  2102     // now flags:16, hinting:4, textAlign:4, flatFlags:8
  2103     uint32_t tmp = *pod++;
  2104     this->setFlags(tmp >> 16);
  2106     // hinting added later. 0 in this nibble means use the default.
  2107     uint32_t hinting = (tmp >> 12) & 0xF;
  2108     this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
  2110     this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
  2112     flatFlags = tmp & 0xFF;
  2114     tmp = *pod++;
  2115     this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
  2116     this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
  2117     this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
  2118     this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
  2120     if (flatFlags & kHasTypeface_FlatFlag) {
  2121         this->setTypeface(buffer.readTypeface());
  2122     } else {
  2123         this->setTypeface(NULL);
  2126     if (flatFlags & kHasEffects_FlatFlag) {
  2127         SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
  2128         SkSafeUnref(this->setShader(buffer.readShader()));
  2129         SkSafeUnref(this->setXfermode(buffer.readXfermode()));
  2130         SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
  2131         SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
  2132         SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
  2133         SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
  2134         SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
  2136         if (buffer.readBool()) {
  2137             this->setAnnotation(SkAnnotation::Create(buffer))->unref();
  2139     } else {
  2140         this->setPathEffect(NULL);
  2141         this->setShader(NULL);
  2142         this->setXfermode(NULL);
  2143         this->setMaskFilter(NULL);
  2144         this->setColorFilter(NULL);
  2145         this->setRasterizer(NULL);
  2146         this->setLooper(NULL);
  2147         this->setImageFilter(NULL);
  2150 #ifdef SK_BUILD_FOR_ANDROID
  2151     this->setPaintOptionsAndroid(SkPaintOptionsAndroid());
  2152 #endif
  2153     if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
  2154         SkPaintOptionsAndroid options;
  2155         options.unflatten(buffer);
  2156 #ifdef SK_BUILD_FOR_ANDROID
  2157         this->setPaintOptionsAndroid(options);
  2158 #endif
  2162 ///////////////////////////////////////////////////////////////////////////////
  2164 SkShader* SkPaint::setShader(SkShader* shader) {
  2165     GEN_ID_INC_EVAL(shader != fShader);
  2166     SkRefCnt_SafeAssign(fShader, shader);
  2167     fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
  2168     return shader;
  2171 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
  2172     GEN_ID_INC_EVAL(filter != fColorFilter);
  2173     SkRefCnt_SafeAssign(fColorFilter, filter);
  2174     fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
  2175     return filter;
  2178 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
  2179     GEN_ID_INC_EVAL(mode != fXfermode);
  2180     SkRefCnt_SafeAssign(fXfermode, mode);
  2181     fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
  2182     return mode;
  2185 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
  2186     SkSafeUnref(fXfermode);
  2187     fXfermode = SkXfermode::Create(mode);
  2188     GEN_ID_INC;
  2189     fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
  2190     return fXfermode;
  2193 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
  2194     GEN_ID_INC_EVAL(effect != fPathEffect);
  2195     SkRefCnt_SafeAssign(fPathEffect, effect);
  2196     fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
  2197     return effect;
  2200 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
  2201     GEN_ID_INC_EVAL(filter != fMaskFilter);
  2202     SkRefCnt_SafeAssign(fMaskFilter, filter);
  2203     fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
  2204     return filter;
  2207 ///////////////////////////////////////////////////////////////////////////////
  2209 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
  2210                           const SkRect* cullRect) const {
  2211     SkStrokeRec rec(*this);
  2213     const SkPath* srcPtr = &src;
  2214     SkPath tmpPath;
  2216     if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
  2217         srcPtr = &tmpPath;
  2220     if (!rec.applyToPath(dst, *srcPtr)) {
  2221         if (srcPtr == &tmpPath) {
  2222             // If path's were copy-on-write, this trick would not be needed.
  2223             // As it is, we want to save making a deep-copy from tmpPath -> dst
  2224             // since we know we're just going to delete tmpPath when we return,
  2225             // so the swap saves that copy.
  2226             dst->swap(tmpPath);
  2227         } else {
  2228             *dst = *srcPtr;
  2231     return !rec.isHairlineStyle();
  2234 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
  2235                                            SkRect* storage,
  2236                                            Style style) const {
  2237     SkASSERT(storage);
  2239     const SkRect* src = &origSrc;
  2241     if (this->getLooper()) {
  2242         SkASSERT(this->getLooper()->canComputeFastBounds(*this));
  2243         this->getLooper()->computeFastBounds(*this, *src, storage);
  2244         return *storage;
  2247     SkRect tmpSrc;
  2248     if (this->getPathEffect()) {
  2249         this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
  2250         src = &tmpSrc;
  2253     if (kFill_Style != style) {
  2254         // since we're stroked, outset the rect by the radius (and join type)
  2255         SkScalar radius = SkScalarHalf(this->getStrokeWidth());
  2256         if (0 == radius) {  // hairline
  2257             radius = SK_Scalar1;
  2258         } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
  2259             SkScalar scale = this->getStrokeMiter();
  2260             if (scale > SK_Scalar1) {
  2261                 radius = SkScalarMul(radius, scale);
  2264         storage->set(src->fLeft - radius, src->fTop - radius,
  2265                      src->fRight + radius, src->fBottom + radius);
  2266     } else {
  2267         *storage = *src;
  2270     if (this->getMaskFilter()) {
  2271         this->getMaskFilter()->computeFastBounds(*storage, storage);
  2274     if (this->getImageFilter()) {
  2275         this->getImageFilter()->computeFastBounds(*storage, storage);
  2278     return *storage;
  2281 #ifndef SK_IGNORE_TO_STRING
  2282 void SkPaint::toString(SkString* str) const {
  2283     str->append("<dl><dt>SkPaint:</dt><dd><dl>");
  2285     SkTypeface* typeface = this->getTypeface();
  2286     if (NULL != typeface) {
  2287         SkDynamicMemoryWStream ostream;
  2288         typeface->serialize(&ostream);
  2289         SkAutoTUnref<SkData> data(ostream.copyToData());
  2291         SkMemoryStream stream(data);
  2292         SkFontDescriptor descriptor(&stream);
  2294         str->append("<dt>Font Family Name:</dt><dd>");
  2295         str->append(descriptor.getFamilyName());
  2296         str->append("</dd><dt>Font Full Name:</dt><dd>");
  2297         str->append(descriptor.getFullName());
  2298         str->append("</dd><dt>Font PS Name:</dt><dd>");
  2299         str->append(descriptor.getPostscriptName());
  2300         str->append("</dd><dt>Font File Name:</dt><dd>");
  2301         str->append(descriptor.getFontFileName());
  2302         str->append("</dd>");
  2305     str->append("<dt>TextSize:</dt><dd>");
  2306     str->appendScalar(this->getTextSize());
  2307     str->append("</dd>");
  2309     str->append("<dt>TextScaleX:</dt><dd>");
  2310     str->appendScalar(this->getTextScaleX());
  2311     str->append("</dd>");
  2313     str->append("<dt>TextSkewX:</dt><dd>");
  2314     str->appendScalar(this->getTextSkewX());
  2315     str->append("</dd>");
  2317     SkPathEffect* pathEffect = this->getPathEffect();
  2318     if (NULL != pathEffect) {
  2319         str->append("<dt>PathEffect:</dt><dd>");
  2320         str->append("</dd>");
  2323     SkShader* shader = this->getShader();
  2324     if (NULL != shader) {
  2325         str->append("<dt>Shader:</dt><dd>");
  2326         shader->toString(str);
  2327         str->append("</dd>");
  2330     SkXfermode* xfer = this->getXfermode();
  2331     if (NULL != xfer) {
  2332         str->append("<dt>Xfermode:</dt><dd>");
  2333         xfer->toString(str);
  2334         str->append("</dd>");
  2337     SkMaskFilter* maskFilter = this->getMaskFilter();
  2338     if (NULL != maskFilter) {
  2339         str->append("<dt>MaskFilter:</dt><dd>");
  2340         maskFilter->toString(str);
  2341         str->append("</dd>");
  2344     SkColorFilter* colorFilter = this->getColorFilter();
  2345     if (NULL != colorFilter) {
  2346         str->append("<dt>ColorFilter:</dt><dd>");
  2347         colorFilter->toString(str);
  2348         str->append("</dd>");
  2351     SkRasterizer* rasterizer = this->getRasterizer();
  2352     if (NULL != rasterizer) {
  2353         str->append("<dt>Rasterizer:</dt><dd>");
  2354         str->append("</dd>");
  2357     SkDrawLooper* looper = this->getLooper();
  2358     if (NULL != looper) {
  2359         str->append("<dt>DrawLooper:</dt><dd>");
  2360         looper->toString(str);
  2361         str->append("</dd>");
  2364     SkImageFilter* imageFilter = this->getImageFilter();
  2365     if (NULL != imageFilter) {
  2366         str->append("<dt>ImageFilter:</dt><dd>");
  2367         str->append("</dd>");
  2370     SkAnnotation* annotation = this->getAnnotation();
  2371     if (NULL != annotation) {
  2372         str->append("<dt>Annotation:</dt><dd>");
  2373         str->append("</dd>");
  2376     str->append("<dt>Color:</dt><dd>0x");
  2377     SkColor color = this->getColor();
  2378     str->appendHex(color);
  2379     str->append("</dd>");
  2381     str->append("<dt>Stroke Width:</dt><dd>");
  2382     str->appendScalar(this->getStrokeWidth());
  2383     str->append("</dd>");
  2385     str->append("<dt>Stroke Miter:</dt><dd>");
  2386     str->appendScalar(this->getStrokeMiter());
  2387     str->append("</dd>");
  2389     str->append("<dt>Flags:</dt><dd>(");
  2390     if (this->getFlags()) {
  2391         bool needSeparator = false;
  2392         SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
  2393         SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
  2394         SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
  2395         SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
  2396         SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
  2397         SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
  2398         SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
  2399         SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
  2400         SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
  2401         SkAddFlagToString(str, this->isEmbeddedBitmapText(),
  2402                           "EmbeddedBitmapText", &needSeparator);
  2403         SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
  2404         SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
  2405         SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
  2406                           "GenA8FromLCD", &needSeparator);
  2407     } else {
  2408         str->append("None");
  2410     str->append(")</dd>");
  2412     str->append("<dt>FilterLevel:</dt><dd>");
  2413     static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
  2414     str->append(gFilterLevelStrings[this->getFilterLevel()]);
  2415     str->append("</dd>");
  2417     str->append("<dt>TextAlign:</dt><dd>");
  2418     static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
  2419     str->append(gTextAlignStrings[this->getTextAlign()]);
  2420     str->append("</dd>");
  2422     str->append("<dt>CapType:</dt><dd>");
  2423     static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
  2424     str->append(gStrokeCapStrings[this->getStrokeCap()]);
  2425     str->append("</dd>");
  2427     str->append("<dt>JoinType:</dt><dd>");
  2428     static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
  2429     str->append(gJoinStrings[this->getStrokeJoin()]);
  2430     str->append("</dd>");
  2432     str->append("<dt>Style:</dt><dd>");
  2433     static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
  2434     str->append(gStyleStrings[this->getStyle()]);
  2435     str->append("</dd>");
  2437     str->append("<dt>TextEncoding:</dt><dd>");
  2438     static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
  2439     str->append(gTextEncodingStrings[this->getTextEncoding()]);
  2440     str->append("</dd>");
  2442     str->append("<dt>Hinting:</dt><dd>");
  2443     static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
  2444     str->append(gHintingStrings[this->getHinting()]);
  2445     str->append("</dd>");
  2447     str->append("</dd></dl></dl>");
  2449 #endif
  2451 ///////////////////////////////////////////////////////////////////////////////
  2453 static bool has_thick_frame(const SkPaint& paint) {
  2454     return  paint.getStrokeWidth() > 0 &&
  2455             paint.getStyle() != SkPaint::kFill_Style;
  2458 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
  2459                                     const SkPaint& paint,
  2460                                     bool applyStrokeAndPathEffects)
  2461                                     : fPaint(paint) {
  2462     fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
  2463                                                 true);
  2465     fPaint.setLinearText(true);
  2466     fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
  2468     if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
  2469         applyStrokeAndPathEffects = false;
  2472     // can't use our canonical size if we need to apply patheffects
  2473     if (fPaint.getPathEffect() == NULL) {
  2474         fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
  2475         fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
  2476         if (has_thick_frame(fPaint)) {
  2477             fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
  2479     } else {
  2480         fScale = SK_Scalar1;
  2483     if (!applyStrokeAndPathEffects) {
  2484         fPaint.setStyle(SkPaint::kFill_Style);
  2485         fPaint.setPathEffect(NULL);
  2488     fCache = fPaint.detachCache(NULL, NULL);
  2490     SkPaint::Style  style = SkPaint::kFill_Style;
  2491     SkPathEffect*   pe = NULL;
  2493     if (!applyStrokeAndPathEffects) {
  2494         style = paint.getStyle();   // restore
  2495         pe = paint.getPathEffect();     // restore
  2497     fPaint.setStyle(style);
  2498     fPaint.setPathEffect(pe);
  2499     fPaint.setMaskFilter(paint.getMaskFilter());    // restore
  2501     // now compute fXOffset if needed
  2503     SkScalar xOffset = 0;
  2504     if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
  2505         int      count;
  2506         SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
  2507                                                          &count, NULL), fScale);
  2508         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
  2509             width = SkScalarHalf(width);
  2511         xOffset = -width;
  2513     fXPos = xOffset;
  2514     fPrevAdvance = 0;
  2516     fText = text;
  2517     fStop = text + length;
  2519     fXYIndex = paint.isVerticalText() ? 1 : 0;
  2522 SkTextToPathIter::~SkTextToPathIter() {
  2523     SkGlyphCache::AttachCache(fCache);
  2526 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
  2527     if (fText < fStop) {
  2528         const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
  2530         fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
  2531         fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
  2533         if (glyph.fWidth) {
  2534             if (path) {
  2535                 *path = fCache->findPath(glyph);
  2537         } else {
  2538             if (path) {
  2539                 *path = NULL;
  2542         if (xpos) {
  2543             *xpos = fXPos;
  2545         return true;
  2547     return false;
  2550 ///////////////////////////////////////////////////////////////////////////////
  2552 bool SkPaint::nothingToDraw() const {
  2553     if (fLooper) {
  2554         return false;
  2556     SkXfermode::Mode mode;
  2557     if (SkXfermode::AsMode(fXfermode, &mode)) {
  2558         switch (mode) {
  2559             case SkXfermode::kSrcOver_Mode:
  2560             case SkXfermode::kSrcATop_Mode:
  2561             case SkXfermode::kDstOut_Mode:
  2562             case SkXfermode::kDstOver_Mode:
  2563             case SkXfermode::kPlus_Mode:
  2564                 return 0 == this->getAlpha();
  2565             case SkXfermode::kDst_Mode:
  2566                 return true;
  2567             default:
  2568                 break;
  2571     return false;
  2574 void SkPaint::setBitfields(uint32_t bitfields) {
  2575     fBitfields = bitfields;
  2576     fDirtyBits |= kBitfields_DirtyBit;
  2579 inline static unsigned popcount(uint8_t x) {
  2580     // As in Hacker's delight, adapted for just 8 bits.
  2581     x = (x & 0x55) + ((x >> 1) & 0x55);  // a b c d w x y z -> a+b c+d w+x y+z
  2582     x = (x & 0x33) + ((x >> 2) & 0x33);  // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
  2583     x = (x & 0x0F) + ((x >> 4) & 0x0F);  // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
  2584     return x;
  2587 void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
  2588     const uint32_t dirty = paint.fDirtyBits;
  2590     // Each of the low 7 dirty bits corresponds to a 4-byte flat value, plus one for the dirty bits.
  2591     const size_t flatBytes = 4 * (popcount(dirty & 127) + 1);
  2592     SkASSERT(flatBytes <= 32);
  2593     uint32_t* u32 = buffer.reserve(flatBytes);
  2594     *u32++ = dirty;
  2595     if (dirty == 0) {
  2596         return;
  2599 #define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
  2600     F(u32, Color);
  2601     F(u32, Bitfields);
  2602     SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
  2603     F(f32, TextSize);
  2604     F(f32, TextScaleX);
  2605     F(f32, TextSkewX);
  2606     F(f32, StrokeWidth);
  2607     F(f32, StrokeMiter);
  2608 #undef F
  2609 #define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
  2610     F(PathEffect);
  2611     F(Shader);
  2612     F(Xfermode);
  2613     F(MaskFilter);
  2614     F(ColorFilter);
  2615     F(Rasterizer);
  2616     F(Looper);
  2617     F(ImageFilter);
  2618 #undef F
  2619     if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
  2620     if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
  2621 #ifdef SK_BUILD_FOR_ANDROID
  2622     if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer);
  2623 #endif
  2626 void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
  2627     const uint32_t dirty = buffer.readUInt();
  2628     if (dirty == 0) {
  2629         return;
  2631 #define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
  2632 // Same function, except it unrefs the object newly set on the paint:
  2633 #define F_UNREF(field, reader)                      \
  2634     if (dirty & k##field##_DirtyBit)                \
  2635         paint->set##field(buffer.reader())->unref()
  2637     F(Color,       readUInt);
  2638     F(Bitfields,   readUInt);
  2639     F(TextSize,    readScalar);
  2640     F(TextScaleX,  readScalar);
  2641     F(TextSkewX,   readScalar);
  2642     F(StrokeWidth, readScalar);
  2643     F(StrokeMiter, readScalar);
  2644     F_UNREF(PathEffect,  readPathEffect);
  2645     F_UNREF(Shader,      readShader);
  2646     F_UNREF(Xfermode,    readXfermode);
  2647     F_UNREF(MaskFilter,  readMaskFilter);
  2648     F_UNREF(ColorFilter, readColorFilter);
  2649     F_UNREF(Rasterizer,  readRasterizer);
  2650     F_UNREF(Looper,      readDrawLooper);
  2651     F_UNREF(ImageFilter, readImageFilter);
  2652     F(Typeface,    readTypeface);
  2653 #undef F
  2654 #undef F_UNREF
  2655     if (dirty & kAnnotation_DirtyBit) {
  2656         paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
  2658 #ifdef SK_BUILD_FOR_ANDROID
  2659     if (dirty & kPaintOptionsAndroid_DirtyBit) {
  2660         SkPaintOptionsAndroid options;
  2661         options.unflatten(buffer);
  2662         paint->setPaintOptionsAndroid(options);
  2664 #endif
  2665     SkASSERT(dirty == paint->fDirtyBits);

mercurial