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