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