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#ifdef SK_USE_FREETYPE_EMBOLDEN 1609 // It is possible that the SkTypeface used to draw glyphs has 1610 // different properties than the SkTypeface set in the SkPaint. 1611 // If we are asked to render bold text with a bold font, and are 1612 // forced to fall back to a font with normal weight for some 1613 // glyphs, we need to use fake bold to render those glyphs. In 1614 // order to do that, we set SkScalerContext's "embolden" flag 1615 // here if we are trying to draw bold text via any means, and 1616 // ignore it at the glyph outline generation stage if the font 1617 // actually being used is already bold. 1618 if (paint.isFakeBoldText() || (typeface && typeface->isBold())) { 1619 flags |= SkScalerContext::kEmbolden_Flag; 1620 } 1621#else 1622 if (paint.isFakeBoldText()) { 1623 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(), 1624 kStdFakeBoldInterpKeys, 1625 kStdFakeBoldInterpValues, 1626 kStdFakeBoldInterpLength); 1627 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); 1628 1629 if (style == SkPaint::kFill_Style) { 1630 style = SkPaint::kStrokeAndFill_Style; 1631 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill" 1632 } else { 1633 strokeWidth += extra; 1634 } 1635 } 1636#endif 1637 1638 if (paint.isDevKernText()) { 1639 flags |= SkScalerContext::kDevKernText_Flag; 1640 } 1641 1642 if (style != SkPaint::kFill_Style && strokeWidth > 0) { 1643 rec->fFrameWidth = strokeWidth; 1644 rec->fMiterLimit = paint.getStrokeMiter(); 1645 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); 1646 1647 if (style == SkPaint::kStrokeAndFill_Style) { 1648 flags |= SkScalerContext::kFrameAndFill_Flag; 1649 } 1650 } else { 1651 rec->fFrameWidth = 0; 1652 rec->fMiterLimit = 0; 1653 rec->fStrokeJoin = 0; 1654 } 1655 1656 rec->fMaskFormat = SkToU8(computeMaskFormat(paint)); 1657 1658 SkDeviceProperties::Geometry geometry = deviceProperties 1659 ? deviceProperties->fGeometry 1660 : SkDeviceProperties::Geometry::MakeDefault(); 1661 if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) { 1662 if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) { 1663 // eeek, can't support LCD 1664 rec->fMaskFormat = SkMask::kA8_Format; 1665 } else { 1666 if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) { 1667 flags |= SkScalerContext::kLCD_Vertical_Flag; 1668 } 1669 if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) { 1670 flags |= SkScalerContext::kLCD_BGROrder_Flag; 1671 } 1672 } 1673 } 1674 1675 if (paint.isEmbeddedBitmapText()) { 1676 flags |= SkScalerContext::kEmbeddedBitmapText_Flag; 1677 } 1678 if (paint.isSubpixelText()) { 1679 flags |= SkScalerContext::kSubpixelPositioning_Flag; 1680 } 1681 if (paint.isAutohinted()) { 1682 flags |= SkScalerContext::kForceAutohinting_Flag; 1683 } 1684 if (paint.isVerticalText()) { 1685 flags |= SkScalerContext::kVertical_Flag; 1686 } 1687 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) { 1688 flags |= SkScalerContext::kGenA8FromLCD_Flag; 1689 } 1690 rec->fFlags = SkToU16(flags); 1691 1692 // these modify fFlags, so do them after assigning fFlags 1693 rec->setHinting(computeHinting(paint)); 1694 1695 rec->setLuminanceColor(computeLuminanceColor(paint)); 1696 1697 if (NULL == deviceProperties) { 1698 rec->setDeviceGamma(SK_GAMMA_EXPONENT); 1699 rec->setPaintGamma(SK_GAMMA_EXPONENT); 1700 } else { 1701 rec->setDeviceGamma(deviceProperties->fGamma); 1702 1703 //For now always set the paint gamma equal to the device gamma. 1704 //The math in SkMaskGamma can handle them being different, 1705 //but it requires superluminous masks when 1706 //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large. 1707 rec->setPaintGamma(deviceProperties->fGamma); 1708 } 1709 1710#ifdef SK_GAMMA_CONTRAST 1711 rec->setContrast(SK_GAMMA_CONTRAST); 1712#else 1713 /** 1714 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise. 1715 * With lower values small text appears washed out (though correctly so). 1716 * With higher values lcd fringing is worse and the smoothing effect of 1717 * partial coverage is diminished. 1718 */ 1719 rec->setContrast(0.5f); 1720#endif 1721 1722 rec->fReservedAlign = 0; 1723 1724 /* Allow the fonthost to modify our rec before we use it as a key into the 1725 cache. This way if we're asking for something that they will ignore, 1726 they can modify our rec up front, so we don't create duplicate cache 1727 entries. 1728 */ 1729 typeface->onFilterRec(rec); 1730 1731 // be sure to call PostMakeRec(rec) before you actually use it! 1732} 1733 1734/** 1735 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or 1736 * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue 1737 * to hold it until the returned pointer is refed or forgotten. 1738 */ 1739SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex); 1740 1741static SkMaskGamma* gLinearMaskGamma = NULL; 1742static SkMaskGamma* gMaskGamma = NULL; 1743static SkScalar gContrast = SK_ScalarMin; 1744static SkScalar gPaintGamma = SK_ScalarMin; 1745static SkScalar gDeviceGamma = SK_ScalarMin; 1746/** 1747 * The caller must hold the gMaskGammaCacheMutex and continue to hold it until 1748 * the returned SkMaskGamma pointer is refed or forgotten. 1749 */ 1750static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) { 1751 gMaskGammaCacheMutex.assertHeld(); 1752 if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) { 1753 if (NULL == gLinearMaskGamma) { 1754 gLinearMaskGamma = SkNEW(SkMaskGamma); 1755 } 1756 return *gLinearMaskGamma; 1757 } 1758 if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) { 1759 SkSafeUnref(gMaskGamma); 1760 gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma)); 1761 gContrast = contrast; 1762 gPaintGamma = paintGamma; 1763 gDeviceGamma = deviceGamma; 1764 } 1765 return *gMaskGamma; 1766} 1767 1768/*static*/ void SkPaint::Term() { 1769 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1770 1771 SkSafeUnref(gLinearMaskGamma); 1772 gLinearMaskGamma = NULL; 1773 SkSafeUnref(gMaskGamma); 1774 gMaskGamma = NULL; 1775 SkDEBUGCODE(gContrast = SK_ScalarMin;) 1776 SkDEBUGCODE(gPaintGamma = SK_ScalarMin;) 1777 SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;) 1778} 1779 1780/** 1781 * We ensure that the rec is self-consistent and efficient (where possible) 1782 */ 1783void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) { 1784 /** 1785 * If we're asking for A8, we force the colorlum to be gray, since that 1786 * limits the number of unique entries, and the scaler will only look at 1787 * the lum of one of them. 1788 */ 1789 switch (rec->fMaskFormat) { 1790 case SkMask::kLCD16_Format: 1791 case SkMask::kLCD32_Format: { 1792 // filter down the luminance color to a finite number of bits 1793 SkColor color = rec->getLuminanceColor(); 1794 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color)); 1795 break; 1796 } 1797 case SkMask::kA8_Format: { 1798 // filter down the luminance to a single component, since A8 can't 1799 // use per-component information 1800 1801 SkColor color = rec->getLuminanceColor(); 1802 U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color); 1803 //If we are asked to look like LCD, look like LCD. 1804 if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) { 1805 // HACK: Prevents green from being pre-blended as white. 1806 lum -= ((255 - lum) * lum) / 255; 1807 } 1808 1809 // reduce to our finite number of bits 1810 color = SkColorSetRGB(lum, lum, lum); 1811 rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color)); 1812 break; 1813 } 1814 case SkMask::kBW_Format: 1815 // No need to differentiate gamma if we're BW 1816 rec->ignorePreBlend(); 1817 break; 1818 } 1819} 1820 1821#define MIN_SIZE_FOR_EFFECT_BUFFER 1024 1822 1823#ifdef SK_DEBUG 1824 #define TEST_DESC 1825#endif 1826 1827/* 1828 * ignoreGamma tells us that the caller just wants metrics that are unaffected 1829 * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1, 1830 * contrast = 0, luminanceColor = transparent black. 1831 */ 1832void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, 1833 const SkMatrix* deviceMatrix, 1834 void (*proc)(SkTypeface*, const SkDescriptor*, void*), 1835 void* context, bool ignoreGamma) const { 1836 SkScalerContext::Rec rec; 1837 1838 SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec); 1839 if (ignoreGamma) { 1840 rec.ignorePreBlend(); 1841 } 1842 1843 size_t descSize = sizeof(rec); 1844 int entryCount = 1; 1845 SkPathEffect* pe = this->getPathEffect(); 1846 SkMaskFilter* mf = this->getMaskFilter(); 1847 SkRasterizer* ra = this->getRasterizer(); 1848 1849 SkWriteBuffer peBuffer, mfBuffer, raBuffer; 1850 1851 if (pe) { 1852 peBuffer.writeFlattenable(pe); 1853 descSize += peBuffer.bytesWritten(); 1854 entryCount += 1; 1855 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1856 // seems like we could support kLCD as well at this point... 1857 } 1858 if (mf) { 1859 mfBuffer.writeFlattenable(mf); 1860 descSize += mfBuffer.bytesWritten(); 1861 entryCount += 1; 1862 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters 1863 /* Pre-blend is not currently applied to filtered text. 1864 The primary filter is blur, for which contrast makes no sense, 1865 and for which the destination guess error is more visible. 1866 Also, all existing users of blur have calibrated for linear. */ 1867 rec.ignorePreBlend(); 1868 } 1869 if (ra) { 1870 raBuffer.writeFlattenable(ra); 1871 descSize += raBuffer.bytesWritten(); 1872 entryCount += 1; 1873 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion 1874 } 1875 1876#ifdef SK_BUILD_FOR_ANDROID 1877 SkWriteBuffer androidBuffer; 1878 fPaintOptionsAndroid.flatten(androidBuffer); 1879 descSize += androidBuffer.bytesWritten(); 1880 entryCount += 1; 1881#endif 1882 1883 /////////////////////////////////////////////////////////////////////////// 1884 // Now that we're done tweaking the rec, call the PostMakeRec cleanup 1885 SkScalerContext::PostMakeRec(*this, &rec); 1886 1887 descSize += SkDescriptor::ComputeOverhead(entryCount); 1888 1889 SkAutoDescriptor ad(descSize); 1890 SkDescriptor* desc = ad.getDesc(); 1891 1892 desc->init(); 1893 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1894 1895#ifdef SK_BUILD_FOR_ANDROID 1896 add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer); 1897#endif 1898 1899 if (pe) { 1900 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); 1901 } 1902 if (mf) { 1903 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer); 1904 } 1905 if (ra) { 1906 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer); 1907 } 1908 1909 SkASSERT(descSize == desc->getLength()); 1910 desc->computeChecksum(); 1911 1912#ifdef TEST_DESC 1913 { 1914 // Check that we completely write the bytes in desc (our key), and that 1915 // there are no uninitialized bytes. If there were, then we would get 1916 // false-misses (or worse, false-hits) in our fontcache. 1917 // 1918 // We do this buy filling 2 others, one with 0s and the other with 1s 1919 // and create those, and then check that all 3 are identical. 1920 SkAutoDescriptor ad1(descSize); 1921 SkAutoDescriptor ad2(descSize); 1922 SkDescriptor* desc1 = ad1.getDesc(); 1923 SkDescriptor* desc2 = ad2.getDesc(); 1924 1925 memset(desc1, 0x00, descSize); 1926 memset(desc2, 0xFF, descSize); 1927 1928 desc1->init(); 1929 desc2->init(); 1930 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1931 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); 1932 1933#ifdef SK_BUILD_FOR_ANDROID 1934 add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer); 1935 add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer); 1936#endif 1937 1938 if (pe) { 1939 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer); 1940 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer); 1941 } 1942 if (mf) { 1943 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer); 1944 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer); 1945 } 1946 if (ra) { 1947 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer); 1948 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer); 1949 } 1950 1951 SkASSERT(descSize == desc1->getLength()); 1952 SkASSERT(descSize == desc2->getLength()); 1953 desc1->computeChecksum(); 1954 desc2->computeChecksum(); 1955 SkASSERT(!memcmp(desc, desc1, descSize)); 1956 SkASSERT(!memcmp(desc, desc2, descSize)); 1957 } 1958#endif 1959 1960 proc(fTypeface, desc, context); 1961} 1962 1963SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties, 1964 const SkMatrix* deviceMatrix, 1965 bool ignoreGamma) const { 1966 SkGlyphCache* cache; 1967 this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma); 1968 return cache; 1969} 1970 1971/** 1972 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend. 1973 */ 1974//static 1975SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) { 1976 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1977 const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(), 1978 rec.getPaintGamma(), 1979 rec.getDeviceGamma()); 1980 return maskGamma.preBlend(rec.getLuminanceColor()); 1981} 1982 1983size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, 1984 SkScalar deviceGamma, int* width, int* height) { 1985 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1986 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, 1987 paintGamma, 1988 deviceGamma); 1989 1990 maskGamma.getGammaTableDimensions(width, height); 1991 size_t size = (*width)*(*height)*sizeof(uint8_t); 1992 1993 return size; 1994} 1995 1996void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma, 1997 void* data) { 1998 SkAutoMutexAcquire ama(gMaskGammaCacheMutex); 1999 const SkMaskGamma& maskGamma = cachedMaskGamma(contrast, 2000 paintGamma, 2001 deviceGamma); 2002 int width, height; 2003 maskGamma.getGammaTableDimensions(&width, &height); 2004 size_t size = width*height*sizeof(uint8_t); 2005 const uint8_t* gammaTables = maskGamma.getGammaTables(); 2006 memcpy(data, gammaTables, size); 2007} 2008 2009 2010/////////////////////////////////////////////////////////////////////////////// 2011 2012#include "SkStream.h" 2013 2014static uintptr_t asint(const void* p) { 2015 return reinterpret_cast<uintptr_t>(p); 2016} 2017 2018union Scalar32 { 2019 SkScalar fScalar; 2020 uint32_t f32; 2021}; 2022 2023static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) { 2024 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 2025 Scalar32 tmp; 2026 tmp.fScalar = value; 2027 *ptr = tmp.f32; 2028 return ptr + 1; 2029} 2030 2031static SkScalar read_scalar(const uint32_t*& ptr) { 2032 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t)); 2033 Scalar32 tmp; 2034 tmp.f32 = *ptr++; 2035 return tmp.fScalar; 2036} 2037 2038static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { 2039 SkASSERT(a == (uint8_t)a); 2040 SkASSERT(b == (uint8_t)b); 2041 SkASSERT(c == (uint8_t)c); 2042 SkASSERT(d == (uint8_t)d); 2043 return (a << 24) | (b << 16) | (c << 8) | d; 2044} 2045 2046#ifdef SK_DEBUG 2047 static void ASSERT_FITS_IN(uint32_t value, int bitCount) { 2048 SkASSERT(bitCount > 0 && bitCount <= 32); 2049 uint32_t mask = ~0U; 2050 mask >>= (32 - bitCount); 2051 SkASSERT(0 == (value & ~mask)); 2052 } 2053#else 2054 #define ASSERT_FITS_IN(value, bitcount) 2055#endif 2056 2057enum FlatFlags { 2058 kHasTypeface_FlatFlag = 0x01, 2059 kHasEffects_FlatFlag = 0x02, 2060 kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04, 2061 2062 kFlatFlagMask = 0x7, 2063}; 2064 2065enum BitsPerField { 2066 kFlags_BPF = 16, 2067 kHint_BPF = 2, 2068 kAlign_BPF = 2, 2069 kFilter_BPF = 2, 2070 kFlatFlags_BPF = 3, 2071}; 2072 2073static inline int BPF_Mask(int bits) { 2074 return (1 << bits) - 1; 2075} 2076 2077static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align, 2078 unsigned filter, unsigned flatFlags) { 2079 ASSERT_FITS_IN(flags, kFlags_BPF); 2080 ASSERT_FITS_IN(hint, kHint_BPF); 2081 ASSERT_FITS_IN(align, kAlign_BPF); 2082 ASSERT_FITS_IN(filter, kFilter_BPF); 2083 ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF); 2084 2085 // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly 2086 // add more bits in the future. 2087 return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags; 2088} 2089 2090static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) { 2091 paint->setFlags(packed >> 16); 2092 paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF))); 2093 paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF))); 2094 paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF))); 2095 return (FlatFlags)(packed & kFlatFlagMask); 2096} 2097 2098// V22_COMPATIBILITY_CODE 2099static FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) { 2100 enum { 2101 kFilterBitmap_Flag = 0x02, 2102 kHighQualityFilterBitmap_Flag = 0x4000, 2103 2104 kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag 2105 }; 2106 2107 // previously flags:16, textAlign:8, flatFlags:8 2108 // now flags:16, hinting:4, textAlign:4, flatFlags:8 2109 unsigned flags = packed >> 16; 2110 int filter = 0; 2111 if (flags & kFilterBitmap_Flag) { 2112 filter |= 1; 2113 } 2114 if (flags & kHighQualityFilterBitmap_Flag) { 2115 filter |= 2; 2116 } 2117 paint->setFilterLevel((SkPaint::FilterLevel)filter); 2118 flags &= ~kAll_Flags; // remove these (now dead) bit flags 2119 2120 paint->setFlags(flags); 2121 2122 // hinting added later. 0 in this nibble means use the default. 2123 uint32_t hinting = (packed >> 12) & 0xF; 2124 paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1)); 2125 paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF)); 2126 return (FlatFlags)(packed & kFlatFlagMask); 2127} 2128 2129// The size of a flat paint's POD fields 2130static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 2131 1 * sizeof(SkColor) + 2132 1 * sizeof(uint16_t) + 2133 6 * sizeof(uint8_t); 2134 2135/* To save space/time, we analyze the paint, and write a truncated version of 2136 it if there are not tricky elements like shaders, etc. 2137 */ 2138void SkPaint::flatten(SkWriteBuffer& buffer) const { 2139 uint8_t flatFlags = 0; 2140 if (this->getTypeface()) { 2141 flatFlags |= kHasTypeface_FlatFlag; 2142 } 2143 if (asint(this->getPathEffect()) | 2144 asint(this->getShader()) | 2145 asint(this->getXfermode()) | 2146 asint(this->getMaskFilter()) | 2147 asint(this->getColorFilter()) | 2148 asint(this->getRasterizer()) | 2149 asint(this->getLooper()) | 2150 asint(this->getAnnotation()) | 2151 asint(this->getImageFilter())) { 2152 flatFlags |= kHasEffects_FlatFlag; 2153 } 2154#ifdef SK_BUILD_FOR_ANDROID 2155 if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) { 2156 flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag; 2157 } 2158#endif 2159 2160 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 2161 uint32_t* ptr = buffer.reserve(kPODPaintSize); 2162 2163 ptr = write_scalar(ptr, this->getTextSize()); 2164 ptr = write_scalar(ptr, this->getTextScaleX()); 2165 ptr = write_scalar(ptr, this->getTextSkewX()); 2166 ptr = write_scalar(ptr, this->getStrokeWidth()); 2167 ptr = write_scalar(ptr, this->getStrokeMiter()); 2168 *ptr++ = this->getColor(); 2169 2170 *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(), 2171 this->getFilterLevel(), flatFlags); 2172 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(), 2173 this->getStyle(), this->getTextEncoding()); 2174 2175 // now we're done with ptr and the (pre)reserved space. If we need to write 2176 // additional fields, use the buffer directly 2177 if (flatFlags & kHasTypeface_FlatFlag) { 2178 buffer.writeTypeface(this->getTypeface()); 2179 } 2180 if (flatFlags & kHasEffects_FlatFlag) { 2181 buffer.writeFlattenable(this->getPathEffect()); 2182 buffer.writeFlattenable(this->getShader()); 2183 buffer.writeFlattenable(this->getXfermode()); 2184 buffer.writeFlattenable(this->getMaskFilter()); 2185 buffer.writeFlattenable(this->getColorFilter()); 2186 buffer.writeFlattenable(this->getRasterizer()); 2187 buffer.writeFlattenable(this->getLooper()); 2188 buffer.writeFlattenable(this->getImageFilter()); 2189 2190 if (fAnnotation) { 2191 buffer.writeBool(true); 2192 fAnnotation->writeToBuffer(buffer); 2193 } else { 2194 buffer.writeBool(false); 2195 } 2196 } 2197#ifdef SK_BUILD_FOR_ANDROID 2198 if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) { 2199 this->getPaintOptionsAndroid().flatten(buffer); 2200 } 2201#endif 2202} 2203 2204void SkPaint::unflatten(SkReadBuffer& buffer) { 2205 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); 2206 const void* podData = buffer.skip(kPODPaintSize); 2207 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData); 2208 2209 // the order we read must match the order we wrote in flatten() 2210 this->setTextSize(read_scalar(pod)); 2211 this->setTextScaleX(read_scalar(pod)); 2212 this->setTextSkewX(read_scalar(pod)); 2213 this->setStrokeWidth(read_scalar(pod)); 2214 this->setStrokeMiter(read_scalar(pod)); 2215 this->setColor(*pod++); 2216 2217 unsigned flatFlags = 0; 2218 if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) { 2219 flatFlags = unpack_paint_flags_v22(this, *pod++); 2220 } else { 2221 flatFlags = unpack_paint_flags(this, *pod++); 2222 } 2223 2224 uint32_t tmp = *pod++; 2225 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); 2226 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); 2227 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); 2228 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); 2229 2230 if (flatFlags & kHasTypeface_FlatFlag) { 2231 this->setTypeface(buffer.readTypeface()); 2232 } else { 2233 this->setTypeface(NULL); 2234 } 2235 2236 if (flatFlags & kHasEffects_FlatFlag) { 2237 SkSafeUnref(this->setPathEffect(buffer.readPathEffect())); 2238 SkSafeUnref(this->setShader(buffer.readShader())); 2239 SkSafeUnref(this->setXfermode(buffer.readXfermode())); 2240 SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter())); 2241 SkSafeUnref(this->setColorFilter(buffer.readColorFilter())); 2242 SkSafeUnref(this->setRasterizer(buffer.readRasterizer())); 2243 SkSafeUnref(this->setLooper(buffer.readDrawLooper())); 2244 SkSafeUnref(this->setImageFilter(buffer.readImageFilter())); 2245 2246 if (buffer.readBool()) { 2247 this->setAnnotation(SkAnnotation::Create(buffer))->unref(); 2248 } 2249 } else { 2250 this->setPathEffect(NULL); 2251 this->setShader(NULL); 2252 this->setXfermode(NULL); 2253 this->setMaskFilter(NULL); 2254 this->setColorFilter(NULL); 2255 this->setRasterizer(NULL); 2256 this->setLooper(NULL); 2257 this->setImageFilter(NULL); 2258 } 2259 2260#ifdef SK_BUILD_FOR_ANDROID 2261 this->setPaintOptionsAndroid(SkPaintOptionsAndroid()); 2262#endif 2263 if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) { 2264 SkPaintOptionsAndroid options; 2265 options.unflatten(buffer); 2266#ifdef SK_BUILD_FOR_ANDROID 2267 this->setPaintOptionsAndroid(options); 2268#endif 2269 } 2270} 2271 2272/////////////////////////////////////////////////////////////////////////////// 2273 2274SkShader* SkPaint::setShader(SkShader* shader) { 2275 GEN_ID_INC_EVAL(shader != fShader); 2276 SkRefCnt_SafeAssign(fShader, shader); 2277 fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL); 2278 return shader; 2279} 2280 2281SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) { 2282 GEN_ID_INC_EVAL(filter != fColorFilter); 2283 SkRefCnt_SafeAssign(fColorFilter, filter); 2284 fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL); 2285 return filter; 2286} 2287 2288SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { 2289 GEN_ID_INC_EVAL(mode != fXfermode); 2290 SkRefCnt_SafeAssign(fXfermode, mode); 2291 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL); 2292 return mode; 2293} 2294 2295SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { 2296 SkSafeUnref(fXfermode); 2297 fXfermode = SkXfermode::Create(mode); 2298 GEN_ID_INC; 2299 fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL); 2300 return fXfermode; 2301} 2302 2303SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) { 2304 GEN_ID_INC_EVAL(effect != fPathEffect); 2305 SkRefCnt_SafeAssign(fPathEffect, effect); 2306 fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL); 2307 return effect; 2308} 2309 2310SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { 2311 GEN_ID_INC_EVAL(filter != fMaskFilter); 2312 SkRefCnt_SafeAssign(fMaskFilter, filter); 2313 fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL); 2314 return filter; 2315} 2316 2317/////////////////////////////////////////////////////////////////////////////// 2318 2319bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, 2320 const SkRect* cullRect) const { 2321 SkStrokeRec rec(*this); 2322 2323 const SkPath* srcPtr = &src; 2324 SkPath tmpPath; 2325 2326 if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) { 2327 srcPtr = &tmpPath; 2328 } 2329 2330 if (!rec.applyToPath(dst, *srcPtr)) { 2331 if (srcPtr == &tmpPath) { 2332 // If path's were copy-on-write, this trick would not be needed. 2333 // As it is, we want to save making a deep-copy from tmpPath -> dst 2334 // since we know we're just going to delete tmpPath when we return, 2335 // so the swap saves that copy. 2336 dst->swap(tmpPath); 2337 } else { 2338 *dst = *srcPtr; 2339 } 2340 } 2341 return !rec.isHairlineStyle(); 2342} 2343 2344const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc, 2345 SkRect* storage, 2346 Style style) const { 2347 SkASSERT(storage); 2348 2349 const SkRect* src = &origSrc; 2350 2351 if (this->getLooper()) { 2352 SkASSERT(this->getLooper()->canComputeFastBounds(*this)); 2353 this->getLooper()->computeFastBounds(*this, *src, storage); 2354 return *storage; 2355 } 2356 2357 SkRect tmpSrc; 2358 if (this->getPathEffect()) { 2359 this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc); 2360 src = &tmpSrc; 2361 } 2362 2363 if (kFill_Style != style) { 2364 // since we're stroked, outset the rect by the radius (and join type) 2365 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); 2366 if (0 == radius) { // hairline 2367 radius = SK_Scalar1; 2368 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { 2369 SkScalar scale = this->getStrokeMiter(); 2370 if (scale > SK_Scalar1) { 2371 radius = SkScalarMul(radius, scale); 2372 } 2373 } 2374 storage->set(src->fLeft - radius, src->fTop - radius, 2375 src->fRight + radius, src->fBottom + radius); 2376 } else { 2377 *storage = *src; 2378 } 2379 2380 if (this->getMaskFilter()) { 2381 this->getMaskFilter()->computeFastBounds(*storage, storage); 2382 } 2383 2384 if (this->getImageFilter()) { 2385 this->getImageFilter()->computeFastBounds(*storage, storage); 2386 } 2387 2388 return *storage; 2389} 2390 2391#ifndef SK_IGNORE_TO_STRING 2392void SkPaint::toString(SkString* str) const { 2393 str->append("<dl><dt>SkPaint:</dt><dd><dl>"); 2394 2395 SkTypeface* typeface = this->getTypeface(); 2396 if (NULL != typeface) { 2397 SkDynamicMemoryWStream ostream; 2398 typeface->serialize(&ostream); 2399 SkAutoTUnref<SkData> data(ostream.copyToData()); 2400 2401 SkMemoryStream stream(data); 2402 SkFontDescriptor descriptor(&stream); 2403 2404 str->append("<dt>Font Family Name:</dt><dd>"); 2405 str->append(descriptor.getFamilyName()); 2406 str->append("</dd><dt>Font Full Name:</dt><dd>"); 2407 str->append(descriptor.getFullName()); 2408 str->append("</dd><dt>Font PS Name:</dt><dd>"); 2409 str->append(descriptor.getPostscriptName()); 2410 str->append("</dd><dt>Font File Name:</dt><dd>"); 2411 str->append(descriptor.getFontFileName()); 2412 str->append("</dd>"); 2413 } 2414 2415 str->append("<dt>TextSize:</dt><dd>"); 2416 str->appendScalar(this->getTextSize()); 2417 str->append("</dd>"); 2418 2419 str->append("<dt>TextScaleX:</dt><dd>"); 2420 str->appendScalar(this->getTextScaleX()); 2421 str->append("</dd>"); 2422 2423 str->append("<dt>TextSkewX:</dt><dd>"); 2424 str->appendScalar(this->getTextSkewX()); 2425 str->append("</dd>"); 2426 2427 SkPathEffect* pathEffect = this->getPathEffect(); 2428 if (NULL != pathEffect) { 2429 str->append("<dt>PathEffect:</dt><dd>"); 2430 str->append("</dd>"); 2431 } 2432 2433 SkShader* shader = this->getShader(); 2434 if (NULL != shader) { 2435 str->append("<dt>Shader:</dt><dd>"); 2436 shader->toString(str); 2437 str->append("</dd>"); 2438 } 2439 2440 SkXfermode* xfer = this->getXfermode(); 2441 if (NULL != xfer) { 2442 str->append("<dt>Xfermode:</dt><dd>"); 2443 xfer->toString(str); 2444 str->append("</dd>"); 2445 } 2446 2447 SkMaskFilter* maskFilter = this->getMaskFilter(); 2448 if (NULL != maskFilter) { 2449 str->append("<dt>MaskFilter:</dt><dd>"); 2450 maskFilter->toString(str); 2451 str->append("</dd>"); 2452 } 2453 2454 SkColorFilter* colorFilter = this->getColorFilter(); 2455 if (NULL != colorFilter) { 2456 str->append("<dt>ColorFilter:</dt><dd>"); 2457 colorFilter->toString(str); 2458 str->append("</dd>"); 2459 } 2460 2461 SkRasterizer* rasterizer = this->getRasterizer(); 2462 if (NULL != rasterizer) { 2463 str->append("<dt>Rasterizer:</dt><dd>"); 2464 str->append("</dd>"); 2465 } 2466 2467 SkDrawLooper* looper = this->getLooper(); 2468 if (NULL != looper) { 2469 str->append("<dt>DrawLooper:</dt><dd>"); 2470 looper->toString(str); 2471 str->append("</dd>"); 2472 } 2473 2474 SkImageFilter* imageFilter = this->getImageFilter(); 2475 if (NULL != imageFilter) { 2476 str->append("<dt>ImageFilter:</dt><dd>"); 2477 str->append("</dd>"); 2478 } 2479 2480 SkAnnotation* annotation = this->getAnnotation(); 2481 if (NULL != annotation) { 2482 str->append("<dt>Annotation:</dt><dd>"); 2483 str->append("</dd>"); 2484 } 2485 2486 str->append("<dt>Color:</dt><dd>0x"); 2487 SkColor color = this->getColor(); 2488 str->appendHex(color); 2489 str->append("</dd>"); 2490 2491 str->append("<dt>Stroke Width:</dt><dd>"); 2492 str->appendScalar(this->getStrokeWidth()); 2493 str->append("</dd>"); 2494 2495 str->append("<dt>Stroke Miter:</dt><dd>"); 2496 str->appendScalar(this->getStrokeMiter()); 2497 str->append("</dd>"); 2498 2499 str->append("<dt>Flags:</dt><dd>("); 2500 if (this->getFlags()) { 2501 bool needSeparator = false; 2502 SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator); 2503 SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator); 2504 SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator); 2505 SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator); 2506 SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator); 2507 SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator); 2508 SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator); 2509 SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator); 2510 SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator); 2511 SkAddFlagToString(str, this->isEmbeddedBitmapText(), 2512 "EmbeddedBitmapText", &needSeparator); 2513 SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator); 2514 SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator); 2515 SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag), 2516 "GenA8FromLCD", &needSeparator); 2517 } else { 2518 str->append("None"); 2519 } 2520 str->append(")</dd>"); 2521 2522 str->append("<dt>FilterLevel:</dt><dd>"); 2523 static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" }; 2524 str->append(gFilterLevelStrings[this->getFilterLevel()]); 2525 str->append("</dd>"); 2526 2527 str->append("<dt>TextAlign:</dt><dd>"); 2528 static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" }; 2529 str->append(gTextAlignStrings[this->getTextAlign()]); 2530 str->append("</dd>"); 2531 2532 str->append("<dt>CapType:</dt><dd>"); 2533 static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" }; 2534 str->append(gStrokeCapStrings[this->getStrokeCap()]); 2535 str->append("</dd>"); 2536 2537 str->append("<dt>JoinType:</dt><dd>"); 2538 static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" }; 2539 str->append(gJoinStrings[this->getStrokeJoin()]); 2540 str->append("</dd>"); 2541 2542 str->append("<dt>Style:</dt><dd>"); 2543 static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" }; 2544 str->append(gStyleStrings[this->getStyle()]); 2545 str->append("</dd>"); 2546 2547 str->append("<dt>TextEncoding:</dt><dd>"); 2548 static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" }; 2549 str->append(gTextEncodingStrings[this->getTextEncoding()]); 2550 str->append("</dd>"); 2551 2552 str->append("<dt>Hinting:</dt><dd>"); 2553 static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" }; 2554 str->append(gHintingStrings[this->getHinting()]); 2555 str->append("</dd>"); 2556 2557 str->append("</dd></dl></dl>"); 2558} 2559#endif 2560 2561/////////////////////////////////////////////////////////////////////////////// 2562 2563static bool has_thick_frame(const SkPaint& paint) { 2564 return paint.getStrokeWidth() > 0 && 2565 paint.getStyle() != SkPaint::kFill_Style; 2566} 2567 2568SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, 2569 const SkPaint& paint, 2570 bool applyStrokeAndPathEffects) 2571 : fPaint(paint) { 2572 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection, 2573 true); 2574 2575 fPaint.setLinearText(true); 2576 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup 2577 2578 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) { 2579 applyStrokeAndPathEffects = false; 2580 } 2581 2582 // can't use our canonical size if we need to apply patheffects 2583 if (fPaint.getPathEffect() == NULL) { 2584 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); 2585 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; 2586 if (has_thick_frame(fPaint)) { 2587 fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale)); 2588 } 2589 } else { 2590 fScale = SK_Scalar1; 2591 } 2592 2593 if (!applyStrokeAndPathEffects) { 2594 fPaint.setStyle(SkPaint::kFill_Style); 2595 fPaint.setPathEffect(NULL); 2596 } 2597 2598 fCache = fPaint.detachCache(NULL, NULL, false); 2599 2600 SkPaint::Style style = SkPaint::kFill_Style; 2601 SkPathEffect* pe = NULL; 2602 2603 if (!applyStrokeAndPathEffects) { 2604 style = paint.getStyle(); // restore 2605 pe = paint.getPathEffect(); // restore 2606 } 2607 fPaint.setStyle(style); 2608 fPaint.setPathEffect(pe); 2609 fPaint.setMaskFilter(paint.getMaskFilter()); // restore 2610 2611 // now compute fXOffset if needed 2612 2613 SkScalar xOffset = 0; 2614 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first 2615 int count; 2616 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, 2617 &count, NULL), fScale); 2618 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2619 width = SkScalarHalf(width); 2620 } 2621 xOffset = -width; 2622 } 2623 fXPos = xOffset; 2624 fPrevAdvance = 0; 2625 2626 fText = text; 2627 fStop = text + length; 2628 2629 fXYIndex = paint.isVerticalText() ? 1 : 0; 2630} 2631 2632SkTextToPathIter::~SkTextToPathIter() { 2633 SkGlyphCache::AttachCache(fCache); 2634} 2635 2636bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) { 2637 if (fText < fStop) { 2638 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); 2639 2640 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale); 2641 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking(); 2642 2643 if (glyph.fWidth) { 2644 if (path) { 2645 *path = fCache->findPath(glyph); 2646 } 2647 } else { 2648 if (path) { 2649 *path = NULL; 2650 } 2651 } 2652 if (xpos) { 2653 *xpos = fXPos; 2654 } 2655 return true; 2656 } 2657 return false; 2658} 2659 2660/////////////////////////////////////////////////////////////////////////////// 2661 2662bool SkPaint::nothingToDraw() const { 2663 if (fLooper) { 2664 return false; 2665 } 2666 SkXfermode::Mode mode; 2667 if (SkXfermode::AsMode(fXfermode, &mode)) { 2668 switch (mode) { 2669 case SkXfermode::kSrcOver_Mode: 2670 case SkXfermode::kSrcATop_Mode: 2671 case SkXfermode::kDstOut_Mode: 2672 case SkXfermode::kDstOver_Mode: 2673 case SkXfermode::kPlus_Mode: 2674 return 0 == this->getAlpha(); 2675 case SkXfermode::kDst_Mode: 2676 return true; 2677 default: 2678 break; 2679 } 2680 } 2681 return false; 2682} 2683 2684void SkPaint::setBitfields(uint32_t bitfields) { 2685 fBitfields = bitfields; 2686} 2687 2688inline static unsigned popcount(uint8_t x) { 2689 // As in Hacker's delight, adapted for just 8 bits. 2690 x = (x & 0x55) + ((x >> 1) & 0x55); // a b c d w x y z -> a+b c+d w+x y+z 2691 x = (x & 0x33) + ((x >> 2) & 0x33); // a+b c+d w+x y+z -> a+b+c+d w+x+y+z 2692 x = (x & 0x0F) + ((x >> 4) & 0x0F); // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z 2693 return x; 2694} 2695 2696void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) { 2697 const uint32_t dirty = paint.fDirtyBits; 2698 2699 // Each of the low 7 dirty bits corresponds to a 4-byte flat value, 2700 // plus one for the dirty bits and one for the bitfields 2701 const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2); 2702 SkASSERT(flatBytes <= 32); 2703 uint32_t* u32 = buffer.reserve(flatBytes); 2704 *u32++ = dirty; 2705 *u32++ = paint.getBitfields(); 2706 if (0 == dirty) { 2707 return; 2708 } 2709 2710#define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field() 2711 F(u32, Color); 2712 SkScalar* f32 = reinterpret_cast<SkScalar*>(u32); 2713 F(f32, TextSize); 2714 F(f32, TextScaleX); 2715 F(f32, TextSkewX); 2716 F(f32, StrokeWidth); 2717 F(f32, StrokeMiter); 2718#undef F 2719#define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field()) 2720 F(PathEffect); 2721 F(Shader); 2722 F(Xfermode); 2723 F(MaskFilter); 2724 F(ColorFilter); 2725 F(Rasterizer); 2726 F(Looper); 2727 F(ImageFilter); 2728#undef F 2729 if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface()); 2730 if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer); 2731#ifdef SK_BUILD_FOR_ANDROID 2732 if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer); 2733#endif 2734} 2735 2736void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) { 2737 const uint32_t dirty = buffer.readUInt(); 2738 paint->setBitfields(buffer.readUInt()); 2739 if (dirty == 0) { 2740 return; 2741 } 2742#define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader()) 2743// Same function, except it unrefs the object newly set on the paint: 2744#define F_UNREF(field, reader) \ 2745 if (dirty & k##field##_DirtyBit) \ 2746 paint->set##field(buffer.reader())->unref() 2747 2748 F(Color, readUInt); 2749 F(TextSize, readScalar); 2750 F(TextScaleX, readScalar); 2751 F(TextSkewX, readScalar); 2752 F(StrokeWidth, readScalar); 2753 F(StrokeMiter, readScalar); 2754 F_UNREF(PathEffect, readPathEffect); 2755 F_UNREF(Shader, readShader); 2756 F_UNREF(Xfermode, readXfermode); 2757 F_UNREF(MaskFilter, readMaskFilter); 2758 F_UNREF(ColorFilter, readColorFilter); 2759 F_UNREF(Rasterizer, readRasterizer); 2760 F_UNREF(Looper, readDrawLooper); 2761 F_UNREF(ImageFilter, readImageFilter); 2762 F(Typeface, readTypeface); 2763#undef F 2764#undef F_UNREF 2765 if (dirty & kAnnotation_DirtyBit) { 2766 paint->setAnnotation(SkAnnotation::Create(buffer))->unref(); 2767 } 2768#ifdef SK_BUILD_FOR_ANDROID 2769 if (dirty & kPaintOptionsAndroid_DirtyBit) { 2770 SkPaintOptionsAndroid options; 2771 options.unflatten(buffer); 2772 paint->setPaintOptionsAndroid(options); 2773 } 2774#endif 2775 SkASSERT(dirty == paint->fDirtyBits); 2776} 2777