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