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