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