SkPaint.cpp revision 9b1cba8ccd7554cb30905711a426bd86ad8dd38c
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 maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize); 820 // this gets restored by restore 821 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 822 } 823 824 SkAutoGlyphCache autoCache(*this, NULL); 825 SkGlyphCache* cache = autoCache.getCache(); 826 827 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); 828 const char* stop; 829 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); 830 SkFixed max = SkScalarToFixed(maxWidth); 831 SkFixed width = 0; 832 833 SkAutoKern autokern; 834 835 if (this->isDevKernText()) 836 { 837 int rsb = 0; 838 while (pred(text, stop)) 839 { 840 const char* curr = text; 841 const SkGlyph& g = glyphCacheProc(cache, &text); 842 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX; 843 if ((width += x) > max) 844 { 845 width -= x; 846 text = curr; 847 break; 848 } 849 rsb = g.fRsbDelta; 850 } 851 } 852 else 853 { 854 while (pred(text, stop)) 855 { 856 const char* curr = text; 857 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX; 858 if ((width += x) > max) 859 { 860 width -= x; 861 text = curr; 862 break; 863 } 864 } 865 } 866 867 if (measuredWidth) 868 { 869 870 SkScalar scalarWidth = SkFixedToScalar(width); 871 if (scale) 872 scalarWidth = SkScalarMul(scalarWidth, scale); 873 *measuredWidth = scalarWidth; 874 } 875 876 // return the number of bytes measured 877 return (kForward_TextBufferDirection == tbd) ? 878 text - stop + length : stop - text + length; 879} 880 881/////////////////////////////////////////////////////////////////////////////// 882 883static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) 884{ 885 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY(); 886 return false; // don't detach the cache 887} 888 889static void FontMetricsDescProc(const SkDescriptor* desc, void* context) 890{ 891 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context); 892} 893 894SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const 895{ 896 SkScalar scale = 0; 897 SkAutoRestorePaintTextSizeAndFrame restore(this); 898 899 if (this->isLinearText()) 900 { 901 scale = fTextSize / kCanonicalTextSizeForPaths; 902 // this gets restored by restore 903 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 904 } 905 906 SkMatrix zoomMatrix, *zoomPtr = NULL; 907 if (zoom) 908 { 909 zoomMatrix.setScale(zoom, zoom); 910 zoomPtr = &zoomMatrix; 911 } 912 913#if 0 914 SkAutoGlyphCache autoCache(*this, zoomPtr); 915 SkGlyphCache* cache = autoCache.getCache(); 916 const FontMetrics& my = cache->getFontMetricsY(); 917#endif 918 FontMetrics storage; 919 if (NULL == metrics) 920 metrics = &storage; 921 922 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics); 923 924 if (scale) 925 { 926 metrics->fTop = SkScalarMul(metrics->fTop, scale); 927 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); 928 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); 929 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); 930 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); 931 } 932 return metrics->fDescent - metrics->fAscent + metrics->fLeading; 933} 934 935//////////////////////////////////////////////////////////////////////////////////////////// 936 937static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) 938{ 939 bounds->set(g.fLeft * scale, 940 g.fTop * scale, 941 (g.fLeft + g.fWidth) * scale, 942 (g.fTop + g.fHeight) * scale); 943} 944 945int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[], 946 SkRect bounds[]) const 947{ 948 if (0 == byteLength) 949 return 0; 950 951 SkASSERT(NULL != textData); 952 953 if (NULL == widths && NULL == bounds) 954 return this->countText(textData, byteLength); 955 956 SkAutoRestorePaintTextSizeAndFrame restore(this); 957 SkScalar scale = 0; 958 959 if (this->isLinearText()) 960 { 961 scale = fTextSize / kCanonicalTextSizeForPaths; 962 // this gets restored by restore 963 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 964 } 965 966 SkAutoGlyphCache autoCache(*this, NULL); 967 SkGlyphCache* cache = autoCache.getCache(); 968 SkMeasureCacheProc glyphCacheProc; 969 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 970 NULL != bounds); 971 972 const char* text = (const char*)textData; 973 const char* stop = text + byteLength; 974 int count = 0; 975 976 if (this->isDevKernText()) 977 { 978 // we adjust the widths returned here through auto-kerning 979 SkAutoKern autokern; 980 SkFixed prevWidth = 0; 981 982 if (scale) { 983 while (text < stop) { 984 const SkGlyph& g = glyphCacheProc(cache, &text); 985 if (widths) { 986 SkFixed adjust = autokern.adjust(g); 987 988 if (count > 0) { 989 SkScalar w = SkFixedToScalar(prevWidth + adjust); 990 *widths++ = SkScalarMul(w, scale); 991 } 992 prevWidth = g.fAdvanceX; 993 } 994 if (bounds) { 995 set_bounds(g, bounds++, scale); 996 } 997 ++count; 998 } 999 if (count > 0 && widths) { 1000 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); 1001 } 1002 } else { 1003 while (text < stop) { 1004 const SkGlyph& g = glyphCacheProc(cache, &text); 1005 if (widths) { 1006 SkFixed adjust = autokern.adjust(g); 1007 1008 if (count > 0) { 1009 *widths++ = SkFixedToScalar(prevWidth + adjust); 1010 } 1011 prevWidth = g.fAdvanceX; 1012 } 1013 if (bounds) { 1014 set_bounds(g, bounds++); 1015 } 1016 ++count; 1017 } 1018 if (count > 0 && widths) { 1019 *widths = SkFixedToScalar(prevWidth); 1020 } 1021 } 1022 } else { // no devkern 1023 if (scale) { 1024 while (text < stop) { 1025 const SkGlyph& g = glyphCacheProc(cache, &text); 1026 if (widths) { 1027 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX), 1028 scale); 1029 } 1030 if (bounds) { 1031 set_bounds(g, bounds++, scale); 1032 } 1033 ++count; 1034 } 1035 } else { 1036 while (text < stop) { 1037 const SkGlyph& g = glyphCacheProc(cache, &text); 1038 if (widths) { 1039 *widths++ = SkFixedToScalar(g.fAdvanceX); 1040 } 1041 if (bounds) { 1042 set_bounds(g, bounds++); 1043 } 1044 ++count; 1045 } 1046 } 1047 } 1048 1049 SkASSERT(text == stop); 1050 return count; 1051} 1052 1053//////////////////////////////////////////////////////////////////////////////////////////// 1054 1055#include "SkDraw.h" 1056 1057void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const 1058{ 1059 const char* text = (const char*)textData; 1060 SkASSERT(length == 0 || text != NULL); 1061 if (text == NULL || length == 0 || path == NULL) 1062 return; 1063 1064 SkTextToPathIter iter(text, length, *this, false, true); 1065 SkMatrix matrix; 1066 SkScalar prevXPos = 0; 1067 1068 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1069 matrix.postTranslate(x, y); 1070 path->reset(); 1071 1072 SkScalar xpos; 1073 const SkPath* iterPath; 1074 while ((iterPath = iter.next(&xpos)) != NULL) 1075 { 1076 matrix.postTranslate(xpos - prevXPos, 0); 1077 path->addPath(*iterPath, matrix); 1078 prevXPos = xpos; 1079 } 1080} 1081 1082static void add_flattenable(SkDescriptor* desc, uint32_t tag, 1083 SkFlattenableWriteBuffer* buffer) { 1084 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL)); 1085} 1086 1087/* 1088 * interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i]) 1089 inspired by a desire to change the multiplier for thickness in fakebold 1090 therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient 1091 repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if 1092 key is the value of a repeated scalar in keys, the first one will be used 1093 - this may change if a binary search is used 1094 - also, this ensures that there is no divide by zero (an assert also checks for that) 1095*/ 1096static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length) 1097{ 1098 1099 SkASSERT(length > 0); 1100 SkASSERT(keys != NULL); 1101 SkASSERT(values != NULL); 1102#ifdef SK_DEBUG 1103 for (int i = 1; i < length; i++) 1104 SkASSERT(keys[i] >= keys[i-1]); 1105#endif 1106 int right = 0; 1107 while (right < length && key > keys[right]) 1108 right++; 1109 //could use sentinal values to eliminate conditionals 1110 //i assume i am not in control of input values, so i want to make it simple 1111 if (length == right) 1112 return values[length-1]; 1113 if (0 == right) 1114 return values[0]; 1115 //otherwise, we interpolate between right-1 and right 1116 SkScalar rVal = values[right]; 1117 SkScalar lVal = values[right-1]; 1118 SkScalar rightKey = keys[right]; 1119 SkScalar leftKey = keys[right-1]; 1120 SkASSERT(rightKey != leftKey); 1121 //fractional amount which we will multiply by the difference in the left value and right value 1122 SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey); 1123 return lVal + SkScalarMul(fract, rVal-lVal); 1124} 1125 1126//used for interpolating in fakeBold 1127static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) }; 1128static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 }; 1129 1130static SkMask::Format computeMaskFormat(const SkPaint& paint) 1131{ 1132 uint32_t flags = paint.getFlags(); 1133 1134 if (flags & SkPaint::kLCDRenderText_Flag) 1135#if defined(SK_SUPPORT_LCDTEXT) 1136 return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ? 1137 SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format; 1138#else 1139 return SkMask::kA8_Format; 1140#endif 1141 if (flags & SkPaint::kAntiAlias_Flag) 1142 return SkMask::kA8_Format; 1143 return SkMask::kBW_Format; 1144} 1145 1146// if linear-text is on, then we force hinting to be off (since that's sort of 1147// the point of linear-text. 1148static SkPaint::Hinting computeHinting(const SkPaint& paint) { 1149 SkPaint::Hinting h = paint.getHinting(); 1150 if (paint.isLinearText()) { 1151 h = SkPaint::kNo_Hinting; 1152 } 1153 return h; 1154} 1155 1156void SkScalerContext::MakeRec(const SkPaint& paint, 1157 const SkMatrix* deviceMatrix, Rec* rec) 1158{ 1159 SkASSERT(deviceMatrix == NULL || 1160 (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0); 1161 1162 rec->fFontID = SkTypeface::UniqueID(paint.getTypeface()); 1163 rec->fTextSize = paint.getTextSize(); 1164 rec->fPreScaleX = paint.getTextScaleX(); 1165 rec->fPreSkewX = paint.getTextSkewX(); 1166 1167 if (deviceMatrix) 1168 { 1169 rec->fPost2x2[0][0] = deviceMatrix->getScaleX(); 1170 rec->fPost2x2[0][1] = deviceMatrix->getSkewX(); 1171 rec->fPost2x2[1][0] = deviceMatrix->getSkewY(); 1172 rec->fPost2x2[1][1] = deviceMatrix->getScaleY(); 1173 } 1174 else 1175 { 1176 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; 1177 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; 1178 } 1179 1180 SkPaint::Style style = paint.getStyle(); 1181 SkScalar strokeWidth = paint.getStrokeWidth(); 1182 1183 if (paint.isFakeBoldText()) 1184 { 1185 SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2); 1186 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); 1187 1188 if (style == SkPaint::kFill_Style) 1189 { 1190 style = SkPaint::kStrokeAndFill_Style; 1191 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill" 1192 } 1193 else 1194 strokeWidth += extra; 1195 } 1196 1197 unsigned flags = SkFontHost::ComputeGammaFlag(paint); 1198 1199 if (paint.isDevKernText()) 1200 flags |= SkScalerContext::kDevKernText_Flag; 1201 1202 if (style != SkPaint::kFill_Style && strokeWidth > 0) 1203 { 1204 rec->fFrameWidth = strokeWidth; 1205 rec->fMiterLimit = paint.getStrokeMiter(); 1206 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); 1207 1208 if (style == SkPaint::kStrokeAndFill_Style) 1209 flags |= SkScalerContext::kFrameAndFill_Flag; 1210 } 1211 else 1212 { 1213 rec->fFrameWidth = 0; 1214 rec->fMiterLimit = 0; 1215 rec->fStrokeJoin = 0; 1216 } 1217 1218 rec->fSubpixelPositioning = paint.isSubpixelText(); 1219 rec->fMaskFormat = SkToU8(computeMaskFormat(paint)); 1220 rec->fFlags = SkToU8(flags); 1221 rec->setHinting(computeHinting(paint)); 1222 1223 /* Allow the fonthost to modify our rec before we use it as a key into the 1224 cache. This way if we're asking for something that they will ignore, 1225 they can modify our rec up front, so we don't create duplicate cache 1226 entries. 1227 */ 1228 SkFontHost::FilterRec(rec); 1229} 1230 1231#define MIN_SIZE_FOR_EFFECT_BUFFER 1024 1232 1233void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, 1234 void (*proc)(const SkDescriptor*, void*), 1235 void* context) const 1236{ 1237 SkScalerContext::Rec rec; 1238 1239 SkScalerContext::MakeRec(*this, deviceMatrix, &rec); 1240 1241 size_t descSize = sizeof(rec); 1242 int entryCount = 1; 1243 SkPathEffect* pe = this->getPathEffect(); 1244 SkMaskFilter* mf = this->getMaskFilter(); 1245 SkRasterizer* ra = this->getRasterizer(); 1246 1247 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1248 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1249 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1250 1251 if (pe) { 1252 peBuffer.writeFlattenable(pe); 1253 descSize += peBuffer.size(); 1254 entryCount += 1; 1255 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1256 // seems like we could support kLCD as well at this point... 1257 } 1258 if (mf) { 1259 mfBuffer.writeFlattenable(mf); 1260 descSize += mfBuffer.size(); 1261 entryCount += 1; 1262 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters 1263 } 1264 if (ra) { 1265 raBuffer.writeFlattenable(ra); 1266 descSize += raBuffer.size(); 1267 entryCount += 1; 1268 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1269 } 1270 descSize += SkDescriptor::ComputeOverhead(entryCount); 1271 1272 SkAutoDescriptor ad(descSize); 1273 SkDescriptor* desc = ad.getDesc(); 1274 1275 desc->init(); 1276 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1277 1278 if (pe) { 1279 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); 1280 } 1281 if (mf) { 1282 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer); 1283 } 1284 if (ra) { 1285 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer); 1286 } 1287 1288 SkASSERT(descSize == desc->getLength()); 1289 desc->computeChecksum(); 1290 1291 proc(desc, context); 1292} 1293 1294static void DetachDescProc(const SkDescriptor* desc, void* context) 1295{ 1296 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); 1297} 1298 1299SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const 1300{ 1301 SkGlyphCache* cache; 1302 this->descriptorProc(deviceMatrix, DetachDescProc, &cache); 1303 return cache; 1304} 1305 1306/////////////////////////////////////////////////////////////////////////////// 1307 1308#include "SkStream.h" 1309 1310static uintptr_t asint(const void* p) { 1311 return reinterpret_cast<uintptr_t>(p); 1312} 1313 1314union Scalar32 { 1315 SkScalar fScalar; 1316 uint32_t f32; 1317}; 1318 1319static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) { 1320 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1321 Scalar32 tmp; 1322 tmp.fScalar = value; 1323 *ptr = tmp.f32; 1324 return ptr + 1; 1325} 1326 1327static SkScalar read_scalar(const uint32_t*& ptr) { 1328 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1329 Scalar32 tmp; 1330 tmp.f32 = *ptr++; 1331 return tmp.fScalar; 1332} 1333 1334static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { 1335 SkASSERT(a == (uint8_t)a); 1336 SkASSERT(b == (uint8_t)b); 1337 SkASSERT(c == (uint8_t)c); 1338 SkASSERT(d == (uint8_t)d); 1339 return (a << 24) | (b << 16) | (c << 8) | d; 1340} 1341 1342enum FlatFlags { 1343 kHasTypeface_FlatFlag = 0x01, 1344 kHasEffects_FlatFlag = 0x02 1345}; 1346 1347// The size of a flat paint's POD fields 1348static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1349 1 * sizeof(SkColor) + 1350 1 * sizeof(uint16_t) + 1351 6 * sizeof(uint8_t); 1352 1353/* To save space/time, we analyze the paint, and write a truncated version of 1354 it if there are not tricky elements like shaders, etc. 1355 */ 1356void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { 1357 uint8_t flatFlags = 0; 1358 if (this->getTypeface()) { 1359 flatFlags |= kHasTypeface_FlatFlag; 1360 } 1361 if (asint(this->getPathEffect()) | 1362 asint(this->getShader()) | 1363 asint(this->getXfermode()) | 1364 asint(this->getMaskFilter()) | 1365 asint(this->getColorFilter()) | 1366 asint(this->getRasterizer()) | 1367 asint(this->getLooper())) { 1368 flatFlags |= kHasEffects_FlatFlag; 1369 } 1370 1371 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1372 uint32_t* ptr = buffer.reserve(kPODPaintSize); 1373 1374 ptr = write_scalar(ptr, this->getTextSize()); 1375 ptr = write_scalar(ptr, this->getTextScaleX()); 1376 ptr = write_scalar(ptr, this->getTextSkewX()); 1377 ptr = write_scalar(ptr, this->getStrokeWidth()); 1378 ptr = write_scalar(ptr, this->getStrokeMiter()); 1379 *ptr++ = this->getColor(); 1380 *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags; 1381 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(), 1382 this->getStyle(), this->getTextEncoding()); 1383 1384 // now we're done with ptr and the (pre)reserved space. If we need to write 1385 // additional fields, use the buffer directly 1386 if (flatFlags & kHasTypeface_FlatFlag) { 1387 buffer.writeTypeface(this->getTypeface()); 1388 } 1389 if (flatFlags & kHasEffects_FlatFlag) { 1390 buffer.writeFlattenable(this->getPathEffect()); 1391 buffer.writeFlattenable(this->getShader()); 1392 buffer.writeFlattenable(this->getXfermode()); 1393 buffer.writeFlattenable(this->getMaskFilter()); 1394 buffer.writeFlattenable(this->getColorFilter()); 1395 buffer.writeFlattenable(this->getRasterizer()); 1396 buffer.writeFlattenable(this->getLooper()); 1397 } 1398} 1399 1400void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { 1401 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1402 const void* podData = buffer.skip(kPODPaintSize); 1403 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData); 1404 1405 // the order we read must match the order we wrote in flatten() 1406 this->setTextSize(read_scalar(pod)); 1407 this->setTextScaleX(read_scalar(pod)); 1408 this->setTextSkewX(read_scalar(pod)); 1409 this->setStrokeWidth(read_scalar(pod)); 1410 this->setStrokeMiter(read_scalar(pod)); 1411 this->setColor(*pod++); 1412 1413 uint32_t tmp = *pod++; 1414 this->setFlags(tmp >> 16); 1415 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF)); 1416 uint8_t flatFlags = tmp & 0xFF; 1417 1418 tmp = *pod++; 1419 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); 1420 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); 1421 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); 1422 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); 1423 1424 if (flatFlags & kHasTypeface_FlatFlag) { 1425 this->setTypeface(buffer.readTypeface()); 1426 } else { 1427 this->setTypeface(NULL); 1428 } 1429 1430 if (flatFlags & kHasEffects_FlatFlag) { 1431 this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref(); 1432 this->setShader((SkShader*) buffer.readFlattenable())->safeUnref(); 1433 this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref(); 1434 this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref(); 1435 this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref(); 1436 this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref(); 1437 this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref(); 1438 } else { 1439 this->setPathEffect(NULL); 1440 this->setShader(NULL); 1441 this->setXfermode(NULL); 1442 this->setMaskFilter(NULL); 1443 this->setColorFilter(NULL); 1444 this->setRasterizer(NULL); 1445 this->setLooper(NULL); 1446 } 1447} 1448 1449/////////////////////////////////////////////////////////////////////////////// 1450 1451SkShader* SkPaint::setShader(SkShader* shader) 1452{ 1453 SkRefCnt_SafeAssign(fShader, shader); 1454 return shader; 1455} 1456 1457SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) 1458{ 1459 SkRefCnt_SafeAssign(fColorFilter, filter); 1460 return filter; 1461} 1462 1463SkXfermode* SkPaint::setXfermode(SkXfermode* mode) 1464{ 1465 SkRefCnt_SafeAssign(fXfermode, mode); 1466 return mode; 1467} 1468 1469SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { 1470 SkSafeUnref(fXfermode); 1471 fXfermode = SkXfermode::Create(mode); 1472 return fXfermode; 1473} 1474 1475SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) 1476{ 1477 SkRefCnt_SafeAssign(fPathEffect, effect); 1478 return effect; 1479} 1480 1481SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) 1482{ 1483 SkRefCnt_SafeAssign(fMaskFilter, filter); 1484 return filter; 1485} 1486 1487//////////////////////////////////////////////////////////////////////////////////////// 1488 1489bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const 1490{ 1491 SkPath effectPath, strokePath; 1492 const SkPath* path = &src; 1493 1494 SkScalar width = this->getStrokeWidth(); 1495 1496 switch (this->getStyle()) { 1497 case SkPaint::kFill_Style: 1498 width = -1; // mark it as no-stroke 1499 break; 1500 case SkPaint::kStrokeAndFill_Style: 1501 if (width == 0) 1502 width = -1; // mark it as no-stroke 1503 break; 1504 case SkPaint::kStroke_Style: 1505 break; 1506 default: 1507 SkASSERT(!"unknown paint style"); 1508 } 1509 1510 if (this->getPathEffect()) 1511 { 1512 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill 1513 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) 1514 width = -1; // mark it as no-stroke 1515 1516 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) 1517 path = &effectPath; 1518 1519 // restore the width if we earlier had to lie, and if we're still set to no-stroke 1520 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change 1521 // and we want to respect that (i.e. don't overwrite their setting for width) 1522 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) 1523 { 1524 width = this->getStrokeWidth(); 1525 if (width == 0) 1526 width = -1; 1527 } 1528 } 1529 1530 if (width > 0 && !path->isEmpty()) 1531 { 1532 SkStroke stroker(*this, width); 1533 stroker.strokePath(*path, &strokePath); 1534 path = &strokePath; 1535 } 1536 1537 if (path == &src) 1538 *dst = src; 1539 else 1540 { 1541 SkASSERT(path == &effectPath || path == &strokePath); 1542 dst->swap(*(SkPath*)path); 1543 } 1544 1545 return width != 0; // return true if we're filled, or false if we're hairline (width == 0) 1546} 1547 1548const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src, 1549 SkRect* storage) const { 1550 SkASSERT(storage); 1551 SkASSERT(this->getStyle() != SkPaint::kFill_Style); 1552 1553 // since we're stroked, outset the rect by the radius (and join type) 1554 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); 1555 if (0 == radius) { // hairline 1556 radius = SK_Scalar1; 1557 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { 1558 SkScalar scale = this->getStrokeMiter(); 1559 if (scale > SK_Scalar1) { 1560 radius = SkScalarMul(radius, scale); 1561 } 1562 } 1563 storage->set(src.fLeft - radius, src.fTop - radius, 1564 src.fRight + radius, src.fBottom + radius); 1565 return *storage; 1566} 1567 1568//////////////////////////////////////////////////////////////////////////////////////// 1569 1570static bool has_thick_frame(const SkPaint& paint) 1571{ 1572 return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style; 1573} 1574 1575SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, 1576 const SkPaint& paint, 1577 bool applyStrokeAndPathEffects, 1578 bool forceLinearTextOn) 1579 : fPaint(paint) /* make a copy of the paint */ 1580{ 1581 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection, 1582 true); 1583 1584 if (forceLinearTextOn) 1585 fPaint.setLinearText(true); 1586 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup 1587 1588 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) 1589 applyStrokeAndPathEffects = false; 1590 1591 // can't use our canonical size if we need to apply patheffects/strokes 1592 if (fPaint.isLinearText() && !applyStrokeAndPathEffects) 1593 { 1594 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 1595 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 1596 } 1597 else 1598 fScale = SK_Scalar1; 1599 1600 if (!applyStrokeAndPathEffects) 1601 { 1602 fPaint.setStyle(SkPaint::kFill_Style); 1603 fPaint.setPathEffect(NULL); 1604 } 1605 1606 fCache = fPaint.detachCache(NULL); 1607 1608 SkPaint::Style style = SkPaint::kFill_Style; 1609 SkPathEffect* pe = NULL; 1610 1611 if (!applyStrokeAndPathEffects) 1612 { 1613 style = paint.getStyle(); // restore 1614 pe = paint.getPathEffect(); // restore 1615 } 1616 fPaint.setStyle(style); 1617 fPaint.setPathEffect(pe); 1618 fPaint.setMaskFilter(paint.getMaskFilter()); // restore 1619 1620 // now compute fXOffset if needed 1621 1622 SkScalar xOffset = 0; 1623 if (paint.getTextAlign() != SkPaint::kLeft_Align) // need to measure first 1624 { 1625 int count; 1626 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale); 1627 if (paint.getTextAlign() == SkPaint::kCenter_Align) 1628 width = SkScalarHalf(width); 1629 xOffset = -width; 1630 } 1631 fXPos = xOffset; 1632 fPrevAdvance = 0; 1633 1634 fText = text; 1635 fStop = text + length; 1636} 1637 1638SkTextToPathIter::~SkTextToPathIter() 1639{ 1640 SkGlyphCache::AttachCache(fCache); 1641} 1642 1643const SkPath* SkTextToPathIter::next(SkScalar* xpos) 1644{ 1645 while (fText < fStop) 1646 { 1647 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 1648 1649 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 1650 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking(); 1651 1652 if (glyph.fWidth) 1653 { 1654 if (xpos) 1655 *xpos = fXPos; 1656 return fCache->findPath(glyph); 1657 } 1658 } 1659 return NULL; 1660} 1661