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