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