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