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