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