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