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 +}