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