SkPaint.cpp revision 137a4ca42423bbb6d683067ea544c9a48f18f06c
1/* libs/graphics/sgl/SkPaint.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkPaint.h" 19#include "SkColorFilter.h" 20#include "SkDrawLooper.h" 21#include "SkFontHost.h" 22#include "SkMaskFilter.h" 23#include "SkPathEffect.h" 24#include "SkRasterizer.h" 25#include "SkShader.h" 26#include "SkScalar.h" 27#include "SkScalerContext.h" 28#include "SkStroke.h" 29#include "SkTextFormatParams.h" 30#include "SkTypeface.h" 31#include "SkXfermode.h" 32#include "SkAutoKern.h" 33 34#define SK_DefaultTextSize SkIntToScalar(12) 35 36#define SK_DefaultFlags 0 //(kNativeHintsText_Flag) 37 38SkPaint::SkPaint() { 39 // since we may have padding, we zero everything so that our memcmp() call 40 // in operator== will work correctly. 41 // with this, we can skip 0 and null individual initializations 42 sk_bzero(this, sizeof(*this)); 43 44#if 0 // not needed with the bzero call above 45 fTypeface = NULL; 46 fTextSkewX = 0; 47 fPathEffect = NULL; 48 fShader = NULL; 49 fXfermode = NULL; 50 fMaskFilter = NULL; 51 fColorFilter = NULL; 52 fRasterizer = NULL; 53 fLooper = NULL; 54 fWidth = 0; 55#endif 56 57 fTextSize = SK_DefaultTextSize; 58 fTextScaleX = SK_Scalar1; 59 fColor = SK_ColorBLACK; 60 fMiterLimit = SK_DefaultMiterLimit; 61 fFlags = SK_DefaultFlags; 62 fCapType = kDefault_Cap; 63 fJoinType = kDefault_Join; 64 fTextAlign = kLeft_Align; 65 fStyle = kFill_Style; 66 fTextEncoding = kUTF8_TextEncoding; 67 fHinting = kNormal_Hinting; 68 fGenerationID = 0; 69} 70 71SkPaint::SkPaint(const SkPaint& src) { 72 memcpy(this, &src, sizeof(src)); 73 74 SkSafeRef(fTypeface); 75 SkSafeRef(fPathEffect); 76 SkSafeRef(fShader); 77 SkSafeRef(fXfermode); 78 SkSafeRef(fMaskFilter); 79 SkSafeRef(fColorFilter); 80 SkSafeRef(fRasterizer); 81 SkSafeRef(fLooper); 82} 83 84SkPaint::~SkPaint() { 85 SkSafeUnref(fTypeface); 86 SkSafeUnref(fPathEffect); 87 SkSafeUnref(fShader); 88 SkSafeUnref(fXfermode); 89 SkSafeUnref(fMaskFilter); 90 SkSafeUnref(fColorFilter); 91 SkSafeUnref(fRasterizer); 92 SkSafeUnref(fLooper); 93} 94 95SkPaint& SkPaint::operator=(const SkPaint& src) { 96 SkASSERT(&src); 97 98 SkSafeRef(src.fTypeface); 99 SkSafeRef(src.fPathEffect); 100 SkSafeRef(src.fShader); 101 SkSafeRef(src.fXfermode); 102 SkSafeRef(src.fMaskFilter); 103 SkSafeRef(src.fColorFilter); 104 SkSafeRef(src.fRasterizer); 105 SkSafeRef(src.fLooper); 106 107 SkSafeUnref(fTypeface); 108 SkSafeUnref(fPathEffect); 109 SkSafeUnref(fShader); 110 SkSafeUnref(fXfermode); 111 SkSafeUnref(fMaskFilter); 112 SkSafeUnref(fColorFilter); 113 SkSafeUnref(fRasterizer); 114 SkSafeUnref(fLooper); 115 116 uint32_t oldGenerationID = fGenerationID; 117 memcpy(this, &src, sizeof(src)); 118 fGenerationID = oldGenerationID + 1; 119 120 return *this; 121} 122 123int operator==(const SkPaint& a, const SkPaint& b) { 124 return memcmp(&a, &b, sizeof(a)) == 0; 125} 126 127void SkPaint::reset() { 128 SkPaint init; 129 130 uint32_t oldGenerationID = fGenerationID; 131 *this = init; 132 fGenerationID = oldGenerationID + 1; 133} 134 135uint32_t SkPaint::getGenerationID() const { 136 return fGenerationID; 137} 138 139void SkPaint::setFlags(uint32_t flags) 140{ 141 if (fFlags != flags) { 142 fFlags = flags; 143 fGenerationID++; 144 } 145} 146 147void SkPaint::setAntiAlias(bool doAA) 148{ 149 if (doAA != isAntiAlias()) { 150 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); 151 fGenerationID++; 152 } 153} 154 155void SkPaint::setDither(bool doDither) 156{ 157 if (doDither != isDither()) { 158 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); 159 fGenerationID++; 160 } 161} 162 163void SkPaint::setSubpixelText(bool doSubpixel) 164{ 165 if (doSubpixel != isSubpixelText()) { 166 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); 167 fGenerationID++; 168 } 169} 170 171void SkPaint::setLCDRenderText(bool doLCDRender) 172{ 173 if (doLCDRender != isLCDRenderText()) { 174 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); 175 fGenerationID++; 176 } 177} 178 179void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) 180{ 181 if (doEmbeddedBitmapText != isEmbeddedBitmapText()) { 182 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); 183 fGenerationID++; 184 } 185} 186 187void SkPaint::setAutohinted(bool useAutohinter) 188{ 189 this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag)); 190} 191 192void SkPaint::setLinearText(bool doLinearText) 193{ 194 if (doLinearText != isLinearText()) { 195 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); 196 fGenerationID++; 197 } 198} 199 200void SkPaint::setUnderlineText(bool doUnderline) 201{ 202 if (doUnderline != isUnderlineText()) { 203 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); 204 fGenerationID++; 205 } 206} 207 208void SkPaint::setStrikeThruText(bool doStrikeThru) 209{ 210 if (doStrikeThru != isStrikeThruText()) { 211 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); 212 fGenerationID++; 213 } 214} 215 216void SkPaint::setFakeBoldText(bool doFakeBold) 217{ 218 if (doFakeBold != isFakeBoldText()) { 219 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); 220 fGenerationID++; 221 } 222} 223 224void SkPaint::setDevKernText(bool doDevKern) 225{ 226 if (doDevKern != isDevKernText()) { 227 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); 228 fGenerationID++; 229 } 230} 231 232void SkPaint::setFilterBitmap(bool doFilter) 233{ 234 if (doFilter != isFilterBitmap()) { 235 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); 236 fGenerationID++; 237 } 238} 239 240void SkPaint::setStyle(Style style) 241{ 242 if ((unsigned)style < kStyleCount) { 243 if ((unsigned)style != fStyle) { 244 fStyle = style; 245 fGenerationID++; 246 } 247 } 248#ifdef SK_DEBUG 249 else { 250 SkDebugf("SkPaint::setStyle(%d) out of range\n", style); 251 } 252#endif 253} 254 255void SkPaint::setColor(SkColor color) 256{ 257 if (color != fColor) { 258 fColor = color; 259 fGenerationID++; 260 } 261} 262 263void SkPaint::setAlpha(U8CPU a) 264{ 265 U8CPU oldA = SkColorGetA(fColor); 266 if (a != oldA) { 267 fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor)); 268 fGenerationID++; 269 } 270} 271 272void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 273{ 274 SkColor oldColor = fColor; 275 fColor = SkColorSetARGB(a, r, g, b); 276 if (oldColor != fColor) { 277 fGenerationID++; 278 } 279} 280 281void SkPaint::setStrokeWidth(SkScalar width) 282{ 283 if (width >= 0) { 284 if (width != fWidth) { 285 fWidth = width; 286 fGenerationID++; 287 } 288 } 289#ifdef SK_DEBUG 290 else { 291 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); 292 } 293#endif 294} 295 296void SkPaint::setStrokeMiter(SkScalar limit) 297{ 298 if (limit >= 0) { 299 if (limit != fMiterLimit) { 300 fMiterLimit = limit; 301 fGenerationID++; 302 } 303 } 304#ifdef SK_DEBUG 305 else { 306 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); 307 } 308#endif 309} 310 311void SkPaint::setStrokeCap(Cap ct) 312{ 313 if ((unsigned)ct < kCapCount) { 314 if ((unsigned)ct != fCapType) { 315 fCapType = SkToU8(ct); 316 fGenerationID++; 317 } 318 } 319#ifdef SK_DEBUG 320 else 321 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); 322#endif 323} 324 325void SkPaint::setStrokeJoin(Join jt) 326{ 327 if ((unsigned)jt < kJoinCount) { 328 if ((unsigned)jt != fJoinType) { 329 fJoinType = SkToU8(jt); 330 fGenerationID++; 331 } 332 } 333#ifdef SK_DEBUG 334 else 335 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); 336#endif 337} 338 339////////////////////////////////////////////////////////////////// 340 341void SkPaint::setTextAlign(Align align) 342{ 343 if ((unsigned)align < kAlignCount) { 344 if ((unsigned)align != fTextAlign) { 345 fTextAlign = SkToU8(align); 346 fGenerationID++; 347 } 348 } 349#ifdef SK_DEBUG 350 else 351 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); 352#endif 353} 354 355void SkPaint::setTextSize(SkScalar ts) 356{ 357 if (ts > 0) { 358 if (ts != fTextSize) { 359 fTextSize = ts; 360 fGenerationID++; 361 } 362 } 363#ifdef SK_DEBUG 364 else 365 SkDebugf("SkPaint::setTextSize() called with negative value\n"); 366#endif 367} 368 369void SkPaint::setTextScaleX(SkScalar scaleX) 370{ 371 if (scaleX != fTextScaleX) { 372 fTextScaleX = scaleX; 373 fGenerationID++; 374 } 375} 376 377void SkPaint::setTextSkewX(SkScalar skewX) 378{ 379 if (skewX != fTextSkewX) { 380 fTextSkewX = skewX; 381 fGenerationID++; 382 } 383} 384 385void SkPaint::setTextEncoding(TextEncoding encoding) 386{ 387 if ((unsigned)encoding <= kGlyphID_TextEncoding) { 388 if ((unsigned)encoding != fTextEncoding) { 389 fTextEncoding = encoding; 390 fGenerationID++; 391 } 392 } 393#ifdef SK_DEBUG 394 else 395 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding); 396#endif 397} 398 399/////////////////////////////////////////////////////////////////////////////////////// 400 401SkTypeface* SkPaint::setTypeface(SkTypeface* font) 402{ 403 SkRefCnt_SafeAssign(fTypeface, font); 404 fGenerationID++; 405 return font; 406} 407 408SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) { 409 SkRefCnt_SafeAssign(fRasterizer, r); 410 fGenerationID++; 411 return r; 412} 413 414SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { 415 SkRefCnt_SafeAssign(fLooper, looper); 416 fGenerationID++; 417 return looper; 418} 419 420/////////////////////////////////////////////////////////////////////////////// 421 422#include "SkGlyphCache.h" 423#include "SkUtils.h" 424 425static void DetachDescProc(const SkDescriptor* desc, void* context) { 426 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); 427} 428 429const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) { 430 SkGlyphCache* cache; 431 descriptorProc(NULL, DetachDescProc, &cache, true); 432 433 const SkGlyph& glyph = cache->getUnicharMetrics(text); 434 435 SkGlyphCache::AttachCache(cache); 436 return glyph; 437} 438 439const void* SkPaint::findImage(const SkGlyph& glyph) { 440 // See ::detachCache() 441 SkGlyphCache* cache; 442 descriptorProc(NULL, DetachDescProc, &cache, true); 443 444 const void* image = cache->findImage(glyph); 445 446 SkGlyphCache::AttachCache(cache); 447 return image; 448} 449 450int SkPaint::textToGlyphs(const void* textData, size_t byteLength, 451 uint16_t glyphs[]) const { 452 if (byteLength == 0) { 453 return 0; 454 } 455 456 SkASSERT(textData != NULL); 457 458 if (NULL == glyphs) { 459 switch (this->getTextEncoding()) { 460 case kUTF8_TextEncoding: 461 return SkUTF8_CountUnichars((const char*)textData, byteLength); 462 case kUTF16_TextEncoding: 463 return SkUTF16_CountUnichars((const uint16_t*)textData, 464 byteLength >> 1); 465 case kGlyphID_TextEncoding: 466 return byteLength >> 1; 467 default: 468 SkASSERT(!"unknown text encoding"); 469 } 470 return 0; 471 } 472 473 // if we get here, we have a valid glyphs[] array, so time to fill it in 474 475 // handle this encoding before the setup for the glyphcache 476 if (this->getTextEncoding() == kGlyphID_TextEncoding) { 477 // we want to ignore the low bit of byteLength 478 memcpy(glyphs, textData, byteLength >> 1 << 1); 479 return byteLength >> 1; 480 } 481 482 SkAutoGlyphCache autoCache(*this, NULL); 483 SkGlyphCache* cache = autoCache.getCache(); 484 485 const char* text = (const char*)textData; 486 const char* stop = text + byteLength; 487 uint16_t* gptr = glyphs; 488 489 switch (this->getTextEncoding()) { 490 case SkPaint::kUTF8_TextEncoding: 491 while (text < stop) { 492 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text)); 493 } 494 break; 495 case SkPaint::kUTF16_TextEncoding: { 496 const uint16_t* text16 = (const uint16_t*)text; 497 const uint16_t* stop16 = (const uint16_t*)stop; 498 while (text16 < stop16) { 499 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16)); 500 } 501 break; 502 } 503 default: 504 SkASSERT(!"unknown text encoding"); 505 } 506 return gptr - glyphs; 507} 508 509bool SkPaint::containsText(const void* textData, size_t byteLength) const { 510 if (0 == byteLength) { 511 return true; 512 } 513 514 SkASSERT(textData != NULL); 515 516 // handle this encoding before the setup for the glyphcache 517 if (this->getTextEncoding() == kGlyphID_TextEncoding) { 518 const uint16_t* glyphID = static_cast<const uint16_t*>(textData); 519 size_t count = byteLength >> 1; 520 for (size_t i = 0; i < count; i++) { 521 if (0 == glyphID[i]) { 522 return false; 523 } 524 } 525 return true; 526 } 527 528 SkAutoGlyphCache autoCache(*this, NULL); 529 SkGlyphCache* cache = autoCache.getCache(); 530 531 switch (this->getTextEncoding()) { 532 case SkPaint::kUTF8_TextEncoding: { 533 const char* text = static_cast<const char*>(textData); 534 const char* stop = text + byteLength; 535 while (text < stop) { 536 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) { 537 return false; 538 } 539 } 540 break; 541 } 542 case SkPaint::kUTF16_TextEncoding: { 543 const uint16_t* text = static_cast<const uint16_t*>(textData); 544 const uint16_t* stop = text + (byteLength >> 1); 545 while (text < stop) { 546 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) { 547 return false; 548 } 549 } 550 break; 551 } 552 default: 553 SkASSERT(!"unknown text encoding"); 554 return false; 555 } 556 return true; 557} 558 559void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count, 560 SkUnichar textData[]) const { 561 if (count <= 0) { 562 return; 563 } 564 565 SkASSERT(glyphs != NULL); 566 SkASSERT(textData != NULL); 567 568 SkAutoGlyphCache autoCache(*this, NULL); 569 SkGlyphCache* cache = autoCache.getCache(); 570 571 for (int index = 0; index < count; index++) { 572 textData[index] = cache->glyphToUnichar(glyphs[index]); 573 } 574} 575 576/////////////////////////////////////////////////////////////////////////////// 577 578static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, 579 const char** text) { 580 SkASSERT(cache != NULL); 581 SkASSERT(text != NULL); 582 583 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text)); 584} 585 586static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache, 587 const char** text) { 588 SkASSERT(cache != NULL); 589 SkASSERT(text != NULL); 590 591 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text)); 592} 593 594static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, 595 const char** text) { 596 SkASSERT(cache != NULL); 597 SkASSERT(text != NULL); 598 599 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text)); 600} 601 602static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache, 603 const char** text) { 604 SkASSERT(cache != NULL); 605 SkASSERT(text != NULL); 606 607 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text)); 608} 609 610static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, 611 const char** text) { 612 SkASSERT(cache != NULL); 613 SkASSERT(text != NULL); 614 615 const uint16_t* ptr = *(const uint16_t**)text; 616 unsigned glyphID = *ptr; 617 ptr += 1; 618 *text = (const char*)ptr; 619 return cache->getGlyphIDMetrics(glyphID); 620} 621 622static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache, 623 const char** text) { 624 SkASSERT(cache != NULL); 625 SkASSERT(text != NULL); 626 627 const uint16_t* ptr = *(const uint16_t**)text; 628 ptr -= 1; 629 unsigned glyphID = *ptr; 630 *text = (const char*)ptr; 631 return cache->getGlyphIDMetrics(glyphID); 632} 633 634static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, 635 const char** text) { 636 SkASSERT(cache != NULL); 637 SkASSERT(text != NULL); 638 639 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text)); 640} 641 642static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache, 643 const char** text) { 644 SkASSERT(cache != NULL); 645 SkASSERT(text != NULL); 646 647 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text)); 648} 649 650static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, 651 const char** text) { 652 SkASSERT(cache != NULL); 653 SkASSERT(text != NULL); 654 655 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text)); 656} 657 658static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache, 659 const char** text) { 660 SkASSERT(cache != NULL); 661 SkASSERT(text != NULL); 662 663 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text)); 664} 665 666static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, 667 const char** text) { 668 SkASSERT(cache != NULL); 669 SkASSERT(text != NULL); 670 671 const uint16_t* ptr = *(const uint16_t**)text; 672 unsigned glyphID = *ptr; 673 ptr += 1; 674 *text = (const char*)ptr; 675 return cache->getGlyphIDAdvance(glyphID); 676} 677 678static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache, 679 const char** text) { 680 SkASSERT(cache != NULL); 681 SkASSERT(text != NULL); 682 683 const uint16_t* ptr = *(const uint16_t**)text; 684 ptr -= 1; 685 unsigned glyphID = *ptr; 686 *text = (const char*)ptr; 687 return cache->getGlyphIDAdvance(glyphID); 688} 689 690SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd, 691 bool needFullMetrics) const { 692 static const SkMeasureCacheProc gMeasureCacheProcs[] = { 693 sk_getMetrics_utf8_next, 694 sk_getMetrics_utf16_next, 695 sk_getMetrics_glyph_next, 696 697 sk_getMetrics_utf8_prev, 698 sk_getMetrics_utf16_prev, 699 sk_getMetrics_glyph_prev, 700 701 sk_getAdvance_utf8_next, 702 sk_getAdvance_utf16_next, 703 sk_getAdvance_glyph_next, 704 705 sk_getAdvance_utf8_prev, 706 sk_getAdvance_utf16_prev, 707 sk_getAdvance_glyph_prev 708 }; 709 710 unsigned index = this->getTextEncoding(); 711 712 if (kBackward_TextBufferDirection == tbd) { 713 index += 3; 714 } 715 if (!needFullMetrics && !this->isDevKernText()) { 716 index += 6; 717 } 718 719 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs)); 720 return gMeasureCacheProcs[index]; 721} 722 723/////////////////////////////////////////////////////////////////////////////// 724 725static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache, 726 const char** text, SkFixed, SkFixed) { 727 SkASSERT(cache != NULL); 728 SkASSERT(text != NULL); 729 730 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text)); 731} 732 733static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache, 734 const char** text, SkFixed x, SkFixed y) { 735 SkASSERT(cache != NULL); 736 SkASSERT(text != NULL); 737 738 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y); 739} 740 741static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache, 742 const char** text, SkFixed, SkFixed) { 743 SkASSERT(cache != NULL); 744 SkASSERT(text != NULL); 745 746 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text)); 747} 748 749static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache, 750 const char** text, SkFixed x, SkFixed y) { 751 SkASSERT(cache != NULL); 752 SkASSERT(text != NULL); 753 754 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text), 755 x, y); 756} 757 758static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache, 759 const char** text, SkFixed, SkFixed) { 760 SkASSERT(cache != NULL); 761 SkASSERT(text != NULL); 762 763 const uint16_t* ptr = *(const uint16_t**)text; 764 unsigned glyphID = *ptr; 765 ptr += 1; 766 *text = (const char*)ptr; 767 return cache->getGlyphIDMetrics(glyphID); 768} 769 770static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache, 771 const char** text, SkFixed x, SkFixed y) { 772 SkASSERT(cache != NULL); 773 SkASSERT(text != NULL); 774 775 const uint16_t* ptr = *(const uint16_t**)text; 776 unsigned glyphID = *ptr; 777 ptr += 1; 778 *text = (const char*)ptr; 779 return cache->getGlyphIDMetrics(glyphID, x, y); 780} 781 782SkDrawCacheProc SkPaint::getDrawCacheProc() const { 783 static const SkDrawCacheProc gDrawCacheProcs[] = { 784 sk_getMetrics_utf8_00, 785 sk_getMetrics_utf16_00, 786 sk_getMetrics_glyph_00, 787 788 sk_getMetrics_utf8_xy, 789 sk_getMetrics_utf16_xy, 790 sk_getMetrics_glyph_xy 791 }; 792 793 unsigned index = this->getTextEncoding(); 794 if (fFlags & kSubpixelText_Flag) { 795 index += 3; 796 } 797 798 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs)); 799 return gDrawCacheProcs[index]; 800} 801 802/////////////////////////////////////////////////////////////////////////////// 803 804class SkAutoRestorePaintTextSizeAndFrame { 805public: 806 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) 807 : fPaint((SkPaint*)paint) { 808 fTextSize = paint->getTextSize(); 809 fStyle = paint->getStyle(); 810 fPaint->setStyle(SkPaint::kFill_Style); 811 } 812 813 ~SkAutoRestorePaintTextSizeAndFrame() { 814 fPaint->setStyle(fStyle); 815 fPaint->setTextSize(fTextSize); 816 } 817 818private: 819 SkPaint* fPaint; 820 SkScalar fTextSize; 821 SkPaint::Style fStyle; 822}; 823 824static void set_bounds(const SkGlyph& g, SkRect* bounds) { 825 bounds->set(SkIntToScalar(g.fLeft), 826 SkIntToScalar(g.fTop), 827 SkIntToScalar(g.fLeft + g.fWidth), 828 SkIntToScalar(g.fTop + g.fHeight)); 829} 830 831// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so 832// we don't overflow along the way 833typedef int64_t Sk48Dot16; 834 835#ifdef SK_SCALAR_IS_FLOAT 836 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) { 837 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f) 838 } 839#else 840 static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) { 841 // just return the low 32bits 842 return static_cast<SkFixed>(x); 843 } 844#endif 845 846static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) { 847 SkScalar sx = Sk48Dot16ToScalar(dx); 848 bounds->join(SkIntToScalar(g.fLeft) + sx, 849 SkIntToScalar(g.fTop), 850 SkIntToScalar(g.fLeft + g.fWidth) + sx, 851 SkIntToScalar(g.fTop + g.fHeight)); 852} 853 854SkScalar SkPaint::measure_text(SkGlyphCache* cache, 855 const char* text, size_t byteLength, 856 int* count, SkRect* bounds) const { 857 SkASSERT(count); 858 if (byteLength == 0) { 859 *count = 0; 860 if (bounds) { 861 bounds->setEmpty(); 862 } 863 return 0; 864 } 865 866 SkMeasureCacheProc glyphCacheProc; 867 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 868 NULL != bounds); 869 870 int n = 1; 871 const char* stop = (const char*)text + byteLength; 872 const SkGlyph* g = &glyphCacheProc(cache, &text); 873 // our accumulated fixed-point advances might overflow 16.16, so we use 874 // a 48.16 (64bit) accumulator, and then convert that to scalar at the 875 // very end. 876 Sk48Dot16 x = g->fAdvanceX; 877 878 SkAutoKern autokern; 879 880 if (NULL == bounds) { 881 if (this->isDevKernText()) { 882 int rsb; 883 for (; text < stop; n++) { 884 rsb = g->fRsbDelta; 885 g = &glyphCacheProc(cache, &text); 886 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX; 887 } 888 } else { 889 for (; text < stop; n++) { 890 x += glyphCacheProc(cache, &text).fAdvanceX; 891 } 892 } 893 } else { 894 set_bounds(*g, bounds); 895 if (this->isDevKernText()) { 896 int rsb; 897 for (; text < stop; n++) { 898 rsb = g->fRsbDelta; 899 g = &glyphCacheProc(cache, &text); 900 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta); 901 join_bounds(*g, bounds, x); 902 x += g->fAdvanceX; 903 } 904 } else { 905 for (; text < stop; n++) { 906 g = &glyphCacheProc(cache, &text); 907 join_bounds(*g, bounds, x); 908 x += g->fAdvanceX; 909 } 910 } 911 } 912 SkASSERT(text == stop); 913 914 *count = n; 915 return Sk48Dot16ToScalar(x); 916} 917 918SkScalar SkPaint::measureText(const void* textData, size_t length, 919 SkRect* bounds, SkScalar zoom) const { 920 const char* text = (const char*)textData; 921 SkASSERT(text != NULL || length == 0); 922 923 SkScalar scale = 0; 924 SkAutoRestorePaintTextSizeAndFrame restore(this); 925 926 if (this->isLinearText()) { 927 scale = fTextSize / kCanonicalTextSizeForPaths; 928 // this gets restored by restore 929 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 930 } 931 932 SkMatrix zoomMatrix, *zoomPtr = NULL; 933 if (zoom) { 934 zoomMatrix.setScale(zoom, zoom); 935 zoomPtr = &zoomMatrix; 936 } 937 938 SkAutoGlyphCache autoCache(*this, zoomPtr); 939 SkGlyphCache* cache = autoCache.getCache(); 940 941 SkScalar width = 0; 942 943 if (length > 0) { 944 int tempCount; 945 946 width = this->measure_text(cache, text, length, &tempCount, bounds); 947 if (scale) { 948 width = SkScalarMul(width, scale); 949 if (bounds) { 950 bounds->fLeft = SkScalarMul(bounds->fLeft, scale); 951 bounds->fTop = SkScalarMul(bounds->fTop, scale); 952 bounds->fRight = SkScalarMul(bounds->fRight, scale); 953 bounds->fBottom = SkScalarMul(bounds->fBottom, scale); 954 } 955 } 956 } 957 return width; 958} 959 960typedef bool (*SkTextBufferPred)(const char* text, const char* stop); 961 962static bool forward_textBufferPred(const char* text, const char* stop) { 963 return text < stop; 964} 965 966static bool backward_textBufferPred(const char* text, const char* stop) { 967 return text > stop; 968} 969 970static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd, 971 const char** text, size_t length, 972 const char** stop) { 973 if (SkPaint::kForward_TextBufferDirection == tbd) { 974 *stop = *text + length; 975 return forward_textBufferPred; 976 } else { 977 // text should point to the end of the buffer, and stop to the beginning 978 *stop = *text; 979 *text += length; 980 return backward_textBufferPred; 981 } 982} 983 984size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, 985 SkScalar* measuredWidth, 986 TextBufferDirection tbd) const { 987 if (0 == length || 0 >= maxWidth) { 988 if (measuredWidth) { 989 *measuredWidth = 0; 990 } 991 return 0; 992 } 993 994 SkASSERT(textD != NULL); 995 const char* text = (const char*)textD; 996 997 SkScalar scale = 0; 998 SkAutoRestorePaintTextSizeAndFrame restore(this); 999 1000 if (this->isLinearText()) { 1001 scale = fTextSize / kCanonicalTextSizeForPaths; 1002 maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize); 1003 // this gets restored by restore 1004 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 1005 } 1006 1007 SkAutoGlyphCache autoCache(*this, NULL); 1008 SkGlyphCache* cache = autoCache.getCache(); 1009 1010 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); 1011 const char* stop; 1012 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); 1013 // use 64bits for our accumulator, to avoid overflowing 16.16 1014 Sk48Dot16 max = SkScalarToFixed(maxWidth); 1015 Sk48Dot16 width = 0; 1016 1017 SkAutoKern autokern; 1018 1019 if (this->isDevKernText()) { 1020 int rsb = 0; 1021 while (pred(text, stop)) { 1022 const char* curr = text; 1023 const SkGlyph& g = glyphCacheProc(cache, &text); 1024 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX; 1025 if ((width += x) > max) { 1026 width -= x; 1027 text = curr; 1028 break; 1029 } 1030 rsb = g.fRsbDelta; 1031 } 1032 } else { 1033 while (pred(text, stop)) { 1034 const char* curr = text; 1035 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX; 1036 if ((width += x) > max) { 1037 width -= x; 1038 text = curr; 1039 break; 1040 } 1041 } 1042 } 1043 1044 if (measuredWidth) { 1045 SkScalar scalarWidth = Sk48Dot16ToScalar(width); 1046 if (scale) { 1047 scalarWidth = SkScalarMul(scalarWidth, scale); 1048 } 1049 *measuredWidth = scalarWidth; 1050 } 1051 1052 // return the number of bytes measured 1053 return (kForward_TextBufferDirection == tbd) ? 1054 text - stop + length : stop - text + length; 1055} 1056 1057/////////////////////////////////////////////////////////////////////////////// 1058 1059static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) { 1060 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY(); 1061 return false; // don't detach the cache 1062} 1063 1064static void FontMetricsDescProc(const SkDescriptor* desc, void* context) { 1065 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context); 1066} 1067 1068SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { 1069 SkScalar scale = 0; 1070 SkAutoRestorePaintTextSizeAndFrame restore(this); 1071 1072 if (this->isLinearText()) { 1073 scale = fTextSize / kCanonicalTextSizeForPaths; 1074 // this gets restored by restore 1075 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 1076 } 1077 1078 SkMatrix zoomMatrix, *zoomPtr = NULL; 1079 if (zoom) { 1080 zoomMatrix.setScale(zoom, zoom); 1081 zoomPtr = &zoomMatrix; 1082 } 1083 1084#if 0 1085 SkAutoGlyphCache autoCache(*this, zoomPtr); 1086 SkGlyphCache* cache = autoCache.getCache(); 1087 const FontMetrics& my = cache->getFontMetricsY(); 1088#endif 1089 FontMetrics storage; 1090 if (NULL == metrics) { 1091 metrics = &storage; 1092 } 1093 1094 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics); 1095 1096 if (scale) { 1097 metrics->fTop = SkScalarMul(metrics->fTop, scale); 1098 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); 1099 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); 1100 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); 1101 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); 1102 } 1103 return metrics->fDescent - metrics->fAscent + metrics->fLeading; 1104} 1105 1106/////////////////////////////////////////////////////////////////////////////// 1107 1108static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) { 1109 bounds->set(g.fLeft * scale, 1110 g.fTop * scale, 1111 (g.fLeft + g.fWidth) * scale, 1112 (g.fTop + g.fHeight) * scale); 1113} 1114 1115int SkPaint::getTextWidths(const void* textData, size_t byteLength, 1116 SkScalar widths[], SkRect bounds[]) const { 1117 if (0 == byteLength) { 1118 return 0; 1119 } 1120 1121 SkASSERT(NULL != textData); 1122 1123 if (NULL == widths && NULL == bounds) { 1124 return this->countText(textData, byteLength); 1125 } 1126 1127 SkAutoRestorePaintTextSizeAndFrame restore(this); 1128 SkScalar scale = 0; 1129 1130 if (this->isLinearText()) { 1131 scale = fTextSize / kCanonicalTextSizeForPaths; 1132 // this gets restored by restore 1133 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 1134 } 1135 1136 SkAutoGlyphCache autoCache(*this, NULL); 1137 SkGlyphCache* cache = autoCache.getCache(); 1138 SkMeasureCacheProc glyphCacheProc; 1139 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 1140 NULL != bounds); 1141 1142 const char* text = (const char*)textData; 1143 const char* stop = text + byteLength; 1144 int count = 0; 1145 1146 if (this->isDevKernText()) { 1147 // we adjust the widths returned here through auto-kerning 1148 SkAutoKern autokern; 1149 SkFixed prevWidth = 0; 1150 1151 if (scale) { 1152 while (text < stop) { 1153 const SkGlyph& g = glyphCacheProc(cache, &text); 1154 if (widths) { 1155 SkFixed adjust = autokern.adjust(g); 1156 1157 if (count > 0) { 1158 SkScalar w = SkFixedToScalar(prevWidth + adjust); 1159 *widths++ = SkScalarMul(w, scale); 1160 } 1161 prevWidth = g.fAdvanceX; 1162 } 1163 if (bounds) { 1164 set_bounds(g, bounds++, scale); 1165 } 1166 ++count; 1167 } 1168 if (count > 0 && widths) { 1169 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); 1170 } 1171 } else { 1172 while (text < stop) { 1173 const SkGlyph& g = glyphCacheProc(cache, &text); 1174 if (widths) { 1175 SkFixed adjust = autokern.adjust(g); 1176 1177 if (count > 0) { 1178 *widths++ = SkFixedToScalar(prevWidth + adjust); 1179 } 1180 prevWidth = g.fAdvanceX; 1181 } 1182 if (bounds) { 1183 set_bounds(g, bounds++); 1184 } 1185 ++count; 1186 } 1187 if (count > 0 && widths) { 1188 *widths = SkFixedToScalar(prevWidth); 1189 } 1190 } 1191 } else { // no devkern 1192 if (scale) { 1193 while (text < stop) { 1194 const SkGlyph& g = glyphCacheProc(cache, &text); 1195 if (widths) { 1196 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX), 1197 scale); 1198 } 1199 if (bounds) { 1200 set_bounds(g, bounds++, scale); 1201 } 1202 ++count; 1203 } 1204 } else { 1205 while (text < stop) { 1206 const SkGlyph& g = glyphCacheProc(cache, &text); 1207 if (widths) { 1208 *widths++ = SkFixedToScalar(g.fAdvanceX); 1209 } 1210 if (bounds) { 1211 set_bounds(g, bounds++); 1212 } 1213 ++count; 1214 } 1215 } 1216 } 1217 1218 SkASSERT(text == stop); 1219 return count; 1220} 1221 1222/////////////////////////////////////////////////////////////////////////////// 1223 1224#include "SkDraw.h" 1225 1226void SkPaint::getTextPath(const void* textData, size_t length, 1227 SkScalar x, SkScalar y, SkPath* path) const { 1228 SkASSERT(length == 0 || textData != NULL); 1229 1230 const char* text = (const char*)textData; 1231 if (text == NULL || length == 0 || path == NULL) { 1232 return; 1233 } 1234 1235 SkTextToPathIter iter(text, length, *this, false, true); 1236 SkMatrix matrix; 1237 SkScalar prevXPos = 0; 1238 1239 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1240 matrix.postTranslate(x, y); 1241 path->reset(); 1242 1243 SkScalar xpos; 1244 const SkPath* iterPath; 1245 while ((iterPath = iter.next(&xpos)) != NULL) { 1246 matrix.postTranslate(xpos - prevXPos, 0); 1247 path->addPath(*iterPath, matrix); 1248 prevXPos = xpos; 1249 } 1250} 1251 1252static void add_flattenable(SkDescriptor* desc, uint32_t tag, 1253 SkFlattenableWriteBuffer* buffer) { 1254 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL)); 1255} 1256 1257static SkMask::Format computeMaskFormat(const SkPaint& paint) { 1258 uint32_t flags = paint.getFlags(); 1259 1260 // Antialiasing being disabled trumps all other settings. 1261 if (!(flags & SkPaint::kAntiAlias_Flag)) { 1262 return SkMask::kBW_Format; 1263 } 1264 1265#if defined(SK_SUPPORT_LCDTEXT) 1266 if (flags & SkPaint::kLCDRenderText_Flag) { 1267 return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ? 1268 SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format; 1269 } 1270#else 1271 if (flags & SkPaint::kLCDRenderText_Flag) { 1272 return SkMask::kLCD16_Format; 1273 } 1274#endif 1275 1276 return SkMask::kA8_Format; 1277} 1278 1279// if linear-text is on, then we force hinting to be off (since that's sort of 1280// the point of linear-text. 1281static SkPaint::Hinting computeHinting(const SkPaint& paint) { 1282 SkPaint::Hinting h = paint.getHinting(); 1283 if (paint.isLinearText()) { 1284 h = SkPaint::kNo_Hinting; 1285 } 1286 return h; 1287} 1288 1289/* 1290 * Return the scalar with only limited fractional precision. Used to consolidate matrices 1291 * that vary only slightly when we create our key into the font cache, since the font scaler 1292 * typically returns the same looking resuts for tiny changes in the matrix. 1293 */ 1294static SkScalar sk_relax(SkScalar x) { 1295#ifdef SK_SCALAR_IS_FLOAT 1296 int n = sk_float_round2int(x * 1024); 1297 return n / 1024.0f; 1298#else 1299 // round to the nearest 10 fractional bits 1300 return (x + (1 << 5)) & ~(1024 - 1); 1301#endif 1302} 1303 1304void SkScalerContext::MakeRec(const SkPaint& paint, 1305 const SkMatrix* deviceMatrix, Rec* rec) { 1306 SkASSERT(deviceMatrix == NULL || 1307 (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0); 1308 1309 rec->fFontID = SkTypeface::UniqueID(paint.getTypeface()); 1310 rec->fTextSize = paint.getTextSize(); 1311 rec->fPreScaleX = paint.getTextScaleX(); 1312 rec->fPreSkewX = paint.getTextSkewX(); 1313 1314 if (deviceMatrix) { 1315 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX()); 1316 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX()); 1317 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY()); 1318 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY()); 1319 } else { 1320 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; 1321 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; 1322 } 1323 1324 SkPaint::Style style = paint.getStyle(); 1325 SkScalar strokeWidth = paint.getStrokeWidth(); 1326 1327 unsigned flags = SkFontHost::ComputeGammaFlag(paint); 1328 1329 if (paint.isFakeBoldText()) { 1330#ifdef SK_USE_FREETYPE_EMBOLDEN 1331 flags |= SkScalerContext::kEmbolden_Flag; 1332#else 1333 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(), 1334 kStdFakeBoldInterpKeys, 1335 kStdFakeBoldInterpValues, 1336 kStdFakeBoldInterpLength); 1337 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); 1338 1339 if (style == SkPaint::kFill_Style) { 1340 style = SkPaint::kStrokeAndFill_Style; 1341 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill" 1342 } else { 1343 strokeWidth += extra; 1344 } 1345#endif 1346 } 1347 1348 if (paint.isDevKernText()) { 1349 flags |= SkScalerContext::kDevKernText_Flag; 1350 } 1351 1352 if (style != SkPaint::kFill_Style && strokeWidth > 0) { 1353 rec->fFrameWidth = strokeWidth; 1354 rec->fMiterLimit = paint.getStrokeMiter(); 1355 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); 1356 1357 if (style == SkPaint::kStrokeAndFill_Style) { 1358 flags |= SkScalerContext::kFrameAndFill_Flag; 1359 } 1360 } else { 1361 rec->fFrameWidth = 0; 1362 rec->fMiterLimit = 0; 1363 rec->fStrokeJoin = 0; 1364 } 1365 1366 rec->fMaskFormat = SkToU8(computeMaskFormat(paint)); 1367 rec->fFlags = SkToU8(flags); 1368 rec->setHinting(computeHinting(paint)); 1369 if (paint.isEmbeddedBitmapText()) { 1370 rec->fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag; 1371 } 1372 if (paint.isSubpixelText()) { 1373 rec->fFlags |= SkScalerContext::kSubpixelPositioning_Flag; 1374 } 1375 if (paint.isAutohinted()) { 1376 rec->fFlags |= SkScalerContext::kAutohinting_Flag; 1377 } 1378 1379 /* Allow the fonthost to modify our rec before we use it as a key into the 1380 cache. This way if we're asking for something that they will ignore, 1381 they can modify our rec up front, so we don't create duplicate cache 1382 entries. 1383 */ 1384 SkFontHost::FilterRec(rec); 1385} 1386 1387#define MIN_SIZE_FOR_EFFECT_BUFFER 1024 1388 1389void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, 1390 void (*proc)(const SkDescriptor*, void*), 1391 void* context, bool ignoreGamma) const { 1392 SkScalerContext::Rec rec; 1393 1394 SkScalerContext::MakeRec(*this, deviceMatrix, &rec); 1395 if (ignoreGamma) { 1396 rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag | 1397 SkScalerContext::kGammaForWhite_Flag); 1398 } 1399 1400 size_t descSize = sizeof(rec); 1401 int entryCount = 1; 1402 SkPathEffect* pe = this->getPathEffect(); 1403 SkMaskFilter* mf = this->getMaskFilter(); 1404 SkRasterizer* ra = this->getRasterizer(); 1405 1406 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1407 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1408 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1409 1410 if (pe) { 1411 peBuffer.writeFlattenable(pe); 1412 descSize += peBuffer.size(); 1413 entryCount += 1; 1414 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1415 // seems like we could support kLCD as well at this point... 1416 } 1417 if (mf) { 1418 mfBuffer.writeFlattenable(mf); 1419 descSize += mfBuffer.size(); 1420 entryCount += 1; 1421 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters 1422 } 1423 if (ra) { 1424 raBuffer.writeFlattenable(ra); 1425 descSize += raBuffer.size(); 1426 entryCount += 1; 1427 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1428 } 1429 descSize += SkDescriptor::ComputeOverhead(entryCount); 1430 1431 SkAutoDescriptor ad(descSize); 1432 SkDescriptor* desc = ad.getDesc(); 1433 1434 desc->init(); 1435 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1436 1437 if (pe) { 1438 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); 1439 } 1440 if (mf) { 1441 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer); 1442 } 1443 if (ra) { 1444 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer); 1445 } 1446 1447 SkASSERT(descSize == desc->getLength()); 1448 desc->computeChecksum(); 1449 1450 proc(desc, context); 1451} 1452 1453SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const { 1454 SkGlyphCache* cache; 1455 this->descriptorProc(deviceMatrix, DetachDescProc, &cache); 1456 return cache; 1457} 1458 1459/////////////////////////////////////////////////////////////////////////////// 1460 1461#include "SkStream.h" 1462 1463static uintptr_t asint(const void* p) { 1464 return reinterpret_cast<uintptr_t>(p); 1465} 1466 1467union Scalar32 { 1468 SkScalar fScalar; 1469 uint32_t f32; 1470}; 1471 1472static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) { 1473 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1474 Scalar32 tmp; 1475 tmp.fScalar = value; 1476 *ptr = tmp.f32; 1477 return ptr + 1; 1478} 1479 1480static SkScalar read_scalar(const uint32_t*& ptr) { 1481 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1482 Scalar32 tmp; 1483 tmp.f32 = *ptr++; 1484 return tmp.fScalar; 1485} 1486 1487static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { 1488 SkASSERT(a == (uint8_t)a); 1489 SkASSERT(b == (uint8_t)b); 1490 SkASSERT(c == (uint8_t)c); 1491 SkASSERT(d == (uint8_t)d); 1492 return (a << 24) | (b << 16) | (c << 8) | d; 1493} 1494 1495enum FlatFlags { 1496 kHasTypeface_FlatFlag = 0x01, 1497 kHasEffects_FlatFlag = 0x02 1498}; 1499 1500// The size of a flat paint's POD fields 1501static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1502 1 * sizeof(SkColor) + 1503 1 * sizeof(uint16_t) + 1504 6 * sizeof(uint8_t); 1505 1506/* To save space/time, we analyze the paint, and write a truncated version of 1507 it if there are not tricky elements like shaders, etc. 1508 */ 1509void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { 1510 uint8_t flatFlags = 0; 1511 if (this->getTypeface()) { 1512 flatFlags |= kHasTypeface_FlatFlag; 1513 } 1514 if (asint(this->getPathEffect()) | 1515 asint(this->getShader()) | 1516 asint(this->getXfermode()) | 1517 asint(this->getMaskFilter()) | 1518 asint(this->getColorFilter()) | 1519 asint(this->getRasterizer()) | 1520 asint(this->getLooper())) { 1521 flatFlags |= kHasEffects_FlatFlag; 1522 } 1523 1524 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1525 uint32_t* ptr = buffer.reserve(kPODPaintSize); 1526 1527 ptr = write_scalar(ptr, this->getTextSize()); 1528 ptr = write_scalar(ptr, this->getTextScaleX()); 1529 ptr = write_scalar(ptr, this->getTextSkewX()); 1530 ptr = write_scalar(ptr, this->getStrokeWidth()); 1531 ptr = write_scalar(ptr, this->getStrokeMiter()); 1532 *ptr++ = this->getColor(); 1533 *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags; 1534 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(), 1535 this->getStyle(), this->getTextEncoding()); 1536 1537 // now we're done with ptr and the (pre)reserved space. If we need to write 1538 // additional fields, use the buffer directly 1539 if (flatFlags & kHasTypeface_FlatFlag) { 1540 buffer.writeTypeface(this->getTypeface()); 1541 } 1542 if (flatFlags & kHasEffects_FlatFlag) { 1543 buffer.writeFlattenable(this->getPathEffect()); 1544 buffer.writeFlattenable(this->getShader()); 1545 buffer.writeFlattenable(this->getXfermode()); 1546 buffer.writeFlattenable(this->getMaskFilter()); 1547 buffer.writeFlattenable(this->getColorFilter()); 1548 buffer.writeFlattenable(this->getRasterizer()); 1549 buffer.writeFlattenable(this->getLooper()); 1550 } 1551} 1552 1553void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { 1554 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1555 const void* podData = buffer.skip(kPODPaintSize); 1556 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData); 1557 1558 // the order we read must match the order we wrote in flatten() 1559 this->setTextSize(read_scalar(pod)); 1560 this->setTextScaleX(read_scalar(pod)); 1561 this->setTextSkewX(read_scalar(pod)); 1562 this->setStrokeWidth(read_scalar(pod)); 1563 this->setStrokeMiter(read_scalar(pod)); 1564 this->setColor(*pod++); 1565 1566 uint32_t tmp = *pod++; 1567 this->setFlags(tmp >> 16); 1568 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF)); 1569 uint8_t flatFlags = tmp & 0xFF; 1570 1571 tmp = *pod++; 1572 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); 1573 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); 1574 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); 1575 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); 1576 1577 if (flatFlags & kHasTypeface_FlatFlag) { 1578 this->setTypeface(buffer.readTypeface()); 1579 } else { 1580 this->setTypeface(NULL); 1581 } 1582 1583 if (flatFlags & kHasEffects_FlatFlag) { 1584 SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable())); 1585 SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable())); 1586 SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable())); 1587 SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())); 1588 SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable())); 1589 SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable())); 1590 SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable())); 1591 } else { 1592 this->setPathEffect(NULL); 1593 this->setShader(NULL); 1594 this->setXfermode(NULL); 1595 this->setMaskFilter(NULL); 1596 this->setColorFilter(NULL); 1597 this->setRasterizer(NULL); 1598 this->setLooper(NULL); 1599 } 1600} 1601 1602/////////////////////////////////////////////////////////////////////////////// 1603 1604SkShader* SkPaint::setShader(SkShader* shader) 1605{ 1606 if (shader != fShader) { 1607 fGenerationID++; 1608 } 1609 SkRefCnt_SafeAssign(fShader, shader); 1610 return shader; 1611} 1612 1613SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) 1614{ 1615 if (filter != fColorFilter) { 1616 fGenerationID++; 1617 } 1618 SkRefCnt_SafeAssign(fColorFilter, filter); 1619 return filter; 1620} 1621 1622SkXfermode* SkPaint::setXfermode(SkXfermode* mode) 1623{ 1624 if (mode != fXfermode) { 1625 fGenerationID++; 1626 } 1627 SkRefCnt_SafeAssign(fXfermode, mode); 1628 return mode; 1629} 1630 1631SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { 1632 SkSafeUnref(fXfermode); 1633 fXfermode = SkXfermode::Create(mode); 1634 fGenerationID++; 1635 return fXfermode; 1636} 1637 1638SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) 1639{ 1640 if (effect != fPathEffect) { 1641 fGenerationID++; 1642 } 1643 SkRefCnt_SafeAssign(fPathEffect, effect); 1644 return effect; 1645} 1646 1647SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) 1648{ 1649 if (filter != fMaskFilter) { 1650 fGenerationID++; 1651 } 1652 SkRefCnt_SafeAssign(fMaskFilter, filter); 1653 return filter; 1654} 1655 1656/////////////////////////////////////////////////////////////////////////////// 1657 1658bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const { 1659 SkPath effectPath, strokePath; 1660 const SkPath* path = &src; 1661 1662 SkScalar width = this->getStrokeWidth(); 1663 1664 switch (this->getStyle()) { 1665 case SkPaint::kFill_Style: 1666 width = -1; // mark it as no-stroke 1667 break; 1668 case SkPaint::kStrokeAndFill_Style: 1669 if (width == 0) { 1670 width = -1; // mark it as no-stroke 1671 } 1672 break; 1673 case SkPaint::kStroke_Style: 1674 break; 1675 default: 1676 SkASSERT(!"unknown paint style"); 1677 } 1678 1679 if (this->getPathEffect()) { 1680 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill 1681 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) { 1682 width = -1; // mark it as no-stroke 1683 } 1684 1685 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) { 1686 path = &effectPath; 1687 } 1688 1689 // restore the width if we earlier had to lie, and if we're still set to no-stroke 1690 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change 1691 // and we want to respect that (i.e. don't overwrite their setting for width) 1692 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) { 1693 width = this->getStrokeWidth(); 1694 if (width == 0) { 1695 width = -1; 1696 } 1697 } 1698 } 1699 1700 if (width > 0 && !path->isEmpty()) { 1701 SkStroke stroker(*this, width); 1702 stroker.strokePath(*path, &strokePath); 1703 path = &strokePath; 1704 } 1705 1706 if (path == &src) { 1707 *dst = src; 1708 } else { 1709 SkASSERT(path == &effectPath || path == &strokePath); 1710 dst->swap(*(SkPath*)path); 1711 } 1712 1713 return width != 0; // return true if we're filled, or false if we're hairline (width == 0) 1714} 1715 1716const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src, 1717 SkRect* storage) const { 1718 SkASSERT(storage); 1719 SkASSERT(this->getStyle() != SkPaint::kFill_Style); 1720 1721 // since we're stroked, outset the rect by the radius (and join type) 1722 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); 1723 if (0 == radius) { // hairline 1724 radius = SK_Scalar1; 1725 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { 1726 SkScalar scale = this->getStrokeMiter(); 1727 if (scale > SK_Scalar1) { 1728 radius = SkScalarMul(radius, scale); 1729 } 1730 } 1731 storage->set(src.fLeft - radius, src.fTop - radius, 1732 src.fRight + radius, src.fBottom + radius); 1733 return *storage; 1734} 1735 1736/////////////////////////////////////////////////////////////////////////////// 1737 1738static bool has_thick_frame(const SkPaint& paint) { 1739 return paint.getStrokeWidth() > 0 && 1740 paint.getStyle() != SkPaint::kFill_Style; 1741} 1742 1743SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, 1744 const SkPaint& paint, 1745 bool applyStrokeAndPathEffects, 1746 bool forceLinearTextOn) : fPaint(paint) { 1747 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection, 1748 true); 1749 1750 if (forceLinearTextOn) { 1751 fPaint.setLinearText(true); 1752 } 1753 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup 1754 1755 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) { 1756 applyStrokeAndPathEffects = false; 1757 } 1758 1759 // can't use our canonical size if we need to apply patheffects/strokes 1760 if (fPaint.isLinearText() && !applyStrokeAndPathEffects) { 1761 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 1762 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 1763 } else { 1764 fScale = SK_Scalar1; 1765 } 1766 1767 if (!applyStrokeAndPathEffects) { 1768 fPaint.setStyle(SkPaint::kFill_Style); 1769 fPaint.setPathEffect(NULL); 1770 } 1771 1772 fCache = fPaint.detachCache(NULL); 1773 1774 SkPaint::Style style = SkPaint::kFill_Style; 1775 SkPathEffect* pe = NULL; 1776 1777 if (!applyStrokeAndPathEffects) { 1778 style = paint.getStyle(); // restore 1779 pe = paint.getPathEffect(); // restore 1780 } 1781 fPaint.setStyle(style); 1782 fPaint.setPathEffect(pe); 1783 fPaint.setMaskFilter(paint.getMaskFilter()); // restore 1784 1785 // now compute fXOffset if needed 1786 1787 SkScalar xOffset = 0; 1788 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first 1789 int count; 1790 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, 1791 &count, NULL), fScale); 1792 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1793 width = SkScalarHalf(width); 1794 } 1795 xOffset = -width; 1796 } 1797 fXPos = xOffset; 1798 fPrevAdvance = 0; 1799 1800 fText = text; 1801 fStop = text + length; 1802} 1803 1804SkTextToPathIter::~SkTextToPathIter() { 1805 SkGlyphCache::AttachCache(fCache); 1806} 1807 1808const SkPath* SkTextToPathIter::next(SkScalar* xpos) { 1809 while (fText < fStop) { 1810 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 1811 1812 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 1813 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking(); 1814 1815 if (glyph.fWidth) { 1816 if (xpos) { 1817 *xpos = fXPos; 1818 } 1819 return fCache->findPath(glyph); 1820 } 1821 } 1822 return NULL; 1823} 1824