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