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