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