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