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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/core/SkPaint.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2666 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +#include "SkPaint.h"
    1.13 +#include "SkAnnotation.h"
    1.14 +#include "SkAutoKern.h"
    1.15 +#include "SkColorFilter.h"
    1.16 +#include "SkData.h"
    1.17 +#include "SkDeviceProperties.h"
    1.18 +#include "SkFontDescriptor.h"
    1.19 +#include "SkFontHost.h"
    1.20 +#include "SkGlyphCache.h"
    1.21 +#include "SkImageFilter.h"
    1.22 +#include "SkMaskFilter.h"
    1.23 +#include "SkMaskGamma.h"
    1.24 +#include "SkReadBuffer.h"
    1.25 +#include "SkWriteBuffer.h"
    1.26 +#include "SkPaintDefaults.h"
    1.27 +#include "SkPaintOptionsAndroid.h"
    1.28 +#include "SkPathEffect.h"
    1.29 +#include "SkRasterizer.h"
    1.30 +#include "SkScalar.h"
    1.31 +#include "SkScalerContext.h"
    1.32 +#include "SkShader.h"
    1.33 +#include "SkStringUtils.h"
    1.34 +#include "SkStroke.h"
    1.35 +#include "SkTextFormatParams.h"
    1.36 +#include "SkTextToPathIter.h"
    1.37 +#include "SkTLazy.h"
    1.38 +#include "SkTypeface.h"
    1.39 +#include "SkXfermode.h"
    1.40 +
    1.41 +enum {
    1.42 +    kColor_DirtyBit               = 1 <<  0,
    1.43 +    kBitfields_DirtyBit           = 1 <<  1,
    1.44 +    kTextSize_DirtyBit            = 1 <<  2,
    1.45 +    kTextScaleX_DirtyBit          = 1 <<  3,
    1.46 +    kTextSkewX_DirtyBit           = 1 <<  4,
    1.47 +    kStrokeWidth_DirtyBit         = 1 <<  5,
    1.48 +    kStrokeMiter_DirtyBit         = 1 <<  6,
    1.49 +    kPathEffect_DirtyBit          = 1 <<  7,
    1.50 +    kShader_DirtyBit              = 1 <<  8,
    1.51 +    kXfermode_DirtyBit            = 1 <<  9,
    1.52 +    kMaskFilter_DirtyBit          = 1 << 10,
    1.53 +    kColorFilter_DirtyBit         = 1 << 11,
    1.54 +    kRasterizer_DirtyBit          = 1 << 12,
    1.55 +    kLooper_DirtyBit              = 1 << 13,
    1.56 +    kImageFilter_DirtyBit         = 1 << 14,
    1.57 +    kTypeface_DirtyBit            = 1 << 15,
    1.58 +    kAnnotation_DirtyBit          = 1 << 16,
    1.59 +    kPaintOptionsAndroid_DirtyBit = 1 << 17,
    1.60 +};
    1.61 +
    1.62 +// define this to get a printf for out-of-range parameter in setters
    1.63 +// e.g. setTextSize(-1)
    1.64 +//#define SK_REPORT_API_RANGE_CHECK
    1.65 +
    1.66 +#ifdef SK_BUILD_FOR_ANDROID
    1.67 +#define GEN_ID_INC                  fGenerationID++
    1.68 +#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
    1.69 +#else
    1.70 +#define GEN_ID_INC
    1.71 +#define GEN_ID_INC_EVAL(expression)
    1.72 +#endif
    1.73 +
    1.74 +SkPaint::SkPaint() {
    1.75 +    // since we may have padding, we zero everything so that our memcmp() call
    1.76 +    // in operator== will work correctly.
    1.77 +    // with this, we can skip 0 and null individual initializations
    1.78 +    sk_bzero(this, sizeof(*this));
    1.79 +
    1.80 +#if 0   // not needed with the bzero call above
    1.81 +    fTypeface    = NULL;
    1.82 +    fTextSkewX   = 0;
    1.83 +    fPathEffect  = NULL;
    1.84 +    fShader      = NULL;
    1.85 +    fXfermode    = NULL;
    1.86 +    fMaskFilter  = NULL;
    1.87 +    fColorFilter = NULL;
    1.88 +    fRasterizer  = NULL;
    1.89 +    fLooper      = NULL;
    1.90 +    fImageFilter = NULL;
    1.91 +    fAnnotation  = NULL;
    1.92 +    fWidth       = 0;
    1.93 +    fDirtyBits   = 0;
    1.94 +#endif
    1.95 +
    1.96 +    fTextSize   = SkPaintDefaults_TextSize;
    1.97 +    fTextScaleX = SK_Scalar1;
    1.98 +    fColor      = SK_ColorBLACK;
    1.99 +    fMiterLimit = SkPaintDefaults_MiterLimit;
   1.100 +    fFlags      = SkPaintDefaults_Flags;
   1.101 +    fCapType    = kDefault_Cap;
   1.102 +    fJoinType   = kDefault_Join;
   1.103 +    fTextAlign  = kLeft_Align;
   1.104 +    fStyle      = kFill_Style;
   1.105 +    fTextEncoding = kUTF8_TextEncoding;
   1.106 +    fHinting    = SkPaintDefaults_Hinting;
   1.107 +#ifdef SK_BUILD_FOR_ANDROID
   1.108 +    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
   1.109 +    fGenerationID = 0;
   1.110 +#endif
   1.111 +}
   1.112 +
   1.113 +SkPaint::SkPaint(const SkPaint& src) {
   1.114 +    memcpy(this, &src, sizeof(src));
   1.115 +
   1.116 +    SkSafeRef(fTypeface);
   1.117 +    SkSafeRef(fPathEffect);
   1.118 +    SkSafeRef(fShader);
   1.119 +    SkSafeRef(fXfermode);
   1.120 +    SkSafeRef(fMaskFilter);
   1.121 +    SkSafeRef(fColorFilter);
   1.122 +    SkSafeRef(fRasterizer);
   1.123 +    SkSafeRef(fLooper);
   1.124 +    SkSafeRef(fImageFilter);
   1.125 +    SkSafeRef(fAnnotation);
   1.126 +
   1.127 +#ifdef SK_BUILD_FOR_ANDROID
   1.128 +    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
   1.129 +#endif
   1.130 +}
   1.131 +
   1.132 +SkPaint::~SkPaint() {
   1.133 +    SkSafeUnref(fTypeface);
   1.134 +    SkSafeUnref(fPathEffect);
   1.135 +    SkSafeUnref(fShader);
   1.136 +    SkSafeUnref(fXfermode);
   1.137 +    SkSafeUnref(fMaskFilter);
   1.138 +    SkSafeUnref(fColorFilter);
   1.139 +    SkSafeUnref(fRasterizer);
   1.140 +    SkSafeUnref(fLooper);
   1.141 +    SkSafeUnref(fImageFilter);
   1.142 +    SkSafeUnref(fAnnotation);
   1.143 +}
   1.144 +
   1.145 +SkPaint& SkPaint::operator=(const SkPaint& src) {
   1.146 +    SkASSERT(&src);
   1.147 +
   1.148 +    SkSafeRef(src.fTypeface);
   1.149 +    SkSafeRef(src.fPathEffect);
   1.150 +    SkSafeRef(src.fShader);
   1.151 +    SkSafeRef(src.fXfermode);
   1.152 +    SkSafeRef(src.fMaskFilter);
   1.153 +    SkSafeRef(src.fColorFilter);
   1.154 +    SkSafeRef(src.fRasterizer);
   1.155 +    SkSafeRef(src.fLooper);
   1.156 +    SkSafeRef(src.fImageFilter);
   1.157 +    SkSafeRef(src.fAnnotation);
   1.158 +
   1.159 +    SkSafeUnref(fTypeface);
   1.160 +    SkSafeUnref(fPathEffect);
   1.161 +    SkSafeUnref(fShader);
   1.162 +    SkSafeUnref(fXfermode);
   1.163 +    SkSafeUnref(fMaskFilter);
   1.164 +    SkSafeUnref(fColorFilter);
   1.165 +    SkSafeUnref(fRasterizer);
   1.166 +    SkSafeUnref(fLooper);
   1.167 +    SkSafeUnref(fImageFilter);
   1.168 +    SkSafeUnref(fAnnotation);
   1.169 +
   1.170 +#ifdef SK_BUILD_FOR_ANDROID
   1.171 +    fPaintOptionsAndroid.~SkPaintOptionsAndroid();
   1.172 +
   1.173 +    uint32_t oldGenerationID = fGenerationID;
   1.174 +#endif
   1.175 +    memcpy(this, &src, sizeof(src));
   1.176 +#ifdef SK_BUILD_FOR_ANDROID
   1.177 +    fGenerationID = oldGenerationID + 1;
   1.178 +
   1.179 +    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
   1.180 +#endif
   1.181 +
   1.182 +    return *this;
   1.183 +}
   1.184 +
   1.185 +bool operator==(const SkPaint& a, const SkPaint& b) {
   1.186 +#ifdef SK_BUILD_FOR_ANDROID
   1.187 +    //assumes that fGenerationID is the last field in the struct
   1.188 +    return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
   1.189 +#else
   1.190 +    return !memcmp(&a, &b, sizeof(a));
   1.191 +#endif
   1.192 +}
   1.193 +
   1.194 +void SkPaint::reset() {
   1.195 +    SkPaint init;
   1.196 +
   1.197 +#ifdef SK_BUILD_FOR_ANDROID
   1.198 +    uint32_t oldGenerationID = fGenerationID;
   1.199 +#endif
   1.200 +    *this = init;
   1.201 +#ifdef SK_BUILD_FOR_ANDROID
   1.202 +    fGenerationID = oldGenerationID + 1;
   1.203 +#endif
   1.204 +}
   1.205 +
   1.206 +#ifdef SK_BUILD_FOR_ANDROID
   1.207 +uint32_t SkPaint::getGenerationID() const {
   1.208 +    return fGenerationID;
   1.209 +}
   1.210 +
   1.211 +void SkPaint::setGenerationID(uint32_t generationID) {
   1.212 +    fGenerationID = generationID;
   1.213 +}
   1.214 +
   1.215 +unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
   1.216 +    SkAutoGlyphCache autoCache(*this, NULL, NULL);
   1.217 +    SkGlyphCache* cache = autoCache.getCache();
   1.218 +    return cache->getBaseGlyphCount(text);
   1.219 +}
   1.220 +
   1.221 +void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
   1.222 +    if (options != fPaintOptionsAndroid) {
   1.223 +        fPaintOptionsAndroid = options;
   1.224 +        GEN_ID_INC;
   1.225 +        fDirtyBits |= kPaintOptionsAndroid_DirtyBit;
   1.226 +    }
   1.227 +}
   1.228 +#endif
   1.229 +
   1.230 +SkPaint::FilterLevel SkPaint::getFilterLevel() const {
   1.231 +    int level = 0;
   1.232 +    if (fFlags & kFilterBitmap_Flag) {
   1.233 +        level |= 1;
   1.234 +    }
   1.235 +    if (fFlags & kHighQualityFilterBitmap_Flag) {
   1.236 +        level |= 2;
   1.237 +    }
   1.238 +    return (FilterLevel)level;
   1.239 +}
   1.240 +
   1.241 +void SkPaint::setFilterLevel(FilterLevel level) {
   1.242 +    unsigned mask = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag;
   1.243 +    unsigned flags = 0;
   1.244 +    if (level & 1) {
   1.245 +        flags |= kFilterBitmap_Flag;
   1.246 +    }
   1.247 +    if (level & 2) {
   1.248 +        flags |= kHighQualityFilterBitmap_Flag;
   1.249 +    }
   1.250 +    this->setFlags((fFlags & ~mask) | flags);
   1.251 +}
   1.252 +
   1.253 +void SkPaint::setHinting(Hinting hintingLevel) {
   1.254 +    GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
   1.255 +    fHinting = hintingLevel;
   1.256 +    fDirtyBits |= kBitfields_DirtyBit;
   1.257 +}
   1.258 +
   1.259 +void SkPaint::setFlags(uint32_t flags) {
   1.260 +    GEN_ID_INC_EVAL(fFlags != flags);
   1.261 +    fFlags = flags;
   1.262 +    fDirtyBits |= kBitfields_DirtyBit;
   1.263 +}
   1.264 +
   1.265 +void SkPaint::setAntiAlias(bool doAA) {
   1.266 +    this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
   1.267 +}
   1.268 +
   1.269 +void SkPaint::setDither(bool doDither) {
   1.270 +    this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
   1.271 +}
   1.272 +
   1.273 +void SkPaint::setSubpixelText(bool doSubpixel) {
   1.274 +    this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
   1.275 +}
   1.276 +
   1.277 +void SkPaint::setLCDRenderText(bool doLCDRender) {
   1.278 +    this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
   1.279 +}
   1.280 +
   1.281 +void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
   1.282 +    this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
   1.283 +}
   1.284 +
   1.285 +void SkPaint::setAutohinted(bool useAutohinter) {
   1.286 +    this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
   1.287 +}
   1.288 +
   1.289 +void SkPaint::setLinearText(bool doLinearText) {
   1.290 +    this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
   1.291 +}
   1.292 +
   1.293 +void SkPaint::setVerticalText(bool doVertical) {
   1.294 +    this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
   1.295 +}
   1.296 +
   1.297 +void SkPaint::setUnderlineText(bool doUnderline) {
   1.298 +    this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
   1.299 +}
   1.300 +
   1.301 +void SkPaint::setStrikeThruText(bool doStrikeThru) {
   1.302 +    this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
   1.303 +}
   1.304 +
   1.305 +void SkPaint::setFakeBoldText(bool doFakeBold) {
   1.306 +    this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
   1.307 +}
   1.308 +
   1.309 +void SkPaint::setDevKernText(bool doDevKern) {
   1.310 +    this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
   1.311 +}
   1.312 +
   1.313 +void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
   1.314 +    this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
   1.315 +}
   1.316 +
   1.317 +void SkPaint::setStyle(Style style) {
   1.318 +    if ((unsigned)style < kStyleCount) {
   1.319 +        GEN_ID_INC_EVAL((unsigned)style != fStyle);
   1.320 +        fStyle = style;
   1.321 +        fDirtyBits |= kBitfields_DirtyBit;
   1.322 +    } else {
   1.323 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.324 +        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
   1.325 +#endif
   1.326 +    }
   1.327 +}
   1.328 +
   1.329 +void SkPaint::setColor(SkColor color) {
   1.330 +    GEN_ID_INC_EVAL(color != fColor);
   1.331 +    fColor = color;
   1.332 +    fDirtyBits |= kColor_DirtyBit;
   1.333 +}
   1.334 +
   1.335 +void SkPaint::setAlpha(U8CPU a) {
   1.336 +    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
   1.337 +                                  SkColorGetG(fColor), SkColorGetB(fColor)));
   1.338 +}
   1.339 +
   1.340 +void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
   1.341 +    this->setColor(SkColorSetARGB(a, r, g, b));
   1.342 +}
   1.343 +
   1.344 +void SkPaint::setStrokeWidth(SkScalar width) {
   1.345 +    if (width >= 0) {
   1.346 +        GEN_ID_INC_EVAL(width != fWidth);
   1.347 +        fWidth = width;
   1.348 +        fDirtyBits |= kStrokeWidth_DirtyBit;
   1.349 +    } else {
   1.350 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.351 +        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
   1.352 +#endif
   1.353 +    }
   1.354 +}
   1.355 +
   1.356 +void SkPaint::setStrokeMiter(SkScalar limit) {
   1.357 +    if (limit >= 0) {
   1.358 +        GEN_ID_INC_EVAL(limit != fMiterLimit);
   1.359 +        fMiterLimit = limit;
   1.360 +        fDirtyBits |= kStrokeMiter_DirtyBit;
   1.361 +    } else {
   1.362 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.363 +        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
   1.364 +#endif
   1.365 +    }
   1.366 +}
   1.367 +
   1.368 +void SkPaint::setStrokeCap(Cap ct) {
   1.369 +    if ((unsigned)ct < kCapCount) {
   1.370 +        GEN_ID_INC_EVAL((unsigned)ct != fCapType);
   1.371 +        fCapType = SkToU8(ct);
   1.372 +        fDirtyBits |= kBitfields_DirtyBit;
   1.373 +    } else {
   1.374 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.375 +        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
   1.376 +#endif
   1.377 +    }
   1.378 +}
   1.379 +
   1.380 +void SkPaint::setStrokeJoin(Join jt) {
   1.381 +    if ((unsigned)jt < kJoinCount) {
   1.382 +        GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
   1.383 +        fJoinType = SkToU8(jt);
   1.384 +        fDirtyBits |= kBitfields_DirtyBit;
   1.385 +    } else {
   1.386 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.387 +        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
   1.388 +#endif
   1.389 +    }
   1.390 +}
   1.391 +
   1.392 +///////////////////////////////////////////////////////////////////////////////
   1.393 +
   1.394 +void SkPaint::setTextAlign(Align align) {
   1.395 +    if ((unsigned)align < kAlignCount) {
   1.396 +        GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
   1.397 +        fTextAlign = SkToU8(align);
   1.398 +        fDirtyBits |= kBitfields_DirtyBit;
   1.399 +    } else {
   1.400 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.401 +        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
   1.402 +#endif
   1.403 +    }
   1.404 +}
   1.405 +
   1.406 +void SkPaint::setTextSize(SkScalar ts) {
   1.407 +    if (ts >= 0) {
   1.408 +        GEN_ID_INC_EVAL(ts != fTextSize);
   1.409 +        fTextSize = ts;
   1.410 +        fDirtyBits |= kTextSize_DirtyBit;
   1.411 +    } else {
   1.412 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.413 +        SkDebugf("SkPaint::setTextSize() called with negative value\n");
   1.414 +#endif
   1.415 +    }
   1.416 +}
   1.417 +
   1.418 +void SkPaint::setTextScaleX(SkScalar scaleX) {
   1.419 +    GEN_ID_INC_EVAL(scaleX != fTextScaleX);
   1.420 +    fTextScaleX = scaleX;
   1.421 +    fDirtyBits |= kTextScaleX_DirtyBit;
   1.422 +}
   1.423 +
   1.424 +void SkPaint::setTextSkewX(SkScalar skewX) {
   1.425 +    GEN_ID_INC_EVAL(skewX != fTextSkewX);
   1.426 +    fTextSkewX = skewX;
   1.427 +    fDirtyBits |= kTextSkewX_DirtyBit;
   1.428 +}
   1.429 +
   1.430 +void SkPaint::setTextEncoding(TextEncoding encoding) {
   1.431 +    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
   1.432 +        GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
   1.433 +        fTextEncoding = encoding;
   1.434 +        fDirtyBits |= kBitfields_DirtyBit;
   1.435 +    } else {
   1.436 +#ifdef SK_REPORT_API_RANGE_CHECK
   1.437 +        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
   1.438 +#endif
   1.439 +    }
   1.440 +}
   1.441 +
   1.442 +///////////////////////////////////////////////////////////////////////////////
   1.443 +
   1.444 +// Returns dst with the given bitmask enabled or disabled, depending on value.
   1.445 +inline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
   1.446 +    return value ? (dst | bitmask) : (dst & ~bitmask);
   1.447 +}
   1.448 +
   1.449 +SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
   1.450 +    SkRefCnt_SafeAssign(fTypeface, font);
   1.451 +    GEN_ID_INC;
   1.452 +    fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
   1.453 +    return font;
   1.454 +}
   1.455 +
   1.456 +SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
   1.457 +    SkRefCnt_SafeAssign(fRasterizer, r);
   1.458 +    GEN_ID_INC;
   1.459 +    fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
   1.460 +    return r;
   1.461 +}
   1.462 +
   1.463 +SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
   1.464 +    SkRefCnt_SafeAssign(fLooper, looper);
   1.465 +    GEN_ID_INC;
   1.466 +    fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
   1.467 +    return looper;
   1.468 +}
   1.469 +
   1.470 +SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
   1.471 +    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
   1.472 +    GEN_ID_INC;
   1.473 +    fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
   1.474 +    return imageFilter;
   1.475 +}
   1.476 +
   1.477 +SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
   1.478 +    SkRefCnt_SafeAssign(fAnnotation, annotation);
   1.479 +    GEN_ID_INC;
   1.480 +    fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
   1.481 +    return annotation;
   1.482 +}
   1.483 +
   1.484 +///////////////////////////////////////////////////////////////////////////////
   1.485 +
   1.486 +static SkScalar mag2(SkScalar x, SkScalar y) {
   1.487 +    return x * x + y * y;
   1.488 +}
   1.489 +
   1.490 +static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
   1.491 +    return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
   1.492 +            ||
   1.493 +            mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
   1.494 +}
   1.495 +
   1.496 +bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
   1.497 +    SkASSERT(!ctm.hasPerspective());
   1.498 +    SkASSERT(!textM.hasPerspective());
   1.499 +
   1.500 +    SkMatrix matrix;
   1.501 +    matrix.setConcat(ctm, textM);
   1.502 +    return tooBig(matrix, MaxCacheSize2());
   1.503 +}
   1.504 +
   1.505 +bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
   1.506 +    SkMatrix textM;
   1.507 +    return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
   1.508 +}
   1.509 +
   1.510 +bool SkPaint::tooBigToUseCache() const {
   1.511 +    SkMatrix textM;
   1.512 +    return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
   1.513 +}
   1.514 +
   1.515 +///////////////////////////////////////////////////////////////////////////////
   1.516 +
   1.517 +#include "SkGlyphCache.h"
   1.518 +#include "SkUtils.h"
   1.519 +
   1.520 +static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
   1.521 +                           void* context) {
   1.522 +    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
   1.523 +}
   1.524 +
   1.525 +int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
   1.526 +                          uint16_t glyphs[]) const {
   1.527 +    if (byteLength == 0) {
   1.528 +        return 0;
   1.529 +    }
   1.530 +
   1.531 +    SkASSERT(textData != NULL);
   1.532 +
   1.533 +    if (NULL == glyphs) {
   1.534 +        switch (this->getTextEncoding()) {
   1.535 +        case kUTF8_TextEncoding:
   1.536 +            return SkUTF8_CountUnichars((const char*)textData, byteLength);
   1.537 +        case kUTF16_TextEncoding:
   1.538 +            return SkUTF16_CountUnichars((const uint16_t*)textData,
   1.539 +                                         byteLength >> 1);
   1.540 +        case kUTF32_TextEncoding:
   1.541 +            return byteLength >> 2;
   1.542 +        case kGlyphID_TextEncoding:
   1.543 +            return byteLength >> 1;
   1.544 +        default:
   1.545 +            SkDEBUGFAIL("unknown text encoding");
   1.546 +        }
   1.547 +        return 0;
   1.548 +    }
   1.549 +
   1.550 +    // if we get here, we have a valid glyphs[] array, so time to fill it in
   1.551 +
   1.552 +    // handle this encoding before the setup for the glyphcache
   1.553 +    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
   1.554 +        // we want to ignore the low bit of byteLength
   1.555 +        memcpy(glyphs, textData, byteLength >> 1 << 1);
   1.556 +        return byteLength >> 1;
   1.557 +    }
   1.558 +
   1.559 +    SkAutoGlyphCache autoCache(*this, NULL, NULL);
   1.560 +    SkGlyphCache*    cache = autoCache.getCache();
   1.561 +
   1.562 +    const char* text = (const char*)textData;
   1.563 +    const char* stop = text + byteLength;
   1.564 +    uint16_t*   gptr = glyphs;
   1.565 +
   1.566 +    switch (this->getTextEncoding()) {
   1.567 +        case SkPaint::kUTF8_TextEncoding:
   1.568 +            while (text < stop) {
   1.569 +                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
   1.570 +            }
   1.571 +            break;
   1.572 +        case SkPaint::kUTF16_TextEncoding: {
   1.573 +            const uint16_t* text16 = (const uint16_t*)text;
   1.574 +            const uint16_t* stop16 = (const uint16_t*)stop;
   1.575 +            while (text16 < stop16) {
   1.576 +                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
   1.577 +            }
   1.578 +            break;
   1.579 +        }
   1.580 +        case kUTF32_TextEncoding: {
   1.581 +            const int32_t* text32 = (const int32_t*)text;
   1.582 +            const int32_t* stop32 = (const int32_t*)stop;
   1.583 +            while (text32 < stop32) {
   1.584 +                *gptr++ = cache->unicharToGlyph(*text32++);
   1.585 +            }
   1.586 +            break;
   1.587 +        }
   1.588 +        default:
   1.589 +            SkDEBUGFAIL("unknown text encoding");
   1.590 +    }
   1.591 +    return gptr - glyphs;
   1.592 +}
   1.593 +
   1.594 +bool SkPaint::containsText(const void* textData, size_t byteLength) const {
   1.595 +    if (0 == byteLength) {
   1.596 +        return true;
   1.597 +    }
   1.598 +
   1.599 +    SkASSERT(textData != NULL);
   1.600 +
   1.601 +    // handle this encoding before the setup for the glyphcache
   1.602 +    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
   1.603 +        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
   1.604 +        size_t count = byteLength >> 1;
   1.605 +        for (size_t i = 0; i < count; i++) {
   1.606 +            if (0 == glyphID[i]) {
   1.607 +                return false;
   1.608 +            }
   1.609 +        }
   1.610 +        return true;
   1.611 +    }
   1.612 +
   1.613 +    SkAutoGlyphCache autoCache(*this, NULL, NULL);
   1.614 +    SkGlyphCache*    cache = autoCache.getCache();
   1.615 +
   1.616 +    switch (this->getTextEncoding()) {
   1.617 +        case SkPaint::kUTF8_TextEncoding: {
   1.618 +            const char* text = static_cast<const char*>(textData);
   1.619 +            const char* stop = text + byteLength;
   1.620 +            while (text < stop) {
   1.621 +                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
   1.622 +                    return false;
   1.623 +                }
   1.624 +            }
   1.625 +            break;
   1.626 +        }
   1.627 +        case SkPaint::kUTF16_TextEncoding: {
   1.628 +            const uint16_t* text = static_cast<const uint16_t*>(textData);
   1.629 +            const uint16_t* stop = text + (byteLength >> 1);
   1.630 +            while (text < stop) {
   1.631 +                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
   1.632 +                    return false;
   1.633 +                }
   1.634 +            }
   1.635 +            break;
   1.636 +        }
   1.637 +        case SkPaint::kUTF32_TextEncoding: {
   1.638 +            const int32_t* text = static_cast<const int32_t*>(textData);
   1.639 +            const int32_t* stop = text + (byteLength >> 2);
   1.640 +            while (text < stop) {
   1.641 +                if (0 == cache->unicharToGlyph(*text++)) {
   1.642 +                    return false;
   1.643 +                }
   1.644 +            }
   1.645 +            break;
   1.646 +        }
   1.647 +        default:
   1.648 +            SkDEBUGFAIL("unknown text encoding");
   1.649 +            return false;
   1.650 +    }
   1.651 +    return true;
   1.652 +}
   1.653 +
   1.654 +void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
   1.655 +                               SkUnichar textData[]) const {
   1.656 +    if (count <= 0) {
   1.657 +        return;
   1.658 +    }
   1.659 +
   1.660 +    SkASSERT(glyphs != NULL);
   1.661 +    SkASSERT(textData != NULL);
   1.662 +
   1.663 +    SkAutoGlyphCache autoCache(*this, NULL, NULL);
   1.664 +    SkGlyphCache*    cache = autoCache.getCache();
   1.665 +
   1.666 +    for (int index = 0; index < count; index++) {
   1.667 +        textData[index] = cache->glyphToUnichar(glyphs[index]);
   1.668 +    }
   1.669 +}
   1.670 +
   1.671 +///////////////////////////////////////////////////////////////////////////////
   1.672 +
   1.673 +static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
   1.674 +                                              const char** text) {
   1.675 +    SkASSERT(cache != NULL);
   1.676 +    SkASSERT(text != NULL);
   1.677 +
   1.678 +    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
   1.679 +}
   1.680 +
   1.681 +static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
   1.682 +                                              const char** text) {
   1.683 +    SkASSERT(cache != NULL);
   1.684 +    SkASSERT(text != NULL);
   1.685 +
   1.686 +    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
   1.687 +}
   1.688 +
   1.689 +static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
   1.690 +                                               const char** text) {
   1.691 +    SkASSERT(cache != NULL);
   1.692 +    SkASSERT(text != NULL);
   1.693 +
   1.694 +    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
   1.695 +}
   1.696 +
   1.697 +static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
   1.698 +                                               const char** text) {
   1.699 +    SkASSERT(cache != NULL);
   1.700 +    SkASSERT(text != NULL);
   1.701 +
   1.702 +    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
   1.703 +}
   1.704 +
   1.705 +static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
   1.706 +                                               const char** text) {
   1.707 +    SkASSERT(cache != NULL);
   1.708 +    SkASSERT(text != NULL);
   1.709 +
   1.710 +    const int32_t* ptr = *(const int32_t**)text;
   1.711 +    SkUnichar uni = *ptr++;
   1.712 +    *text = (const char*)ptr;
   1.713 +    return cache->getUnicharMetrics(uni);
   1.714 +}
   1.715 +
   1.716 +static const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
   1.717 +                                               const char** text) {
   1.718 +    SkASSERT(cache != NULL);
   1.719 +    SkASSERT(text != NULL);
   1.720 +
   1.721 +    const int32_t* ptr = *(const int32_t**)text;
   1.722 +    SkUnichar uni = *--ptr;
   1.723 +    *text = (const char*)ptr;
   1.724 +    return cache->getUnicharMetrics(uni);
   1.725 +}
   1.726 +
   1.727 +static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
   1.728 +                                               const char** text) {
   1.729 +    SkASSERT(cache != NULL);
   1.730 +    SkASSERT(text != NULL);
   1.731 +
   1.732 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.733 +    unsigned glyphID = *ptr;
   1.734 +    ptr += 1;
   1.735 +    *text = (const char*)ptr;
   1.736 +    return cache->getGlyphIDMetrics(glyphID);
   1.737 +}
   1.738 +
   1.739 +static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
   1.740 +                                               const char** text) {
   1.741 +    SkASSERT(cache != NULL);
   1.742 +    SkASSERT(text != NULL);
   1.743 +
   1.744 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.745 +    ptr -= 1;
   1.746 +    unsigned glyphID = *ptr;
   1.747 +    *text = (const char*)ptr;
   1.748 +    return cache->getGlyphIDMetrics(glyphID);
   1.749 +}
   1.750 +
   1.751 +static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
   1.752 +                                              const char** text) {
   1.753 +    SkASSERT(cache != NULL);
   1.754 +    SkASSERT(text != NULL);
   1.755 +
   1.756 +    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
   1.757 +}
   1.758 +
   1.759 +static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
   1.760 +                                              const char** text) {
   1.761 +    SkASSERT(cache != NULL);
   1.762 +    SkASSERT(text != NULL);
   1.763 +
   1.764 +    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
   1.765 +}
   1.766 +
   1.767 +static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
   1.768 +                                               const char** text) {
   1.769 +    SkASSERT(cache != NULL);
   1.770 +    SkASSERT(text != NULL);
   1.771 +
   1.772 +    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
   1.773 +}
   1.774 +
   1.775 +static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
   1.776 +                                               const char** text) {
   1.777 +    SkASSERT(cache != NULL);
   1.778 +    SkASSERT(text != NULL);
   1.779 +
   1.780 +    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
   1.781 +}
   1.782 +
   1.783 +static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
   1.784 +                                               const char** text) {
   1.785 +    SkASSERT(cache != NULL);
   1.786 +    SkASSERT(text != NULL);
   1.787 +
   1.788 +    const int32_t* ptr = *(const int32_t**)text;
   1.789 +    SkUnichar uni = *ptr++;
   1.790 +    *text = (const char*)ptr;
   1.791 +    return cache->getUnicharAdvance(uni);
   1.792 +}
   1.793 +
   1.794 +static const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
   1.795 +                                               const char** text) {
   1.796 +    SkASSERT(cache != NULL);
   1.797 +    SkASSERT(text != NULL);
   1.798 +
   1.799 +    const int32_t* ptr = *(const int32_t**)text;
   1.800 +    SkUnichar uni = *--ptr;
   1.801 +    *text = (const char*)ptr;
   1.802 +    return cache->getUnicharAdvance(uni);
   1.803 +}
   1.804 +
   1.805 +static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
   1.806 +                                               const char** text) {
   1.807 +    SkASSERT(cache != NULL);
   1.808 +    SkASSERT(text != NULL);
   1.809 +
   1.810 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.811 +    unsigned glyphID = *ptr;
   1.812 +    ptr += 1;
   1.813 +    *text = (const char*)ptr;
   1.814 +    return cache->getGlyphIDAdvance(glyphID);
   1.815 +}
   1.816 +
   1.817 +static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
   1.818 +                                               const char** text) {
   1.819 +    SkASSERT(cache != NULL);
   1.820 +    SkASSERT(text != NULL);
   1.821 +
   1.822 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.823 +    ptr -= 1;
   1.824 +    unsigned glyphID = *ptr;
   1.825 +    *text = (const char*)ptr;
   1.826 +    return cache->getGlyphIDAdvance(glyphID);
   1.827 +}
   1.828 +
   1.829 +SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
   1.830 +                                                bool needFullMetrics) const {
   1.831 +    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
   1.832 +        sk_getMetrics_utf8_next,
   1.833 +        sk_getMetrics_utf16_next,
   1.834 +        sk_getMetrics_utf32_next,
   1.835 +        sk_getMetrics_glyph_next,
   1.836 +
   1.837 +        sk_getMetrics_utf8_prev,
   1.838 +        sk_getMetrics_utf16_prev,
   1.839 +        sk_getMetrics_utf32_prev,
   1.840 +        sk_getMetrics_glyph_prev,
   1.841 +
   1.842 +        sk_getAdvance_utf8_next,
   1.843 +        sk_getAdvance_utf16_next,
   1.844 +        sk_getAdvance_utf32_next,
   1.845 +        sk_getAdvance_glyph_next,
   1.846 +
   1.847 +        sk_getAdvance_utf8_prev,
   1.848 +        sk_getAdvance_utf16_prev,
   1.849 +        sk_getAdvance_utf32_prev,
   1.850 +        sk_getAdvance_glyph_prev
   1.851 +    };
   1.852 +
   1.853 +    unsigned index = this->getTextEncoding();
   1.854 +
   1.855 +    if (kBackward_TextBufferDirection == tbd) {
   1.856 +        index += 4;
   1.857 +    }
   1.858 +    if (!needFullMetrics && !this->isDevKernText()) {
   1.859 +        index += 8;
   1.860 +    }
   1.861 +
   1.862 +    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
   1.863 +    return gMeasureCacheProcs[index];
   1.864 +}
   1.865 +
   1.866 +///////////////////////////////////////////////////////////////////////////////
   1.867 +
   1.868 +static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
   1.869 +                                        const char** text, SkFixed, SkFixed) {
   1.870 +    SkASSERT(cache != NULL);
   1.871 +    SkASSERT(text != NULL);
   1.872 +
   1.873 +    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
   1.874 +}
   1.875 +
   1.876 +static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
   1.877 +                                    const char** text, SkFixed x, SkFixed y) {
   1.878 +    SkASSERT(cache != NULL);
   1.879 +    SkASSERT(text != NULL);
   1.880 +
   1.881 +    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
   1.882 +}
   1.883 +
   1.884 +static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
   1.885 +                                        const char** text, SkFixed, SkFixed) {
   1.886 +    SkASSERT(cache != NULL);
   1.887 +    SkASSERT(text != NULL);
   1.888 +
   1.889 +    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
   1.890 +}
   1.891 +
   1.892 +static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
   1.893 +                                     const char** text, SkFixed x, SkFixed y) {
   1.894 +    SkASSERT(cache != NULL);
   1.895 +    SkASSERT(text != NULL);
   1.896 +
   1.897 +    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
   1.898 +                                    x, y);
   1.899 +}
   1.900 +
   1.901 +static const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
   1.902 +                                    const char** text, SkFixed, SkFixed) {
   1.903 +    SkASSERT(cache != NULL);
   1.904 +    SkASSERT(text != NULL);
   1.905 +
   1.906 +    const int32_t* ptr = *(const int32_t**)text;
   1.907 +    SkUnichar uni = *ptr++;
   1.908 +    *text = (const char*)ptr;
   1.909 +    return cache->getUnicharMetrics(uni);
   1.910 +}
   1.911 +
   1.912 +static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
   1.913 +                                    const char** text, SkFixed x, SkFixed y) {
   1.914 +    SkASSERT(cache != NULL);
   1.915 +    SkASSERT(text != NULL);
   1.916 +
   1.917 +    const int32_t* ptr = *(const int32_t**)text;
   1.918 +    SkUnichar uni = *--ptr;
   1.919 +    *text = (const char*)ptr;
   1.920 +    return cache->getUnicharMetrics(uni, x, y);
   1.921 +}
   1.922 +
   1.923 +static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
   1.924 +                                         const char** text, SkFixed, SkFixed) {
   1.925 +    SkASSERT(cache != NULL);
   1.926 +    SkASSERT(text != NULL);
   1.927 +
   1.928 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.929 +    unsigned glyphID = *ptr;
   1.930 +    ptr += 1;
   1.931 +    *text = (const char*)ptr;
   1.932 +    return cache->getGlyphIDMetrics(glyphID);
   1.933 +}
   1.934 +
   1.935 +static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
   1.936 +                                     const char** text, SkFixed x, SkFixed y) {
   1.937 +    SkASSERT(cache != NULL);
   1.938 +    SkASSERT(text != NULL);
   1.939 +
   1.940 +    const uint16_t* ptr = *(const uint16_t**)text;
   1.941 +    unsigned glyphID = *ptr;
   1.942 +    ptr += 1;
   1.943 +    *text = (const char*)ptr;
   1.944 +    return cache->getGlyphIDMetrics(glyphID, x, y);
   1.945 +}
   1.946 +
   1.947 +SkDrawCacheProc SkPaint::getDrawCacheProc() const {
   1.948 +    static const SkDrawCacheProc gDrawCacheProcs[] = {
   1.949 +        sk_getMetrics_utf8_00,
   1.950 +        sk_getMetrics_utf16_00,
   1.951 +        sk_getMetrics_utf32_00,
   1.952 +        sk_getMetrics_glyph_00,
   1.953 +
   1.954 +        sk_getMetrics_utf8_xy,
   1.955 +        sk_getMetrics_utf16_xy,
   1.956 +        sk_getMetrics_utf32_xy,
   1.957 +        sk_getMetrics_glyph_xy
   1.958 +    };
   1.959 +
   1.960 +    unsigned index = this->getTextEncoding();
   1.961 +    if (fFlags & kSubpixelText_Flag) {
   1.962 +        index += 4;
   1.963 +    }
   1.964 +
   1.965 +    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
   1.966 +    return gDrawCacheProcs[index];
   1.967 +}
   1.968 +
   1.969 +///////////////////////////////////////////////////////////////////////////////
   1.970 +
   1.971 +#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
   1.972 +SkPaint::kDevKernText_Flag          |       \
   1.973 +SkPaint::kLinearText_Flag           |       \
   1.974 +SkPaint::kLCDRenderText_Flag        |       \
   1.975 +SkPaint::kEmbeddedBitmapText_Flag   |       \
   1.976 +SkPaint::kAutoHinting_Flag          |       \
   1.977 +SkPaint::kGenA8FromLCD_Flag )
   1.978 +
   1.979 +SkScalar SkPaint::setupForAsPaths() {
   1.980 +    uint32_t flags = this->getFlags();
   1.981 +    // clear the flags we don't care about
   1.982 +    flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
   1.983 +    // set the flags we do care about
   1.984 +    flags |= SkPaint::kSubpixelText_Flag;
   1.985 +
   1.986 +    this->setFlags(flags);
   1.987 +    this->setHinting(SkPaint::kNo_Hinting);
   1.988 +
   1.989 +    SkScalar textSize = fTextSize;
   1.990 +    this->setTextSize(kCanonicalTextSizeForPaths);
   1.991 +    return textSize / kCanonicalTextSizeForPaths;
   1.992 +}
   1.993 +
   1.994 +class SkCanonicalizePaint {
   1.995 +public:
   1.996 +    SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
   1.997 +        if (paint.isLinearText() || paint.tooBigToUseCache()) {
   1.998 +            SkPaint* p = fLazy.set(paint);
   1.999 +            fScale = p->setupForAsPaths();
  1.1000 +            fPaint = p;
  1.1001 +        }
  1.1002 +    }
  1.1003 +
  1.1004 +    const SkPaint& getPaint() const { return *fPaint; }
  1.1005 +
  1.1006 +    /**
  1.1007 +     *  Returns 0 if the paint was unmodified, or the scale factor need to
  1.1008 +     *  the original textSize
  1.1009 +     */
  1.1010 +    SkScalar getScale() const { return fScale; }
  1.1011 +
  1.1012 +private:
  1.1013 +    const SkPaint*   fPaint;
  1.1014 +    SkScalar         fScale;
  1.1015 +    SkTLazy<SkPaint> fLazy;
  1.1016 +};
  1.1017 +
  1.1018 +static void set_bounds(const SkGlyph& g, SkRect* bounds) {
  1.1019 +    bounds->set(SkIntToScalar(g.fLeft),
  1.1020 +                SkIntToScalar(g.fTop),
  1.1021 +                SkIntToScalar(g.fLeft + g.fWidth),
  1.1022 +                SkIntToScalar(g.fTop + g.fHeight));
  1.1023 +}
  1.1024 +
  1.1025 +// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
  1.1026 +// we don't overflow along the way
  1.1027 +typedef int64_t Sk48Dot16;
  1.1028 +
  1.1029 +static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
  1.1030 +    return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
  1.1031 +}
  1.1032 +
  1.1033 +static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
  1.1034 +    SkScalar sx = Sk48Dot16ToScalar(dx);
  1.1035 +    bounds->join(SkIntToScalar(g.fLeft) + sx,
  1.1036 +                 SkIntToScalar(g.fTop),
  1.1037 +                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
  1.1038 +                 SkIntToScalar(g.fTop + g.fHeight));
  1.1039 +}
  1.1040 +
  1.1041 +static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
  1.1042 +    SkScalar sy = Sk48Dot16ToScalar(dy);
  1.1043 +    bounds->join(SkIntToScalar(g.fLeft),
  1.1044 +                 SkIntToScalar(g.fTop) + sy,
  1.1045 +                 SkIntToScalar(g.fLeft + g.fWidth),
  1.1046 +                 SkIntToScalar(g.fTop + g.fHeight) + sy);
  1.1047 +}
  1.1048 +
  1.1049 +typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
  1.1050 +
  1.1051 +// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
  1.1052 +static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
  1.1053 +    SkASSERT(0 == xyIndex || 1 == xyIndex);
  1.1054 +    return (&glyph.fAdvanceX)[xyIndex];
  1.1055 +}
  1.1056 +
  1.1057 +SkScalar SkPaint::measure_text(SkGlyphCache* cache,
  1.1058 +                               const char* text, size_t byteLength,
  1.1059 +                               int* count, SkRect* bounds) const {
  1.1060 +    SkASSERT(count);
  1.1061 +    if (byteLength == 0) {
  1.1062 +        *count = 0;
  1.1063 +        if (bounds) {
  1.1064 +            bounds->setEmpty();
  1.1065 +        }
  1.1066 +        return 0;
  1.1067 +    }
  1.1068 +
  1.1069 +    SkMeasureCacheProc glyphCacheProc;
  1.1070 +    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
  1.1071 +                                               NULL != bounds);
  1.1072 +
  1.1073 +    int xyIndex;
  1.1074 +    JoinBoundsProc joinBoundsProc;
  1.1075 +    if (this->isVerticalText()) {
  1.1076 +        xyIndex = 1;
  1.1077 +        joinBoundsProc = join_bounds_y;
  1.1078 +    } else {
  1.1079 +        xyIndex = 0;
  1.1080 +        joinBoundsProc = join_bounds_x;
  1.1081 +    }
  1.1082 +
  1.1083 +    int         n = 1;
  1.1084 +    const char* stop = (const char*)text + byteLength;
  1.1085 +    const SkGlyph* g = &glyphCacheProc(cache, &text);
  1.1086 +    // our accumulated fixed-point advances might overflow 16.16, so we use
  1.1087 +    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
  1.1088 +    // very end.
  1.1089 +    Sk48Dot16 x = advance(*g, xyIndex);
  1.1090 +
  1.1091 +    SkAutoKern  autokern;
  1.1092 +
  1.1093 +    if (NULL == bounds) {
  1.1094 +        if (this->isDevKernText()) {
  1.1095 +            int rsb;
  1.1096 +            for (; text < stop; n++) {
  1.1097 +                rsb = g->fRsbDelta;
  1.1098 +                g = &glyphCacheProc(cache, &text);
  1.1099 +                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
  1.1100 +            }
  1.1101 +        } else {
  1.1102 +            for (; text < stop; n++) {
  1.1103 +                x += advance(glyphCacheProc(cache, &text), xyIndex);
  1.1104 +            }
  1.1105 +        }
  1.1106 +    } else {
  1.1107 +        set_bounds(*g, bounds);
  1.1108 +        if (this->isDevKernText()) {
  1.1109 +            int rsb;
  1.1110 +            for (; text < stop; n++) {
  1.1111 +                rsb = g->fRsbDelta;
  1.1112 +                g = &glyphCacheProc(cache, &text);
  1.1113 +                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
  1.1114 +                joinBoundsProc(*g, bounds, x);
  1.1115 +                x += advance(*g, xyIndex);
  1.1116 +            }
  1.1117 +        } else {
  1.1118 +            for (; text < stop; n++) {
  1.1119 +                g = &glyphCacheProc(cache, &text);
  1.1120 +                joinBoundsProc(*g, bounds, x);
  1.1121 +                x += advance(*g, xyIndex);
  1.1122 +            }
  1.1123 +        }
  1.1124 +    }
  1.1125 +    SkASSERT(text == stop);
  1.1126 +
  1.1127 +    *count = n;
  1.1128 +    return Sk48Dot16ToScalar(x);
  1.1129 +}
  1.1130 +
  1.1131 +SkScalar SkPaint::measureText(const void* textData, size_t length,
  1.1132 +                              SkRect* bounds, SkScalar zoom) const {
  1.1133 +    const char* text = (const char*)textData;
  1.1134 +    SkASSERT(text != NULL || length == 0);
  1.1135 +
  1.1136 +    SkCanonicalizePaint canon(*this);
  1.1137 +    const SkPaint& paint = canon.getPaint();
  1.1138 +    SkScalar scale = canon.getScale();
  1.1139 +
  1.1140 +    SkMatrix zoomMatrix, *zoomPtr = NULL;
  1.1141 +    if (zoom) {
  1.1142 +        zoomMatrix.setScale(zoom, zoom);
  1.1143 +        zoomPtr = &zoomMatrix;
  1.1144 +    }
  1.1145 +
  1.1146 +    SkAutoGlyphCache    autoCache(paint, NULL, zoomPtr);
  1.1147 +    SkGlyphCache*       cache = autoCache.getCache();
  1.1148 +
  1.1149 +    SkScalar width = 0;
  1.1150 +
  1.1151 +    if (length > 0) {
  1.1152 +        int tempCount;
  1.1153 +
  1.1154 +        width = paint.measure_text(cache, text, length, &tempCount, bounds);
  1.1155 +        if (scale) {
  1.1156 +            width = SkScalarMul(width, scale);
  1.1157 +            if (bounds) {
  1.1158 +                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
  1.1159 +                bounds->fTop = SkScalarMul(bounds->fTop, scale);
  1.1160 +                bounds->fRight = SkScalarMul(bounds->fRight, scale);
  1.1161 +                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
  1.1162 +            }
  1.1163 +        }
  1.1164 +    } else if (bounds) {
  1.1165 +        // ensure that even if we don't measure_text we still update the bounds
  1.1166 +        bounds->setEmpty();
  1.1167 +    }
  1.1168 +    return width;
  1.1169 +}
  1.1170 +
  1.1171 +typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
  1.1172 +
  1.1173 +static bool forward_textBufferPred(const char* text, const char* stop) {
  1.1174 +    return text < stop;
  1.1175 +}
  1.1176 +
  1.1177 +static bool backward_textBufferPred(const char* text, const char* stop) {
  1.1178 +    return text > stop;
  1.1179 +}
  1.1180 +
  1.1181 +static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
  1.1182 +                                             const char** text, size_t length,
  1.1183 +                                             const char** stop) {
  1.1184 +    if (SkPaint::kForward_TextBufferDirection == tbd) {
  1.1185 +        *stop = *text + length;
  1.1186 +        return forward_textBufferPred;
  1.1187 +    } else {
  1.1188 +        // text should point to the end of the buffer, and stop to the beginning
  1.1189 +        *stop = *text;
  1.1190 +        *text += length;
  1.1191 +        return backward_textBufferPred;
  1.1192 +    }
  1.1193 +}
  1.1194 +
  1.1195 +size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
  1.1196 +                          SkScalar* measuredWidth,
  1.1197 +                          TextBufferDirection tbd) const {
  1.1198 +    if (0 == length || 0 >= maxWidth) {
  1.1199 +        if (measuredWidth) {
  1.1200 +            *measuredWidth = 0;
  1.1201 +        }
  1.1202 +        return 0;
  1.1203 +    }
  1.1204 +
  1.1205 +    if (0 == fTextSize) {
  1.1206 +        if (measuredWidth) {
  1.1207 +            *measuredWidth = 0;
  1.1208 +        }
  1.1209 +        return length;
  1.1210 +    }
  1.1211 +
  1.1212 +    SkASSERT(textD != NULL);
  1.1213 +    const char* text = (const char*)textD;
  1.1214 +
  1.1215 +    SkCanonicalizePaint canon(*this);
  1.1216 +    const SkPaint& paint = canon.getPaint();
  1.1217 +    SkScalar scale = canon.getScale();
  1.1218 +
  1.1219 +    // adjust max in case we changed the textSize in paint
  1.1220 +    if (scale) {
  1.1221 +        maxWidth /= scale;
  1.1222 +    }
  1.1223 +
  1.1224 +    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
  1.1225 +    SkGlyphCache*       cache = autoCache.getCache();
  1.1226 +
  1.1227 +    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
  1.1228 +    const char*      stop;
  1.1229 +    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
  1.1230 +    const int        xyIndex = paint.isVerticalText() ? 1 : 0;
  1.1231 +    // use 64bits for our accumulator, to avoid overflowing 16.16
  1.1232 +    Sk48Dot16        max = SkScalarToFixed(maxWidth);
  1.1233 +    Sk48Dot16        width = 0;
  1.1234 +
  1.1235 +    SkAutoKern  autokern;
  1.1236 +
  1.1237 +    if (this->isDevKernText()) {
  1.1238 +        int rsb = 0;
  1.1239 +        while (pred(text, stop)) {
  1.1240 +            const char* curr = text;
  1.1241 +            const SkGlyph& g = glyphCacheProc(cache, &text);
  1.1242 +            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
  1.1243 +            if ((width += x) > max) {
  1.1244 +                width -= x;
  1.1245 +                text = curr;
  1.1246 +                break;
  1.1247 +            }
  1.1248 +            rsb = g.fRsbDelta;
  1.1249 +        }
  1.1250 +    } else {
  1.1251 +        while (pred(text, stop)) {
  1.1252 +            const char* curr = text;
  1.1253 +            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
  1.1254 +            if ((width += x) > max) {
  1.1255 +                width -= x;
  1.1256 +                text = curr;
  1.1257 +                break;
  1.1258 +            }
  1.1259 +        }
  1.1260 +    }
  1.1261 +
  1.1262 +    if (measuredWidth) {
  1.1263 +        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
  1.1264 +        if (scale) {
  1.1265 +            scalarWidth = SkScalarMul(scalarWidth, scale);
  1.1266 +        }
  1.1267 +        *measuredWidth = scalarWidth;
  1.1268 +    }
  1.1269 +
  1.1270 +    // return the number of bytes measured
  1.1271 +    return (kForward_TextBufferDirection == tbd) ?
  1.1272 +                text - stop + length : stop - text + length;
  1.1273 +}
  1.1274 +
  1.1275 +///////////////////////////////////////////////////////////////////////////////
  1.1276 +
  1.1277 +static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
  1.1278 +    *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
  1.1279 +    return false;   // don't detach the cache
  1.1280 +}
  1.1281 +
  1.1282 +static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
  1.1283 +                                void* context) {
  1.1284 +    SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
  1.1285 +}
  1.1286 +
  1.1287 +SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
  1.1288 +    SkCanonicalizePaint canon(*this);
  1.1289 +    const SkPaint& paint = canon.getPaint();
  1.1290 +    SkScalar scale = canon.getScale();
  1.1291 +
  1.1292 +    SkMatrix zoomMatrix, *zoomPtr = NULL;
  1.1293 +    if (zoom) {
  1.1294 +        zoomMatrix.setScale(zoom, zoom);
  1.1295 +        zoomPtr = &zoomMatrix;
  1.1296 +    }
  1.1297 +
  1.1298 +    FontMetrics storage;
  1.1299 +    if (NULL == metrics) {
  1.1300 +        metrics = &storage;
  1.1301 +    }
  1.1302 +
  1.1303 +    paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
  1.1304 +
  1.1305 +    if (scale) {
  1.1306 +        metrics->fTop = SkScalarMul(metrics->fTop, scale);
  1.1307 +        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
  1.1308 +        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
  1.1309 +        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
  1.1310 +        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
  1.1311 +        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
  1.1312 +        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
  1.1313 +        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
  1.1314 +        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
  1.1315 +        metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
  1.1316 +        metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
  1.1317 +    }
  1.1318 +    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
  1.1319 +}
  1.1320 +
  1.1321 +///////////////////////////////////////////////////////////////////////////////
  1.1322 +
  1.1323 +static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
  1.1324 +    bounds->set(g.fLeft * scale,
  1.1325 +                g.fTop * scale,
  1.1326 +                (g.fLeft + g.fWidth) * scale,
  1.1327 +                (g.fTop + g.fHeight) * scale);
  1.1328 +}
  1.1329 +
  1.1330 +int SkPaint::getTextWidths(const void* textData, size_t byteLength,
  1.1331 +                           SkScalar widths[], SkRect bounds[]) const {
  1.1332 +    if (0 == byteLength) {
  1.1333 +        return 0;
  1.1334 +    }
  1.1335 +
  1.1336 +    SkASSERT(NULL != textData);
  1.1337 +
  1.1338 +    if (NULL == widths && NULL == bounds) {
  1.1339 +        return this->countText(textData, byteLength);
  1.1340 +    }
  1.1341 +
  1.1342 +    SkCanonicalizePaint canon(*this);
  1.1343 +    const SkPaint& paint = canon.getPaint();
  1.1344 +    SkScalar scale = canon.getScale();
  1.1345 +
  1.1346 +    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
  1.1347 +    SkGlyphCache*       cache = autoCache.getCache();
  1.1348 +    SkMeasureCacheProc  glyphCacheProc;
  1.1349 +    glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
  1.1350 +                                               NULL != bounds);
  1.1351 +
  1.1352 +    const char* text = (const char*)textData;
  1.1353 +    const char* stop = text + byteLength;
  1.1354 +    int         count = 0;
  1.1355 +    const int   xyIndex = paint.isVerticalText() ? 1 : 0;
  1.1356 +
  1.1357 +    if (this->isDevKernText()) {
  1.1358 +        // we adjust the widths returned here through auto-kerning
  1.1359 +        SkAutoKern  autokern;
  1.1360 +        SkFixed     prevWidth = 0;
  1.1361 +
  1.1362 +        if (scale) {
  1.1363 +            while (text < stop) {
  1.1364 +                const SkGlyph& g = glyphCacheProc(cache, &text);
  1.1365 +                if (widths) {
  1.1366 +                    SkFixed  adjust = autokern.adjust(g);
  1.1367 +
  1.1368 +                    if (count > 0) {
  1.1369 +                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
  1.1370 +                        *widths++ = SkScalarMul(w, scale);
  1.1371 +                    }
  1.1372 +                    prevWidth = advance(g, xyIndex);
  1.1373 +                }
  1.1374 +                if (bounds) {
  1.1375 +                    set_bounds(g, bounds++, scale);
  1.1376 +                }
  1.1377 +                ++count;
  1.1378 +            }
  1.1379 +            if (count > 0 && widths) {
  1.1380 +                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
  1.1381 +            }
  1.1382 +        } else {
  1.1383 +            while (text < stop) {
  1.1384 +                const SkGlyph& g = glyphCacheProc(cache, &text);
  1.1385 +                if (widths) {
  1.1386 +                    SkFixed  adjust = autokern.adjust(g);
  1.1387 +
  1.1388 +                    if (count > 0) {
  1.1389 +                        *widths++ = SkFixedToScalar(prevWidth + adjust);
  1.1390 +                    }
  1.1391 +                    prevWidth = advance(g, xyIndex);
  1.1392 +                }
  1.1393 +                if (bounds) {
  1.1394 +                    set_bounds(g, bounds++);
  1.1395 +                }
  1.1396 +                ++count;
  1.1397 +            }
  1.1398 +            if (count > 0 && widths) {
  1.1399 +                *widths = SkFixedToScalar(prevWidth);
  1.1400 +            }
  1.1401 +        }
  1.1402 +    } else {    // no devkern
  1.1403 +        if (scale) {
  1.1404 +            while (text < stop) {
  1.1405 +                const SkGlyph& g = glyphCacheProc(cache, &text);
  1.1406 +                if (widths) {
  1.1407 +                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
  1.1408 +                                            scale);
  1.1409 +                }
  1.1410 +                if (bounds) {
  1.1411 +                    set_bounds(g, bounds++, scale);
  1.1412 +                }
  1.1413 +                ++count;
  1.1414 +            }
  1.1415 +        } else {
  1.1416 +            while (text < stop) {
  1.1417 +                const SkGlyph& g = glyphCacheProc(cache, &text);
  1.1418 +                if (widths) {
  1.1419 +                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
  1.1420 +                }
  1.1421 +                if (bounds) {
  1.1422 +                    set_bounds(g, bounds++);
  1.1423 +                }
  1.1424 +                ++count;
  1.1425 +            }
  1.1426 +        }
  1.1427 +    }
  1.1428 +
  1.1429 +    SkASSERT(text == stop);
  1.1430 +    return count;
  1.1431 +}
  1.1432 +
  1.1433 +///////////////////////////////////////////////////////////////////////////////
  1.1434 +
  1.1435 +#include "SkDraw.h"
  1.1436 +
  1.1437 +void SkPaint::getTextPath(const void* textData, size_t length,
  1.1438 +                          SkScalar x, SkScalar y, SkPath* path) const {
  1.1439 +    SkASSERT(length == 0 || textData != NULL);
  1.1440 +
  1.1441 +    const char* text = (const char*)textData;
  1.1442 +    if (text == NULL || length == 0 || path == NULL) {
  1.1443 +        return;
  1.1444 +    }
  1.1445 +
  1.1446 +    SkTextToPathIter    iter(text, length, *this, false);
  1.1447 +    SkMatrix            matrix;
  1.1448 +    SkScalar            prevXPos = 0;
  1.1449 +
  1.1450 +    matrix.setScale(iter.getPathScale(), iter.getPathScale());
  1.1451 +    matrix.postTranslate(x, y);
  1.1452 +    path->reset();
  1.1453 +
  1.1454 +    SkScalar        xpos;
  1.1455 +    const SkPath*   iterPath;
  1.1456 +    while (iter.next(&iterPath, &xpos)) {
  1.1457 +        matrix.postTranslate(xpos - prevXPos, 0);
  1.1458 +        if (iterPath) {
  1.1459 +            path->addPath(*iterPath, matrix);
  1.1460 +        }
  1.1461 +        prevXPos = xpos;
  1.1462 +    }
  1.1463 +}
  1.1464 +
  1.1465 +void SkPaint::getPosTextPath(const void* textData, size_t length,
  1.1466 +                             const SkPoint pos[], SkPath* path) const {
  1.1467 +    SkASSERT(length == 0 || textData != NULL);
  1.1468 +
  1.1469 +    const char* text = (const char*)textData;
  1.1470 +    if (text == NULL || length == 0 || path == NULL) {
  1.1471 +        return;
  1.1472 +    }
  1.1473 +
  1.1474 +    SkTextToPathIter    iter(text, length, *this, false);
  1.1475 +    SkMatrix            matrix;
  1.1476 +    SkPoint             prevPos;
  1.1477 +    prevPos.set(0, 0);
  1.1478 +
  1.1479 +    matrix.setScale(iter.getPathScale(), iter.getPathScale());
  1.1480 +    path->reset();
  1.1481 +
  1.1482 +    unsigned int    i = 0;
  1.1483 +    const SkPath*   iterPath;
  1.1484 +    while (iter.next(&iterPath, NULL)) {
  1.1485 +        matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
  1.1486 +        if (iterPath) {
  1.1487 +            path->addPath(*iterPath, matrix);
  1.1488 +        }
  1.1489 +        prevPos = pos[i];
  1.1490 +        i++;
  1.1491 +    }
  1.1492 +}
  1.1493 +
  1.1494 +static void add_flattenable(SkDescriptor* desc, uint32_t tag,
  1.1495 +                            SkWriteBuffer* buffer) {
  1.1496 +    buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
  1.1497 +}
  1.1498 +
  1.1499 +// SkFontHost can override this choice in FilterRec()
  1.1500 +static SkMask::Format computeMaskFormat(const SkPaint& paint) {
  1.1501 +    uint32_t flags = paint.getFlags();
  1.1502 +
  1.1503 +    // Antialiasing being disabled trumps all other settings.
  1.1504 +    if (!(flags & SkPaint::kAntiAlias_Flag)) {
  1.1505 +        return SkMask::kBW_Format;
  1.1506 +    }
  1.1507 +
  1.1508 +    if (flags & SkPaint::kLCDRenderText_Flag) {
  1.1509 +        return SkMask::kLCD16_Format;
  1.1510 +    }
  1.1511 +
  1.1512 +    return SkMask::kA8_Format;
  1.1513 +}
  1.1514 +
  1.1515 +// if linear-text is on, then we force hinting to be off (since that's sort of
  1.1516 +// the point of linear-text.
  1.1517 +static SkPaint::Hinting computeHinting(const SkPaint& paint) {
  1.1518 +    SkPaint::Hinting h = paint.getHinting();
  1.1519 +    if (paint.isLinearText()) {
  1.1520 +        h = SkPaint::kNo_Hinting;
  1.1521 +    }
  1.1522 +    return h;
  1.1523 +}
  1.1524 +
  1.1525 +// return true if the paint is just a single color (i.e. not a shader). If its
  1.1526 +// a shader, then we can't compute a const luminance for it :(
  1.1527 +static bool justAColor(const SkPaint& paint, SkColor* color) {
  1.1528 +    if (paint.getShader()) {
  1.1529 +        return false;
  1.1530 +    }
  1.1531 +    SkColor c = paint.getColor();
  1.1532 +    if (paint.getColorFilter()) {
  1.1533 +        c = paint.getColorFilter()->filterColor(c);
  1.1534 +    }
  1.1535 +    if (color) {
  1.1536 +        *color = c;
  1.1537 +    }
  1.1538 +    return true;
  1.1539 +}
  1.1540 +
  1.1541 +static SkColor computeLuminanceColor(const SkPaint& paint) {
  1.1542 +    SkColor c;
  1.1543 +    if (!justAColor(paint, &c)) {
  1.1544 +        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
  1.1545 +    }
  1.1546 +    return c;
  1.1547 +}
  1.1548 +
  1.1549 +#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
  1.1550 +
  1.1551 +// Beyond this size, LCD doesn't appreciably improve quality, but it always
  1.1552 +// cost more RAM and draws slower, so we set a cap.
  1.1553 +#ifndef SK_MAX_SIZE_FOR_LCDTEXT
  1.1554 +    #define SK_MAX_SIZE_FOR_LCDTEXT    48
  1.1555 +#endif
  1.1556 +
  1.1557 +static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
  1.1558 +    SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
  1.1559 +                    rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
  1.1560 +    SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
  1.1561 +    return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
  1.1562 +}
  1.1563 +
  1.1564 +/*
  1.1565 + *  Return the scalar with only limited fractional precision. Used to consolidate matrices
  1.1566 + *  that vary only slightly when we create our key into the font cache, since the font scaler
  1.1567 + *  typically returns the same looking resuts for tiny changes in the matrix.
  1.1568 + */
  1.1569 +static SkScalar sk_relax(SkScalar x) {
  1.1570 +    int n = sk_float_round2int(x * 1024);
  1.1571 +    return n / 1024.0f;
  1.1572 +}
  1.1573 +
  1.1574 +void SkScalerContext::MakeRec(const SkPaint& paint,
  1.1575 +                              const SkDeviceProperties* deviceProperties,
  1.1576 +                              const SkMatrix* deviceMatrix,
  1.1577 +                              Rec* rec) {
  1.1578 +    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
  1.1579 +
  1.1580 +    SkTypeface* typeface = paint.getTypeface();
  1.1581 +    if (NULL == typeface) {
  1.1582 +        typeface = SkTypeface::GetDefaultTypeface();
  1.1583 +    }
  1.1584 +    rec->fOrigFontID = typeface->uniqueID();
  1.1585 +    rec->fFontID = rec->fOrigFontID;
  1.1586 +    rec->fTextSize = paint.getTextSize();
  1.1587 +    rec->fPreScaleX = paint.getTextScaleX();
  1.1588 +    rec->fPreSkewX  = paint.getTextSkewX();
  1.1589 +
  1.1590 +    if (deviceMatrix) {
  1.1591 +        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
  1.1592 +        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
  1.1593 +        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
  1.1594 +        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
  1.1595 +    } else {
  1.1596 +        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
  1.1597 +        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
  1.1598 +    }
  1.1599 +
  1.1600 +    SkPaint::Style  style = paint.getStyle();
  1.1601 +    SkScalar        strokeWidth = paint.getStrokeWidth();
  1.1602 +
  1.1603 +    unsigned flags = 0;
  1.1604 +
  1.1605 +    if (paint.isFakeBoldText()) {
  1.1606 +#ifdef SK_USE_FREETYPE_EMBOLDEN
  1.1607 +        flags |= SkScalerContext::kEmbolden_Flag;
  1.1608 +#else
  1.1609 +        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
  1.1610 +                                                    kStdFakeBoldInterpKeys,
  1.1611 +                                                    kStdFakeBoldInterpValues,
  1.1612 +                                                    kStdFakeBoldInterpLength);
  1.1613 +        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
  1.1614 +
  1.1615 +        if (style == SkPaint::kFill_Style) {
  1.1616 +            style = SkPaint::kStrokeAndFill_Style;
  1.1617 +            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
  1.1618 +        } else {
  1.1619 +            strokeWidth += extra;
  1.1620 +        }
  1.1621 +#endif
  1.1622 +    }
  1.1623 +
  1.1624 +    if (paint.isDevKernText()) {
  1.1625 +        flags |= SkScalerContext::kDevKernText_Flag;
  1.1626 +    }
  1.1627 +
  1.1628 +    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
  1.1629 +        rec->fFrameWidth = strokeWidth;
  1.1630 +        rec->fMiterLimit = paint.getStrokeMiter();
  1.1631 +        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
  1.1632 +
  1.1633 +        if (style == SkPaint::kStrokeAndFill_Style) {
  1.1634 +            flags |= SkScalerContext::kFrameAndFill_Flag;
  1.1635 +        }
  1.1636 +    } else {
  1.1637 +        rec->fFrameWidth = 0;
  1.1638 +        rec->fMiterLimit = 0;
  1.1639 +        rec->fStrokeJoin = 0;
  1.1640 +    }
  1.1641 +
  1.1642 +    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
  1.1643 +
  1.1644 +    SkDeviceProperties::Geometry geometry = deviceProperties
  1.1645 +                                          ? deviceProperties->fGeometry
  1.1646 +                                          : SkDeviceProperties::Geometry::MakeDefault();
  1.1647 +    if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
  1.1648 +        if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) {
  1.1649 +            // eeek, can't support LCD
  1.1650 +            rec->fMaskFormat = SkMask::kA8_Format;
  1.1651 +        } else {
  1.1652 +            if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) {
  1.1653 +                flags |= SkScalerContext::kLCD_Vertical_Flag;
  1.1654 +            }
  1.1655 +            if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) {
  1.1656 +                flags |= SkScalerContext::kLCD_BGROrder_Flag;
  1.1657 +            }
  1.1658 +        }
  1.1659 +    }
  1.1660 +
  1.1661 +    if (paint.isEmbeddedBitmapText()) {
  1.1662 +        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
  1.1663 +    }
  1.1664 +    if (paint.isSubpixelText()) {
  1.1665 +        flags |= SkScalerContext::kSubpixelPositioning_Flag;
  1.1666 +    }
  1.1667 +    if (paint.isAutohinted()) {
  1.1668 +        flags |= SkScalerContext::kForceAutohinting_Flag;
  1.1669 +    }
  1.1670 +    if (paint.isVerticalText()) {
  1.1671 +        flags |= SkScalerContext::kVertical_Flag;
  1.1672 +    }
  1.1673 +    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
  1.1674 +        flags |= SkScalerContext::kGenA8FromLCD_Flag;
  1.1675 +    }
  1.1676 +    rec->fFlags = SkToU16(flags);
  1.1677 +
  1.1678 +    // these modify fFlags, so do them after assigning fFlags
  1.1679 +    rec->setHinting(computeHinting(paint));
  1.1680 +
  1.1681 +    rec->setLuminanceColor(computeLuminanceColor(paint));
  1.1682 +
  1.1683 +    if (NULL == deviceProperties) {
  1.1684 +        rec->setDeviceGamma(SK_GAMMA_EXPONENT);
  1.1685 +        rec->setPaintGamma(SK_GAMMA_EXPONENT);
  1.1686 +    } else {
  1.1687 +        rec->setDeviceGamma(deviceProperties->fGamma);
  1.1688 +
  1.1689 +        //For now always set the paint gamma equal to the device gamma.
  1.1690 +        //The math in SkMaskGamma can handle them being different,
  1.1691 +        //but it requires superluminous masks when
  1.1692 +        //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
  1.1693 +        rec->setPaintGamma(deviceProperties->fGamma);
  1.1694 +    }
  1.1695 +
  1.1696 +#ifdef SK_GAMMA_CONTRAST
  1.1697 +    rec->setContrast(SK_GAMMA_CONTRAST);
  1.1698 +#else
  1.1699 +    /**
  1.1700 +     * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
  1.1701 +     * With lower values small text appears washed out (though correctly so).
  1.1702 +     * With higher values lcd fringing is worse and the smoothing effect of
  1.1703 +     * partial coverage is diminished.
  1.1704 +     */
  1.1705 +    rec->setContrast(0.5f);
  1.1706 +#endif
  1.1707 +
  1.1708 +    rec->fReservedAlign = 0;
  1.1709 +
  1.1710 +    /*  Allow the fonthost to modify our rec before we use it as a key into the
  1.1711 +        cache. This way if we're asking for something that they will ignore,
  1.1712 +        they can modify our rec up front, so we don't create duplicate cache
  1.1713 +        entries.
  1.1714 +     */
  1.1715 +    typeface->onFilterRec(rec);
  1.1716 +
  1.1717 +    // be sure to call PostMakeRec(rec) before you actually use it!
  1.1718 +}
  1.1719 +
  1.1720 +/**
  1.1721 + * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
  1.1722 + * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
  1.1723 + * to hold it until the returned pointer is refed or forgotten.
  1.1724 + */
  1.1725 +SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
  1.1726 +
  1.1727 +static SkMaskGamma* gLinearMaskGamma = NULL;
  1.1728 +static SkMaskGamma* gMaskGamma = NULL;
  1.1729 +static SkScalar gContrast = SK_ScalarMin;
  1.1730 +static SkScalar gPaintGamma = SK_ScalarMin;
  1.1731 +static SkScalar gDeviceGamma = SK_ScalarMin;
  1.1732 +/**
  1.1733 + * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
  1.1734 + * the returned SkMaskGamma pointer is refed or forgotten.
  1.1735 + */
  1.1736 +static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
  1.1737 +    if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
  1.1738 +        if (NULL == gLinearMaskGamma) {
  1.1739 +            gLinearMaskGamma = SkNEW(SkMaskGamma);
  1.1740 +        }
  1.1741 +        return *gLinearMaskGamma;
  1.1742 +    }
  1.1743 +    if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
  1.1744 +        SkSafeUnref(gMaskGamma);
  1.1745 +        gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
  1.1746 +        gContrast = contrast;
  1.1747 +        gPaintGamma = paintGamma;
  1.1748 +        gDeviceGamma = deviceGamma;
  1.1749 +    }
  1.1750 +    return *gMaskGamma;
  1.1751 +}
  1.1752 +
  1.1753 +/*static*/ void SkPaint::Term() {
  1.1754 +    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
  1.1755 +
  1.1756 +    SkSafeUnref(gLinearMaskGamma);
  1.1757 +    gLinearMaskGamma = NULL;
  1.1758 +    SkSafeUnref(gMaskGamma);
  1.1759 +    gMaskGamma = NULL;
  1.1760 +    SkDEBUGCODE(gContrast = SK_ScalarMin;)
  1.1761 +    SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
  1.1762 +    SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
  1.1763 +}
  1.1764 +
  1.1765 +/**
  1.1766 + *  We ensure that the rec is self-consistent and efficient (where possible)
  1.1767 + */
  1.1768 +void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
  1.1769 +    /**
  1.1770 +     *  If we're asking for A8, we force the colorlum to be gray, since that
  1.1771 +     *  limits the number of unique entries, and the scaler will only look at
  1.1772 +     *  the lum of one of them.
  1.1773 +     */
  1.1774 +    switch (rec->fMaskFormat) {
  1.1775 +        case SkMask::kLCD16_Format:
  1.1776 +        case SkMask::kLCD32_Format: {
  1.1777 +            // filter down the luminance color to a finite number of bits
  1.1778 +            SkColor color = rec->getLuminanceColor();
  1.1779 +            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
  1.1780 +            break;
  1.1781 +        }
  1.1782 +        case SkMask::kA8_Format: {
  1.1783 +            // filter down the luminance to a single component, since A8 can't
  1.1784 +            // use per-component information
  1.1785 +
  1.1786 +            SkColor color = rec->getLuminanceColor();
  1.1787 +            U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color);
  1.1788 +            //If we are asked to look like LCD, look like LCD.
  1.1789 +            if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
  1.1790 +                // HACK: Prevents green from being pre-blended as white.
  1.1791 +                lum -= ((255 - lum) * lum) / 255;
  1.1792 +            }
  1.1793 +
  1.1794 +            // reduce to our finite number of bits
  1.1795 +            color = SkColorSetRGB(lum, lum, lum);
  1.1796 +            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
  1.1797 +            break;
  1.1798 +        }
  1.1799 +        case SkMask::kBW_Format:
  1.1800 +            // No need to differentiate gamma if we're BW
  1.1801 +            rec->ignorePreBlend();
  1.1802 +            break;
  1.1803 +    }
  1.1804 +}
  1.1805 +
  1.1806 +#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
  1.1807 +
  1.1808 +#ifdef SK_DEBUG
  1.1809 +    #define TEST_DESC
  1.1810 +#endif
  1.1811 +
  1.1812 +/*
  1.1813 + *  ignoreGamma tells us that the caller just wants metrics that are unaffected
  1.1814 + *  by gamma correction, so we jam the luminance field to 0 (most common value
  1.1815 + *  for black text) in hopes that we get a cache hit easier. A better solution
  1.1816 + *  would be for the fontcache lookup to know to ignore the luminance field
  1.1817 + *  entirely, but not sure how to do that and keep it fast.
  1.1818 + */
  1.1819 +void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
  1.1820 +                             const SkMatrix* deviceMatrix,
  1.1821 +                             void (*proc)(SkTypeface*, const SkDescriptor*, void*),
  1.1822 +                             void* context, bool ignoreGamma) const {
  1.1823 +    SkScalerContext::Rec    rec;
  1.1824 +
  1.1825 +    SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
  1.1826 +    if (ignoreGamma) {
  1.1827 +        rec.setLuminanceColor(0);
  1.1828 +    }
  1.1829 +
  1.1830 +    size_t          descSize = sizeof(rec);
  1.1831 +    int             entryCount = 1;
  1.1832 +    SkPathEffect*   pe = this->getPathEffect();
  1.1833 +    SkMaskFilter*   mf = this->getMaskFilter();
  1.1834 +    SkRasterizer*   ra = this->getRasterizer();
  1.1835 +
  1.1836 +    SkWriteBuffer    peBuffer, mfBuffer, raBuffer;
  1.1837 +
  1.1838 +    if (pe) {
  1.1839 +        peBuffer.writeFlattenable(pe);
  1.1840 +        descSize += peBuffer.bytesWritten();
  1.1841 +        entryCount += 1;
  1.1842 +        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
  1.1843 +        // seems like we could support kLCD as well at this point...
  1.1844 +    }
  1.1845 +    if (mf) {
  1.1846 +        mfBuffer.writeFlattenable(mf);
  1.1847 +        descSize += mfBuffer.bytesWritten();
  1.1848 +        entryCount += 1;
  1.1849 +        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
  1.1850 +        /* Pre-blend is not currently applied to filtered text.
  1.1851 +           The primary filter is blur, for which contrast makes no sense,
  1.1852 +           and for which the destination guess error is more visible.
  1.1853 +           Also, all existing users of blur have calibrated for linear. */
  1.1854 +        rec.ignorePreBlend();
  1.1855 +    }
  1.1856 +    if (ra) {
  1.1857 +        raBuffer.writeFlattenable(ra);
  1.1858 +        descSize += raBuffer.bytesWritten();
  1.1859 +        entryCount += 1;
  1.1860 +        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
  1.1861 +    }
  1.1862 +
  1.1863 +#ifdef SK_BUILD_FOR_ANDROID
  1.1864 +    SkWriteBuffer androidBuffer;
  1.1865 +    fPaintOptionsAndroid.flatten(androidBuffer);
  1.1866 +    descSize += androidBuffer.bytesWritten();
  1.1867 +    entryCount += 1;
  1.1868 +#endif
  1.1869 +
  1.1870 +    ///////////////////////////////////////////////////////////////////////////
  1.1871 +    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
  1.1872 +    SkScalerContext::PostMakeRec(*this, &rec);
  1.1873 +
  1.1874 +    descSize += SkDescriptor::ComputeOverhead(entryCount);
  1.1875 +
  1.1876 +    SkAutoDescriptor    ad(descSize);
  1.1877 +    SkDescriptor*       desc = ad.getDesc();
  1.1878 +
  1.1879 +    desc->init();
  1.1880 +    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1.1881 +
  1.1882 +#ifdef SK_BUILD_FOR_ANDROID
  1.1883 +    add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1.1884 +#endif
  1.1885 +
  1.1886 +    if (pe) {
  1.1887 +        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
  1.1888 +    }
  1.1889 +    if (mf) {
  1.1890 +        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1.1891 +    }
  1.1892 +    if (ra) {
  1.1893 +        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
  1.1894 +    }
  1.1895 +
  1.1896 +    SkASSERT(descSize == desc->getLength());
  1.1897 +    desc->computeChecksum();
  1.1898 +
  1.1899 +#ifdef TEST_DESC
  1.1900 +    {
  1.1901 +        // Check that we completely write the bytes in desc (our key), and that
  1.1902 +        // there are no uninitialized bytes. If there were, then we would get
  1.1903 +        // false-misses (or worse, false-hits) in our fontcache.
  1.1904 +        //
  1.1905 +        // We do this buy filling 2 others, one with 0s and the other with 1s
  1.1906 +        // and create those, and then check that all 3 are identical.
  1.1907 +        SkAutoDescriptor    ad1(descSize);
  1.1908 +        SkAutoDescriptor    ad2(descSize);
  1.1909 +        SkDescriptor*       desc1 = ad1.getDesc();
  1.1910 +        SkDescriptor*       desc2 = ad2.getDesc();
  1.1911 +
  1.1912 +        memset(desc1, 0x00, descSize);
  1.1913 +        memset(desc2, 0xFF, descSize);
  1.1914 +
  1.1915 +        desc1->init();
  1.1916 +        desc2->init();
  1.1917 +        desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1.1918 +        desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
  1.1919 +
  1.1920 +#ifdef SK_BUILD_FOR_ANDROID
  1.1921 +        add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1.1922 +        add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer);
  1.1923 +#endif
  1.1924 +
  1.1925 +        if (pe) {
  1.1926 +            add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
  1.1927 +            add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
  1.1928 +        }
  1.1929 +        if (mf) {
  1.1930 +            add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1.1931 +            add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
  1.1932 +        }
  1.1933 +        if (ra) {
  1.1934 +            add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
  1.1935 +            add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
  1.1936 +        }
  1.1937 +
  1.1938 +        SkASSERT(descSize == desc1->getLength());
  1.1939 +        SkASSERT(descSize == desc2->getLength());
  1.1940 +        desc1->computeChecksum();
  1.1941 +        desc2->computeChecksum();
  1.1942 +        SkASSERT(!memcmp(desc, desc1, descSize));
  1.1943 +        SkASSERT(!memcmp(desc, desc2, descSize));
  1.1944 +    }
  1.1945 +#endif
  1.1946 +
  1.1947 +    proc(fTypeface, desc, context);
  1.1948 +}
  1.1949 +
  1.1950 +SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
  1.1951 +                                   const SkMatrix* deviceMatrix) const {
  1.1952 +    SkGlyphCache* cache;
  1.1953 +    this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false);
  1.1954 +    return cache;
  1.1955 +}
  1.1956 +
  1.1957 +/**
  1.1958 + * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
  1.1959 + */
  1.1960 +//static
  1.1961 +SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
  1.1962 +    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
  1.1963 +    const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
  1.1964 +                                                   rec.getPaintGamma(),
  1.1965 +                                                   rec.getDeviceGamma());
  1.1966 +    return maskGamma.preBlend(rec.getLuminanceColor());
  1.1967 +}
  1.1968 +
  1.1969 +///////////////////////////////////////////////////////////////////////////////
  1.1970 +
  1.1971 +#include "SkStream.h"
  1.1972 +
  1.1973 +static uintptr_t asint(const void* p) {
  1.1974 +    return reinterpret_cast<uintptr_t>(p);
  1.1975 +}
  1.1976 +
  1.1977 +union Scalar32 {
  1.1978 +    SkScalar    fScalar;
  1.1979 +    uint32_t    f32;
  1.1980 +};
  1.1981 +
  1.1982 +static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
  1.1983 +    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
  1.1984 +    Scalar32 tmp;
  1.1985 +    tmp.fScalar = value;
  1.1986 +    *ptr = tmp.f32;
  1.1987 +    return ptr + 1;
  1.1988 +}
  1.1989 +
  1.1990 +static SkScalar read_scalar(const uint32_t*& ptr) {
  1.1991 +    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
  1.1992 +    Scalar32 tmp;
  1.1993 +    tmp.f32 = *ptr++;
  1.1994 +    return tmp.fScalar;
  1.1995 +}
  1.1996 +
  1.1997 +static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
  1.1998 +    SkASSERT(a == (uint8_t)a);
  1.1999 +    SkASSERT(b == (uint8_t)b);
  1.2000 +    SkASSERT(c == (uint8_t)c);
  1.2001 +    SkASSERT(d == (uint8_t)d);
  1.2002 +    return (a << 24) | (b << 16) | (c << 8) | d;
  1.2003 +}
  1.2004 +
  1.2005 +enum FlatFlags {
  1.2006 +    kHasTypeface_FlatFlag                      = 0x01,
  1.2007 +    kHasEffects_FlatFlag                       = 0x02,
  1.2008 +    kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
  1.2009 +};
  1.2010 +
  1.2011 +// The size of a flat paint's POD fields
  1.2012 +static const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
  1.2013 +                                        1 * sizeof(SkColor) +
  1.2014 +                                        1 * sizeof(uint16_t) +
  1.2015 +                                        6 * sizeof(uint8_t);
  1.2016 +
  1.2017 +/*  To save space/time, we analyze the paint, and write a truncated version of
  1.2018 +    it if there are not tricky elements like shaders, etc.
  1.2019 + */
  1.2020 +void SkPaint::flatten(SkWriteBuffer& buffer) const {
  1.2021 +    uint8_t flatFlags = 0;
  1.2022 +    if (this->getTypeface()) {
  1.2023 +        flatFlags |= kHasTypeface_FlatFlag;
  1.2024 +    }
  1.2025 +    if (asint(this->getPathEffect()) |
  1.2026 +        asint(this->getShader()) |
  1.2027 +        asint(this->getXfermode()) |
  1.2028 +        asint(this->getMaskFilter()) |
  1.2029 +        asint(this->getColorFilter()) |
  1.2030 +        asint(this->getRasterizer()) |
  1.2031 +        asint(this->getLooper()) |
  1.2032 +        asint(this->getAnnotation()) |
  1.2033 +        asint(this->getImageFilter())) {
  1.2034 +        flatFlags |= kHasEffects_FlatFlag;
  1.2035 +    }
  1.2036 +#ifdef SK_BUILD_FOR_ANDROID
  1.2037 +    if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) {
  1.2038 +        flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag;
  1.2039 +    }
  1.2040 +#endif
  1.2041 +
  1.2042 +    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
  1.2043 +    uint32_t* ptr = buffer.reserve(kPODPaintSize);
  1.2044 +
  1.2045 +    ptr = write_scalar(ptr, this->getTextSize());
  1.2046 +    ptr = write_scalar(ptr, this->getTextScaleX());
  1.2047 +    ptr = write_scalar(ptr, this->getTextSkewX());
  1.2048 +    ptr = write_scalar(ptr, this->getStrokeWidth());
  1.2049 +    ptr = write_scalar(ptr, this->getStrokeMiter());
  1.2050 +    *ptr++ = this->getColor();
  1.2051 +    // previously flags:16, textAlign:8, flatFlags:8
  1.2052 +    // now flags:16, hinting:4, textAlign:4, flatFlags:8
  1.2053 +    *ptr++ = (this->getFlags() << 16) |
  1.2054 +        // hinting added later. 0 in this nibble means use the default.
  1.2055 +        ((this->getHinting()+1) << 12) |
  1.2056 +        (this->getTextAlign() << 8) |
  1.2057 +        flatFlags;
  1.2058 +    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
  1.2059 +                    this->getStyle(), this->getTextEncoding());
  1.2060 +
  1.2061 +    // now we're done with ptr and the (pre)reserved space. If we need to write
  1.2062 +    // additional fields, use the buffer directly
  1.2063 +    if (flatFlags & kHasTypeface_FlatFlag) {
  1.2064 +        buffer.writeTypeface(this->getTypeface());
  1.2065 +    }
  1.2066 +    if (flatFlags & kHasEffects_FlatFlag) {
  1.2067 +        buffer.writeFlattenable(this->getPathEffect());
  1.2068 +        buffer.writeFlattenable(this->getShader());
  1.2069 +        buffer.writeFlattenable(this->getXfermode());
  1.2070 +        buffer.writeFlattenable(this->getMaskFilter());
  1.2071 +        buffer.writeFlattenable(this->getColorFilter());
  1.2072 +        buffer.writeFlattenable(this->getRasterizer());
  1.2073 +        buffer.writeFlattenable(this->getLooper());
  1.2074 +        buffer.writeFlattenable(this->getImageFilter());
  1.2075 +
  1.2076 +        if (fAnnotation) {
  1.2077 +            buffer.writeBool(true);
  1.2078 +            fAnnotation->writeToBuffer(buffer);
  1.2079 +        } else {
  1.2080 +            buffer.writeBool(false);
  1.2081 +        }
  1.2082 +    }
  1.2083 +#ifdef SK_BUILD_FOR_ANDROID
  1.2084 +    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
  1.2085 +        this->getPaintOptionsAndroid().flatten(buffer);
  1.2086 +    }
  1.2087 +#endif
  1.2088 +}
  1.2089 +
  1.2090 +void SkPaint::unflatten(SkReadBuffer& buffer) {
  1.2091 +    uint8_t flatFlags = 0;
  1.2092 +    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
  1.2093 +    const void* podData = buffer.skip(kPODPaintSize);
  1.2094 +    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
  1.2095 +
  1.2096 +    // the order we read must match the order we wrote in flatten()
  1.2097 +    this->setTextSize(read_scalar(pod));
  1.2098 +    this->setTextScaleX(read_scalar(pod));
  1.2099 +    this->setTextSkewX(read_scalar(pod));
  1.2100 +    this->setStrokeWidth(read_scalar(pod));
  1.2101 +    this->setStrokeMiter(read_scalar(pod));
  1.2102 +    this->setColor(*pod++);
  1.2103 +
  1.2104 +    // previously flags:16, textAlign:8, flatFlags:8
  1.2105 +    // now flags:16, hinting:4, textAlign:4, flatFlags:8
  1.2106 +    uint32_t tmp = *pod++;
  1.2107 +    this->setFlags(tmp >> 16);
  1.2108 +
  1.2109 +    // hinting added later. 0 in this nibble means use the default.
  1.2110 +    uint32_t hinting = (tmp >> 12) & 0xF;
  1.2111 +    this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
  1.2112 +
  1.2113 +    this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
  1.2114 +
  1.2115 +    flatFlags = tmp & 0xFF;
  1.2116 +
  1.2117 +    tmp = *pod++;
  1.2118 +    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
  1.2119 +    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
  1.2120 +    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
  1.2121 +    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
  1.2122 +
  1.2123 +    if (flatFlags & kHasTypeface_FlatFlag) {
  1.2124 +        this->setTypeface(buffer.readTypeface());
  1.2125 +    } else {
  1.2126 +        this->setTypeface(NULL);
  1.2127 +    }
  1.2128 +
  1.2129 +    if (flatFlags & kHasEffects_FlatFlag) {
  1.2130 +        SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
  1.2131 +        SkSafeUnref(this->setShader(buffer.readShader()));
  1.2132 +        SkSafeUnref(this->setXfermode(buffer.readXfermode()));
  1.2133 +        SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
  1.2134 +        SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
  1.2135 +        SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
  1.2136 +        SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
  1.2137 +        SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
  1.2138 +
  1.2139 +        if (buffer.readBool()) {
  1.2140 +            this->setAnnotation(SkAnnotation::Create(buffer))->unref();
  1.2141 +        }
  1.2142 +    } else {
  1.2143 +        this->setPathEffect(NULL);
  1.2144 +        this->setShader(NULL);
  1.2145 +        this->setXfermode(NULL);
  1.2146 +        this->setMaskFilter(NULL);
  1.2147 +        this->setColorFilter(NULL);
  1.2148 +        this->setRasterizer(NULL);
  1.2149 +        this->setLooper(NULL);
  1.2150 +        this->setImageFilter(NULL);
  1.2151 +    }
  1.2152 +
  1.2153 +#ifdef SK_BUILD_FOR_ANDROID
  1.2154 +    this->setPaintOptionsAndroid(SkPaintOptionsAndroid());
  1.2155 +#endif
  1.2156 +    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
  1.2157 +        SkPaintOptionsAndroid options;
  1.2158 +        options.unflatten(buffer);
  1.2159 +#ifdef SK_BUILD_FOR_ANDROID
  1.2160 +        this->setPaintOptionsAndroid(options);
  1.2161 +#endif
  1.2162 +    }
  1.2163 +}
  1.2164 +
  1.2165 +///////////////////////////////////////////////////////////////////////////////
  1.2166 +
  1.2167 +SkShader* SkPaint::setShader(SkShader* shader) {
  1.2168 +    GEN_ID_INC_EVAL(shader != fShader);
  1.2169 +    SkRefCnt_SafeAssign(fShader, shader);
  1.2170 +    fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
  1.2171 +    return shader;
  1.2172 +}
  1.2173 +
  1.2174 +SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
  1.2175 +    GEN_ID_INC_EVAL(filter != fColorFilter);
  1.2176 +    SkRefCnt_SafeAssign(fColorFilter, filter);
  1.2177 +    fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
  1.2178 +    return filter;
  1.2179 +}
  1.2180 +
  1.2181 +SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
  1.2182 +    GEN_ID_INC_EVAL(mode != fXfermode);
  1.2183 +    SkRefCnt_SafeAssign(fXfermode, mode);
  1.2184 +    fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
  1.2185 +    return mode;
  1.2186 +}
  1.2187 +
  1.2188 +SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
  1.2189 +    SkSafeUnref(fXfermode);
  1.2190 +    fXfermode = SkXfermode::Create(mode);
  1.2191 +    GEN_ID_INC;
  1.2192 +    fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
  1.2193 +    return fXfermode;
  1.2194 +}
  1.2195 +
  1.2196 +SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
  1.2197 +    GEN_ID_INC_EVAL(effect != fPathEffect);
  1.2198 +    SkRefCnt_SafeAssign(fPathEffect, effect);
  1.2199 +    fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
  1.2200 +    return effect;
  1.2201 +}
  1.2202 +
  1.2203 +SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
  1.2204 +    GEN_ID_INC_EVAL(filter != fMaskFilter);
  1.2205 +    SkRefCnt_SafeAssign(fMaskFilter, filter);
  1.2206 +    fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
  1.2207 +    return filter;
  1.2208 +}
  1.2209 +
  1.2210 +///////////////////////////////////////////////////////////////////////////////
  1.2211 +
  1.2212 +bool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
  1.2213 +                          const SkRect* cullRect) const {
  1.2214 +    SkStrokeRec rec(*this);
  1.2215 +
  1.2216 +    const SkPath* srcPtr = &src;
  1.2217 +    SkPath tmpPath;
  1.2218 +
  1.2219 +    if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
  1.2220 +        srcPtr = &tmpPath;
  1.2221 +    }
  1.2222 +
  1.2223 +    if (!rec.applyToPath(dst, *srcPtr)) {
  1.2224 +        if (srcPtr == &tmpPath) {
  1.2225 +            // If path's were copy-on-write, this trick would not be needed.
  1.2226 +            // As it is, we want to save making a deep-copy from tmpPath -> dst
  1.2227 +            // since we know we're just going to delete tmpPath when we return,
  1.2228 +            // so the swap saves that copy.
  1.2229 +            dst->swap(tmpPath);
  1.2230 +        } else {
  1.2231 +            *dst = *srcPtr;
  1.2232 +        }
  1.2233 +    }
  1.2234 +    return !rec.isHairlineStyle();
  1.2235 +}
  1.2236 +
  1.2237 +const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
  1.2238 +                                           SkRect* storage,
  1.2239 +                                           Style style) const {
  1.2240 +    SkASSERT(storage);
  1.2241 +
  1.2242 +    const SkRect* src = &origSrc;
  1.2243 +
  1.2244 +    if (this->getLooper()) {
  1.2245 +        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
  1.2246 +        this->getLooper()->computeFastBounds(*this, *src, storage);
  1.2247 +        return *storage;
  1.2248 +    }
  1.2249 +
  1.2250 +    SkRect tmpSrc;
  1.2251 +    if (this->getPathEffect()) {
  1.2252 +        this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
  1.2253 +        src = &tmpSrc;
  1.2254 +    }
  1.2255 +
  1.2256 +    if (kFill_Style != style) {
  1.2257 +        // since we're stroked, outset the rect by the radius (and join type)
  1.2258 +        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
  1.2259 +        if (0 == radius) {  // hairline
  1.2260 +            radius = SK_Scalar1;
  1.2261 +        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
  1.2262 +            SkScalar scale = this->getStrokeMiter();
  1.2263 +            if (scale > SK_Scalar1) {
  1.2264 +                radius = SkScalarMul(radius, scale);
  1.2265 +            }
  1.2266 +        }
  1.2267 +        storage->set(src->fLeft - radius, src->fTop - radius,
  1.2268 +                     src->fRight + radius, src->fBottom + radius);
  1.2269 +    } else {
  1.2270 +        *storage = *src;
  1.2271 +    }
  1.2272 +
  1.2273 +    if (this->getMaskFilter()) {
  1.2274 +        this->getMaskFilter()->computeFastBounds(*storage, storage);
  1.2275 +    }
  1.2276 +
  1.2277 +    if (this->getImageFilter()) {
  1.2278 +        this->getImageFilter()->computeFastBounds(*storage, storage);
  1.2279 +    }
  1.2280 +
  1.2281 +    return *storage;
  1.2282 +}
  1.2283 +
  1.2284 +#ifndef SK_IGNORE_TO_STRING
  1.2285 +void SkPaint::toString(SkString* str) const {
  1.2286 +    str->append("<dl><dt>SkPaint:</dt><dd><dl>");
  1.2287 +
  1.2288 +    SkTypeface* typeface = this->getTypeface();
  1.2289 +    if (NULL != typeface) {
  1.2290 +        SkDynamicMemoryWStream ostream;
  1.2291 +        typeface->serialize(&ostream);
  1.2292 +        SkAutoTUnref<SkData> data(ostream.copyToData());
  1.2293 +
  1.2294 +        SkMemoryStream stream(data);
  1.2295 +        SkFontDescriptor descriptor(&stream);
  1.2296 +
  1.2297 +        str->append("<dt>Font Family Name:</dt><dd>");
  1.2298 +        str->append(descriptor.getFamilyName());
  1.2299 +        str->append("</dd><dt>Font Full Name:</dt><dd>");
  1.2300 +        str->append(descriptor.getFullName());
  1.2301 +        str->append("</dd><dt>Font PS Name:</dt><dd>");
  1.2302 +        str->append(descriptor.getPostscriptName());
  1.2303 +        str->append("</dd><dt>Font File Name:</dt><dd>");
  1.2304 +        str->append(descriptor.getFontFileName());
  1.2305 +        str->append("</dd>");
  1.2306 +    }
  1.2307 +
  1.2308 +    str->append("<dt>TextSize:</dt><dd>");
  1.2309 +    str->appendScalar(this->getTextSize());
  1.2310 +    str->append("</dd>");
  1.2311 +
  1.2312 +    str->append("<dt>TextScaleX:</dt><dd>");
  1.2313 +    str->appendScalar(this->getTextScaleX());
  1.2314 +    str->append("</dd>");
  1.2315 +
  1.2316 +    str->append("<dt>TextSkewX:</dt><dd>");
  1.2317 +    str->appendScalar(this->getTextSkewX());
  1.2318 +    str->append("</dd>");
  1.2319 +
  1.2320 +    SkPathEffect* pathEffect = this->getPathEffect();
  1.2321 +    if (NULL != pathEffect) {
  1.2322 +        str->append("<dt>PathEffect:</dt><dd>");
  1.2323 +        str->append("</dd>");
  1.2324 +    }
  1.2325 +
  1.2326 +    SkShader* shader = this->getShader();
  1.2327 +    if (NULL != shader) {
  1.2328 +        str->append("<dt>Shader:</dt><dd>");
  1.2329 +        shader->toString(str);
  1.2330 +        str->append("</dd>");
  1.2331 +    }
  1.2332 +
  1.2333 +    SkXfermode* xfer = this->getXfermode();
  1.2334 +    if (NULL != xfer) {
  1.2335 +        str->append("<dt>Xfermode:</dt><dd>");
  1.2336 +        xfer->toString(str);
  1.2337 +        str->append("</dd>");
  1.2338 +    }
  1.2339 +
  1.2340 +    SkMaskFilter* maskFilter = this->getMaskFilter();
  1.2341 +    if (NULL != maskFilter) {
  1.2342 +        str->append("<dt>MaskFilter:</dt><dd>");
  1.2343 +        maskFilter->toString(str);
  1.2344 +        str->append("</dd>");
  1.2345 +    }
  1.2346 +
  1.2347 +    SkColorFilter* colorFilter = this->getColorFilter();
  1.2348 +    if (NULL != colorFilter) {
  1.2349 +        str->append("<dt>ColorFilter:</dt><dd>");
  1.2350 +        colorFilter->toString(str);
  1.2351 +        str->append("</dd>");
  1.2352 +    }
  1.2353 +
  1.2354 +    SkRasterizer* rasterizer = this->getRasterizer();
  1.2355 +    if (NULL != rasterizer) {
  1.2356 +        str->append("<dt>Rasterizer:</dt><dd>");
  1.2357 +        str->append("</dd>");
  1.2358 +    }
  1.2359 +
  1.2360 +    SkDrawLooper* looper = this->getLooper();
  1.2361 +    if (NULL != looper) {
  1.2362 +        str->append("<dt>DrawLooper:</dt><dd>");
  1.2363 +        looper->toString(str);
  1.2364 +        str->append("</dd>");
  1.2365 +    }
  1.2366 +
  1.2367 +    SkImageFilter* imageFilter = this->getImageFilter();
  1.2368 +    if (NULL != imageFilter) {
  1.2369 +        str->append("<dt>ImageFilter:</dt><dd>");
  1.2370 +        str->append("</dd>");
  1.2371 +    }
  1.2372 +
  1.2373 +    SkAnnotation* annotation = this->getAnnotation();
  1.2374 +    if (NULL != annotation) {
  1.2375 +        str->append("<dt>Annotation:</dt><dd>");
  1.2376 +        str->append("</dd>");
  1.2377 +    }
  1.2378 +
  1.2379 +    str->append("<dt>Color:</dt><dd>0x");
  1.2380 +    SkColor color = this->getColor();
  1.2381 +    str->appendHex(color);
  1.2382 +    str->append("</dd>");
  1.2383 +
  1.2384 +    str->append("<dt>Stroke Width:</dt><dd>");
  1.2385 +    str->appendScalar(this->getStrokeWidth());
  1.2386 +    str->append("</dd>");
  1.2387 +
  1.2388 +    str->append("<dt>Stroke Miter:</dt><dd>");
  1.2389 +    str->appendScalar(this->getStrokeMiter());
  1.2390 +    str->append("</dd>");
  1.2391 +
  1.2392 +    str->append("<dt>Flags:</dt><dd>(");
  1.2393 +    if (this->getFlags()) {
  1.2394 +        bool needSeparator = false;
  1.2395 +        SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
  1.2396 +        SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
  1.2397 +        SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
  1.2398 +        SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
  1.2399 +        SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
  1.2400 +        SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
  1.2401 +        SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
  1.2402 +        SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
  1.2403 +        SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
  1.2404 +        SkAddFlagToString(str, this->isEmbeddedBitmapText(),
  1.2405 +                          "EmbeddedBitmapText", &needSeparator);
  1.2406 +        SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
  1.2407 +        SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
  1.2408 +        SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
  1.2409 +                          "GenA8FromLCD", &needSeparator);
  1.2410 +    } else {
  1.2411 +        str->append("None");
  1.2412 +    }
  1.2413 +    str->append(")</dd>");
  1.2414 +
  1.2415 +    str->append("<dt>FilterLevel:</dt><dd>");
  1.2416 +    static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
  1.2417 +    str->append(gFilterLevelStrings[this->getFilterLevel()]);
  1.2418 +    str->append("</dd>");
  1.2419 +
  1.2420 +    str->append("<dt>TextAlign:</dt><dd>");
  1.2421 +    static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
  1.2422 +    str->append(gTextAlignStrings[this->getTextAlign()]);
  1.2423 +    str->append("</dd>");
  1.2424 +
  1.2425 +    str->append("<dt>CapType:</dt><dd>");
  1.2426 +    static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
  1.2427 +    str->append(gStrokeCapStrings[this->getStrokeCap()]);
  1.2428 +    str->append("</dd>");
  1.2429 +
  1.2430 +    str->append("<dt>JoinType:</dt><dd>");
  1.2431 +    static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
  1.2432 +    str->append(gJoinStrings[this->getStrokeJoin()]);
  1.2433 +    str->append("</dd>");
  1.2434 +
  1.2435 +    str->append("<dt>Style:</dt><dd>");
  1.2436 +    static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
  1.2437 +    str->append(gStyleStrings[this->getStyle()]);
  1.2438 +    str->append("</dd>");
  1.2439 +
  1.2440 +    str->append("<dt>TextEncoding:</dt><dd>");
  1.2441 +    static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
  1.2442 +    str->append(gTextEncodingStrings[this->getTextEncoding()]);
  1.2443 +    str->append("</dd>");
  1.2444 +
  1.2445 +    str->append("<dt>Hinting:</dt><dd>");
  1.2446 +    static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
  1.2447 +    str->append(gHintingStrings[this->getHinting()]);
  1.2448 +    str->append("</dd>");
  1.2449 +
  1.2450 +    str->append("</dd></dl></dl>");
  1.2451 +}
  1.2452 +#endif
  1.2453 +
  1.2454 +///////////////////////////////////////////////////////////////////////////////
  1.2455 +
  1.2456 +static bool has_thick_frame(const SkPaint& paint) {
  1.2457 +    return  paint.getStrokeWidth() > 0 &&
  1.2458 +            paint.getStyle() != SkPaint::kFill_Style;
  1.2459 +}
  1.2460 +
  1.2461 +SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
  1.2462 +                                    const SkPaint& paint,
  1.2463 +                                    bool applyStrokeAndPathEffects)
  1.2464 +                                    : fPaint(paint) {
  1.2465 +    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
  1.2466 +                                                true);
  1.2467 +
  1.2468 +    fPaint.setLinearText(true);
  1.2469 +    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
  1.2470 +
  1.2471 +    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
  1.2472 +        applyStrokeAndPathEffects = false;
  1.2473 +    }
  1.2474 +
  1.2475 +    // can't use our canonical size if we need to apply patheffects
  1.2476 +    if (fPaint.getPathEffect() == NULL) {
  1.2477 +        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
  1.2478 +        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
  1.2479 +        if (has_thick_frame(fPaint)) {
  1.2480 +            fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
  1.2481 +        }
  1.2482 +    } else {
  1.2483 +        fScale = SK_Scalar1;
  1.2484 +    }
  1.2485 +
  1.2486 +    if (!applyStrokeAndPathEffects) {
  1.2487 +        fPaint.setStyle(SkPaint::kFill_Style);
  1.2488 +        fPaint.setPathEffect(NULL);
  1.2489 +    }
  1.2490 +
  1.2491 +    fCache = fPaint.detachCache(NULL, NULL);
  1.2492 +
  1.2493 +    SkPaint::Style  style = SkPaint::kFill_Style;
  1.2494 +    SkPathEffect*   pe = NULL;
  1.2495 +
  1.2496 +    if (!applyStrokeAndPathEffects) {
  1.2497 +        style = paint.getStyle();   // restore
  1.2498 +        pe = paint.getPathEffect();     // restore
  1.2499 +    }
  1.2500 +    fPaint.setStyle(style);
  1.2501 +    fPaint.setPathEffect(pe);
  1.2502 +    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
  1.2503 +
  1.2504 +    // now compute fXOffset if needed
  1.2505 +
  1.2506 +    SkScalar xOffset = 0;
  1.2507 +    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
  1.2508 +        int      count;
  1.2509 +        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
  1.2510 +                                                         &count, NULL), fScale);
  1.2511 +        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
  1.2512 +            width = SkScalarHalf(width);
  1.2513 +        }
  1.2514 +        xOffset = -width;
  1.2515 +    }
  1.2516 +    fXPos = xOffset;
  1.2517 +    fPrevAdvance = 0;
  1.2518 +
  1.2519 +    fText = text;
  1.2520 +    fStop = text + length;
  1.2521 +
  1.2522 +    fXYIndex = paint.isVerticalText() ? 1 : 0;
  1.2523 +}
  1.2524 +
  1.2525 +SkTextToPathIter::~SkTextToPathIter() {
  1.2526 +    SkGlyphCache::AttachCache(fCache);
  1.2527 +}
  1.2528 +
  1.2529 +bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
  1.2530 +    if (fText < fStop) {
  1.2531 +        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
  1.2532 +
  1.2533 +        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
  1.2534 +        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
  1.2535 +
  1.2536 +        if (glyph.fWidth) {
  1.2537 +            if (path) {
  1.2538 +                *path = fCache->findPath(glyph);
  1.2539 +            }
  1.2540 +        } else {
  1.2541 +            if (path) {
  1.2542 +                *path = NULL;
  1.2543 +            }
  1.2544 +        }
  1.2545 +        if (xpos) {
  1.2546 +            *xpos = fXPos;
  1.2547 +        }
  1.2548 +        return true;
  1.2549 +    }
  1.2550 +    return false;
  1.2551 +}
  1.2552 +
  1.2553 +///////////////////////////////////////////////////////////////////////////////
  1.2554 +
  1.2555 +bool SkPaint::nothingToDraw() const {
  1.2556 +    if (fLooper) {
  1.2557 +        return false;
  1.2558 +    }
  1.2559 +    SkXfermode::Mode mode;
  1.2560 +    if (SkXfermode::AsMode(fXfermode, &mode)) {
  1.2561 +        switch (mode) {
  1.2562 +            case SkXfermode::kSrcOver_Mode:
  1.2563 +            case SkXfermode::kSrcATop_Mode:
  1.2564 +            case SkXfermode::kDstOut_Mode:
  1.2565 +            case SkXfermode::kDstOver_Mode:
  1.2566 +            case SkXfermode::kPlus_Mode:
  1.2567 +                return 0 == this->getAlpha();
  1.2568 +            case SkXfermode::kDst_Mode:
  1.2569 +                return true;
  1.2570 +            default:
  1.2571 +                break;
  1.2572 +        }
  1.2573 +    }
  1.2574 +    return false;
  1.2575 +}
  1.2576 +
  1.2577 +void SkPaint::setBitfields(uint32_t bitfields) {
  1.2578 +    fBitfields = bitfields;
  1.2579 +    fDirtyBits |= kBitfields_DirtyBit;
  1.2580 +}
  1.2581 +
  1.2582 +inline static unsigned popcount(uint8_t x) {
  1.2583 +    // As in Hacker's delight, adapted for just 8 bits.
  1.2584 +    x = (x & 0x55) + ((x >> 1) & 0x55);  // a b c d w x y z -> a+b c+d w+x y+z
  1.2585 +    x = (x & 0x33) + ((x >> 2) & 0x33);  // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
  1.2586 +    x = (x & 0x0F) + ((x >> 4) & 0x0F);  // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
  1.2587 +    return x;
  1.2588 +}
  1.2589 +
  1.2590 +void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
  1.2591 +    const uint32_t dirty = paint.fDirtyBits;
  1.2592 +
  1.2593 +    // Each of the low 7 dirty bits corresponds to a 4-byte flat value, plus one for the dirty bits.
  1.2594 +    const size_t flatBytes = 4 * (popcount(dirty & 127) + 1);
  1.2595 +    SkASSERT(flatBytes <= 32);
  1.2596 +    uint32_t* u32 = buffer.reserve(flatBytes);
  1.2597 +    *u32++ = dirty;
  1.2598 +    if (dirty == 0) {
  1.2599 +        return;
  1.2600 +    }
  1.2601 +
  1.2602 +#define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
  1.2603 +    F(u32, Color);
  1.2604 +    F(u32, Bitfields);
  1.2605 +    SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
  1.2606 +    F(f32, TextSize);
  1.2607 +    F(f32, TextScaleX);
  1.2608 +    F(f32, TextSkewX);
  1.2609 +    F(f32, StrokeWidth);
  1.2610 +    F(f32, StrokeMiter);
  1.2611 +#undef F
  1.2612 +#define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
  1.2613 +    F(PathEffect);
  1.2614 +    F(Shader);
  1.2615 +    F(Xfermode);
  1.2616 +    F(MaskFilter);
  1.2617 +    F(ColorFilter);
  1.2618 +    F(Rasterizer);
  1.2619 +    F(Looper);
  1.2620 +    F(ImageFilter);
  1.2621 +#undef F
  1.2622 +    if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
  1.2623 +    if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
  1.2624 +#ifdef SK_BUILD_FOR_ANDROID
  1.2625 +    if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer);
  1.2626 +#endif
  1.2627 +}
  1.2628 +
  1.2629 +void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
  1.2630 +    const uint32_t dirty = buffer.readUInt();
  1.2631 +    if (dirty == 0) {
  1.2632 +        return;
  1.2633 +    }
  1.2634 +#define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
  1.2635 +// Same function, except it unrefs the object newly set on the paint:
  1.2636 +#define F_UNREF(field, reader)                      \
  1.2637 +    if (dirty & k##field##_DirtyBit)                \
  1.2638 +        paint->set##field(buffer.reader())->unref()
  1.2639 +
  1.2640 +    F(Color,       readUInt);
  1.2641 +    F(Bitfields,   readUInt);
  1.2642 +    F(TextSize,    readScalar);
  1.2643 +    F(TextScaleX,  readScalar);
  1.2644 +    F(TextSkewX,   readScalar);
  1.2645 +    F(StrokeWidth, readScalar);
  1.2646 +    F(StrokeMiter, readScalar);
  1.2647 +    F_UNREF(PathEffect,  readPathEffect);
  1.2648 +    F_UNREF(Shader,      readShader);
  1.2649 +    F_UNREF(Xfermode,    readXfermode);
  1.2650 +    F_UNREF(MaskFilter,  readMaskFilter);
  1.2651 +    F_UNREF(ColorFilter, readColorFilter);
  1.2652 +    F_UNREF(Rasterizer,  readRasterizer);
  1.2653 +    F_UNREF(Looper,      readDrawLooper);
  1.2654 +    F_UNREF(ImageFilter, readImageFilter);
  1.2655 +    F(Typeface,    readTypeface);
  1.2656 +#undef F
  1.2657 +#undef F_UNREF
  1.2658 +    if (dirty & kAnnotation_DirtyBit) {
  1.2659 +        paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
  1.2660 +    }
  1.2661 +#ifdef SK_BUILD_FOR_ANDROID
  1.2662 +    if (dirty & kPaintOptionsAndroid_DirtyBit) {
  1.2663 +        SkPaintOptionsAndroid options;
  1.2664 +        options.unflatten(buffer);
  1.2665 +        paint->setPaintOptionsAndroid(options);
  1.2666 +    }
  1.2667 +#endif
  1.2668 +    SkASSERT(dirty == paint->fDirtyBits);
  1.2669 +}

mercurial