1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkPaint.h" 9 #include "SkAnnotation.h" 10 #include "SkAutoKern.h" 11 #include "SkChecksum.h" 12 #include "SkColorFilter.h" 13 #include "SkData.h" 14 #include "SkDraw.h" 15 #include "SkFontDescriptor.h" 16 #include "SkGlyphCache.h" 17 #include "SkImageFilter.h" 18 #include "SkMaskFilter.h" 19 #include "SkMaskGamma.h" 20 #include "SkMutex.h" 21 #include "SkReadBuffer.h" 22 #include "SkWriteBuffer.h" 23 #include "SkPaintDefaults.h" 24 #include "SkPathEffect.h" 25 #include "SkRasterizer.h" 26 #include "SkScalar.h" 27 #include "SkScalerContext.h" 28 #include "SkShader.h" 29 #include "SkStringUtils.h" 30 #include "SkStroke.h" 31 #include "SkTextFormatParams.h" 32 #include "SkTextToPathIter.h" 33 #include "SkTLazy.h" 34 #include "SkTypeface.h" 35 #include "SkStrokeRec.h" 36 #include "SkSurfacePriv.h" 37 #include "SkXfermode.h" 38 39 static inline uint32_t set_clear_mask(uint32_t bits, bool cond, uint32_t mask) { 40 return cond ? bits | mask : bits & ~mask; 41 } 42 43 // define this to get a printf for out-of-range parameter in setters 44 // e.g. setTextSize(-1) 45 //#define SK_REPORT_API_RANGE_CHECK 46 47 SkPaint::SkPaint() { 48 fTypeface = nullptr; 49 fPathEffect = nullptr; 50 fShader = nullptr; 51 fXfermode = nullptr; 52 fMaskFilter = nullptr; 53 fColorFilter = nullptr; 54 fRasterizer = nullptr; 55 fLooper = nullptr; 56 fImageFilter = nullptr; 57 fAnnotation = nullptr; 58 59 fTextSize = SkPaintDefaults_TextSize; 60 fTextScaleX = SK_Scalar1; 61 fTextSkewX = 0; 62 fColor = SK_ColorBLACK; 63 fWidth = 0; 64 fMiterLimit = SkPaintDefaults_MiterLimit; 65 66 // Zero all bitfields, then set some non-zero defaults. 67 fBitfieldsUInt = 0; 68 fBitfields.fFlags = SkPaintDefaults_Flags; 69 fBitfields.fCapType = kDefault_Cap; 70 fBitfields.fJoinType = kDefault_Join; 71 fBitfields.fTextAlign = kLeft_Align; 72 fBitfields.fStyle = kFill_Style; 73 fBitfields.fTextEncoding = kUTF8_TextEncoding; 74 fBitfields.fHinting = SkPaintDefaults_Hinting; 75 } 76 77 SkPaint::SkPaint(const SkPaint& src) { 78 #define COPY(field) field = src.field 79 #define REF_COPY(field) field = SkSafeRef(src.field) 80 81 REF_COPY(fTypeface); 82 REF_COPY(fPathEffect); 83 REF_COPY(fShader); 84 REF_COPY(fXfermode); 85 REF_COPY(fMaskFilter); 86 REF_COPY(fColorFilter); 87 REF_COPY(fRasterizer); 88 REF_COPY(fLooper); 89 REF_COPY(fImageFilter); 90 REF_COPY(fAnnotation); 91 92 COPY(fTextSize); 93 COPY(fTextScaleX); 94 COPY(fTextSkewX); 95 COPY(fColor); 96 COPY(fWidth); 97 COPY(fMiterLimit); 98 COPY(fBitfields); 99 100 #undef COPY 101 #undef REF_COPY 102 } 103 104 SkPaint::SkPaint(SkPaint&& src) { 105 #define MOVE(field) field = std::move(src.field) 106 #define REF_MOVE(field) field = src.field; src.field = nullptr 107 108 REF_MOVE(fTypeface); 109 REF_MOVE(fPathEffect); 110 REF_MOVE(fShader); 111 REF_MOVE(fXfermode); 112 REF_MOVE(fMaskFilter); 113 REF_MOVE(fColorFilter); 114 REF_MOVE(fRasterizer); 115 REF_MOVE(fLooper); 116 REF_MOVE(fImageFilter); 117 REF_MOVE(fAnnotation); 118 119 MOVE(fTextSize); 120 MOVE(fTextScaleX); 121 MOVE(fTextSkewX); 122 MOVE(fColor); 123 MOVE(fWidth); 124 MOVE(fMiterLimit); 125 MOVE(fBitfields); 126 127 #undef MOVE 128 #undef REF_MOVE 129 } 130 131 SkPaint::~SkPaint() { 132 SkSafeUnref(fTypeface); 133 SkSafeUnref(fPathEffect); 134 SkSafeUnref(fShader); 135 SkSafeUnref(fXfermode); 136 SkSafeUnref(fMaskFilter); 137 SkSafeUnref(fColorFilter); 138 SkSafeUnref(fRasterizer); 139 SkSafeUnref(fLooper); 140 SkSafeUnref(fImageFilter); 141 SkSafeUnref(fAnnotation); 142 } 143 144 SkPaint& SkPaint::operator=(const SkPaint& src) { 145 if (this == &src) { 146 return *this; 147 } 148 149 #define COPY(field) field = src.field 150 #define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field) 151 152 REF_COPY(fTypeface); 153 REF_COPY(fPathEffect); 154 REF_COPY(fShader); 155 REF_COPY(fXfermode); 156 REF_COPY(fMaskFilter); 157 REF_COPY(fColorFilter); 158 REF_COPY(fRasterizer); 159 REF_COPY(fLooper); 160 REF_COPY(fImageFilter); 161 REF_COPY(fAnnotation); 162 163 COPY(fTextSize); 164 COPY(fTextScaleX); 165 COPY(fTextSkewX); 166 COPY(fColor); 167 COPY(fWidth); 168 COPY(fMiterLimit); 169 COPY(fBitfields); 170 171 return *this; 172 173 #undef COPY 174 #undef REF_COPY 175 } 176 177 SkPaint& SkPaint::operator=(SkPaint&& src) { 178 if (this == &src) { 179 return *this; 180 } 181 182 #define MOVE(field) field = std::move(src.field) 183 #define REF_MOVE(field) SkSafeUnref(field); field = src.field; src.field = nullptr 184 185 REF_MOVE(fTypeface); 186 REF_MOVE(fPathEffect); 187 REF_MOVE(fShader); 188 REF_MOVE(fXfermode); 189 REF_MOVE(fMaskFilter); 190 REF_MOVE(fColorFilter); 191 REF_MOVE(fRasterizer); 192 REF_MOVE(fLooper); 193 REF_MOVE(fImageFilter); 194 REF_MOVE(fAnnotation); 195 196 MOVE(fTextSize); 197 MOVE(fTextScaleX); 198 MOVE(fTextSkewX); 199 MOVE(fColor); 200 MOVE(fWidth); 201 MOVE(fMiterLimit); 202 MOVE(fBitfields); 203 204 return *this; 205 206 #undef MOVE 207 #undef REF_MOVE 208 } 209 210 bool operator==(const SkPaint& a, const SkPaint& b) { 211 #define EQUAL(field) (a.field == b.field) 212 return EQUAL(fTypeface) 213 && EQUAL(fPathEffect) 214 && EQUAL(fShader) 215 && EQUAL(fXfermode) 216 && EQUAL(fMaskFilter) 217 && EQUAL(fColorFilter) 218 && EQUAL(fRasterizer) 219 && EQUAL(fLooper) 220 && EQUAL(fImageFilter) 221 && EQUAL(fAnnotation) 222 && EQUAL(fTextSize) 223 && EQUAL(fTextScaleX) 224 && EQUAL(fTextSkewX) 225 && EQUAL(fColor) 226 && EQUAL(fWidth) 227 && EQUAL(fMiterLimit) 228 && EQUAL(fBitfieldsUInt) 229 ; 230 #undef EQUAL 231 } 232 233 void SkPaint::reset() { 234 SkPaint init; 235 *this = init; 236 } 237 238 void SkPaint::setFilterQuality(SkFilterQuality quality) { 239 fBitfields.fFilterQuality = quality; 240 } 241 242 void SkPaint::setHinting(Hinting hintingLevel) { 243 fBitfields.fHinting = hintingLevel; 244 } 245 246 void SkPaint::setFlags(uint32_t flags) { 247 fBitfields.fFlags = flags; 248 } 249 250 void SkPaint::setAntiAlias(bool doAA) { 251 this->setFlags(set_clear_mask(fBitfields.fFlags, doAA, kAntiAlias_Flag)); 252 } 253 254 void SkPaint::setDither(bool doDither) { 255 this->setFlags(set_clear_mask(fBitfields.fFlags, doDither, kDither_Flag)); 256 } 257 258 void SkPaint::setSubpixelText(bool doSubpixel) { 259 this->setFlags(set_clear_mask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag)); 260 } 261 262 void SkPaint::setLCDRenderText(bool doLCDRender) { 263 this->setFlags(set_clear_mask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag)); 264 } 265 266 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) { 267 this->setFlags(set_clear_mask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); 268 } 269 270 void SkPaint::setAutohinted(bool useAutohinter) { 271 this->setFlags(set_clear_mask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag)); 272 } 273 274 void SkPaint::setLinearText(bool doLinearText) { 275 this->setFlags(set_clear_mask(fBitfields.fFlags, doLinearText, kLinearText_Flag)); 276 } 277 278 void SkPaint::setVerticalText(bool doVertical) { 279 this->setFlags(set_clear_mask(fBitfields.fFlags, doVertical, kVerticalText_Flag)); 280 } 281 282 void SkPaint::setUnderlineText(bool doUnderline) { 283 this->setFlags(set_clear_mask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag)); 284 } 285 286 void SkPaint::setStrikeThruText(bool doStrikeThru) { 287 this->setFlags(set_clear_mask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag)); 288 } 289 290 void SkPaint::setFakeBoldText(bool doFakeBold) { 291 this->setFlags(set_clear_mask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag)); 292 } 293 294 void SkPaint::setDevKernText(bool doDevKern) { 295 this->setFlags(set_clear_mask(fBitfields.fFlags, doDevKern, kDevKernText_Flag)); 296 } 297 298 void SkPaint::setStyle(Style style) { 299 if ((unsigned)style < kStyleCount) { 300 fBitfields.fStyle = style; 301 } else { 302 #ifdef SK_REPORT_API_RANGE_CHECK 303 SkDebugf("SkPaint::setStyle(%d) out of range\n", style); 304 #endif 305 } 306 } 307 308 void SkPaint::setColor(SkColor color) { 309 fColor = color; 310 } 311 312 void SkPaint::setAlpha(U8CPU a) { 313 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor), 314 SkColorGetG(fColor), SkColorGetB(fColor))); 315 } 316 317 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 318 this->setColor(SkColorSetARGB(a, r, g, b)); 319 } 320 321 void SkPaint::setStrokeWidth(SkScalar width) { 322 if (width >= 0) { 323 fWidth = width; 324 } else { 325 #ifdef SK_REPORT_API_RANGE_CHECK 326 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); 327 #endif 328 } 329 } 330 331 void SkPaint::setStrokeMiter(SkScalar limit) { 332 if (limit >= 0) { 333 fMiterLimit = limit; 334 } else { 335 #ifdef SK_REPORT_API_RANGE_CHECK 336 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); 337 #endif 338 } 339 } 340 341 void SkPaint::setStrokeCap(Cap ct) { 342 if ((unsigned)ct < kCapCount) { 343 fBitfields.fCapType = SkToU8(ct); 344 } else { 345 #ifdef SK_REPORT_API_RANGE_CHECK 346 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); 347 #endif 348 } 349 } 350 351 void SkPaint::setStrokeJoin(Join jt) { 352 if ((unsigned)jt < kJoinCount) { 353 fBitfields.fJoinType = SkToU8(jt); 354 } else { 355 #ifdef SK_REPORT_API_RANGE_CHECK 356 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); 357 #endif 358 } 359 } 360 361 /////////////////////////////////////////////////////////////////////////////// 362 363 void SkPaint::setTextAlign(Align align) { 364 if ((unsigned)align < kAlignCount) { 365 fBitfields.fTextAlign = SkToU8(align); 366 } else { 367 #ifdef SK_REPORT_API_RANGE_CHECK 368 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); 369 #endif 370 } 371 } 372 373 void SkPaint::setTextSize(SkScalar ts) { 374 if (ts >= 0) { 375 fTextSize = ts; 376 } else { 377 #ifdef SK_REPORT_API_RANGE_CHECK 378 SkDebugf("SkPaint::setTextSize() called with negative value\n"); 379 #endif 380 } 381 } 382 383 void SkPaint::setTextScaleX(SkScalar scaleX) { 384 fTextScaleX = scaleX; 385 } 386 387 void SkPaint::setTextSkewX(SkScalar skewX) { 388 fTextSkewX = skewX; 389 } 390 391 void SkPaint::setTextEncoding(TextEncoding encoding) { 392 if ((unsigned)encoding <= kGlyphID_TextEncoding) { 393 fBitfields.fTextEncoding = encoding; 394 } else { 395 #ifdef SK_REPORT_API_RANGE_CHECK 396 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding); 397 #endif 398 } 399 } 400 401 /////////////////////////////////////////////////////////////////////////////// 402 403 SkTypeface* SkPaint::setTypeface(SkTypeface* font) { 404 SkRefCnt_SafeAssign(fTypeface, font); 405 return font; 406 } 407 408 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) { 409 SkRefCnt_SafeAssign(fRasterizer, r); 410 return r; 411 } 412 413 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { 414 SkRefCnt_SafeAssign(fLooper, looper); 415 return looper; 416 } 417 418 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) { 419 SkRefCnt_SafeAssign(fImageFilter, imageFilter); 420 return imageFilter; 421 } 422 423 SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) { 424 SkRefCnt_SafeAssign(fAnnotation, annotation); 425 return annotation; 426 } 427 428 /////////////////////////////////////////////////////////////////////////////// 429 430 static SkScalar mag2(SkScalar x, SkScalar y) { 431 return x * x + y * y; 432 } 433 434 static bool tooBig(const SkMatrix& m, SkScalar ma2max) { 435 return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max 436 || 437 mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max; 438 } 439 440 bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) { 441 SkASSERT(!ctm.hasPerspective()); 442 SkASSERT(!textM.hasPerspective()); 443 444 SkMatrix matrix; 445 matrix.setConcat(ctm, textM); 446 return tooBig(matrix, MaxCacheSize2()); 447 } 448 449 450 /////////////////////////////////////////////////////////////////////////////// 451 452 #include "SkGlyphCache.h" 453 #include "SkUtils.h" 454 455 static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc, 456 void* context) { 457 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc); 458 } 459 460 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, 461 uint16_t glyphs[]) const { 462 if (byteLength == 0) { 463 return 0; 464 } 465 466 SkASSERT(textData != nullptr); 467 468 if (nullptr == glyphs) { 469 switch (this->getTextEncoding()) { 470 case kUTF8_TextEncoding: 471 return SkUTF8_CountUnichars((const char*)textData, byteLength); 472 case kUTF16_TextEncoding: 473 return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1)); 474 case kUTF32_TextEncoding: 475 return SkToInt(byteLength >> 2); 476 case kGlyphID_TextEncoding: 477 return SkToInt(byteLength >> 1); 478 default: 479 SkDEBUGFAIL("unknown text encoding"); 480 } 481 return 0; 482 } 483 484 // if we get here, we have a valid glyphs[] array, so time to fill it in 485 486 // handle this encoding before the setup for the glyphcache 487 if (this->getTextEncoding() == kGlyphID_TextEncoding) { 488 // we want to ignore the low bit of byteLength 489 memcpy(glyphs, textData, byteLength >> 1 << 1); 490 return SkToInt(byteLength >> 1); 491 } 492 493 SkAutoGlyphCache autoCache(*this, nullptr, nullptr); 494 SkGlyphCache* cache = autoCache.getCache(); 495 496 const char* text = (const char*)textData; 497 const char* stop = text + byteLength; 498 uint16_t* gptr = glyphs; 499 500 switch (this->getTextEncoding()) { 501 case SkPaint::kUTF8_TextEncoding: 502 while (text < stop) { 503 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text)); 504 } 505 break; 506 case SkPaint::kUTF16_TextEncoding: { 507 const uint16_t* text16 = (const uint16_t*)text; 508 const uint16_t* stop16 = (const uint16_t*)stop; 509 while (text16 < stop16) { 510 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16)); 511 } 512 break; 513 } 514 case kUTF32_TextEncoding: { 515 const int32_t* text32 = (const int32_t*)text; 516 const int32_t* stop32 = (const int32_t*)stop; 517 while (text32 < stop32) { 518 *gptr++ = cache->unicharToGlyph(*text32++); 519 } 520 break; 521 } 522 default: 523 SkDEBUGFAIL("unknown text encoding"); 524 } 525 return SkToInt(gptr - glyphs); 526 } 527 528 bool SkPaint::containsText(const void* textData, size_t byteLength) const { 529 if (0 == byteLength) { 530 return true; 531 } 532 533 SkASSERT(textData != nullptr); 534 535 // handle this encoding before the setup for the glyphcache 536 if (this->getTextEncoding() == kGlyphID_TextEncoding) { 537 const uint16_t* glyphID = static_cast<const uint16_t*>(textData); 538 size_t count = byteLength >> 1; 539 for (size_t i = 0; i < count; i++) { 540 if (0 == glyphID[i]) { 541 return false; 542 } 543 } 544 return true; 545 } 546 547 SkAutoGlyphCache autoCache(*this, nullptr, nullptr); 548 SkGlyphCache* cache = autoCache.getCache(); 549 550 switch (this->getTextEncoding()) { 551 case SkPaint::kUTF8_TextEncoding: { 552 const char* text = static_cast<const char*>(textData); 553 const char* stop = text + byteLength; 554 while (text < stop) { 555 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) { 556 return false; 557 } 558 } 559 break; 560 } 561 case SkPaint::kUTF16_TextEncoding: { 562 const uint16_t* text = static_cast<const uint16_t*>(textData); 563 const uint16_t* stop = text + (byteLength >> 1); 564 while (text < stop) { 565 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) { 566 return false; 567 } 568 } 569 break; 570 } 571 case SkPaint::kUTF32_TextEncoding: { 572 const int32_t* text = static_cast<const int32_t*>(textData); 573 const int32_t* stop = text + (byteLength >> 2); 574 while (text < stop) { 575 if (0 == cache->unicharToGlyph(*text++)) { 576 return false; 577 } 578 } 579 break; 580 } 581 default: 582 SkDEBUGFAIL("unknown text encoding"); 583 return false; 584 } 585 return true; 586 } 587 588 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count, SkUnichar textData[]) const { 589 if (count <= 0) { 590 return; 591 } 592 593 SkASSERT(glyphs != nullptr); 594 SkASSERT(textData != nullptr); 595 596 SkSurfaceProps props(0, kUnknown_SkPixelGeometry); 597 SkAutoGlyphCache autoCache(*this, &props, nullptr); 598 SkGlyphCache* cache = autoCache.getCache(); 599 600 for (int index = 0; index < count; index++) { 601 textData[index] = cache->glyphToUnichar(glyphs[index]); 602 } 603 } 604 605 /////////////////////////////////////////////////////////////////////////////// 606 607 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, 608 const char** text) { 609 SkASSERT(cache != nullptr); 610 SkASSERT(text != nullptr); 611 612 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text)); 613 } 614 615 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, 616 const char** text) { 617 SkASSERT(cache != nullptr); 618 SkASSERT(text != nullptr); 619 620 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text)); 621 } 622 623 static const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache, 624 const char** text) { 625 SkASSERT(cache != nullptr); 626 SkASSERT(text != nullptr); 627 628 const int32_t* ptr = *(const int32_t**)text; 629 SkUnichar uni = *ptr++; 630 *text = (const char*)ptr; 631 return cache->getUnicharMetrics(uni); 632 } 633 634 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, 635 const char** text) { 636 SkASSERT(cache != nullptr); 637 SkASSERT(text != nullptr); 638 639 const uint16_t* ptr = *(const uint16_t**)text; 640 unsigned glyphID = *ptr; 641 ptr += 1; 642 *text = (const char*)ptr; 643 return cache->getGlyphIDMetrics(glyphID); 644 } 645 646 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, 647 const char** text) { 648 SkASSERT(cache != nullptr); 649 SkASSERT(text != nullptr); 650 651 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text)); 652 } 653 654 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, 655 const char** text) { 656 SkASSERT(cache != nullptr); 657 SkASSERT(text != nullptr); 658 659 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text)); 660 } 661 662 static const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache, 663 const char** text) { 664 SkASSERT(cache != nullptr); 665 SkASSERT(text != nullptr); 666 667 const int32_t* ptr = *(const int32_t**)text; 668 SkUnichar uni = *ptr++; 669 *text = (const char*)ptr; 670 return cache->getUnicharAdvance(uni); 671 } 672 673 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, 674 const char** text) { 675 SkASSERT(cache != nullptr); 676 SkASSERT(text != nullptr); 677 678 const uint16_t* ptr = *(const uint16_t**)text; 679 unsigned glyphID = *ptr; 680 ptr += 1; 681 *text = (const char*)ptr; 682 return cache->getGlyphIDAdvance(glyphID); 683 } 684 685 SkPaint::GlyphCacheProc SkPaint::getGlyphCacheProc(bool needFullMetrics) const { 686 static const GlyphCacheProc gGlyphCacheProcs[] = { 687 sk_getMetrics_utf8_next, 688 sk_getMetrics_utf16_next, 689 sk_getMetrics_utf32_next, 690 sk_getMetrics_glyph_next, 691 692 sk_getAdvance_utf8_next, 693 sk_getAdvance_utf16_next, 694 sk_getAdvance_utf32_next, 695 sk_getAdvance_glyph_next, 696 }; 697 698 unsigned index = this->getTextEncoding(); 699 700 if (!needFullMetrics && !this->isDevKernText()) { 701 index += 4; 702 } 703 704 SkASSERT(index < SK_ARRAY_COUNT(gGlyphCacheProcs)); 705 return gGlyphCacheProcs[index]; 706 } 707 708 /////////////////////////////////////////////////////////////////////////////// 709 710 #define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \ 711 SkPaint::kDevKernText_Flag | \ 712 SkPaint::kLinearText_Flag | \ 713 SkPaint::kLCDRenderText_Flag | \ 714 SkPaint::kEmbeddedBitmapText_Flag | \ 715 SkPaint::kAutoHinting_Flag | \ 716 SkPaint::kGenA8FromLCD_Flag ) 717 718 SkScalar SkPaint::setupForAsPaths() { 719 uint32_t flags = this->getFlags(); 720 // clear the flags we don't care about 721 flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE; 722 // set the flags we do care about 723 flags |= SkPaint::kSubpixelText_Flag; 724 725 this->setFlags(flags); 726 this->setHinting(SkPaint::kNo_Hinting); 727 728 SkScalar textSize = fTextSize; 729 this->setTextSize(kCanonicalTextSizeForPaths); 730 return textSize / kCanonicalTextSizeForPaths; 731 } 732 733 class SkCanonicalizePaint { 734 public: 735 SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) { 736 if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) { 737 SkPaint* p = fLazy.set(paint); 738 fScale = p->setupForAsPaths(); 739 fPaint = p; 740 } 741 } 742 743 const SkPaint& getPaint() const { return *fPaint; } 744 745 /** 746 * Returns 0 if the paint was unmodified, or the scale factor need to 747 * the original textSize 748 */ 749 SkScalar getScale() const { return fScale; } 750 751 private: 752 const SkPaint* fPaint; 753 SkScalar fScale; 754 SkTLazy<SkPaint> fLazy; 755 }; 756 757 static void set_bounds(const SkGlyph& g, SkRect* bounds) { 758 bounds->set(SkIntToScalar(g.fLeft), 759 SkIntToScalar(g.fTop), 760 SkIntToScalar(g.fLeft + g.fWidth), 761 SkIntToScalar(g.fTop + g.fHeight)); 762 } 763 764 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) { 765 SkScalar sx = Sk48Dot16ToScalar(dx); 766 bounds->join(SkIntToScalar(g.fLeft) + sx, 767 SkIntToScalar(g.fTop), 768 SkIntToScalar(g.fLeft + g.fWidth) + sx, 769 SkIntToScalar(g.fTop + g.fHeight)); 770 } 771 772 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) { 773 SkScalar sy = Sk48Dot16ToScalar(dy); 774 bounds->join(SkIntToScalar(g.fLeft), 775 SkIntToScalar(g.fTop) + sy, 776 SkIntToScalar(g.fLeft + g.fWidth), 777 SkIntToScalar(g.fTop + g.fHeight) + sy); 778 } 779 780 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16); 781 782 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY 783 static SkFixed advance(const SkGlyph& glyph, int xyIndex) { 784 SkASSERT(0 == xyIndex || 1 == xyIndex); 785 return (&glyph.fAdvanceX)[xyIndex]; 786 } 787 788 SkScalar SkPaint::measure_text(SkGlyphCache* cache, 789 const char* text, size_t byteLength, 790 int* count, SkRect* bounds) const { 791 SkASSERT(count); 792 if (byteLength == 0) { 793 *count = 0; 794 if (bounds) { 795 bounds->setEmpty(); 796 } 797 return 0; 798 } 799 800 GlyphCacheProc glyphCacheProc = this->getGlyphCacheProc(nullptr != bounds); 801 802 int xyIndex; 803 JoinBoundsProc joinBoundsProc; 804 if (this->isVerticalText()) { 805 xyIndex = 1; 806 joinBoundsProc = join_bounds_y; 807 } else { 808 xyIndex = 0; 809 joinBoundsProc = join_bounds_x; 810 } 811 812 int n = 1; 813 const char* stop = (const char*)text + byteLength; 814 const SkGlyph* g = &glyphCacheProc(cache, &text); 815 // our accumulated fixed-point advances might overflow 16.16, so we use 816 // a 48.16 (64bit) accumulator, and then convert that to scalar at the 817 // very end. 818 Sk48Dot16 x = advance(*g, xyIndex); 819 820 SkAutoKern autokern; 821 822 if (nullptr == bounds) { 823 if (this->isDevKernText()) { 824 int rsb; 825 for (; text < stop; n++) { 826 rsb = g->fRsbDelta; 827 g = &glyphCacheProc(cache, &text); 828 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex); 829 } 830 } else { 831 for (; text < stop; n++) { 832 x += advance(glyphCacheProc(cache, &text), xyIndex); 833 } 834 } 835 } else { 836 set_bounds(*g, bounds); 837 if (this->isDevKernText()) { 838 int rsb; 839 for (; text < stop; n++) { 840 rsb = g->fRsbDelta; 841 g = &glyphCacheProc(cache, &text); 842 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta); 843 joinBoundsProc(*g, bounds, x); 844 x += advance(*g, xyIndex); 845 } 846 } else { 847 for (; text < stop; n++) { 848 g = &glyphCacheProc(cache, &text); 849 joinBoundsProc(*g, bounds, x); 850 x += advance(*g, xyIndex); 851 } 852 } 853 } 854 SkASSERT(text == stop); 855 856 *count = n; 857 return Sk48Dot16ToScalar(x); 858 } 859 860 SkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const { 861 const char* text = (const char*)textData; 862 SkASSERT(text != nullptr || length == 0); 863 864 SkCanonicalizePaint canon(*this); 865 const SkPaint& paint = canon.getPaint(); 866 SkScalar scale = canon.getScale(); 867 868 SkAutoGlyphCache autoCache(paint, nullptr, nullptr); 869 SkGlyphCache* cache = autoCache.getCache(); 870 871 SkScalar width = 0; 872 873 if (length > 0) { 874 int tempCount; 875 876 width = paint.measure_text(cache, text, length, &tempCount, bounds); 877 if (scale) { 878 width = SkScalarMul(width, scale); 879 if (bounds) { 880 bounds->fLeft = SkScalarMul(bounds->fLeft, scale); 881 bounds->fTop = SkScalarMul(bounds->fTop, scale); 882 bounds->fRight = SkScalarMul(bounds->fRight, scale); 883 bounds->fBottom = SkScalarMul(bounds->fBottom, scale); 884 } 885 } 886 } else if (bounds) { 887 // ensure that even if we don't measure_text we still update the bounds 888 bounds->setEmpty(); 889 } 890 return width; 891 } 892 893 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, 894 SkScalar* measuredWidth) const { 895 if (0 == length || 0 >= maxWidth) { 896 if (measuredWidth) { 897 *measuredWidth = 0; 898 } 899 return 0; 900 } 901 902 if (0 == fTextSize) { 903 if (measuredWidth) { 904 *measuredWidth = 0; 905 } 906 return length; 907 } 908 909 SkASSERT(textD != nullptr); 910 const char* text = (const char*)textD; 911 const char* stop = text + length; 912 913 SkCanonicalizePaint canon(*this); 914 const SkPaint& paint = canon.getPaint(); 915 SkScalar scale = canon.getScale(); 916 917 // adjust max in case we changed the textSize in paint 918 if (scale) { 919 maxWidth /= scale; 920 } 921 922 SkAutoGlyphCache autoCache(paint, nullptr, nullptr); 923 SkGlyphCache* cache = autoCache.getCache(); 924 925 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(false); 926 const int xyIndex = paint.isVerticalText() ? 1 : 0; 927 // use 64bits for our accumulator, to avoid overflowing 16.16 928 Sk48Dot16 max = SkScalarTo48Dot16(maxWidth); 929 Sk48Dot16 width = 0; 930 931 SkAutoKern autokern; 932 933 if (this->isDevKernText()) { 934 int rsb = 0; 935 while (text < stop) { 936 const char* curr = text; 937 const SkGlyph& g = glyphCacheProc(cache, &text); 938 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex); 939 if ((width += x) > max) { 940 width -= x; 941 text = curr; 942 break; 943 } 944 rsb = g.fRsbDelta; 945 } 946 } else { 947 while (text < stop) { 948 const char* curr = text; 949 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex); 950 if ((width += x) > max) { 951 width -= x; 952 text = curr; 953 break; 954 } 955 } 956 } 957 958 if (measuredWidth) { 959 SkScalar scalarWidth = Sk48Dot16ToScalar(width); 960 if (scale) { 961 scalarWidth = SkScalarMul(scalarWidth, scale); 962 } 963 *measuredWidth = scalarWidth; 964 } 965 966 // return the number of bytes measured 967 return text - stop + length; 968 } 969 970 /////////////////////////////////////////////////////////////////////////////// 971 972 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) { 973 *(SkPaint::FontMetrics*)context = cache->getFontMetrics(); 974 return false; // don't detach the cache 975 } 976 977 static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc, 978 void* context) { 979 SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context); 980 } 981 982 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { 983 SkCanonicalizePaint canon(*this); 984 const SkPaint& paint = canon.getPaint(); 985 SkScalar scale = canon.getScale(); 986 987 SkMatrix zoomMatrix, *zoomPtr = nullptr; 988 if (zoom) { 989 zoomMatrix.setScale(zoom, zoom); 990 zoomPtr = &zoomMatrix; 991 } 992 993 FontMetrics storage; 994 if (nullptr == metrics) { 995 metrics = &storage; 996 } 997 998 paint.descriptorProc(nullptr, FakeGamma::Off, zoomPtr, FontMetricsDescProc, metrics); 999 1000 if (scale) { 1001 metrics->fTop = SkScalarMul(metrics->fTop, scale); 1002 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); 1003 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); 1004 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); 1005 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); 1006 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale); 1007 metrics->fXMin = SkScalarMul(metrics->fXMin, scale); 1008 metrics->fXMax = SkScalarMul(metrics->fXMax, scale); 1009 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale); 1010 metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale); 1011 metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale); 1012 } 1013 return metrics->fDescent - metrics->fAscent + metrics->fLeading; 1014 } 1015 1016 /////////////////////////////////////////////////////////////////////////////// 1017 1018 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) { 1019 bounds->set(g.fLeft * scale, 1020 g.fTop * scale, 1021 (g.fLeft + g.fWidth) * scale, 1022 (g.fTop + g.fHeight) * scale); 1023 } 1024 1025 int SkPaint::getTextWidths(const void* textData, size_t byteLength, 1026 SkScalar widths[], SkRect bounds[]) const { 1027 if (0 == byteLength) { 1028 return 0; 1029 } 1030 1031 SkASSERT(textData); 1032 1033 if (nullptr == widths && nullptr == bounds) { 1034 return this->countText(textData, byteLength); 1035 } 1036 1037 SkCanonicalizePaint canon(*this); 1038 const SkPaint& paint = canon.getPaint(); 1039 SkScalar scale = canon.getScale(); 1040 1041 SkAutoGlyphCache autoCache(paint, nullptr, nullptr); 1042 SkGlyphCache* cache = autoCache.getCache(); 1043 GlyphCacheProc glyphCacheProc = paint.getGlyphCacheProc(nullptr != bounds); 1044 1045 const char* text = (const char*)textData; 1046 const char* stop = text + byteLength; 1047 int count = 0; 1048 const int xyIndex = paint.isVerticalText() ? 1 : 0; 1049 1050 if (this->isDevKernText()) { 1051 // we adjust the widths returned here through auto-kerning 1052 SkAutoKern autokern; 1053 SkFixed prevWidth = 0; 1054 1055 if (scale) { 1056 while (text < stop) { 1057 const SkGlyph& g = glyphCacheProc(cache, &text); 1058 if (widths) { 1059 SkFixed adjust = autokern.adjust(g); 1060 1061 if (count > 0) { 1062 SkScalar w = SkFixedToScalar(prevWidth + adjust); 1063 *widths++ = SkScalarMul(w, scale); 1064 } 1065 prevWidth = advance(g, xyIndex); 1066 } 1067 if (bounds) { 1068 set_bounds(g, bounds++, scale); 1069 } 1070 ++count; 1071 } 1072 if (count > 0 && widths) { 1073 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); 1074 } 1075 } else { 1076 while (text < stop) { 1077 const SkGlyph& g = glyphCacheProc(cache, &text); 1078 if (widths) { 1079 SkFixed adjust = autokern.adjust(g); 1080 1081 if (count > 0) { 1082 *widths++ = SkFixedToScalar(prevWidth + adjust); 1083 } 1084 prevWidth = advance(g, xyIndex); 1085 } 1086 if (bounds) { 1087 set_bounds(g, bounds++); 1088 } 1089 ++count; 1090 } 1091 if (count > 0 && widths) { 1092 *widths = SkFixedToScalar(prevWidth); 1093 } 1094 } 1095 } else { // no devkern 1096 if (scale) { 1097 while (text < stop) { 1098 const SkGlyph& g = glyphCacheProc(cache, &text); 1099 if (widths) { 1100 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)), 1101 scale); 1102 } 1103 if (bounds) { 1104 set_bounds(g, bounds++, scale); 1105 } 1106 ++count; 1107 } 1108 } else { 1109 while (text < stop) { 1110 const SkGlyph& g = glyphCacheProc(cache, &text); 1111 if (widths) { 1112 *widths++ = SkFixedToScalar(advance(g, xyIndex)); 1113 } 1114 if (bounds) { 1115 set_bounds(g, bounds++); 1116 } 1117 ++count; 1118 } 1119 } 1120 } 1121 1122 SkASSERT(text == stop); 1123 return count; 1124 } 1125 1126 /////////////////////////////////////////////////////////////////////////////// 1127 1128 #include "SkDraw.h" 1129 1130 void SkPaint::getTextPath(const void* textData, size_t length, 1131 SkScalar x, SkScalar y, SkPath* path) const { 1132 SkASSERT(length == 0 || textData != nullptr); 1133 1134 const char* text = (const char*)textData; 1135 if (text == nullptr || length == 0 || path == nullptr) { 1136 return; 1137 } 1138 1139 SkTextToPathIter iter(text, length, *this, false); 1140 SkMatrix matrix; 1141 SkScalar prevXPos = 0; 1142 1143 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1144 matrix.postTranslate(x, y); 1145 path->reset(); 1146 1147 SkScalar xpos; 1148 const SkPath* iterPath; 1149 while (iter.next(&iterPath, &xpos)) { 1150 matrix.postTranslate(xpos - prevXPos, 0); 1151 if (iterPath) { 1152 path->addPath(*iterPath, matrix); 1153 } 1154 prevXPos = xpos; 1155 } 1156 } 1157 1158 int SkPaint::getTextIntercepts(const void* textData, size_t length, 1159 SkScalar x, SkScalar y, const SkScalar bounds[2], 1160 SkScalar* array) const { 1161 SkASSERT(length == 0 || textData != nullptr); 1162 if (!length) { 1163 return 0; 1164 } 1165 1166 const char* text = (const char*) textData; 1167 SkTextInterceptsIter iter(text, length, *this, bounds, x, y, 1168 SkTextInterceptsIter::TextType::kText); 1169 int count = 0; 1170 while (iter.next(array, &count)) { 1171 } 1172 return count; 1173 } 1174 1175 void SkPaint::getPosTextPath(const void* textData, size_t length, 1176 const SkPoint pos[], SkPath* path) const { 1177 SkASSERT(length == 0 || textData != nullptr); 1178 1179 const char* text = (const char*)textData; 1180 if (text == nullptr || length == 0 || path == nullptr) { 1181 return; 1182 } 1183 1184 SkTextToPathIter iter(text, length, *this, false); 1185 SkMatrix matrix; 1186 SkPoint prevPos; 1187 prevPos.set(0, 0); 1188 1189 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1190 path->reset(); 1191 1192 unsigned int i = 0; 1193 const SkPath* iterPath; 1194 while (iter.next(&iterPath, nullptr)) { 1195 matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY); 1196 if (iterPath) { 1197 path->addPath(*iterPath, matrix); 1198 } 1199 prevPos = pos[i]; 1200 i++; 1201 } 1202 } 1203 1204 int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[], 1205 const SkScalar bounds[2], SkScalar* array) const { 1206 SkASSERT(length == 0 || textData != nullptr); 1207 if (!length) { 1208 return 0; 1209 } 1210 1211 const char* text = (const char*) textData; 1212 SkTextInterceptsIter iter(text, length, *this, bounds, pos[0].fX, pos[0].fY, 1213 SkTextInterceptsIter::TextType::kPosText); 1214 int i = 0; 1215 int count = 0; 1216 while (iter.next(array, &count)) { 1217 i++; 1218 iter.setPosition(pos[i].fX, pos[i].fY); 1219 } 1220 return count; 1221 } 1222 1223 SkRect SkPaint::getFontBounds() const { 1224 SkMatrix m; 1225 m.setScale(fTextSize * fTextScaleX, fTextSize); 1226 m.postSkew(fTextSkewX, 0); 1227 1228 SkTypeface* typeface = this->getTypeface(); 1229 if (nullptr == typeface) { 1230 typeface = SkTypeface::GetDefaultTypeface(); 1231 } 1232 1233 SkRect bounds; 1234 m.mapRect(&bounds, typeface->getBounds()); 1235 return bounds; 1236 } 1237 1238 static void add_flattenable(SkDescriptor* desc, uint32_t tag, 1239 SkWriteBuffer* buffer) { 1240 buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), nullptr)); 1241 } 1242 1243 static SkMask::Format compute_mask_format(const SkPaint& paint) { 1244 uint32_t flags = paint.getFlags(); 1245 1246 // Antialiasing being disabled trumps all other settings. 1247 if (!(flags & SkPaint::kAntiAlias_Flag)) { 1248 return SkMask::kBW_Format; 1249 } 1250 1251 if (flags & SkPaint::kLCDRenderText_Flag) { 1252 return SkMask::kLCD16_Format; 1253 } 1254 1255 return SkMask::kA8_Format; 1256 } 1257 1258 // if linear-text is on, then we force hinting to be off (since that's sort of 1259 // the point of linear-text. 1260 static SkPaint::Hinting computeHinting(const SkPaint& paint) { 1261 SkPaint::Hinting h = paint.getHinting(); 1262 if (paint.isLinearText()) { 1263 h = SkPaint::kNo_Hinting; 1264 } 1265 return h; 1266 } 1267 1268 // return true if the paint is just a single color (i.e. not a shader). If its 1269 // a shader, then we can't compute a const luminance for it :( 1270 static bool justAColor(const SkPaint& paint, SkColor* color) { 1271 SkColor c = paint.getColor(); 1272 1273 SkShader* shader = paint.getShader(); 1274 if (shader && !shader->asLuminanceColor(&c)) { 1275 return false; 1276 } 1277 if (paint.getColorFilter()) { 1278 c = paint.getColorFilter()->filterColor(c); 1279 } 1280 if (color) { 1281 *color = c; 1282 } 1283 return true; 1284 } 1285 1286 SkColor SkPaint::computeLuminanceColor() const { 1287 SkColor c; 1288 if (!justAColor(*this, &c)) { 1289 c = SkColorSetRGB(0x7F, 0x80, 0x7F); 1290 } 1291 return c; 1292 } 1293 1294 #define assert_byte(x) SkASSERT(0 == ((x) >> 8)) 1295 1296 // Beyond this size, LCD doesn't appreciably improve quality, but it always 1297 // cost more RAM and draws slower, so we set a cap. 1298 #ifndef SK_MAX_SIZE_FOR_LCDTEXT 1299 #define SK_MAX_SIZE_FOR_LCDTEXT 48 1300 #endif 1301 1302 const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT; 1303 1304 static bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) { 1305 if (checkPost2x2) { 1306 SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] - 1307 rec.fPost2x2[1][0] * rec.fPost2x2[0][1]; 1308 area *= rec.fTextSize * rec.fTextSize; 1309 return area > gMaxSize2ForLCDText; 1310 } else { 1311 return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT; 1312 } 1313 } 1314 1315 /* 1316 * Return the scalar with only limited fractional precision. Used to consolidate matrices 1317 * that vary only slightly when we create our key into the font cache, since the font scaler 1318 * typically returns the same looking resuts for tiny changes in the matrix. 1319 */ 1320 static SkScalar sk_relax(SkScalar x) { 1321 int n = sk_float_round2int(x * 1024); 1322 return n / 1024.0f; 1323 } 1324 1325 void SkScalerContext::MakeRec(const SkPaint& paint, 1326 const SkSurfaceProps* surfaceProps, 1327 const SkMatrix* deviceMatrix, 1328 Rec* rec) { 1329 SkASSERT(deviceMatrix == nullptr || !deviceMatrix->hasPerspective()); 1330 1331 SkTypeface* typeface = paint.getTypeface(); 1332 if (nullptr == typeface) { 1333 typeface = SkTypeface::GetDefaultTypeface(); 1334 } 1335 rec->fFontID = typeface->uniqueID(); 1336 rec->fTextSize = paint.getTextSize(); 1337 rec->fPreScaleX = paint.getTextScaleX(); 1338 rec->fPreSkewX = paint.getTextSkewX(); 1339 1340 bool checkPost2x2 = false; 1341 1342 if (deviceMatrix) { 1343 const SkMatrix::TypeMask mask = deviceMatrix->getType(); 1344 if (mask & SkMatrix::kScale_Mask) { 1345 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX()); 1346 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY()); 1347 checkPost2x2 = true; 1348 } else { 1349 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; 1350 } 1351 if (mask & SkMatrix::kAffine_Mask) { 1352 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX()); 1353 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY()); 1354 checkPost2x2 = true; 1355 } else { 1356 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; 1357 } 1358 } else { 1359 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; 1360 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; 1361 } 1362 1363 SkPaint::Style style = paint.getStyle(); 1364 SkScalar strokeWidth = paint.getStrokeWidth(); 1365 1366 unsigned flags = 0; 1367 1368 if (paint.isFakeBoldText()) { 1369 #ifdef SK_USE_FREETYPE_EMBOLDEN 1370 flags |= SkScalerContext::kEmbolden_Flag; 1371 #else 1372 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(), 1373 kStdFakeBoldInterpKeys, 1374 kStdFakeBoldInterpValues, 1375 kStdFakeBoldInterpLength); 1376 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); 1377 1378 if (style == SkPaint::kFill_Style) { 1379 style = SkPaint::kStrokeAndFill_Style; 1380 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill" 1381 } else { 1382 strokeWidth += extra; 1383 } 1384 #endif 1385 } 1386 1387 if (paint.isDevKernText()) { 1388 flags |= SkScalerContext::kDevKernText_Flag; 1389 } 1390 1391 if (style != SkPaint::kFill_Style && strokeWidth > 0) { 1392 rec->fFrameWidth = strokeWidth; 1393 rec->fMiterLimit = paint.getStrokeMiter(); 1394 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); 1395 1396 if (style == SkPaint::kStrokeAndFill_Style) { 1397 flags |= SkScalerContext::kFrameAndFill_Flag; 1398 } 1399 } else { 1400 rec->fFrameWidth = 0; 1401 rec->fMiterLimit = 0; 1402 rec->fStrokeJoin = 0; 1403 } 1404 1405 rec->fMaskFormat = SkToU8(compute_mask_format(paint)); 1406 1407 if (SkMask::kLCD16_Format == rec->fMaskFormat) { 1408 if (too_big_for_lcd(*rec, checkPost2x2)) { 1409 rec->fMaskFormat = SkMask::kA8_Format; 1410 flags |= SkScalerContext::kGenA8FromLCD_Flag; 1411 } else { 1412 SkPixelGeometry geometry = surfaceProps 1413 ? surfaceProps->pixelGeometry() 1414 : SkSurfacePropsDefaultPixelGeometry(); 1415 switch (geometry) { 1416 case kUnknown_SkPixelGeometry: 1417 // eeek, can't support LCD 1418 rec->fMaskFormat = SkMask::kA8_Format; 1419 flags |= SkScalerContext::kGenA8FromLCD_Flag; 1420 break; 1421 case kRGB_H_SkPixelGeometry: 1422 // our default, do nothing. 1423 break; 1424 case kBGR_H_SkPixelGeometry: 1425 flags |= SkScalerContext::kLCD_BGROrder_Flag; 1426 break; 1427 case kRGB_V_SkPixelGeometry: 1428 flags |= SkScalerContext::kLCD_Vertical_Flag; 1429 break; 1430 case kBGR_V_SkPixelGeometry: 1431 flags |= SkScalerContext::kLCD_Vertical_Flag; 1432 flags |= SkScalerContext::kLCD_BGROrder_Flag; 1433 break; 1434 } 1435 } 1436 } 1437 1438 if (paint.isEmbeddedBitmapText()) { 1439 flags |= SkScalerContext::kEmbeddedBitmapText_Flag; 1440 } 1441 if (paint.isSubpixelText()) { 1442 flags |= SkScalerContext::kSubpixelPositioning_Flag; 1443 } 1444 if (paint.isAutohinted()) { 1445 flags |= SkScalerContext::kForceAutohinting_Flag; 1446 } 1447 if (paint.isVerticalText()) { 1448 flags |= SkScalerContext::kVertical_Flag; 1449 } 1450 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) { 1451 flags |= SkScalerContext::kGenA8FromLCD_Flag; 1452 } 1453 rec->fFlags = SkToU16(flags); 1454 1455 // these modify fFlags, so do them after assigning fFlags 1456 rec->setHinting(computeHinting(paint)); 1457 1458 rec->setLuminanceColor(paint.computeLuminanceColor()); 1459 1460 //For now always set the paint gamma equal to the device gamma. 1461 //The math in SkMaskGamma can handle them being different, 1462 //but it requires superluminous masks when 1463 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large. 1464 rec->setDeviceGamma(SK_GAMMA_EXPONENT); 1465 rec->setPaintGamma(SK_GAMMA_EXPONENT); 1466 1467 #ifdef SK_GAMMA_CONTRAST 1468 rec->setContrast(SK_GAMMA_CONTRAST); 1469 #else 1470 /** 1471 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise. 1472 * With lower values small text appears washed out (though correctly so). 1473 * With higher values lcd fringing is worse and the smoothing effect of 1474 * partial coverage is diminished. 1475 */ 1476 rec->setContrast(0.5f); 1477 #endif 1478 1479 rec->fReservedAlign = 0; 1480 1481 /* Allow the fonthost to modify our rec before we use it as a key into the 1482 cache. This way if we're asking for something that they will ignore, 1483 they can modify our rec up front, so we don't create duplicate cache 1484 entries. 1485 */ 1486 typeface->onFilterRec(rec); 1487 1488 // be sure to call PostMakeRec(rec) before you actually use it! 1489 } 1490 1491 /** 1492 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or 1493 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue 1494 * to hold it until the returned pointer is refed or forgotten. 1495 */ 1496 SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex); 1497 1498 static SkMaskGamma* gLinearMaskGamma = nullptr; 1499 static SkMaskGamma* gMaskGamma = nullptr; 1500 static SkScalar gContrast = SK_ScalarMin; 1501 static SkScalar gPaintGamma = SK_ScalarMin; 1502 static SkScalar gDeviceGamma = SK_ScalarMin; 1503 /** 1504 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until 1505 * the returned SkMaskGamma pointer is refed or forgotten. 1506 */ 1507 static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) { 1508 gMaskGammaCacheMutex.assertHeld(); 1509 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) { 1510 if (nullptr == gLinearMaskGamma) { 1511 gLinearMaskGamma = new SkMaskGamma; 1512 } 1513 return *gLinearMaskGamma; 1514 } 1515 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) { 1516 SkSafeUnref(gMaskGamma); 1517 gMaskGamma = new SkMaskGamma(contrast, paintGamma, deviceGamma); 1518 gContrast = contrast; 1519 gPaintGamma = paintGamma; 1520 gDeviceGamma = deviceGamma; 1521 } 1522 return *gMaskGamma; 1523 } 1524 1525 /** 1526 * We ensure that the rec is self-consistent and efficient (where possible) 1527 */ 1528 void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) { 1529 /** 1530 * If we're asking for A8, we force the colorlum to be gray, since that 1531 * limits the number of unique entries, and the scaler will only look at 1532 * the lum of one of them. 1533 */ 1534 switch (rec->fMaskFormat) { 1535 case SkMask::kLCD16_Format: { 1536 // filter down the luminance color to a finite number of bits 1537 SkColor color = rec->getLuminanceColor(); 1538 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color)); 1539 break; 1540 } 1541 case SkMask::kA8_Format: { 1542 // filter down the luminance to a single component, since A8 can't 1543 // use per-component information 1544 SkColor color = rec->getLuminanceColor(); 1545 U8CPU lum = SkComputeLuminance(SkColorGetR(color), 1546 SkColorGetG(color), 1547 SkColorGetB(color)); 1548 // reduce to our finite number of bits 1549 color = SkColorSetRGB(lum, lum, lum); 1550 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color)); 1551 break; 1552 } 1553 case SkMask::kBW_Format: 1554 // No need to differentiate gamma if we're BW 1555 rec->ignorePreBlend(); 1556 break; 1557 } 1558 } 1559 1560 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024 1561 1562 #ifdef SK_DEBUG 1563 #define TEST_DESC 1564 #endif 1565 1566 static void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec, 1567 const SkPathEffect* pe, SkWriteBuffer* peBuffer, 1568 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer, 1569 const SkRasterizer* ra, SkWriteBuffer* raBuffer, 1570 size_t descSize) { 1571 desc->init(); 1572 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1573 1574 if (pe) { 1575 add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer); 1576 } 1577 if (mf) { 1578 add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer); 1579 } 1580 if (ra) { 1581 add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer); 1582 } 1583 1584 desc->computeChecksum(); 1585 } 1586 1587 static size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec, 1588 const SkSurfaceProps* surfaceProps, 1589 bool fakeGamma, 1590 const SkMatrix* deviceMatrix, 1591 const SkPathEffect* pe, SkWriteBuffer* peBuffer, 1592 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer, 1593 const SkRasterizer* ra, SkWriteBuffer* raBuffer) { 1594 SkScalerContext::MakeRec(paint, surfaceProps, deviceMatrix, rec); 1595 if (!fakeGamma) { 1596 rec->ignorePreBlend(); 1597 } 1598 1599 int entryCount = 1; 1600 size_t descSize = sizeof(*rec); 1601 1602 if (pe) { 1603 peBuffer->writeFlattenable(pe); 1604 descSize += peBuffer->bytesWritten(); 1605 entryCount += 1; 1606 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1607 // seems like we could support kLCD as well at this point... 1608 } 1609 if (mf) { 1610 mfBuffer->writeFlattenable(mf); 1611 descSize += mfBuffer->bytesWritten(); 1612 entryCount += 1; 1613 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters 1614 /* Pre-blend is not currently applied to filtered text. 1615 The primary filter is blur, for which contrast makes no sense, 1616 and for which the destination guess error is more visible. 1617 Also, all existing users of blur have calibrated for linear. */ 1618 rec->ignorePreBlend(); 1619 } 1620 if (ra) { 1621 raBuffer->writeFlattenable(ra); 1622 descSize += raBuffer->bytesWritten(); 1623 entryCount += 1; 1624 rec->fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1625 } 1626 1627 /////////////////////////////////////////////////////////////////////////// 1628 // Now that we're done tweaking the rec, call the PostMakeRec cleanup 1629 SkScalerContext::PostMakeRec(paint, rec); 1630 1631 descSize += SkDescriptor::ComputeOverhead(entryCount); 1632 return descSize; 1633 } 1634 1635 #ifdef TEST_DESC 1636 static void test_desc(const SkScalerContext::Rec& rec, 1637 const SkPathEffect* pe, SkWriteBuffer* peBuffer, 1638 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer, 1639 const SkRasterizer* ra, SkWriteBuffer* raBuffer, 1640 const SkDescriptor* desc, size_t descSize) { 1641 // Check that we completely write the bytes in desc (our key), and that 1642 // there are no uninitialized bytes. If there were, then we would get 1643 // false-misses (or worse, false-hits) in our fontcache. 1644 // 1645 // We do this buy filling 2 others, one with 0s and the other with 1s 1646 // and create those, and then check that all 3 are identical. 1647 SkAutoDescriptor ad1(descSize); 1648 SkAutoDescriptor ad2(descSize); 1649 SkDescriptor* desc1 = ad1.getDesc(); 1650 SkDescriptor* desc2 = ad2.getDesc(); 1651 1652 memset(desc1, 0x00, descSize); 1653 memset(desc2, 0xFF, descSize); 1654 1655 desc1->init(); 1656 desc2->init(); 1657 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1658 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1659 1660 if (pe) { 1661 add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer); 1662 add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer); 1663 } 1664 if (mf) { 1665 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer); 1666 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer); 1667 } 1668 if (ra) { 1669 add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer); 1670 add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer); 1671 } 1672 1673 SkASSERT(descSize == desc1->getLength()); 1674 SkASSERT(descSize == desc2->getLength()); 1675 desc1->computeChecksum(); 1676 desc2->computeChecksum(); 1677 SkASSERT(!memcmp(desc, desc1, descSize)); 1678 SkASSERT(!memcmp(desc, desc2, descSize)); 1679 } 1680 #endif 1681 1682 /* see the note on ignoreGamma on descriptorProc */ 1683 void SkPaint::getScalerContextDescriptor(SkAutoDescriptor* ad, 1684 const SkSurfaceProps& surfaceProps, 1685 FakeGamma fakeGamma, 1686 const SkMatrix* deviceMatrix) const { 1687 SkScalerContext::Rec rec; 1688 1689 SkPathEffect* pe = this->getPathEffect(); 1690 SkMaskFilter* mf = this->getMaskFilter(); 1691 SkRasterizer* ra = this->getRasterizer(); 1692 1693 SkWriteBuffer peBuffer, mfBuffer, raBuffer; 1694 size_t descSize = fill_out_rec(*this, &rec, 1695 &surfaceProps, FakeGamma::On == fakeGamma, deviceMatrix, 1696 pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer); 1697 1698 ad->reset(descSize); 1699 SkDescriptor* desc = ad->getDesc(); 1700 1701 write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize); 1702 1703 SkASSERT(descSize == desc->getLength()); 1704 1705 #ifdef TEST_DESC 1706 test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize); 1707 #endif 1708 } 1709 1710 /* 1711 * ignoreGamma tells us that the caller just wants metrics that are unaffected 1712 * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1, 1713 * contrast = 0, luminanceColor = transparent black. 1714 */ 1715 void SkPaint::descriptorProc(const SkSurfaceProps* surfaceProps, 1716 FakeGamma fakeGamma, 1717 const SkMatrix* deviceMatrix, 1718 void (*proc)(SkTypeface*, const SkDescriptor*, void*), 1719 void* context) const { 1720 SkScalerContext::Rec rec; 1721 1722 SkPathEffect* pe = this->getPathEffect(); 1723 SkMaskFilter* mf = this->getMaskFilter(); 1724 SkRasterizer* ra = this->getRasterizer(); 1725 1726 SkWriteBuffer peBuffer, mfBuffer, raBuffer; 1727 size_t descSize = fill_out_rec(*this, &rec, 1728 surfaceProps, FakeGamma::On == fakeGamma, deviceMatrix, 1729 pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer); 1730 1731 SkAutoDescriptor ad(descSize); 1732 SkDescriptor* desc = ad.getDesc(); 1733 1734 write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize); 1735 1736 SkASSERT(descSize == desc->getLength()); 1737 1738 #ifdef TEST_DESC 1739 test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize); 1740 #endif 1741 1742 proc(fTypeface, desc, context); 1743 } 1744 1745 SkGlyphCache* SkPaint::detachCache(const SkSurfaceProps* surfaceProps, 1746 FakeGamma fakeGamma, 1747 const SkMatrix* deviceMatrix) const { 1748 SkGlyphCache* cache; 1749 this->descriptorProc(surfaceProps, fakeGamma, deviceMatrix, DetachDescProc, &cache); 1750 return cache; 1751 } 1752 1753 /** 1754 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend. 1755 */ 1756 //static 1757 SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) { 1758 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1759 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(), 1760 rec.getPaintGamma(), 1761 rec.getDeviceGamma()); 1762 return maskGamma.preBlend(rec.getLuminanceColor()); 1763 } 1764 1765 size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, 1766 SkScalar deviceGamma, int* width, int* height) { 1767 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1768 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, 1769 paintGamma, 1770 deviceGamma); 1771 1772 maskGamma.getGammaTableDimensions(width, height); 1773 size_t size = (*width)*(*height)*sizeof(uint8_t); 1774 1775 return size; 1776 } 1777 1778 void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma, 1779 void* data) { 1780 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1781 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, 1782 paintGamma, 1783 deviceGamma); 1784 int width, height; 1785 maskGamma.getGammaTableDimensions(&width, &height); 1786 size_t size = width*height*sizeof(uint8_t); 1787 const uint8_t* gammaTables = maskGamma.getGammaTables(); 1788 memcpy(data, gammaTables, size); 1789 } 1790 1791 1792 /////////////////////////////////////////////////////////////////////////////// 1793 1794 #include "SkStream.h" 1795 1796 static uintptr_t asint(const void* p) { 1797 return reinterpret_cast<uintptr_t>(p); 1798 } 1799 1800 union Scalar32 { 1801 SkScalar fScalar; 1802 uint32_t f32; 1803 }; 1804 1805 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) { 1806 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1807 Scalar32 tmp; 1808 tmp.fScalar = value; 1809 *ptr = tmp.f32; 1810 return ptr + 1; 1811 } 1812 1813 static SkScalar read_scalar(const uint32_t*& ptr) { 1814 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 1815 Scalar32 tmp; 1816 tmp.f32 = *ptr++; 1817 return tmp.fScalar; 1818 } 1819 1820 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { 1821 SkASSERT(a == (uint8_t)a); 1822 SkASSERT(b == (uint8_t)b); 1823 SkASSERT(c == (uint8_t)c); 1824 SkASSERT(d == (uint8_t)d); 1825 return (a << 24) | (b << 16) | (c << 8) | d; 1826 } 1827 1828 #ifdef SK_DEBUG 1829 static void ASSERT_FITS_IN(uint32_t value, int bitCount) { 1830 SkASSERT(bitCount > 0 && bitCount <= 32); 1831 uint32_t mask = ~0U; 1832 mask >>= (32 - bitCount); 1833 SkASSERT(0 == (value & ~mask)); 1834 } 1835 #else 1836 #define ASSERT_FITS_IN(value, bitcount) 1837 #endif 1838 1839 enum FlatFlags { 1840 kHasTypeface_FlatFlag = 0x1, 1841 kHasEffects_FlatFlag = 0x2, 1842 1843 kFlatFlagMask = 0x3, 1844 }; 1845 1846 enum BitsPerField { 1847 kFlags_BPF = 16, 1848 kHint_BPF = 2, 1849 kAlign_BPF = 2, 1850 kFilter_BPF = 2, 1851 kFlatFlags_BPF = 3, 1852 }; 1853 1854 static inline int BPF_Mask(int bits) { 1855 return (1 << bits) - 1; 1856 } 1857 1858 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align, 1859 unsigned filter, unsigned flatFlags) { 1860 ASSERT_FITS_IN(flags, kFlags_BPF); 1861 ASSERT_FITS_IN(hint, kHint_BPF); 1862 ASSERT_FITS_IN(align, kAlign_BPF); 1863 ASSERT_FITS_IN(filter, kFilter_BPF); 1864 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF); 1865 1866 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly 1867 // add more bits in the future. 1868 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags; 1869 } 1870 1871 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) { 1872 paint->setFlags(packed >> 16); 1873 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF))); 1874 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF))); 1875 paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF))); 1876 return (FlatFlags)(packed & kFlatFlagMask); 1877 } 1878 1879 // The size of a flat paint's POD fields 1880 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1881 1 * sizeof(SkColor) + 1882 1 * sizeof(uint16_t) + 1883 6 * sizeof(uint8_t); 1884 1885 /* To save space/time, we analyze the paint, and write a truncated version of 1886 it if there are not tricky elements like shaders, etc. 1887 */ 1888 void SkPaint::flatten(SkWriteBuffer& buffer) const { 1889 uint8_t flatFlags = 0; 1890 if (this->getTypeface()) { 1891 flatFlags |= kHasTypeface_FlatFlag; 1892 } 1893 if (asint(this->getPathEffect()) | 1894 asint(this->getShader()) | 1895 asint(this->getXfermode()) | 1896 asint(this->getMaskFilter()) | 1897 asint(this->getColorFilter()) | 1898 asint(this->getRasterizer()) | 1899 asint(this->getLooper()) | 1900 asint(this->getAnnotation()) | 1901 asint(this->getImageFilter())) { 1902 flatFlags |= kHasEffects_FlatFlag; 1903 } 1904 1905 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1906 uint32_t* ptr = buffer.reserve(kPODPaintSize); 1907 1908 ptr = write_scalar(ptr, this->getTextSize()); 1909 ptr = write_scalar(ptr, this->getTextScaleX()); 1910 ptr = write_scalar(ptr, this->getTextSkewX()); 1911 ptr = write_scalar(ptr, this->getStrokeWidth()); 1912 ptr = write_scalar(ptr, this->getStrokeMiter()); 1913 *ptr++ = this->getColor(); 1914 1915 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(), 1916 this->getFilterQuality(), flatFlags); 1917 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(), 1918 this->getStyle(), this->getTextEncoding()); 1919 1920 // now we're done with ptr and the (pre)reserved space. If we need to write 1921 // additional fields, use the buffer directly 1922 if (flatFlags & kHasTypeface_FlatFlag) { 1923 buffer.writeTypeface(this->getTypeface()); 1924 } 1925 if (flatFlags & kHasEffects_FlatFlag) { 1926 buffer.writeFlattenable(this->getPathEffect()); 1927 buffer.writeFlattenable(this->getShader()); 1928 buffer.writeFlattenable(this->getXfermode()); 1929 buffer.writeFlattenable(this->getMaskFilter()); 1930 buffer.writeFlattenable(this->getColorFilter()); 1931 buffer.writeFlattenable(this->getRasterizer()); 1932 buffer.writeFlattenable(this->getLooper()); 1933 buffer.writeFlattenable(this->getImageFilter()); 1934 1935 if (fAnnotation) { 1936 buffer.writeBool(true); 1937 fAnnotation->writeToBuffer(buffer); 1938 } else { 1939 buffer.writeBool(false); 1940 } 1941 } 1942 } 1943 1944 void SkPaint::unflatten(SkReadBuffer& buffer) { 1945 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 1946 if (!buffer.validateAvailable(kPODPaintSize)) { 1947 return; 1948 } 1949 const void* podData = buffer.skip(kPODPaintSize); 1950 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData); 1951 1952 // the order we read must match the order we wrote in flatten() 1953 this->setTextSize(read_scalar(pod)); 1954 this->setTextScaleX(read_scalar(pod)); 1955 this->setTextSkewX(read_scalar(pod)); 1956 this->setStrokeWidth(read_scalar(pod)); 1957 this->setStrokeMiter(read_scalar(pod)); 1958 this->setColor(*pod++); 1959 1960 unsigned flatFlags = unpack_paint_flags(this, *pod++); 1961 1962 uint32_t tmp = *pod++; 1963 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); 1964 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); 1965 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); 1966 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); 1967 1968 if (flatFlags & kHasTypeface_FlatFlag) { 1969 this->setTypeface(buffer.readTypeface()); 1970 } else { 1971 this->setTypeface(nullptr); 1972 } 1973 1974 if (flatFlags & kHasEffects_FlatFlag) { 1975 SkSafeUnref(this->setPathEffect(buffer.readPathEffect())); 1976 SkSafeUnref(this->setShader(buffer.readShader())); 1977 SkSafeUnref(this->setXfermode(buffer.readXfermode())); 1978 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter())); 1979 SkSafeUnref(this->setColorFilter(buffer.readColorFilter())); 1980 SkSafeUnref(this->setRasterizer(buffer.readRasterizer())); 1981 SkSafeUnref(this->setLooper(buffer.readDrawLooper())); 1982 SkSafeUnref(this->setImageFilter(buffer.readImageFilter())); 1983 1984 if (buffer.readBool()) { 1985 this->setAnnotation(SkAnnotation::Create(buffer))->unref(); 1986 } 1987 } else { 1988 this->setPathEffect(nullptr); 1989 this->setShader(nullptr); 1990 this->setXfermode(nullptr); 1991 this->setMaskFilter(nullptr); 1992 this->setColorFilter(nullptr); 1993 this->setRasterizer(nullptr); 1994 this->setLooper(nullptr); 1995 this->setImageFilter(nullptr); 1996 } 1997 } 1998 1999 /////////////////////////////////////////////////////////////////////////////// 2000 2001 SkShader* SkPaint::setShader(SkShader* shader) { 2002 SkRefCnt_SafeAssign(fShader, shader); 2003 return shader; 2004 } 2005 2006 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) { 2007 SkRefCnt_SafeAssign(fColorFilter, filter); 2008 return filter; 2009 } 2010 2011 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { 2012 SkRefCnt_SafeAssign(fXfermode, mode); 2013 return mode; 2014 } 2015 2016 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { 2017 SkSafeUnref(fXfermode); 2018 fXfermode = SkXfermode::Create(mode); 2019 return fXfermode; 2020 } 2021 2022 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) { 2023 SkRefCnt_SafeAssign(fPathEffect, effect); 2024 return effect; 2025 } 2026 2027 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { 2028 SkRefCnt_SafeAssign(fMaskFilter, filter); 2029 return filter; 2030 } 2031 2032 /////////////////////////////////////////////////////////////////////////////// 2033 2034 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, 2035 SkScalar resScale) const { 2036 SkStrokeRec rec(*this, resScale); 2037 2038 const SkPath* srcPtr = &src; 2039 SkPath tmpPath; 2040 2041 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) { 2042 srcPtr = &tmpPath; 2043 } 2044 2045 if (!rec.applyToPath(dst, *srcPtr)) { 2046 if (srcPtr == &tmpPath) { 2047 // If path's were copy-on-write, this trick would not be needed. 2048 // As it is, we want to save making a deep-copy from tmpPath -> dst 2049 // since we know we're just going to delete tmpPath when we return, 2050 // so the swap saves that copy. 2051 dst->swap(tmpPath); 2052 } else { 2053 *dst = *srcPtr; 2054 } 2055 } 2056 return !rec.isHairlineStyle(); 2057 } 2058 2059 bool SkPaint::canComputeFastBounds() const { 2060 if (this->getLooper()) { 2061 return this->getLooper()->canComputeFastBounds(*this); 2062 } 2063 if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) { 2064 return false; 2065 } 2066 return !this->getRasterizer(); 2067 } 2068 2069 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc, 2070 SkRect* storage, 2071 Style style) const { 2072 SkASSERT(storage); 2073 2074 const SkRect* src = &origSrc; 2075 2076 if (this->getLooper()) { 2077 SkASSERT(this->getLooper()->canComputeFastBounds(*this)); 2078 this->getLooper()->computeFastBounds(*this, *src, storage); 2079 return *storage; 2080 } 2081 2082 SkRect tmpSrc; 2083 if (this->getPathEffect()) { 2084 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc); 2085 src = &tmpSrc; 2086 } 2087 2088 if (kFill_Style != style) { 2089 // since we're stroked, outset the rect by the radius (and join type) 2090 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); 2091 if (0 == radius) { // hairline 2092 radius = SK_Scalar1; 2093 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { 2094 SkScalar scale = this->getStrokeMiter(); 2095 if (scale > SK_Scalar1) { 2096 radius = SkScalarMul(radius, scale); 2097 } 2098 } 2099 storage->set(src->fLeft - radius, src->fTop - radius, 2100 src->fRight + radius, src->fBottom + radius); 2101 } else { 2102 *storage = *src; 2103 } 2104 2105 if (this->getMaskFilter()) { 2106 this->getMaskFilter()->computeFastBounds(*storage, storage); 2107 } 2108 2109 if (this->getImageFilter()) { 2110 this->getImageFilter()->computeFastBounds(*storage, storage); 2111 } 2112 2113 return *storage; 2114 } 2115 2116 #ifndef SK_IGNORE_TO_STRING 2117 2118 void SkPaint::toString(SkString* str) const { 2119 str->append("<dl><dt>SkPaint:</dt><dd><dl>"); 2120 2121 SkTypeface* typeface = this->getTypeface(); 2122 if (typeface) { 2123 SkDynamicMemoryWStream ostream; 2124 typeface->serialize(&ostream); 2125 SkAutoTDelete<SkStreamAsset> istream(ostream.detachAsStream()); 2126 2127 SkFontDescriptor descriptor; 2128 if (!SkFontDescriptor::Deserialize(istream, &descriptor)) { 2129 str->append("<dt>FontDescriptor deserialization failed</dt>"); 2130 } else { 2131 str->append("<dt>Font Family Name:</dt><dd>"); 2132 str->append(descriptor.getFamilyName()); 2133 str->append("</dd><dt>Font Full Name:</dt><dd>"); 2134 str->append(descriptor.getFullName()); 2135 str->append("</dd><dt>Font PS Name:</dt><dd>"); 2136 str->append(descriptor.getPostscriptName()); 2137 str->append("</dd>"); 2138 } 2139 } 2140 2141 str->append("<dt>TextSize:</dt><dd>"); 2142 str->appendScalar(this->getTextSize()); 2143 str->append("</dd>"); 2144 2145 str->append("<dt>TextScaleX:</dt><dd>"); 2146 str->appendScalar(this->getTextScaleX()); 2147 str->append("</dd>"); 2148 2149 str->append("<dt>TextSkewX:</dt><dd>"); 2150 str->appendScalar(this->getTextSkewX()); 2151 str->append("</dd>"); 2152 2153 SkPathEffect* pathEffect = this->getPathEffect(); 2154 if (pathEffect) { 2155 str->append("<dt>PathEffect:</dt><dd>"); 2156 pathEffect->toString(str); 2157 str->append("</dd>"); 2158 } 2159 2160 SkShader* shader = this->getShader(); 2161 if (shader) { 2162 str->append("<dt>Shader:</dt><dd>"); 2163 shader->toString(str); 2164 str->append("</dd>"); 2165 } 2166 2167 SkXfermode* xfer = this->getXfermode(); 2168 if (xfer) { 2169 str->append("<dt>Xfermode:</dt><dd>"); 2170 xfer->toString(str); 2171 str->append("</dd>"); 2172 } 2173 2174 SkMaskFilter* maskFilter = this->getMaskFilter(); 2175 if (maskFilter) { 2176 str->append("<dt>MaskFilter:</dt><dd>"); 2177 maskFilter->toString(str); 2178 str->append("</dd>"); 2179 } 2180 2181 SkColorFilter* colorFilter = this->getColorFilter(); 2182 if (colorFilter) { 2183 str->append("<dt>ColorFilter:</dt><dd>"); 2184 colorFilter->toString(str); 2185 str->append("</dd>"); 2186 } 2187 2188 SkRasterizer* rasterizer = this->getRasterizer(); 2189 if (rasterizer) { 2190 str->append("<dt>Rasterizer:</dt><dd>"); 2191 str->append("</dd>"); 2192 } 2193 2194 SkDrawLooper* looper = this->getLooper(); 2195 if (looper) { 2196 str->append("<dt>DrawLooper:</dt><dd>"); 2197 looper->toString(str); 2198 str->append("</dd>"); 2199 } 2200 2201 SkImageFilter* imageFilter = this->getImageFilter(); 2202 if (imageFilter) { 2203 str->append("<dt>ImageFilter:</dt><dd>"); 2204 imageFilter->toString(str); 2205 str->append("</dd>"); 2206 } 2207 2208 SkAnnotation* annotation = this->getAnnotation(); 2209 if (annotation) { 2210 str->append("<dt>Annotation:</dt><dd>"); 2211 str->append("</dd>"); 2212 } 2213 2214 str->append("<dt>Color:</dt><dd>0x"); 2215 SkColor color = this->getColor(); 2216 str->appendHex(color); 2217 str->append("</dd>"); 2218 2219 str->append("<dt>Stroke Width:</dt><dd>"); 2220 str->appendScalar(this->getStrokeWidth()); 2221 str->append("</dd>"); 2222 2223 str->append("<dt>Stroke Miter:</dt><dd>"); 2224 str->appendScalar(this->getStrokeMiter()); 2225 str->append("</dd>"); 2226 2227 str->append("<dt>Flags:</dt><dd>("); 2228 if (this->getFlags()) { 2229 bool needSeparator = false; 2230 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator); 2231 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator); 2232 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator); 2233 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator); 2234 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator); 2235 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator); 2236 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator); 2237 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator); 2238 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator); 2239 SkAddFlagToString(str, this->isEmbeddedBitmapText(), 2240 "EmbeddedBitmapText", &needSeparator); 2241 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator); 2242 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator); 2243 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag), 2244 "GenA8FromLCD", &needSeparator); 2245 } else { 2246 str->append("None"); 2247 } 2248 str->append(")</dd>"); 2249 2250 str->append("<dt>FilterLevel:</dt><dd>"); 2251 static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" }; 2252 str->append(gFilterQualityStrings[this->getFilterQuality()]); 2253 str->append("</dd>"); 2254 2255 str->append("<dt>TextAlign:</dt><dd>"); 2256 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" }; 2257 str->append(gTextAlignStrings[this->getTextAlign()]); 2258 str->append("</dd>"); 2259 2260 str->append("<dt>CapType:</dt><dd>"); 2261 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" }; 2262 str->append(gStrokeCapStrings[this->getStrokeCap()]); 2263 str->append("</dd>"); 2264 2265 str->append("<dt>JoinType:</dt><dd>"); 2266 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" }; 2267 str->append(gJoinStrings[this->getStrokeJoin()]); 2268 str->append("</dd>"); 2269 2270 str->append("<dt>Style:</dt><dd>"); 2271 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" }; 2272 str->append(gStyleStrings[this->getStyle()]); 2273 str->append("</dd>"); 2274 2275 str->append("<dt>TextEncoding:</dt><dd>"); 2276 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" }; 2277 str->append(gTextEncodingStrings[this->getTextEncoding()]); 2278 str->append("</dd>"); 2279 2280 str->append("<dt>Hinting:</dt><dd>"); 2281 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" }; 2282 str->append(gHintingStrings[this->getHinting()]); 2283 str->append("</dd>"); 2284 2285 str->append("</dd></dl></dl>"); 2286 } 2287 #endif 2288 2289 /////////////////////////////////////////////////////////////////////////////// 2290 2291 static bool has_thick_frame(const SkPaint& paint) { 2292 return paint.getStrokeWidth() > 0 && 2293 paint.getStyle() != SkPaint::kFill_Style; 2294 } 2295 2296 SkTextBaseIter::SkTextBaseIter(const char text[], size_t length, 2297 const SkPaint& paint, 2298 bool applyStrokeAndPathEffects) 2299 : fPaint(paint) { 2300 fGlyphCacheProc = paint.getGlyphCacheProc(true); 2301 2302 fPaint.setLinearText(true); 2303 fPaint.setMaskFilter(nullptr); // don't want this affecting our path-cache lookup 2304 2305 if (fPaint.getPathEffect() == nullptr && !has_thick_frame(fPaint)) { 2306 applyStrokeAndPathEffects = false; 2307 } 2308 2309 // can't use our canonical size if we need to apply patheffects 2310 if (fPaint.getPathEffect() == nullptr) { 2311 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 2312 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 2313 if (has_thick_frame(fPaint)) { 2314 fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale); 2315 } 2316 } else { 2317 fScale = SK_Scalar1; 2318 } 2319 2320 if (!applyStrokeAndPathEffects) { 2321 fPaint.setStyle(SkPaint::kFill_Style); 2322 fPaint.setPathEffect(nullptr); 2323 } 2324 2325 fCache = fPaint.detachCache(nullptr, SkPaint::FakeGamma::On, nullptr); 2326 2327 SkPaint::Style style = SkPaint::kFill_Style; 2328 SkPathEffect* pe = nullptr; 2329 2330 if (!applyStrokeAndPathEffects) { 2331 style = paint.getStyle(); // restore 2332 pe = paint.getPathEffect(); // restore 2333 } 2334 fPaint.setStyle(style); 2335 fPaint.setPathEffect(pe); 2336 fPaint.setMaskFilter(paint.getMaskFilter()); // restore 2337 2338 // now compute fXOffset if needed 2339 2340 SkScalar xOffset = 0; 2341 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first 2342 int count; 2343 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, 2344 &count, nullptr), fScale); 2345 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2346 width = SkScalarHalf(width); 2347 } 2348 xOffset = -width; 2349 } 2350 fXPos = xOffset; 2351 fPrevAdvance = 0; 2352 2353 fText = text; 2354 fStop = text + length; 2355 2356 fXYIndex = paint.isVerticalText() ? 1 : 0; 2357 } 2358 2359 SkTextBaseIter::~SkTextBaseIter() { 2360 SkGlyphCache::AttachCache(fCache); 2361 } 2362 2363 bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) { 2364 if (fText < fStop) { 2365 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 2366 2367 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 2368 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking(); 2369 2370 if (glyph.fWidth) { 2371 if (path) { 2372 *path = fCache->findPath(glyph); 2373 } 2374 } else { 2375 if (path) { 2376 *path = nullptr; 2377 } 2378 } 2379 if (xpos) { 2380 *xpos = fXPos; 2381 } 2382 return true; 2383 } 2384 return false; 2385 } 2386 2387 bool SkTextInterceptsIter::next(SkScalar* array, int* count) { 2388 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 2389 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 2390 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking(); 2391 if (fCache->findPath(glyph)) { 2392 fCache->findIntercepts(fBounds, fScale, fXPos, SkToBool(fXYIndex), 2393 const_cast<SkGlyph*>(&glyph), array, count); 2394 } 2395 return fText < fStop; 2396 } 2397 2398 /////////////////////////////////////////////////////////////////////////////// 2399 2400 // return true if the filter exists, and may affect alpha 2401 static bool affects_alpha(const SkColorFilter* cf) { 2402 return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); 2403 } 2404 2405 // return true if the filter exists, and may affect alpha 2406 static bool affects_alpha(const SkImageFilter* imf) { 2407 // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha 2408 // ala colorfilters 2409 return imf != nullptr; 2410 } 2411 2412 bool SkPaint::nothingToDraw() const { 2413 if (fLooper) { 2414 return false; 2415 } 2416 SkXfermode::Mode mode; 2417 if (SkXfermode::AsMode(fXfermode, &mode)) { 2418 switch (mode) { 2419 case SkXfermode::kSrcOver_Mode: 2420 case SkXfermode::kSrcATop_Mode: 2421 case SkXfermode::kDstOut_Mode: 2422 case SkXfermode::kDstOver_Mode: 2423 case SkXfermode::kPlus_Mode: 2424 if (0 == this->getAlpha()) { 2425 return !affects_alpha(fColorFilter) && !affects_alpha(fImageFilter); 2426 } 2427 break; 2428 case SkXfermode::kDst_Mode: 2429 return true; 2430 default: 2431 break; 2432 } 2433 } 2434 return false; 2435 } 2436 2437 uint32_t SkPaint::getHash() const { 2438 // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields, 2439 // so fBitfields should be 10 pointers and 6 32-bit values from the start. 2440 static_assert(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t), 2441 "SkPaint_notPackedTightly"); 2442 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this), 2443 offsetof(SkPaint, fBitfields) + sizeof(fBitfields)); 2444 } 2445