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 36 SkPaint::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 68 SkPaint::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 82 SkPaint::~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 94 SkPaint& 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 121 int operator==(const SkPaint& a, const SkPaint& b) 122 { 123 return memcmp(&a, &b, sizeof(a)) == 0; 124 } 125 126 void SkPaint::reset() 127 { 128 SkPaint init; 129 130 *this = init; 131 } 132 133 void SkPaint::setFlags(uint32_t flags) 134 { 135 fFlags = flags; 136 } 137 138 void SkPaint::setAntiAlias(bool doAA) 139 { 140 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); 141 } 142 143 void SkPaint::setDither(bool doDither) 144 { 145 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); 146 } 147 148 void SkPaint::setSubpixelText(bool doSubpixel) 149 { 150 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); 151 } 152 153 void SkPaint::setLCDRenderText(bool doLCDRender) 154 { 155 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); 156 } 157 158 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) 159 { 160 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); 161 } 162 163 void SkPaint::setLinearText(bool doLinearText) 164 { 165 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); 166 } 167 168 void SkPaint::setUnderlineText(bool doUnderline) 169 { 170 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); 171 } 172 173 void SkPaint::setStrikeThruText(bool doStrikeThru) 174 { 175 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); 176 } 177 178 void SkPaint::setFakeBoldText(bool doFakeBold) 179 { 180 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); 181 } 182 183 void SkPaint::setDevKernText(bool doDevKern) 184 { 185 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); 186 } 187 188 void SkPaint::setFilterBitmap(bool doFilter) 189 { 190 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); 191 } 192 193 void 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 203 void SkPaint::setColor(SkColor color) 204 { 205 fColor = color; 206 } 207 208 void SkPaint::setAlpha(U8CPU a) 209 { 210 fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor)); 211 } 212 213 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 214 { 215 fColor = SkColorSetARGB(a, r, g, b); 216 } 217 218 void 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 228 void 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 238 void 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 248 void 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 260 void 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 270 void 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 280 void SkPaint::setTextScaleX(SkScalar scaleX) 281 { 282 fTextScaleX = scaleX; 283 } 284 285 void SkPaint::setTextSkewX(SkScalar skewX) 286 { 287 fTextSkewX = skewX; 288 } 289 290 void 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 302 SkTypeface* SkPaint::setTypeface(SkTypeface* font) 303 { 304 SkRefCnt_SafeAssign(fTypeface, font); 305 return font; 306 } 307 308 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) 309 { 310 SkRefCnt_SafeAssign(fRasterizer, r); 311 return r; 312 } 313 314 SkDrawLooper* 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 325 int 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 384 bool 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 434 void 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 453 static 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 461 static 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 469 static 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 477 static 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 485 static 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 497 static 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 511 static 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 519 static 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 527 static 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 535 static 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 543 static 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 555 static 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 567 SkMeasureCacheProc 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 601 static 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 610 static 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 619 static 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 628 static 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 638 static 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 651 static 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 664 SkDrawCacheProc 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 686 class SkAutoRestorePaintTextSizeAndFrame { 687 public: 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 700 private: 701 SkPaint* fPaint; 702 SkScalar fTextSize; 703 SkPaint::Style fStyle; 704 }; 705 706 static 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 714 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so 715 // we don't overflow along the way 716 typedef int64_t Sk48Dot16; 717 718 #ifdef SK_SCALAR_IS_FLOAT 719 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) { 720 return x * 1.5258789e-5f; // x * (1 / 65536.0f) 721 } 722 #else 723 static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) { 724 // just return the low 32bits 725 return static_cast<SkFixed>(x); 726 } 727 #endif 728 729 static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) 730 { 731 SkScalar sx = Sk48Dot16ToScalar(dx); 732 bounds->join(SkIntToScalar(g.fLeft) + sx, 733 SkIntToScalar(g.fTop), 734 SkIntToScalar(g.fLeft + g.fWidth) + sx, 735 SkIntToScalar(g.fTop + g.fHeight)); 736 } 737 738 SkScalar SkPaint::measure_text(SkGlyphCache* cache, 739 const char* text, size_t byteLength, 740 int* count, SkRect* bounds) const 741 { 742 SkASSERT(count); 743 if (byteLength == 0) 744 { 745 *count = 0; 746 if (bounds) 747 bounds->setEmpty(); 748 return 0; 749 } 750 751 SkMeasureCacheProc glyphCacheProc; 752 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 753 NULL != bounds); 754 755 int n = 1; 756 const char* stop = (const char*)text + byteLength; 757 const SkGlyph* g = &glyphCacheProc(cache, &text); 758 // our accumulated fixed-point advances might overflow 16.16, so we use 759 // a 48.16 (64bit) accumulator, and then convert that to scalar at the 760 // very end. 761 Sk48Dot16 x = g->fAdvanceX; 762 763 SkAutoKern autokern; 764 765 if (NULL == bounds) 766 { 767 if (this->isDevKernText()) 768 { 769 int rsb; 770 for (; text < stop; n++) { 771 rsb = g->fRsbDelta; 772 g = &glyphCacheProc(cache, &text); 773 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX; 774 } 775 } 776 else 777 { 778 for (; text < stop; n++) { 779 x += glyphCacheProc(cache, &text).fAdvanceX; 780 } 781 } 782 } 783 else 784 { 785 set_bounds(*g, bounds); 786 if (this->isDevKernText()) 787 { 788 int rsb; 789 for (; text < stop; n++) { 790 rsb = g->fRsbDelta; 791 g = &glyphCacheProc(cache, &text); 792 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta); 793 join_bounds(*g, bounds, x); 794 x += g->fAdvanceX; 795 } 796 } 797 else 798 { 799 for (; text < stop; n++) { 800 g = &glyphCacheProc(cache, &text); 801 join_bounds(*g, bounds, x); 802 x += g->fAdvanceX; 803 } 804 } 805 } 806 SkASSERT(text == stop); 807 808 *count = n; 809 return Sk48Dot16ToScalar(x); 810 } 811 812 SkScalar SkPaint::measureText(const void* textData, size_t length, 813 SkRect* bounds, SkScalar zoom) const 814 { 815 const char* text = (const char*)textData; 816 SkASSERT(text != NULL || length == 0); 817 818 SkScalar scale = 0; 819 SkAutoRestorePaintTextSizeAndFrame restore(this); 820 821 if (this->isLinearText()) 822 { 823 scale = fTextSize / kCanonicalTextSizeForPaths; 824 // this gets restored by restore 825 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 826 } 827 828 SkMatrix zoomMatrix, *zoomPtr = NULL; 829 if (zoom) 830 { 831 zoomMatrix.setScale(zoom, zoom); 832 zoomPtr = &zoomMatrix; 833 } 834 835 SkAutoGlyphCache autoCache(*this, zoomPtr); 836 SkGlyphCache* cache = autoCache.getCache(); 837 838 SkScalar width = 0; 839 840 if (length > 0) 841 { 842 int tempCount; 843 844 width = this->measure_text(cache, text, length, &tempCount, bounds); 845 if (scale) 846 { 847 width = SkScalarMul(width, scale); 848 if (bounds) 849 { 850 bounds->fLeft = SkScalarMul(bounds->fLeft, scale); 851 bounds->fTop = SkScalarMul(bounds->fTop, scale); 852 bounds->fRight = SkScalarMul(bounds->fRight, scale); 853 bounds->fBottom = SkScalarMul(bounds->fBottom, scale); 854 } 855 } 856 } 857 return width; 858 } 859 860 typedef bool (*SkTextBufferPred)(const char* text, const char* stop); 861 862 static bool forward_textBufferPred(const char* text, const char* stop) 863 { 864 return text < stop; 865 } 866 867 static bool backward_textBufferPred(const char* text, const char* stop) 868 { 869 return text > stop; 870 } 871 872 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd, 873 const char** text, size_t length, const char** stop) 874 { 875 if (SkPaint::kForward_TextBufferDirection == tbd) 876 { 877 *stop = *text + length; 878 return forward_textBufferPred; 879 } 880 else 881 { 882 // text should point to the end of the buffer, and stop to the beginning 883 *stop = *text; 884 *text += length; 885 return backward_textBufferPred; 886 } 887 } 888 889 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, 890 SkScalar* measuredWidth, 891 TextBufferDirection tbd) const 892 { 893 if (0 == length || 0 >= maxWidth) 894 { 895 if (measuredWidth) 896 *measuredWidth = 0; 897 return 0; 898 } 899 900 SkASSERT(textD != NULL); 901 const char* text = (const char*)textD; 902 903 SkScalar scale = 0; 904 SkAutoRestorePaintTextSizeAndFrame restore(this); 905 906 if (this->isLinearText()) 907 { 908 scale = fTextSize / kCanonicalTextSizeForPaths; 909 // this gets restored by restore 910 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 911 } 912 913 SkAutoGlyphCache autoCache(*this, NULL); 914 SkGlyphCache* cache = autoCache.getCache(); 915 916 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); 917 const char* stop; 918 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); 919 // use 64bits for our accumulator, to avoid overflowing 16.16 920 Sk48Dot16 max = SkScalarToFixed(maxWidth); 921 Sk48Dot16 width = 0; 922 923 SkAutoKern autokern; 924 925 if (this->isDevKernText()) 926 { 927 int rsb = 0; 928 while (pred(text, stop)) 929 { 930 const char* curr = text; 931 const SkGlyph& g = glyphCacheProc(cache, &text); 932 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX; 933 if ((width += x) > max) 934 { 935 width -= x; 936 text = curr; 937 break; 938 } 939 rsb = g.fRsbDelta; 940 } 941 } 942 else 943 { 944 while (pred(text, stop)) 945 { 946 const char* curr = text; 947 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX; 948 if ((width += x) > max) 949 { 950 width -= x; 951 text = curr; 952 break; 953 } 954 } 955 } 956 957 if (measuredWidth) 958 { 959 960 SkScalar scalarWidth = Sk48Dot16ToScalar(width); 961 if (scale) 962 scalarWidth = SkScalarMul(scalarWidth, scale); 963 *measuredWidth = scalarWidth; 964 } 965 966 // return the number of bytes measured 967 return (kForward_TextBufferDirection == tbd) ? 968 text - stop + length : stop - text + length; 969 } 970 971 /////////////////////////////////////////////////////////////////////////////// 972 973 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) 974 { 975 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY(); 976 return false; // don't detach the cache 977 } 978 979 static void FontMetricsDescProc(const SkDescriptor* desc, void* context) 980 { 981 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context); 982 } 983 984 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const 985 { 986 SkScalar scale = 0; 987 SkAutoRestorePaintTextSizeAndFrame restore(this); 988 989 if (this->isLinearText()) 990 { 991 scale = fTextSize / kCanonicalTextSizeForPaths; 992 // this gets restored by restore 993 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 994 } 995 996 SkMatrix zoomMatrix, *zoomPtr = NULL; 997 if (zoom) 998 { 999 zoomMatrix.setScale(zoom, zoom); 1000 zoomPtr = &zoomMatrix; 1001 } 1002 1003 #if 0 1004 SkAutoGlyphCache autoCache(*this, zoomPtr); 1005 SkGlyphCache* cache = autoCache.getCache(); 1006 const FontMetrics& my = cache->getFontMetricsY(); 1007 #endif 1008 FontMetrics storage; 1009 if (NULL == metrics) 1010 metrics = &storage; 1011 1012 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics); 1013 1014 if (scale) 1015 { 1016 metrics->fTop = SkScalarMul(metrics->fTop, scale); 1017 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); 1018 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); 1019 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); 1020 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); 1021 } 1022 return metrics->fDescent - metrics->fAscent + metrics->fLeading; 1023 } 1024 1025 //////////////////////////////////////////////////////////////////////////////////////////// 1026 1027 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) 1028 { 1029 bounds->set(g.fLeft * scale, 1030 g.fTop * scale, 1031 (g.fLeft + g.fWidth) * scale, 1032 (g.fTop + g.fHeight) * scale); 1033 } 1034 1035 int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[], 1036 SkRect bounds[]) const 1037 { 1038 if (0 == byteLength) 1039 return 0; 1040 1041 SkASSERT(NULL != textData); 1042 1043 if (NULL == widths && NULL == bounds) 1044 return this->countText(textData, byteLength); 1045 1046 SkAutoRestorePaintTextSizeAndFrame restore(this); 1047 SkScalar scale = 0; 1048 1049 if (this->isLinearText()) 1050 { 1051 scale = fTextSize / kCanonicalTextSizeForPaths; 1052 // this gets restored by restore 1053 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); 1054 } 1055 1056 SkAutoGlyphCache autoCache(*this, NULL); 1057 SkGlyphCache* cache = autoCache.getCache(); 1058 SkMeasureCacheProc glyphCacheProc; 1059 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, 1060 NULL != bounds); 1061 1062 const char* text = (const char*)textData; 1063 const char* stop = text + byteLength; 1064 int count = 0; 1065 1066 if (this->isDevKernText()) 1067 { 1068 // we adjust the widths returned here through auto-kerning 1069 SkAutoKern autokern; 1070 SkFixed prevWidth = 0; 1071 1072 if (scale) { 1073 while (text < stop) { 1074 const SkGlyph& g = glyphCacheProc(cache, &text); 1075 if (widths) { 1076 SkFixed adjust = autokern.adjust(g); 1077 1078 if (count > 0) { 1079 SkScalar w = SkFixedToScalar(prevWidth + adjust); 1080 *widths++ = SkScalarMul(w, scale); 1081 } 1082 prevWidth = g.fAdvanceX; 1083 } 1084 if (bounds) { 1085 set_bounds(g, bounds++, scale); 1086 } 1087 ++count; 1088 } 1089 if (count > 0 && widths) { 1090 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); 1091 } 1092 } else { 1093 while (text < stop) { 1094 const SkGlyph& g = glyphCacheProc(cache, &text); 1095 if (widths) { 1096 SkFixed adjust = autokern.adjust(g); 1097 1098 if (count > 0) { 1099 *widths++ = SkFixedToScalar(prevWidth + adjust); 1100 } 1101 prevWidth = g.fAdvanceX; 1102 } 1103 if (bounds) { 1104 set_bounds(g, bounds++); 1105 } 1106 ++count; 1107 } 1108 if (count > 0 && widths) { 1109 *widths = SkFixedToScalar(prevWidth); 1110 } 1111 } 1112 } else { // no devkern 1113 if (scale) { 1114 while (text < stop) { 1115 const SkGlyph& g = glyphCacheProc(cache, &text); 1116 if (widths) { 1117 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX), 1118 scale); 1119 } 1120 if (bounds) { 1121 set_bounds(g, bounds++, scale); 1122 } 1123 ++count; 1124 } 1125 } else { 1126 while (text < stop) { 1127 const SkGlyph& g = glyphCacheProc(cache, &text); 1128 if (widths) { 1129 *widths++ = SkFixedToScalar(g.fAdvanceX); 1130 } 1131 if (bounds) { 1132 set_bounds(g, bounds++); 1133 } 1134 ++count; 1135 } 1136 } 1137 } 1138 1139 SkASSERT(text == stop); 1140 return count; 1141 } 1142 1143 //////////////////////////////////////////////////////////////////////////////////////////// 1144 1145 #include "SkDraw.h" 1146 1147 void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const 1148 { 1149 const char* text = (const char*)textData; 1150 SkASSERT(length == 0 || text != NULL); 1151 if (text == NULL || length == 0 || path == NULL) 1152 return; 1153 1154 SkTextToPathIter iter(text, length, *this, false, true); 1155 SkMatrix matrix; 1156 SkScalar prevXPos = 0; 1157 1158 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1159 matrix.postTranslate(x, y); 1160 path->reset(); 1161 1162 SkScalar xpos; 1163 const SkPath* iterPath; 1164 while ((iterPath = iter.next(&xpos)) != NULL) 1165 { 1166 matrix.postTranslate(xpos - prevXPos, 0); 1167 path->addPath(*iterPath, matrix); 1168 prevXPos = xpos; 1169 } 1170 } 1171 1172 static void add_flattenable(SkDescriptor* desc, uint32_t tag, 1173 SkFlattenableWriteBuffer* buffer) { 1174 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL)); 1175 } 1176 1177 /* 1178 * interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i]) 1179 inspired by a desire to change the multiplier for thickness in fakebold 1180 therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient 1181 repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if 1182 key is the value of a repeated scalar in keys, the first one will be used 1183 - this may change if a binary search is used 1184 - also, this ensures that there is no divide by zero (an assert also checks for that) 1185 */ 1186 static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length) 1187 { 1188 1189 SkASSERT(length > 0); 1190 SkASSERT(keys != NULL); 1191 SkASSERT(values != NULL); 1192 #ifdef SK_DEBUG 1193 for (int i = 1; i < length; i++) 1194 SkASSERT(keys[i] >= keys[i-1]); 1195 #endif 1196 int right = 0; 1197 while (right < length && key > keys[right]) 1198 right++; 1199 //could use sentinal values to eliminate conditionals 1200 //i assume i am not in control of input values, so i want to make it simple 1201 if (length == right) 1202 return values[length-1]; 1203 if (0 == right) 1204 return values[0]; 1205 //otherwise, we interpolate between right-1 and right 1206 SkScalar rVal = values[right]; 1207 SkScalar lVal = values[right-1]; 1208 SkScalar rightKey = keys[right]; 1209 SkScalar leftKey = keys[right-1]; 1210 SkASSERT(rightKey != leftKey); 1211 //fractional amount which we will multiply by the difference in the left value and right value 1212 SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey); 1213 return lVal + SkScalarMul(fract, rVal-lVal); 1214 } 1215 1216 //used for interpolating in fakeBold 1217 static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) }; 1218 static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 }; 1219 1220 static SkMask::Format computeMaskFormat(const SkPaint& paint) 1221 { 1222 uint32_t flags = paint.getFlags(); 1223 1224 // Antialiasing being disabled trumps all other settings. 1225 if (!(flags & SkPaint::kAntiAlias_Flag)) 1226 return SkMask::kBW_Format; 1227 1228 #if defined(SK_SUPPORT_LCDTEXT) 1229 if (flags & SkPaint::kLCDRenderText_Flag) 1230 return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ? 1231 SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format; 1232 #endif 1233 1234 return SkMask::kA8_Format; 1235 } 1236 1237 // if linear-text is on, then we force hinting to be off (since that's sort of 1238 // the point of linear-text. 1239 static SkPaint::Hinting computeHinting(const SkPaint& paint) { 1240 SkPaint::Hinting h = paint.getHinting(); 1241 if (paint.isLinearText()) { 1242 h = SkPaint::kNo_Hinting; 1243 } 1244 return h; 1245 } 1246 1247 void SkScalerContext::MakeRec(const SkPaint& paint, 1248 const SkMatrix* deviceMatrix, Rec* rec) 1249 { 1250 SkASSERT(deviceMatrix == NULL || 1251 (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0); 1252 1253 rec->fFontID = SkTypeface::UniqueID(paint.getTypeface()); 1254 rec->fTextSize = paint.getTextSize(); 1255 rec->fPreScaleX = paint.getTextScaleX(); 1256 rec->fPreSkewX = paint.getTextSkewX(); 1257 1258 if (deviceMatrix) 1259 { 1260 rec->fPost2x2[0][0] = deviceMatrix->getScaleX(); 1261 rec->fPost2x2[0][1] = deviceMatrix->getSkewX(); 1262 rec->fPost2x2[1][0] = deviceMatrix->getSkewY(); 1263 rec->fPost2x2[1][1] = deviceMatrix->getScaleY(); 1264 } 1265 else 1266 { 1267 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; 1268 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; 1269 } 1270 1271 SkPaint::Style style = paint.getStyle(); 1272 SkScalar strokeWidth = paint.getStrokeWidth(); 1273 1274 unsigned flags = SkFontHost::ComputeGammaFlag(paint); 1275 1276 if (paint.isFakeBoldText()) 1277 { 1278 #ifdef SK_USE_FREETYPE_EMBOLDEN 1279 flags |= SkScalerContext::kEmbolden_Flag; 1280 #else 1281 SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2); 1282 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); 1283 1284 if (style == SkPaint::kFill_Style) 1285 { 1286 style = SkPaint::kStrokeAndFill_Style; 1287 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill" 1288 } 1289 else 1290 strokeWidth += extra; 1291 #endif 1292 } 1293 1294 if (paint.isDevKernText()) 1295 flags |= SkScalerContext::kDevKernText_Flag; 1296 1297 if (style != SkPaint::kFill_Style && strokeWidth > 0) 1298 { 1299 rec->fFrameWidth = strokeWidth; 1300 rec->fMiterLimit = paint.getStrokeMiter(); 1301 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); 1302 1303 if (style == SkPaint::kStrokeAndFill_Style) 1304 flags |= SkScalerContext::kFrameAndFill_Flag; 1305 } 1306 else 1307 { 1308 rec->fFrameWidth = 0; 1309 rec->fMiterLimit = 0; 1310 rec->fStrokeJoin = 0; 1311 } 1312 1313 rec->fSubpixelPositioning = paint.isSubpixelText(); 1314 rec->fMaskFormat = SkToU8(computeMaskFormat(paint)); 1315 rec->fFlags = SkToU8(flags); 1316 rec->setHinting(computeHinting(paint)); 1317 if (paint.isEmbeddedBitmapText()) 1318 rec->fFlags |= SkScalerContext::kEmbeddedBitmapText_Flag; 1319 1320 /* Allow the fonthost to modify our rec before we use it as a key into the 1321 cache. This way if we're asking for something that they will ignore, 1322 they can modify our rec up front, so we don't create duplicate cache 1323 entries. 1324 */ 1325 SkFontHost::FilterRec(rec); 1326 } 1327 1328 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024 1329 1330 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, 1331 void (*proc)(const SkDescriptor*, void*), 1332 void* context) const 1333 { 1334 SkScalerContext::Rec rec; 1335 1336 SkScalerContext::MakeRec(*this, deviceMatrix, &rec); 1337 1338 size_t descSize = sizeof(rec); 1339 int entryCount = 1; 1340 SkPathEffect* pe = this->getPathEffect(); 1341 SkMaskFilter* mf = this->getMaskFilter(); 1342 SkRasterizer* ra = this->getRasterizer(); 1343 1344 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1345 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1346 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); 1347 1348 if (pe) { 1349 peBuffer.writeFlattenable(pe); 1350 descSize += peBuffer.size(); 1351 entryCount += 1; 1352 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1353 // seems like we could support kLCD as well at this point... 1354 } 1355 if (mf) { 1356 mfBuffer.writeFlattenable(mf); 1357 descSize += mfBuffer.size(); 1358 entryCount += 1; 1359 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters 1360 } 1361 if (ra) { 1362 raBuffer.writeFlattenable(ra); 1363 descSize += raBuffer.size(); 1364 entryCount += 1; 1365 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1366 } 1367 descSize += SkDescriptor::ComputeOverhead(entryCount); 1368 1369 SkAutoDescriptor ad(descSize); 1370 SkDescriptor* desc = ad.getDesc(); 1371 1372 desc->init(); 1373 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1374 1375 if (pe) { 1376 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); 1377 } 1378 if (mf) { 1379 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer); 1380 } 1381 if (ra) { 1382 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer); 1383 } 1384 1385 SkASSERT(descSize == desc->getLength()); 1386 desc->computeChecksum(); 1387 1388 proc(desc, context); 1389 } 1390 1391 static void DetachDescProc(const SkDescriptor* desc, void* context) 1392 { 1393 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); 1394 } 1395 1396 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const 1397 { 1398 SkGlyphCache* cache; 1399 this->descriptorProc(deviceMatrix, DetachDescProc, &cache); 1400 return cache; 1401 } 1402 1403 /////////////////////////////////////////////////////////////////////////////// 1404 1405 #include "SkStream.h" 1406 1407 static uintptr_t asint(const void* p) { 1408 return reinterpret_cast<uintptr_t>(p); 1409 } 1410 1411 union Scalar32 { 1412 SkScalar fScalar; 1413 uint32_t f32; 1414 }; 1415 1416 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) { 1417 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1418 Scalar32 tmp; 1419 tmp.fScalar = value; 1420 *ptr = tmp.f32; 1421 return ptr + 1; 1422 } 1423 1424 static SkScalar read_scalar(const uint32_t*& ptr) { 1425 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1426 Scalar32 tmp; 1427 tmp.f32 = *ptr++; 1428 return tmp.fScalar; 1429 } 1430 1431 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { 1432 SkASSERT(a == (uint8_t)a); 1433 SkASSERT(b == (uint8_t)b); 1434 SkASSERT(c == (uint8_t)c); 1435 SkASSERT(d == (uint8_t)d); 1436 return (a << 24) | (b << 16) | (c << 8) | d; 1437 } 1438 1439 enum FlatFlags { 1440 kHasTypeface_FlatFlag = 0x01, 1441 kHasEffects_FlatFlag = 0x02 1442 }; 1443 1444 // The size of a flat paint's POD fields 1445 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1446 1 * sizeof(SkColor) + 1447 1 * sizeof(uint16_t) + 1448 6 * sizeof(uint8_t); 1449 1450 /* To save space/time, we analyze the paint, and write a truncated version of 1451 it if there are not tricky elements like shaders, etc. 1452 */ 1453 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { 1454 uint8_t flatFlags = 0; 1455 if (this->getTypeface()) { 1456 flatFlags |= kHasTypeface_FlatFlag; 1457 } 1458 if (asint(this->getPathEffect()) | 1459 asint(this->getShader()) | 1460 asint(this->getXfermode()) | 1461 asint(this->getMaskFilter()) | 1462 asint(this->getColorFilter()) | 1463 asint(this->getRasterizer()) | 1464 asint(this->getLooper())) { 1465 flatFlags |= kHasEffects_FlatFlag; 1466 } 1467 1468 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1469 uint32_t* ptr = buffer.reserve(kPODPaintSize); 1470 1471 ptr = write_scalar(ptr, this->getTextSize()); 1472 ptr = write_scalar(ptr, this->getTextScaleX()); 1473 ptr = write_scalar(ptr, this->getTextSkewX()); 1474 ptr = write_scalar(ptr, this->getStrokeWidth()); 1475 ptr = write_scalar(ptr, this->getStrokeMiter()); 1476 *ptr++ = this->getColor(); 1477 *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags; 1478 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(), 1479 this->getStyle(), this->getTextEncoding()); 1480 1481 // now we're done with ptr and the (pre)reserved space. If we need to write 1482 // additional fields, use the buffer directly 1483 if (flatFlags & kHasTypeface_FlatFlag) { 1484 buffer.writeTypeface(this->getTypeface()); 1485 } 1486 if (flatFlags & kHasEffects_FlatFlag) { 1487 buffer.writeFlattenable(this->getPathEffect()); 1488 buffer.writeFlattenable(this->getShader()); 1489 buffer.writeFlattenable(this->getXfermode()); 1490 buffer.writeFlattenable(this->getMaskFilter()); 1491 buffer.writeFlattenable(this->getColorFilter()); 1492 buffer.writeFlattenable(this->getRasterizer()); 1493 buffer.writeFlattenable(this->getLooper()); 1494 } 1495 } 1496 1497 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { 1498 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1499 const void* podData = buffer.skip(kPODPaintSize); 1500 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData); 1501 1502 // the order we read must match the order we wrote in flatten() 1503 this->setTextSize(read_scalar(pod)); 1504 this->setTextScaleX(read_scalar(pod)); 1505 this->setTextSkewX(read_scalar(pod)); 1506 this->setStrokeWidth(read_scalar(pod)); 1507 this->setStrokeMiter(read_scalar(pod)); 1508 this->setColor(*pod++); 1509 1510 uint32_t tmp = *pod++; 1511 this->setFlags(tmp >> 16); 1512 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF)); 1513 uint8_t flatFlags = tmp & 0xFF; 1514 1515 tmp = *pod++; 1516 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); 1517 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); 1518 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); 1519 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); 1520 1521 if (flatFlags & kHasTypeface_FlatFlag) { 1522 this->setTypeface(buffer.readTypeface()); 1523 } else { 1524 this->setTypeface(NULL); 1525 } 1526 1527 if (flatFlags & kHasEffects_FlatFlag) { 1528 this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref(); 1529 this->setShader((SkShader*) buffer.readFlattenable())->safeUnref(); 1530 this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref(); 1531 this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref(); 1532 this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref(); 1533 this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref(); 1534 this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref(); 1535 } else { 1536 this->setPathEffect(NULL); 1537 this->setShader(NULL); 1538 this->setXfermode(NULL); 1539 this->setMaskFilter(NULL); 1540 this->setColorFilter(NULL); 1541 this->setRasterizer(NULL); 1542 this->setLooper(NULL); 1543 } 1544 } 1545 1546 /////////////////////////////////////////////////////////////////////////////// 1547 1548 SkShader* SkPaint::setShader(SkShader* shader) 1549 { 1550 SkRefCnt_SafeAssign(fShader, shader); 1551 return shader; 1552 } 1553 1554 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) 1555 { 1556 SkRefCnt_SafeAssign(fColorFilter, filter); 1557 return filter; 1558 } 1559 1560 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) 1561 { 1562 SkRefCnt_SafeAssign(fXfermode, mode); 1563 return mode; 1564 } 1565 1566 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { 1567 SkSafeUnref(fXfermode); 1568 fXfermode = SkXfermode::Create(mode); 1569 return fXfermode; 1570 } 1571 1572 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) 1573 { 1574 SkRefCnt_SafeAssign(fPathEffect, effect); 1575 return effect; 1576 } 1577 1578 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) 1579 { 1580 SkRefCnt_SafeAssign(fMaskFilter, filter); 1581 return filter; 1582 } 1583 1584 //////////////////////////////////////////////////////////////////////////////////////// 1585 1586 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const 1587 { 1588 SkPath effectPath, strokePath; 1589 const SkPath* path = &src; 1590 1591 SkScalar width = this->getStrokeWidth(); 1592 1593 switch (this->getStyle()) { 1594 case SkPaint::kFill_Style: 1595 width = -1; // mark it as no-stroke 1596 break; 1597 case SkPaint::kStrokeAndFill_Style: 1598 if (width == 0) 1599 width = -1; // mark it as no-stroke 1600 break; 1601 case SkPaint::kStroke_Style: 1602 break; 1603 default: 1604 SkASSERT(!"unknown paint style"); 1605 } 1606 1607 if (this->getPathEffect()) 1608 { 1609 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill 1610 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) 1611 width = -1; // mark it as no-stroke 1612 1613 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) 1614 path = &effectPath; 1615 1616 // restore the width if we earlier had to lie, and if we're still set to no-stroke 1617 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change 1618 // and we want to respect that (i.e. don't overwrite their setting for width) 1619 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) 1620 { 1621 width = this->getStrokeWidth(); 1622 if (width == 0) 1623 width = -1; 1624 } 1625 } 1626 1627 if (width > 0 && !path->isEmpty()) 1628 { 1629 SkStroke stroker(*this, width); 1630 stroker.strokePath(*path, &strokePath); 1631 path = &strokePath; 1632 } 1633 1634 if (path == &src) 1635 *dst = src; 1636 else 1637 { 1638 SkASSERT(path == &effectPath || path == &strokePath); 1639 dst->swap(*(SkPath*)path); 1640 } 1641 1642 return width != 0; // return true if we're filled, or false if we're hairline (width == 0) 1643 } 1644 1645 const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src, 1646 SkRect* storage) const { 1647 SkASSERT(storage); 1648 SkASSERT(this->getStyle() != SkPaint::kFill_Style); 1649 1650 // since we're stroked, outset the rect by the radius (and join type) 1651 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); 1652 if (0 == radius) { // hairline 1653 radius = SK_Scalar1; 1654 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { 1655 SkScalar scale = this->getStrokeMiter(); 1656 if (scale > SK_Scalar1) { 1657 radius = SkScalarMul(radius, scale); 1658 } 1659 } 1660 storage->set(src.fLeft - radius, src.fTop - radius, 1661 src.fRight + radius, src.fBottom + radius); 1662 return *storage; 1663 } 1664 1665 //////////////////////////////////////////////////////////////////////////////////////// 1666 1667 static bool has_thick_frame(const SkPaint& paint) 1668 { 1669 return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style; 1670 } 1671 1672 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, 1673 const SkPaint& paint, 1674 bool applyStrokeAndPathEffects, 1675 bool forceLinearTextOn) 1676 : fPaint(paint) /* make a copy of the paint */ 1677 { 1678 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection, 1679 true); 1680 1681 if (forceLinearTextOn) 1682 fPaint.setLinearText(true); 1683 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup 1684 1685 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) 1686 applyStrokeAndPathEffects = false; 1687 1688 // can't use our canonical size if we need to apply patheffects/strokes 1689 if (fPaint.isLinearText() && !applyStrokeAndPathEffects) 1690 { 1691 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 1692 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 1693 } 1694 else 1695 fScale = SK_Scalar1; 1696 1697 if (!applyStrokeAndPathEffects) 1698 { 1699 fPaint.setStyle(SkPaint::kFill_Style); 1700 fPaint.setPathEffect(NULL); 1701 } 1702 1703 fCache = fPaint.detachCache(NULL); 1704 1705 SkPaint::Style style = SkPaint::kFill_Style; 1706 SkPathEffect* pe = NULL; 1707 1708 if (!applyStrokeAndPathEffects) 1709 { 1710 style = paint.getStyle(); // restore 1711 pe = paint.getPathEffect(); // restore 1712 } 1713 fPaint.setStyle(style); 1714 fPaint.setPathEffect(pe); 1715 fPaint.setMaskFilter(paint.getMaskFilter()); // restore 1716 1717 // now compute fXOffset if needed 1718 1719 SkScalar xOffset = 0; 1720 if (paint.getTextAlign() != SkPaint::kLeft_Align) // need to measure first 1721 { 1722 int count; 1723 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale); 1724 if (paint.getTextAlign() == SkPaint::kCenter_Align) 1725 width = SkScalarHalf(width); 1726 xOffset = -width; 1727 } 1728 fXPos = xOffset; 1729 fPrevAdvance = 0; 1730 1731 fText = text; 1732 fStop = text + length; 1733 } 1734 1735 SkTextToPathIter::~SkTextToPathIter() 1736 { 1737 SkGlyphCache::AttachCache(fCache); 1738 } 1739 1740 const SkPath* SkTextToPathIter::next(SkScalar* xpos) 1741 { 1742 while (fText < fStop) 1743 { 1744 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 1745 1746 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 1747 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking(); 1748 1749 if (glyph.fWidth) 1750 { 1751 if (xpos) 1752 *xpos = fXPos; 1753 return fCache->findPath(glyph); 1754 } 1755 } 1756 return NULL; 1757 } 1758