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