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