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