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