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