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