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