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