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