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