| OLD | NEW |
| (Empty) |
| 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 "SkScalerContext.h" | |
| 27 #include "SkStroke.h" | |
| 28 #include "SkTypeface.h" | |
| 29 #include "SkXfermode.h" | |
| 30 #include "SkAutoKern.h" | |
| 31 | |
| 32 #define SK_DefaultTextSize SkIntToScalar(12) | |
| 33 | |
| 34 #define SK_DefaultFlags 0 //(kNativeHintsText_Flag) | |
| 35 | |
| 36 SkPaint::SkPaint() | |
| 37 { | |
| 38 fTypeface = NULL; | |
| 39 fTextSize = SK_DefaultTextSize; | |
| 40 fTextScaleX = SK_Scalar1; | |
| 41 fTextSkewX = 0; | |
| 42 | |
| 43 fPathEffect = NULL; | |
| 44 fShader = NULL; | |
| 45 fXfermode = NULL; | |
| 46 fMaskFilter = NULL; | |
| 47 fColorFilter = NULL; | |
| 48 fRasterizer = NULL; | |
| 49 fLooper = NULL; | |
| 50 | |
| 51 fColor = SK_ColorBLACK; | |
| 52 fWidth = 0; | |
| 53 fMiterLimit = SK_DefaultMiterLimit; | |
| 54 fFlags = SK_DefaultFlags; | |
| 55 fCapType = kDefault_Cap; | |
| 56 fJoinType = kDefault_Join; | |
| 57 fTextAlign = kLeft_Align; | |
| 58 fStyle = kFill_Style; | |
| 59 fTextEncoding = kUTF8_TextEncoding; | |
| 60 } | |
| 61 | |
| 62 SkPaint::SkPaint(const SkPaint& src) | |
| 63 { | |
| 64 memcpy(this, &src, sizeof(src)); | |
| 65 | |
| 66 fTypeface->safeRef(); | |
| 67 fPathEffect->safeRef(); | |
| 68 fShader->safeRef(); | |
| 69 fXfermode->safeRef(); | |
| 70 fMaskFilter->safeRef(); | |
| 71 fColorFilter->safeRef(); | |
| 72 fRasterizer->safeRef(); | |
| 73 fLooper->safeRef(); | |
| 74 } | |
| 75 | |
| 76 SkPaint::~SkPaint() | |
| 77 { | |
| 78 fTypeface->safeUnref(); | |
| 79 fPathEffect->safeUnref(); | |
| 80 fShader->safeUnref(); | |
| 81 fXfermode->safeUnref(); | |
| 82 fMaskFilter->safeUnref(); | |
| 83 fColorFilter->safeUnref(); | |
| 84 fRasterizer->safeUnref(); | |
| 85 fLooper->safeUnref(); | |
| 86 } | |
| 87 | |
| 88 SkPaint& SkPaint::operator=(const SkPaint& src) | |
| 89 { | |
| 90 SkASSERT(&src); | |
| 91 | |
| 92 src.fTypeface->safeRef(); | |
| 93 src.fPathEffect->safeRef(); | |
| 94 src.fShader->safeRef(); | |
| 95 src.fXfermode->safeRef(); | |
| 96 src.fMaskFilter->safeRef(); | |
| 97 src.fColorFilter->safeRef(); | |
| 98 src.fRasterizer->safeRef(); | |
| 99 src.fLooper->safeRef(); | |
| 100 | |
| 101 fTypeface->safeUnref(); | |
| 102 fPathEffect->safeUnref(); | |
| 103 fShader->safeUnref(); | |
| 104 fXfermode->safeUnref(); | |
| 105 fMaskFilter->safeUnref(); | |
| 106 fColorFilter->safeUnref(); | |
| 107 fRasterizer->safeUnref(); | |
| 108 fLooper->safeUnref(); | |
| 109 | |
| 110 memcpy(this, &src, sizeof(src)); | |
| 111 | |
| 112 return *this; | |
| 113 } | |
| 114 | |
| 115 int operator==(const SkPaint& a, const SkPaint& b) | |
| 116 { | |
| 117 return memcmp(&a, &b, sizeof(a)) == 0; | |
| 118 } | |
| 119 | |
| 120 void SkPaint::reset() | |
| 121 { | |
| 122 SkPaint init; | |
| 123 | |
| 124 *this = init; | |
| 125 } | |
| 126 | |
| 127 void SkPaint::setFlags(uint32_t flags) | |
| 128 { | |
| 129 fFlags = flags; | |
| 130 } | |
| 131 | |
| 132 void SkPaint::setAntiAlias(bool doAA) | |
| 133 { | |
| 134 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); | |
| 135 } | |
| 136 | |
| 137 void SkPaint::setDither(bool doDither) | |
| 138 { | |
| 139 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); | |
| 140 } | |
| 141 | |
| 142 void SkPaint::setSubpixelText(bool doSubpixel) | |
| 143 { | |
| 144 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); | |
| 145 } | |
| 146 | |
| 147 void SkPaint::setLinearText(bool doLinearText) | |
| 148 { | |
| 149 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); | |
| 150 } | |
| 151 | |
| 152 void SkPaint::setUnderlineText(bool doUnderline) | |
| 153 { | |
| 154 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); | |
| 155 } | |
| 156 | |
| 157 void SkPaint::setStrikeThruText(bool doStrikeThru) | |
| 158 { | |
| 159 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); | |
| 160 } | |
| 161 | |
| 162 void SkPaint::setFakeBoldText(bool doFakeBold) | |
| 163 { | |
| 164 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); | |
| 165 } | |
| 166 | |
| 167 void SkPaint::setDevKernText(bool doDevKern) | |
| 168 { | |
| 169 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); | |
| 170 } | |
| 171 | |
| 172 void SkPaint::setFilterBitmap(bool doFilter) | |
| 173 { | |
| 174 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); | |
| 175 } | |
| 176 | |
| 177 void SkPaint::setStyle(Style style) | |
| 178 { | |
| 179 if ((unsigned)style < kStyleCount) | |
| 180 fStyle = style; | |
| 181 #ifdef SK_DEBUG | |
| 182 else | |
| 183 SkDebugf("SkPaint::setStyle(%d) out of range\n", style); | |
| 184 #endif | |
| 185 } | |
| 186 | |
| 187 void SkPaint::setColor(SkColor color) | |
| 188 { | |
| 189 fColor = color; | |
| 190 } | |
| 191 | |
| 192 void SkPaint::setAlpha(U8CPU a) | |
| 193 { | |
| 194 fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColor
GetB(fColor)); | |
| 195 } | |
| 196 | |
| 197 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) | |
| 198 { | |
| 199 fColor = SkColorSetARGB(a, r, g, b); | |
| 200 } | |
| 201 | |
| 202 void SkPaint::setStrokeWidth(SkScalar width) | |
| 203 { | |
| 204 if (width >= 0) | |
| 205 fWidth = width; | |
| 206 #ifdef SK_DEBUG | |
| 207 else | |
| 208 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); | |
| 209 #endif | |
| 210 } | |
| 211 | |
| 212 void SkPaint::setStrokeMiter(SkScalar limit) | |
| 213 { | |
| 214 if (limit >= 0) | |
| 215 fMiterLimit = limit; | |
| 216 #ifdef SK_DEBUG | |
| 217 else | |
| 218 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); | |
| 219 #endif | |
| 220 } | |
| 221 | |
| 222 void SkPaint::setStrokeCap(Cap ct) | |
| 223 { | |
| 224 if ((unsigned)ct < kCapCount) | |
| 225 fCapType = SkToU8(ct); | |
| 226 #ifdef SK_DEBUG | |
| 227 else | |
| 228 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); | |
| 229 #endif | |
| 230 } | |
| 231 | |
| 232 void SkPaint::setStrokeJoin(Join jt) | |
| 233 { | |
| 234 if ((unsigned)jt < kJoinCount) | |
| 235 fJoinType = SkToU8(jt); | |
| 236 #ifdef SK_DEBUG | |
| 237 else | |
| 238 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); | |
| 239 #endif | |
| 240 } | |
| 241 | |
| 242 ////////////////////////////////////////////////////////////////// | |
| 243 | |
| 244 void SkPaint::setTextAlign(Align align) | |
| 245 { | |
| 246 if ((unsigned)align < kAlignCount) | |
| 247 fTextAlign = SkToU8(align); | |
| 248 #ifdef SK_DEBUG | |
| 249 else | |
| 250 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); | |
| 251 #endif | |
| 252 } | |
| 253 | |
| 254 void SkPaint::setTextSize(SkScalar ts) | |
| 255 { | |
| 256 if (ts > 0) | |
| 257 fTextSize = ts; | |
| 258 #ifdef SK_DEBUG | |
| 259 else | |
| 260 SkDebugf("SkPaint::setTextSize() called with non-positive value\n"); | |
| 261 #endif | |
| 262 } | |
| 263 | |
| 264 void SkPaint::setTextScaleX(SkScalar scaleX) | |
| 265 { | |
| 266 fTextScaleX = scaleX; | |
| 267 } | |
| 268 | |
| 269 void SkPaint::setTextSkewX(SkScalar skewX) | |
| 270 { | |
| 271 fTextSkewX = skewX; | |
| 272 } | |
| 273 | |
| 274 void SkPaint::setTextEncoding(TextEncoding encoding) | |
| 275 { | |
| 276 if ((unsigned)encoding <= kGlyphID_TextEncoding) | |
| 277 fTextEncoding = encoding; | |
| 278 #ifdef SK_DEBUG | |
| 279 else | |
| 280 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding); | |
| 281 #endif | |
| 282 } | |
| 283 | |
| 284 ////////////////////////////////////////////////////////////////////////////////
/////// | |
| 285 | |
| 286 SkTypeface* SkPaint::setTypeface(SkTypeface* font) | |
| 287 { | |
| 288 SkRefCnt_SafeAssign(fTypeface, font); | |
| 289 return font; | |
| 290 } | |
| 291 | |
| 292 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) | |
| 293 { | |
| 294 SkRefCnt_SafeAssign(fRasterizer, r); | |
| 295 return r; | |
| 296 } | |
| 297 | |
| 298 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) | |
| 299 { | |
| 300 SkRefCnt_SafeAssign(fLooper, looper); | |
| 301 return looper; | |
| 302 } | |
| 303 | |
| 304 /////////////////////////////////////////////////////////////////////////////// | |
| 305 | |
| 306 #include "SkGlyphCache.h" | |
| 307 #include "SkUtils.h" | |
| 308 | |
| 309 int SkPaint::textToGlyphs(const void* textData, size_t byteLength, | |
| 310 uint16_t glyphs[]) const { | |
| 311 if (byteLength == 0) { | |
| 312 return 0; | |
| 313 } | |
| 314 | |
| 315 SkASSERT(textData != NULL); | |
| 316 | |
| 317 if (NULL == glyphs) { | |
| 318 switch (this->getTextEncoding()) { | |
| 319 case kUTF8_TextEncoding: | |
| 320 return SkUTF8_CountUnichars((const char*)textData, byteLength); | |
| 321 case kUTF16_TextEncoding: | |
| 322 return SkUTF16_CountUnichars((const uint16_t*)textData, | |
| 323 byteLength >> 1); | |
| 324 case kGlyphID_TextEncoding: | |
| 325 return byteLength >> 1; | |
| 326 default: | |
| 327 SkASSERT(!"unknown text encoding"); | |
| 328 } | |
| 329 return 0; | |
| 330 } | |
| 331 | |
| 332 // if we get here, we have a valid glyphs[] array, so time to fill it in | |
| 333 | |
| 334 // handle this encoding before the setup for the glyphcache | |
| 335 if (this->getTextEncoding() == kGlyphID_TextEncoding) { | |
| 336 // we want to ignore the low bit of byteLength | |
| 337 memcpy(glyphs, textData, byteLength >> 1 << 1); | |
| 338 return byteLength >> 1; | |
| 339 } | |
| 340 | |
| 341 SkAutoGlyphCache autoCache(*this, NULL); | |
| 342 SkGlyphCache* cache = autoCache.getCache(); | |
| 343 | |
| 344 const char* text = (const char*)textData; | |
| 345 const char* stop = text + byteLength; | |
| 346 uint16_t* gptr = glyphs; | |
| 347 | |
| 348 switch (this->getTextEncoding()) { | |
| 349 case SkPaint::kUTF8_TextEncoding: | |
| 350 while (text < stop) { | |
| 351 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text)); | |
| 352 } | |
| 353 break; | |
| 354 case SkPaint::kUTF16_TextEncoding: { | |
| 355 const uint16_t* text16 = (const uint16_t*)text; | |
| 356 const uint16_t* stop16 = (const uint16_t*)stop; | |
| 357 while (text16 < stop16) { | |
| 358 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16)); | |
| 359 } | |
| 360 break; | |
| 361 } | |
| 362 default: | |
| 363 SkASSERT(!"unknown text encoding"); | |
| 364 } | |
| 365 return gptr - glyphs; | |
| 366 } | |
| 367 | |
| 368 /////////////////////////////////////////////////////////////////////////////// | |
| 369 | |
| 370 static uint32_t sk_glyphID_next(const char** text) | |
| 371 { | |
| 372 const uint16_t* glyph = (const uint16_t*)text; | |
| 373 int32_t value = *glyph; | |
| 374 glyph += 1; | |
| 375 *text = (const char*)glyph; | |
| 376 return value; | |
| 377 } | |
| 378 | |
| 379 static uint32_t sk_glyphID_prev(const char** text) | |
| 380 { | |
| 381 const uint16_t* glyph = (const uint16_t*)text; | |
| 382 glyph -= 1; | |
| 383 int32_t value = *glyph; | |
| 384 *text = (const char*)glyph; | |
| 385 return value; | |
| 386 } | |
| 387 | |
| 388 ////////////////////////////////////////////////////////////////////////////// | |
| 389 | |
| 390 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, const char**
text) | |
| 391 { | |
| 392 SkASSERT(cache != NULL); | |
| 393 SkASSERT(text != NULL); | |
| 394 | |
| 395 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text)); | |
| 396 } | |
| 397 | |
| 398 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache, const char**
text) | |
| 399 { | |
| 400 SkASSERT(cache != NULL); | |
| 401 SkASSERT(text != NULL); | |
| 402 | |
| 403 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text)); | |
| 404 } | |
| 405 | |
| 406 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, const char**
text) | |
| 407 { | |
| 408 SkASSERT(cache != NULL); | |
| 409 SkASSERT(text != NULL); | |
| 410 | |
| 411 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text))
; | |
| 412 } | |
| 413 | |
| 414 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache, const char**
text) | |
| 415 { | |
| 416 SkASSERT(cache != NULL); | |
| 417 SkASSERT(text != NULL); | |
| 418 | |
| 419 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text))
; | |
| 420 } | |
| 421 | |
| 422 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, const char**
text) | |
| 423 { | |
| 424 SkASSERT(cache != NULL); | |
| 425 SkASSERT(text != NULL); | |
| 426 | |
| 427 const uint16_t* ptr = *(const uint16_t**)text; | |
| 428 unsigned glyphID = *ptr; | |
| 429 ptr += 1; | |
| 430 *text = (const char*)ptr; | |
| 431 return cache->getGlyphIDMetrics(glyphID); | |
| 432 } | |
| 433 | |
| 434 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache, const char**
text) | |
| 435 { | |
| 436 SkASSERT(cache != NULL); | |
| 437 SkASSERT(text != NULL); | |
| 438 | |
| 439 const uint16_t* ptr = *(const uint16_t**)text; | |
| 440 ptr -= 1; | |
| 441 unsigned glyphID = *ptr; | |
| 442 *text = (const char*)ptr; | |
| 443 return cache->getGlyphIDMetrics(glyphID); | |
| 444 } | |
| 445 | |
| 446 /// | |
| 447 | |
| 448 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, const char**
text) | |
| 449 { | |
| 450 SkASSERT(cache != NULL); | |
| 451 SkASSERT(text != NULL); | |
| 452 | |
| 453 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text)); | |
| 454 } | |
| 455 | |
| 456 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache, const char**
text) | |
| 457 { | |
| 458 SkASSERT(cache != NULL); | |
| 459 SkASSERT(text != NULL); | |
| 460 | |
| 461 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text)); | |
| 462 } | |
| 463 | |
| 464 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, const char**
text) | |
| 465 { | |
| 466 SkASSERT(cache != NULL); | |
| 467 SkASSERT(text != NULL); | |
| 468 | |
| 469 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text))
; | |
| 470 } | |
| 471 | |
| 472 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache, const char**
text) | |
| 473 { | |
| 474 SkASSERT(cache != NULL); | |
| 475 SkASSERT(text != NULL); | |
| 476 | |
| 477 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text))
; | |
| 478 } | |
| 479 | |
| 480 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, const char**
text) | |
| 481 { | |
| 482 SkASSERT(cache != NULL); | |
| 483 SkASSERT(text != NULL); | |
| 484 | |
| 485 const uint16_t* ptr = *(const uint16_t**)text; | |
| 486 unsigned glyphID = *ptr; | |
| 487 ptr += 1; | |
| 488 *text = (const char*)ptr; | |
| 489 return cache->getGlyphIDAdvance(glyphID); | |
| 490 } | |
| 491 | |
| 492 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache, const char**
text) | |
| 493 { | |
| 494 SkASSERT(cache != NULL); | |
| 495 SkASSERT(text != NULL); | |
| 496 | |
| 497 const uint16_t* ptr = *(const uint16_t**)text; | |
| 498 ptr -= 1; | |
| 499 unsigned glyphID = *ptr; | |
| 500 *text = (const char*)ptr; | |
| 501 return cache->getGlyphIDAdvance(glyphID); | |
| 502 } | |
| 503 | |
| 504 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd, | |
| 505 bool needFullMetrics) const | |
| 506 { | |
| 507 static const SkMeasureCacheProc gMeasureCacheProcs[] = { | |
| 508 sk_getMetrics_utf8_next, | |
| 509 sk_getMetrics_utf16_next, | |
| 510 sk_getMetrics_glyph_next, | |
| 511 | |
| 512 sk_getMetrics_utf8_prev, | |
| 513 sk_getMetrics_utf16_prev, | |
| 514 sk_getMetrics_glyph_prev, | |
| 515 | |
| 516 sk_getAdvance_utf8_next, | |
| 517 sk_getAdvance_utf16_next, | |
| 518 sk_getAdvance_glyph_next, | |
| 519 | |
| 520 sk_getAdvance_utf8_prev, | |
| 521 sk_getAdvance_utf16_prev, | |
| 522 sk_getAdvance_glyph_prev | |
| 523 }; | |
| 524 | |
| 525 unsigned index = this->getTextEncoding(); | |
| 526 | |
| 527 if (kBackward_TextBufferDirection == tbd) | |
| 528 index += 3; | |
| 529 if (!needFullMetrics && !this->isDevKernText()) | |
| 530 index += 6; | |
| 531 | |
| 532 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs)); | |
| 533 return gMeasureCacheProcs[index]; | |
| 534 } | |
| 535 | |
| 536 /////////////////////////////////////////////////////////////////////////////// | |
| 537 | |
| 538 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache, | |
| 539 const char** text, SkFixed, SkFixed) | |
| 540 { | |
| 541 SkASSERT(cache != NULL); | |
| 542 SkASSERT(text != NULL); | |
| 543 | |
| 544 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text)); | |
| 545 } | |
| 546 | |
| 547 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache, | |
| 548 const char** text, SkFixed x, SkFixe
d y) | |
| 549 { | |
| 550 SkASSERT(cache != NULL); | |
| 551 SkASSERT(text != NULL); | |
| 552 | |
| 553 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y); | |
| 554 } | |
| 555 | |
| 556 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache, const char** t
ext, | |
| 557 SkFixed, SkFixed) | |
| 558 { | |
| 559 SkASSERT(cache != NULL); | |
| 560 SkASSERT(text != NULL); | |
| 561 | |
| 562 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text))
; | |
| 563 } | |
| 564 | |
| 565 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache, | |
| 566 const char** text, SkFixed x, SkFix
ed y) | |
| 567 { | |
| 568 SkASSERT(cache != NULL); | |
| 569 SkASSERT(text != NULL); | |
| 570 | |
| 571 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text), | |
| 572 x, y); | |
| 573 } | |
| 574 | |
| 575 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache, const char** t
ext, | |
| 576 SkFixed, SkFixed) | |
| 577 { | |
| 578 SkASSERT(cache != NULL); | |
| 579 SkASSERT(text != NULL); | |
| 580 | |
| 581 const uint16_t* ptr = *(const uint16_t**)text; | |
| 582 unsigned glyphID = *ptr; | |
| 583 ptr += 1; | |
| 584 *text = (const char*)ptr; | |
| 585 return cache->getGlyphIDMetrics(glyphID); | |
| 586 } | |
| 587 | |
| 588 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache, | |
| 589 const char** text, SkFixed x, SkFix
ed y) | |
| 590 { | |
| 591 SkASSERT(cache != NULL); | |
| 592 SkASSERT(text != NULL); | |
| 593 | |
| 594 const uint16_t* ptr = *(const uint16_t**)text; | |
| 595 unsigned glyphID = *ptr; | |
| 596 ptr += 1; | |
| 597 *text = (const char*)ptr; | |
| 598 return cache->getGlyphIDMetrics(glyphID, x, y); | |
| 599 } | |
| 600 | |
| 601 SkDrawCacheProc SkPaint::getDrawCacheProc() const | |
| 602 { | |
| 603 static const SkDrawCacheProc gDrawCacheProcs[] = { | |
| 604 sk_getMetrics_utf8_00, | |
| 605 sk_getMetrics_utf16_00, | |
| 606 sk_getMetrics_glyph_00, | |
| 607 | |
| 608 sk_getMetrics_utf8_xy, | |
| 609 sk_getMetrics_utf16_xy, | |
| 610 sk_getMetrics_glyph_xy | |
| 611 }; | |
| 612 | |
| 613 unsigned index = this->getTextEncoding(); | |
| 614 if (fFlags & kSubpixelText_Flag) | |
| 615 index += 3; | |
| 616 | |
| 617 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs)); | |
| 618 return gDrawCacheProcs[index]; | |
| 619 } | |
| 620 | |
| 621 /////////////////////////////////////////////////////////////////////////////// | |
| 622 | |
| 623 class SkAutoRestorePaintTextSizeAndFrame { | |
| 624 public: | |
| 625 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) : fPaint((SkPaint*)
paint) | |
| 626 { | |
| 627 fTextSize = paint->getTextSize(); | |
| 628 fStyle = paint->getStyle(); | |
| 629 fPaint->setStyle(SkPaint::kFill_Style); | |
| 630 } | |
| 631 ~SkAutoRestorePaintTextSizeAndFrame() | |
| 632 { | |
| 633 fPaint->setStyle(fStyle); | |
| 634 fPaint->setTextSize(fTextSize); | |
| 635 } | |
| 636 | |
| 637 private: | |
| 638 SkPaint* fPaint; | |
| 639 SkScalar fTextSize; | |
| 640 SkPaint::Style fStyle; | |
| 641 }; | |
| 642 | |
| 643 static void set_bounds(const SkGlyph& g, SkRect* bounds) | |
| 644 { | |
| 645 bounds->set(SkIntToScalar(g.fLeft), | |
| 646 SkIntToScalar(g.fTop), | |
| 647 SkIntToScalar(g.fLeft + g.fWidth), | |
| 648 SkIntToScalar(g.fTop + g.fHeight)); | |
| 649 } | |
| 650 | |
| 651 static void join_bounds(const SkGlyph& g, SkRect* bounds, SkFixed dx) | |
| 652 { | |
| 653 SkScalar sx = SkFixedToScalar(dx); | |
| 654 bounds->join(SkIntToScalar(g.fLeft) + sx, | |
| 655 SkIntToScalar(g.fTop), | |
| 656 SkIntToScalar(g.fLeft + g.fWidth) + sx, | |
| 657 SkIntToScalar(g.fTop + g.fHeight)); | |
| 658 } | |
| 659 | |
| 660 SkScalar SkPaint::measure_text(SkGlyphCache* cache, | |
| 661 const char* text, size_t byteLength, | |
| 662 int* count, SkRect* bounds) const | |
| 663 { | |
| 664 SkASSERT(count); | |
| 665 if (byteLength == 0) | |
| 666 { | |
| 667 *count = 0; | |
| 668 if (bounds) | |
| 669 bounds->setEmpty(); | |
| 670 return 0; | |
| 671 } | |
| 672 | |
| 673 SkMeasureCacheProc glyphCacheProc; | |
| 674 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, | |
| 675 NULL != bounds); | |
| 676 | |
| 677 int n = 1; | |
| 678 const char* stop = (const char*)text + byteLength; | |
| 679 const SkGlyph* g = &glyphCacheProc(cache, &text); | |
| 680 SkFixed x = g->fAdvanceX; | |
| 681 | |
| 682 SkAutoKern autokern; | |
| 683 | |
| 684 if (NULL == bounds) | |
| 685 { | |
| 686 if (this->isDevKernText()) | |
| 687 { | |
| 688 int rsb; | |
| 689 for (; text < stop; n++) { | |
| 690 rsb = g->fRsbDelta; | |
| 691 g = &glyphCacheProc(cache, &text); | |
| 692 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX; | |
| 693 } | |
| 694 } | |
| 695 else | |
| 696 { | |
| 697 for (; text < stop; n++) { | |
| 698 x += glyphCacheProc(cache, &text).fAdvanceX; | |
| 699 } | |
| 700 } | |
| 701 } | |
| 702 else | |
| 703 { | |
| 704 set_bounds(*g, bounds); | |
| 705 if (this->isDevKernText()) | |
| 706 { | |
| 707 int rsb; | |
| 708 for (; text < stop; n++) { | |
| 709 rsb = g->fRsbDelta; | |
| 710 g = &glyphCacheProc(cache, &text); | |
| 711 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta); | |
| 712 join_bounds(*g, bounds, x); | |
| 713 x += g->fAdvanceX; | |
| 714 } | |
| 715 } | |
| 716 else | |
| 717 { | |
| 718 for (; text < stop; n++) { | |
| 719 g = &glyphCacheProc(cache, &text); | |
| 720 join_bounds(*g, bounds, x); | |
| 721 x += g->fAdvanceX; | |
| 722 } | |
| 723 } | |
| 724 } | |
| 725 SkASSERT(text == stop); | |
| 726 | |
| 727 *count = n; | |
| 728 return SkFixedToScalar(x); | |
| 729 } | |
| 730 | |
| 731 SkScalar SkPaint::measureText(const void* textData, size_t length, | |
| 732 SkRect* bounds, SkScalar zoom) const | |
| 733 { | |
| 734 const char* text = (const char*)textData; | |
| 735 SkASSERT(text != NULL || length == 0); | |
| 736 | |
| 737 SkScalar scale = 0; | |
| 738 SkAutoRestorePaintTextSizeAndFrame restore(this); | |
| 739 | |
| 740 if (this->isLinearText()) | |
| 741 { | |
| 742 scale = fTextSize / kCanonicalTextSizeForPaths; | |
| 743 // this gets restored by restore | |
| 744 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths))
; | |
| 745 } | |
| 746 | |
| 747 SkMatrix zoomMatrix, *zoomPtr = NULL; | |
| 748 if (zoom) | |
| 749 { | |
| 750 zoomMatrix.setScale(zoom, zoom); | |
| 751 zoomPtr = &zoomMatrix; | |
| 752 } | |
| 753 | |
| 754 SkAutoGlyphCache autoCache(*this, zoomPtr); | |
| 755 SkGlyphCache* cache = autoCache.getCache(); | |
| 756 | |
| 757 SkScalar width = 0; | |
| 758 | |
| 759 if (length > 0) | |
| 760 { | |
| 761 int tempCount; | |
| 762 | |
| 763 width = this->measure_text(cache, text, length, &tempCount, bounds); | |
| 764 if (scale) | |
| 765 { | |
| 766 width = SkScalarMul(width, scale); | |
| 767 if (bounds) | |
| 768 { | |
| 769 bounds->fLeft = SkScalarMul(bounds->fLeft, scale); | |
| 770 bounds->fTop = SkScalarMul(bounds->fTop, scale); | |
| 771 bounds->fRight = SkScalarMul(bounds->fRight, scale); | |
| 772 bounds->fBottom = SkScalarMul(bounds->fBottom, scale); | |
| 773 } | |
| 774 } | |
| 775 } | |
| 776 return width; | |
| 777 } | |
| 778 | |
| 779 typedef bool (*SkTextBufferPred)(const char* text, const char* stop); | |
| 780 | |
| 781 static bool forward_textBufferPred(const char* text, const char* stop) | |
| 782 { | |
| 783 return text < stop; | |
| 784 } | |
| 785 | |
| 786 static bool backward_textBufferPred(const char* text, const char* stop) | |
| 787 { | |
| 788 return text > stop; | |
| 789 } | |
| 790 | |
| 791 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd, | |
| 792 const char** text, size_t length, const char** stop) | |
| 793 { | |
| 794 if (SkPaint::kForward_TextBufferDirection == tbd) | |
| 795 { | |
| 796 *stop = *text + length; | |
| 797 return forward_textBufferPred; | |
| 798 } | |
| 799 else | |
| 800 { | |
| 801 // text should point to the end of the buffer, and stop to the beginning | |
| 802 *stop = *text; | |
| 803 *text += length; | |
| 804 return backward_textBufferPred; | |
| 805 } | |
| 806 } | |
| 807 | |
| 808 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, | |
| 809 SkScalar* measuredWidth, | |
| 810 TextBufferDirection tbd) const | |
| 811 { | |
| 812 if (0 == length || 0 >= maxWidth) | |
| 813 { | |
| 814 if (measuredWidth) | |
| 815 *measuredWidth = 0; | |
| 816 return 0; | |
| 817 } | |
| 818 | |
| 819 SkASSERT(textD != NULL); | |
| 820 const char* text = (const char*)textD; | |
| 821 | |
| 822 SkScalar scale = 0; | |
| 823 SkAutoRestorePaintTextSizeAndFrame restore(this); | |
| 824 | |
| 825 if (this->isLinearText()) | |
| 826 { | |
| 827 scale = fTextSize / kCanonicalTextSizeForPaths; | |
| 828 // this gets restored by restore | |
| 829 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths))
; | |
| 830 } | |
| 831 | |
| 832 SkAutoGlyphCache autoCache(*this, NULL); | |
| 833 SkGlyphCache* cache = autoCache.getCache(); | |
| 834 | |
| 835 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); | |
| 836 const char* stop; | |
| 837 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); | |
| 838 SkFixed max = SkScalarToFixed(maxWidth); | |
| 839 SkFixed width = 0; | |
| 840 | |
| 841 SkAutoKern autokern; | |
| 842 | |
| 843 if (this->isDevKernText()) | |
| 844 { | |
| 845 int rsb = 0; | |
| 846 while (pred(text, stop)) | |
| 847 { | |
| 848 const char* curr = text; | |
| 849 const SkGlyph& g = glyphCacheProc(cache, &text); | |
| 850 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX; | |
| 851 if ((width += x) > max) | |
| 852 { | |
| 853 width -= x; | |
| 854 text = curr; | |
| 855 break; | |
| 856 } | |
| 857 rsb = g.fRsbDelta; | |
| 858 } | |
| 859 } | |
| 860 else | |
| 861 { | |
| 862 while (pred(text, stop)) | |
| 863 { | |
| 864 const char* curr = text; | |
| 865 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX; | |
| 866 if ((width += x) > max) | |
| 867 { | |
| 868 width -= x; | |
| 869 text = curr; | |
| 870 break; | |
| 871 } | |
| 872 } | |
| 873 } | |
| 874 | |
| 875 if (measuredWidth) | |
| 876 { | |
| 877 | |
| 878 SkScalar scalarWidth = SkFixedToScalar(width); | |
| 879 if (scale) | |
| 880 scalarWidth = SkScalarMul(scalarWidth, scale); | |
| 881 *measuredWidth = scalarWidth; | |
| 882 } | |
| 883 | |
| 884 // return the number of bytes measured | |
| 885 return (kForward_TextBufferDirection == tbd) ? | |
| 886 text - stop + length : stop - text + length; | |
| 887 } | |
| 888 | |
| 889 /////////////////////////////////////////////////////////////////////////////// | |
| 890 | |
| 891 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) | |
| 892 { | |
| 893 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY(); | |
| 894 return false; // don't detach the cache | |
| 895 } | |
| 896 | |
| 897 static void FontMetricsDescProc(const SkDescriptor* desc, void* context) | |
| 898 { | |
| 899 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context); | |
| 900 } | |
| 901 | |
| 902 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const | |
| 903 { | |
| 904 SkScalar scale = 0; | |
| 905 SkAutoRestorePaintTextSizeAndFrame restore(this); | |
| 906 | |
| 907 if (this->isLinearText()) | |
| 908 { | |
| 909 scale = fTextSize / kCanonicalTextSizeForPaths; | |
| 910 // this gets restored by restore | |
| 911 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths))
; | |
| 912 } | |
| 913 | |
| 914 SkMatrix zoomMatrix, *zoomPtr = NULL; | |
| 915 if (zoom) | |
| 916 { | |
| 917 zoomMatrix.setScale(zoom, zoom); | |
| 918 zoomPtr = &zoomMatrix; | |
| 919 } | |
| 920 | |
| 921 #if 0 | |
| 922 SkAutoGlyphCache autoCache(*this, zoomPtr); | |
| 923 SkGlyphCache* cache = autoCache.getCache(); | |
| 924 const FontMetrics& my = cache->getFontMetricsY(); | |
| 925 #endif | |
| 926 FontMetrics storage; | |
| 927 if (NULL == metrics) | |
| 928 metrics = &storage; | |
| 929 | |
| 930 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics); | |
| 931 | |
| 932 if (scale) | |
| 933 { | |
| 934 metrics->fTop = SkScalarMul(metrics->fTop, scale); | |
| 935 metrics->fAscent = SkScalarMul(metrics->fAscent, scale); | |
| 936 metrics->fDescent = SkScalarMul(metrics->fDescent, scale); | |
| 937 metrics->fBottom = SkScalarMul(metrics->fBottom, scale); | |
| 938 metrics->fLeading = SkScalarMul(metrics->fLeading, scale); | |
| 939 } | |
| 940 return metrics->fDescent - metrics->fAscent + metrics->fLeading; | |
| 941 } | |
| 942 | |
| 943 ////////////////////////////////////////////////////////////////////////////////
//////////// | |
| 944 | |
| 945 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) | |
| 946 { | |
| 947 bounds->set(g.fLeft * scale, | |
| 948 g.fTop * scale, | |
| 949 (g.fLeft + g.fWidth) * scale, | |
| 950 (g.fTop + g.fHeight) * scale); | |
| 951 } | |
| 952 | |
| 953 int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar wid
ths[], | |
| 954 SkRect bounds[]) const | |
| 955 { | |
| 956 if (0 == byteLength) | |
| 957 return 0; | |
| 958 | |
| 959 SkASSERT(NULL != textData); | |
| 960 | |
| 961 if (NULL == widths && NULL == bounds) | |
| 962 return this->countText(textData, byteLength); | |
| 963 | |
| 964 SkAutoRestorePaintTextSizeAndFrame restore(this); | |
| 965 SkScalar scale = 0; | |
| 966 | |
| 967 if (this->isLinearText()) | |
| 968 { | |
| 969 scale = fTextSize / kCanonicalTextSizeForPaths; | |
| 970 // this gets restored by restore | |
| 971 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths))
; | |
| 972 } | |
| 973 | |
| 974 SkAutoGlyphCache autoCache(*this, NULL); | |
| 975 SkGlyphCache* cache = autoCache.getCache(); | |
| 976 SkMeasureCacheProc glyphCacheProc; | |
| 977 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, | |
| 978 NULL != bounds); | |
| 979 | |
| 980 const char* text = (const char*)textData; | |
| 981 const char* stop = text + byteLength; | |
| 982 int count = 0; | |
| 983 | |
| 984 if (this->isDevKernText()) | |
| 985 { | |
| 986 // we adjust the widths returned here through auto-kerning | |
| 987 SkAutoKern autokern; | |
| 988 SkFixed prevWidth = 0; | |
| 989 | |
| 990 if (scale) { | |
| 991 while (text < stop) { | |
| 992 const SkGlyph& g = glyphCacheProc(cache, &text); | |
| 993 if (widths) { | |
| 994 SkFixed adjust = autokern.adjust(g); | |
| 995 | |
| 996 if (count > 0) { | |
| 997 SkScalar w = SkFixedToScalar(prevWidth + adjust); | |
| 998 *widths++ = SkScalarMul(w, scale); | |
| 999 } | |
| 1000 prevWidth = g.fAdvanceX; | |
| 1001 } | |
| 1002 if (bounds) { | |
| 1003 set_bounds(g, bounds++, scale); | |
| 1004 } | |
| 1005 ++count; | |
| 1006 } | |
| 1007 if (count > 0 && widths) { | |
| 1008 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale); | |
| 1009 } | |
| 1010 } else { | |
| 1011 while (text < stop) { | |
| 1012 const SkGlyph& g = glyphCacheProc(cache, &text); | |
| 1013 if (widths) { | |
| 1014 SkFixed adjust = autokern.adjust(g); | |
| 1015 | |
| 1016 if (count > 0) { | |
| 1017 *widths++ = SkFixedToScalar(prevWidth + adjust); | |
| 1018 } | |
| 1019 prevWidth = g.fAdvanceX; | |
| 1020 } | |
| 1021 if (bounds) { | |
| 1022 set_bounds(g, bounds++); | |
| 1023 } | |
| 1024 ++count; | |
| 1025 } | |
| 1026 if (count > 0 && widths) { | |
| 1027 *widths = SkFixedToScalar(prevWidth); | |
| 1028 } | |
| 1029 } | |
| 1030 } else { // no devkern | |
| 1031 if (scale) { | |
| 1032 while (text < stop) { | |
| 1033 const SkGlyph& g = glyphCacheProc(cache, &text); | |
| 1034 if (widths) { | |
| 1035 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX), | |
| 1036 scale); | |
| 1037 } | |
| 1038 if (bounds) { | |
| 1039 set_bounds(g, bounds++, scale); | |
| 1040 } | |
| 1041 ++count; | |
| 1042 } | |
| 1043 } else { | |
| 1044 while (text < stop) { | |
| 1045 const SkGlyph& g = glyphCacheProc(cache, &text); | |
| 1046 if (widths) { | |
| 1047 *widths++ = SkFixedToScalar(g.fAdvanceX); | |
| 1048 } | |
| 1049 if (bounds) { | |
| 1050 set_bounds(g, bounds++); | |
| 1051 } | |
| 1052 ++count; | |
| 1053 } | |
| 1054 } | |
| 1055 } | |
| 1056 | |
| 1057 SkASSERT(text == stop); | |
| 1058 return count; | |
| 1059 } | |
| 1060 | |
| 1061 ////////////////////////////////////////////////////////////////////////////////
//////////// | |
| 1062 | |
| 1063 #include "SkDraw.h" | |
| 1064 | |
| 1065 void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkSca
lar y, SkPath* path) const | |
| 1066 { | |
| 1067 const char* text = (const char*)textData; | |
| 1068 SkASSERT(length == 0 || text != NULL); | |
| 1069 if (text == NULL || length == 0 || path == NULL) | |
| 1070 return; | |
| 1071 | |
| 1072 SkTextToPathIter iter(text, length, *this, false, true); | |
| 1073 SkMatrix matrix; | |
| 1074 SkScalar prevXPos = 0; | |
| 1075 | |
| 1076 matrix.setScale(iter.getPathScale(), iter.getPathScale()); | |
| 1077 matrix.postTranslate(x, y); | |
| 1078 path->reset(); | |
| 1079 | |
| 1080 SkScalar xpos; | |
| 1081 const SkPath* iterPath; | |
| 1082 while ((iterPath = iter.next(&xpos)) != NULL) | |
| 1083 { | |
| 1084 matrix.postTranslate(xpos - prevXPos, 0); | |
| 1085 path->addPath(*iterPath, matrix); | |
| 1086 prevXPos = xpos; | |
| 1087 } | |
| 1088 } | |
| 1089 | |
| 1090 static void add_flattenable(SkDescriptor* desc, uint32_t tag, | |
| 1091 SkFlattenableWriteBuffer* buffer) { | |
| 1092 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL)); | |
| 1093 } | |
| 1094 | |
| 1095 /* | |
| 1096 * interpolates to find the right value for key, in the function represented by
the 'length' number of pairs: (keys[i], values[i]) | |
| 1097 inspired by a desire to change the multiplier for thickness in fakebold | |
| 1098 therefore, i assumed number of pairs (length) will be small, so a linear sea
rch is sufficient | |
| 1099 repeated keys are allowed for discontinuous functions (so long as keys is mo
notonically increasing), and if | |
| 1100 key is the value of a repeated scalar in keys, the first one will be use
d | |
| 1101 - this may change if a binary search is used | |
| 1102 - also, this ensures that there is no divide by zero (an assert also checks
for that) | |
| 1103 */ | |
| 1104 static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar
values[], int length) | |
| 1105 { | |
| 1106 | |
| 1107 SkASSERT(length > 0); | |
| 1108 SkASSERT(keys != NULL); | |
| 1109 SkASSERT(values != NULL); | |
| 1110 #ifdef SK_DEBUG | |
| 1111 for (int i = 1; i < length; i++) | |
| 1112 SkASSERT(keys[i] >= keys[i-1]); | |
| 1113 #endif | |
| 1114 int right = 0; | |
| 1115 while (right < length && key > keys[right]) | |
| 1116 right++; | |
| 1117 //could use sentinal values to eliminate conditionals | |
| 1118 //i assume i am not in control of input values, so i want to make it simple | |
| 1119 if (length == right) | |
| 1120 return values[length-1]; | |
| 1121 if (0 == right) | |
| 1122 return values[0]; | |
| 1123 //otherwise, we interpolate between right-1 and right | |
| 1124 SkScalar rVal = values[right]; | |
| 1125 SkScalar lVal = values[right-1]; | |
| 1126 SkScalar rightKey = keys[right]; | |
| 1127 SkScalar leftKey = keys[right-1]; | |
| 1128 SkASSERT(rightKey != leftKey); | |
| 1129 //fractional amount which we will multiply by the difference in the left val
ue and right value | |
| 1130 SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey); | |
| 1131 return lVal + SkScalarMul(fract, rVal-lVal); | |
| 1132 } | |
| 1133 | |
| 1134 //used for interpolating in fakeBold | |
| 1135 static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) }; | |
| 1136 static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 }; | |
| 1137 | |
| 1138 static SkMask::Format computeMaskFormat(const SkPaint& paint) | |
| 1139 { | |
| 1140 uint32_t flags = paint.getFlags(); | |
| 1141 | |
| 1142 return (flags & SkPaint::kAntiAlias_Flag) ? SkMask::kA8_Format : SkMask::kBW
_Format; | |
| 1143 } | |
| 1144 | |
| 1145 static SkScalerContext::Hints computeScalerHints(const SkPaint& paint) | |
| 1146 { | |
| 1147 uint32_t flags = paint.getFlags(); | |
| 1148 | |
| 1149 if (flags & SkPaint::kLinearText_Flag) | |
| 1150 return SkScalerContext::kNo_Hints; | |
| 1151 else if (flags & SkPaint::kSubpixelText_Flag) | |
| 1152 return SkScalerContext::kSubpixel_Hints; | |
| 1153 else | |
| 1154 return SkScalerContext::kNormal_Hints; | |
| 1155 } | |
| 1156 | |
| 1157 void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix
, Rec* rec) | |
| 1158 { | |
| 1159 SkASSERT(deviceMatrix == NULL || (deviceMatrix->getType() & SkMatrix::kPersp
ective_Mask) == 0); | |
| 1160 | |
| 1161 rec->fFontID = SkTypeface::UniqueID(paint.getTypeface()); | |
| 1162 rec->fTextSize = paint.getTextSize(); | |
| 1163 rec->fPreScaleX = paint.getTextScaleX(); | |
| 1164 rec->fPreSkewX = paint.getTextSkewX(); | |
| 1165 | |
| 1166 if (deviceMatrix) | |
| 1167 { | |
| 1168 rec->fPost2x2[0][0] = deviceMatrix->getScaleX(); | |
| 1169 rec->fPost2x2[0][1] = deviceMatrix->getSkewX(); | |
| 1170 rec->fPost2x2[1][0] = deviceMatrix->getSkewY(); | |
| 1171 rec->fPost2x2[1][1] = deviceMatrix->getScaleY(); | |
| 1172 } | |
| 1173 else | |
| 1174 { | |
| 1175 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1; | |
| 1176 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0; | |
| 1177 } | |
| 1178 | |
| 1179 SkPaint::Style style = paint.getStyle(); | |
| 1180 SkScalar strokeWidth = paint.getStrokeWidth(); | |
| 1181 | |
| 1182 if (paint.isFakeBoldText()) | |
| 1183 { | |
| 1184 SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, mu
ltipliers, 2); | |
| 1185 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale); | |
| 1186 | |
| 1187 if (style == SkPaint::kFill_Style) | |
| 1188 { | |
| 1189 style = SkPaint::kStrokeAndFill_Style; | |
| 1190 strokeWidth = extra; // ignore paint's strokeWidth if it was "fil
l" | |
| 1191 } | |
| 1192 else | |
| 1193 strokeWidth += extra; | |
| 1194 } | |
| 1195 | |
| 1196 unsigned flags = SkFontHost::ComputeGammaFlag(paint); | |
| 1197 | |
| 1198 if (paint.isDevKernText()) | |
| 1199 flags |= SkScalerContext::kDevKernText_Flag; | |
| 1200 | |
| 1201 if (style != SkPaint::kFill_Style && strokeWidth > 0) | |
| 1202 { | |
| 1203 rec->fFrameWidth = strokeWidth; | |
| 1204 rec->fMiterLimit = paint.getStrokeMiter(); | |
| 1205 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin()); | |
| 1206 | |
| 1207 if (style == SkPaint::kStrokeAndFill_Style) | |
| 1208 flags |= SkScalerContext::kFrameAndFill_Flag; | |
| 1209 } | |
| 1210 else | |
| 1211 { | |
| 1212 rec->fFrameWidth = 0; | |
| 1213 rec->fMiterLimit = 0; | |
| 1214 rec->fStrokeJoin = 0; | |
| 1215 } | |
| 1216 | |
| 1217 rec->fHints = SkToU8(computeScalerHints(paint)); | |
| 1218 rec->fMaskFormat = SkToU8(computeMaskFormat(paint)); | |
| 1219 rec->fFlags = SkToU8(flags); | |
| 1220 } | |
| 1221 | |
| 1222 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024 | |
| 1223 | |
| 1224 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, | |
| 1225 void (*proc)(const SkDescriptor*, void*), | |
| 1226 void* context) const | |
| 1227 { | |
| 1228 SkScalerContext::Rec rec; | |
| 1229 | |
| 1230 SkScalerContext::MakeRec(*this, deviceMatrix, &rec); | |
| 1231 | |
| 1232 size_t descSize = sizeof(rec); | |
| 1233 int entryCount = 1; | |
| 1234 SkPathEffect* pe = this->getPathEffect(); | |
| 1235 SkMaskFilter* mf = this->getMaskFilter(); | |
| 1236 SkRasterizer* ra = this->getRasterizer(); | |
| 1237 | |
| 1238 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); | |
| 1239 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); | |
| 1240 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER); | |
| 1241 | |
| 1242 if (pe) { | |
| 1243 peBuffer.writeFlattenable(pe); | |
| 1244 descSize += peBuffer.size(); | |
| 1245 entryCount += 1; | |
| 1246 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do
the scan conversion | |
| 1247 // seems like we could support kLCD as well at this point... | |
| 1248 } | |
| 1249 if (mf) { | |
| 1250 mfBuffer.writeFlattenable(mf); | |
| 1251 descSize += mfBuffer.size(); | |
| 1252 entryCount += 1; | |
| 1253 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskf
ilters | |
| 1254 } | |
| 1255 if (ra) { | |
| 1256 raBuffer.writeFlattenable(ra); | |
| 1257 descSize += raBuffer.size(); | |
| 1258 entryCount += 1; | |
| 1259 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do
the scan conversion | |
| 1260 } | |
| 1261 descSize += SkDescriptor::ComputeOverhead(entryCount); | |
| 1262 | |
| 1263 SkAutoDescriptor ad(descSize); | |
| 1264 SkDescriptor* desc = ad.getDesc(); | |
| 1265 | |
| 1266 desc->init(); | |
| 1267 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); | |
| 1268 | |
| 1269 if (pe) { | |
| 1270 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); | |
| 1271 } | |
| 1272 if (mf) { | |
| 1273 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer); | |
| 1274 } | |
| 1275 if (ra) { | |
| 1276 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer); | |
| 1277 } | |
| 1278 | |
| 1279 SkASSERT(descSize == desc->getLength()); | |
| 1280 desc->computeChecksum(); | |
| 1281 | |
| 1282 proc(desc, context); | |
| 1283 } | |
| 1284 | |
| 1285 static void DetachDescProc(const SkDescriptor* desc, void* context) | |
| 1286 { | |
| 1287 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); | |
| 1288 } | |
| 1289 | |
| 1290 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const | |
| 1291 { | |
| 1292 SkGlyphCache* cache; | |
| 1293 this->descriptorProc(deviceMatrix, DetachDescProc, &cache); | |
| 1294 return cache; | |
| 1295 } | |
| 1296 | |
| 1297 /////////////////////////////////////////////////////////////////////////////// | |
| 1298 | |
| 1299 #include "SkStream.h" | |
| 1300 | |
| 1301 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { | |
| 1302 buffer.writeTypeface(this->getTypeface()); | |
| 1303 buffer.writeScalar(this->getTextSize()); | |
| 1304 buffer.writeScalar(this->getTextScaleX()); | |
| 1305 buffer.writeScalar(this->getTextSkewX()); | |
| 1306 buffer.writeFlattenable(this->getPathEffect()); | |
| 1307 buffer.writeFlattenable(this->getShader()); | |
| 1308 buffer.writeFlattenable(this->getXfermode()); | |
| 1309 buffer.writeFlattenable(this->getMaskFilter()); | |
| 1310 buffer.writeFlattenable(this->getColorFilter()); | |
| 1311 buffer.writeFlattenable(this->getRasterizer()); | |
| 1312 buffer.writeFlattenable(this->getLooper()); | |
| 1313 buffer.write32(this->getColor()); | |
| 1314 buffer.writeScalar(this->getStrokeWidth()); | |
| 1315 buffer.writeScalar(this->getStrokeMiter()); | |
| 1316 buffer.write16(this->getFlags()); | |
| 1317 buffer.write8(this->getTextAlign()); | |
| 1318 buffer.write8(this->getStrokeCap()); | |
| 1319 buffer.write8(this->getStrokeJoin()); | |
| 1320 buffer.write8(this->getStyle()); | |
| 1321 buffer.write8(this->getTextEncoding()); | |
| 1322 } | |
| 1323 | |
| 1324 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { | |
| 1325 this->setTypeface(buffer.readTypeface()); | |
| 1326 this->setTextSize(buffer.readScalar()); | |
| 1327 this->setTextScaleX(buffer.readScalar()); | |
| 1328 this->setTextSkewX(buffer.readScalar()); | |
| 1329 this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref(); | |
| 1330 this->setShader((SkShader*) buffer.readFlattenable())->safeUnref(); | |
| 1331 this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref(); | |
| 1332 this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref(); | |
| 1333 this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref()
; | |
| 1334 this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref(); | |
| 1335 this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref(); | |
| 1336 this->setColor(buffer.readU32()); | |
| 1337 this->setStrokeWidth(buffer.readScalar()); | |
| 1338 this->setStrokeMiter(buffer.readScalar()); | |
| 1339 this->setFlags(buffer.readU16()); | |
| 1340 this->setTextAlign((SkPaint::Align) buffer.readU8()); | |
| 1341 this->setStrokeCap((SkPaint::Cap) buffer.readU8()); | |
| 1342 this->setStrokeJoin((SkPaint::Join) buffer.readU8()); | |
| 1343 this->setStyle((SkPaint::Style) buffer.readU8()); | |
| 1344 this->setTextEncoding((SkPaint::TextEncoding) buffer.readU8()); | |
| 1345 } | |
| 1346 | |
| 1347 /////////////////////////////////////////////////////////////////////////////// | |
| 1348 | |
| 1349 SkShader* SkPaint::setShader(SkShader* shader) | |
| 1350 { | |
| 1351 SkRefCnt_SafeAssign(fShader, shader); | |
| 1352 return shader; | |
| 1353 } | |
| 1354 | |
| 1355 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) | |
| 1356 { | |
| 1357 SkRefCnt_SafeAssign(fColorFilter, filter); | |
| 1358 return filter; | |
| 1359 } | |
| 1360 | |
| 1361 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) | |
| 1362 { | |
| 1363 SkRefCnt_SafeAssign(fXfermode, mode); | |
| 1364 return mode; | |
| 1365 } | |
| 1366 | |
| 1367 SkXfermode* SkPaint::setPorterDuffXfermode(SkPorterDuff::Mode mode) | |
| 1368 { | |
| 1369 fXfermode->safeUnref(); | |
| 1370 fXfermode = SkPorterDuff::CreateXfermode(mode); | |
| 1371 return fXfermode; | |
| 1372 } | |
| 1373 | |
| 1374 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) | |
| 1375 { | |
| 1376 SkRefCnt_SafeAssign(fPathEffect, effect); | |
| 1377 return effect; | |
| 1378 } | |
| 1379 | |
| 1380 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) | |
| 1381 { | |
| 1382 SkRefCnt_SafeAssign(fMaskFilter, filter); | |
| 1383 return filter; | |
| 1384 } | |
| 1385 | |
| 1386 ////////////////////////////////////////////////////////////////////////////////
//////// | |
| 1387 | |
| 1388 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const | |
| 1389 { | |
| 1390 SkPath effectPath, strokePath; | |
| 1391 const SkPath* path = &src; | |
| 1392 | |
| 1393 SkScalar width = this->getStrokeWidth(); | |
| 1394 | |
| 1395 switch (this->getStyle()) { | |
| 1396 case SkPaint::kFill_Style: | |
| 1397 width = -1; // mark it as no-stroke | |
| 1398 break; | |
| 1399 case SkPaint::kStrokeAndFill_Style: | |
| 1400 if (width == 0) | |
| 1401 width = -1; // mark it as no-stroke | |
| 1402 break; | |
| 1403 case SkPaint::kStroke_Style: | |
| 1404 break; | |
| 1405 default: | |
| 1406 SkASSERT(!"unknown paint style"); | |
| 1407 } | |
| 1408 | |
| 1409 if (this->getPathEffect()) | |
| 1410 { | |
| 1411 // lie to the pathEffect if our style is strokeandfill, so that it treat
s us as just fill | |
| 1412 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) | |
| 1413 width = -1; // mark it as no-stroke | |
| 1414 | |
| 1415 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) | |
| 1416 path = &effectPath; | |
| 1417 | |
| 1418 // restore the width if we earlier had to lie, and if we're still set to
no-stroke | |
| 1419 // note: if we're now stroke (width >= 0), then the pathEffect asked for
that change | |
| 1420 // and we want to respect that (i.e. don't overwrite their setting for w
idth) | |
| 1421 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) | |
| 1422 { | |
| 1423 width = this->getStrokeWidth(); | |
| 1424 if (width == 0) | |
| 1425 width = -1; | |
| 1426 } | |
| 1427 } | |
| 1428 | |
| 1429 if (width > 0 && !path->isEmpty()) | |
| 1430 { | |
| 1431 SkStroke stroker(*this, width); | |
| 1432 stroker.strokePath(*path, &strokePath); | |
| 1433 path = &strokePath; | |
| 1434 } | |
| 1435 | |
| 1436 if (path == &src) | |
| 1437 *dst = src; | |
| 1438 else | |
| 1439 { | |
| 1440 SkASSERT(path == &effectPath || path == &strokePath); | |
| 1441 dst->swap(*(SkPath*)path); | |
| 1442 } | |
| 1443 | |
| 1444 return width != 0; // return true if we're filled, or false if we're hairli
ne (width == 0) | |
| 1445 } | |
| 1446 | |
| 1447 bool SkPaint::canComputeFastBounds() const { | |
| 1448 // use bit-or since no need for early exit | |
| 1449 return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) | | |
| 1450 reinterpret_cast<uintptr_t>(this->getLooper()) | | |
| 1451 reinterpret_cast<uintptr_t>(this->getRasterizer()) | | |
| 1452 reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0; | |
| 1453 } | |
| 1454 | |
| 1455 const SkRect& SkPaint::computeFastBounds(const SkRect& src, | |
| 1456 SkRect* storage) const { | |
| 1457 SkASSERT(storage); | |
| 1458 | |
| 1459 if (this->getStyle() != SkPaint::kFill_Style) { | |
| 1460 // if we're stroked, outset the rect by the radius (and join type) | |
| 1461 SkScalar radius = SkScalarHalf(this->getStrokeWidth()); | |
| 1462 | |
| 1463 if (0 == radius) { // hairline | |
| 1464 radius = SK_Scalar1; | |
| 1465 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) { | |
| 1466 SkScalar scale = this->getStrokeMiter(); | |
| 1467 if (scale > SK_Scalar1) { | |
| 1468 radius = SkScalarMul(radius, scale); | |
| 1469 } | |
| 1470 } | |
| 1471 storage->set(src.fLeft - radius, src.fTop - radius, | |
| 1472 src.fRight + radius, src.fBottom + radius); | |
| 1473 return *storage; | |
| 1474 } | |
| 1475 // no adjustments needed, just return the original rect | |
| 1476 return src; | |
| 1477 } | |
| 1478 | |
| 1479 ////////////////////////////////////////////////////////////////////////////////
//////// | |
| 1480 | |
| 1481 static bool has_thick_frame(const SkPaint& paint) | |
| 1482 { | |
| 1483 return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Styl
e; | |
| 1484 } | |
| 1485 | |
| 1486 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length, | |
| 1487 const SkPaint& paint, | |
| 1488 bool applyStrokeAndPathEffects, | |
| 1489 bool forceLinearTextOn) | |
| 1490 : fPaint(paint) /* make a copy of the paint
*/ | |
| 1491 { | |
| 1492 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDire
ction, | |
| 1493 true); | |
| 1494 | |
| 1495 if (forceLinearTextOn) | |
| 1496 fPaint.setLinearText(true); | |
| 1497 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lo
okup | |
| 1498 | |
| 1499 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) | |
| 1500 applyStrokeAndPathEffects = false; | |
| 1501 | |
| 1502 // can't use our canonical size if we need to apply patheffects/strokes | |
| 1503 if (fPaint.isLinearText() && !applyStrokeAndPathEffects) | |
| 1504 { | |
| 1505 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)); | |
| 1506 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths; | |
| 1507 } | |
| 1508 else | |
| 1509 fScale = SK_Scalar1; | |
| 1510 | |
| 1511 if (!applyStrokeAndPathEffects) | |
| 1512 { | |
| 1513 fPaint.setStyle(SkPaint::kFill_Style); | |
| 1514 fPaint.setPathEffect(NULL); | |
| 1515 } | |
| 1516 | |
| 1517 fCache = fPaint.detachCache(NULL); | |
| 1518 | |
| 1519 SkPaint::Style style = SkPaint::kFill_Style; | |
| 1520 SkPathEffect* pe = NULL; | |
| 1521 | |
| 1522 if (!applyStrokeAndPathEffects) | |
| 1523 { | |
| 1524 style = paint.getStyle(); // restore | |
| 1525 pe = paint.getPathEffect(); // restore | |
| 1526 } | |
| 1527 fPaint.setStyle(style); | |
| 1528 fPaint.setPathEffect(pe); | |
| 1529 fPaint.setMaskFilter(paint.getMaskFilter()); // restore | |
| 1530 | |
| 1531 // now compute fXOffset if needed | |
| 1532 | |
| 1533 SkScalar xOffset = 0; | |
| 1534 if (paint.getTextAlign() != SkPaint::kLeft_Align) // need to measure first | |
| 1535 { | |
| 1536 int count; | |
| 1537 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &
count, NULL), fScale); | |
| 1538 if (paint.getTextAlign() == SkPaint::kCenter_Align) | |
| 1539 width = SkScalarHalf(width); | |
| 1540 xOffset = -width; | |
| 1541 } | |
| 1542 fXPos = xOffset; | |
| 1543 fPrevAdvance = 0; | |
| 1544 | |
| 1545 fText = text; | |
| 1546 fStop = text + length; | |
| 1547 } | |
| 1548 | |
| 1549 SkTextToPathIter::~SkTextToPathIter() | |
| 1550 { | |
| 1551 SkGlyphCache::AttachCache(fCache); | |
| 1552 } | |
| 1553 | |
| 1554 const SkPath* SkTextToPathIter::next(SkScalar* xpos) | |
| 1555 { | |
| 1556 while (fText < fStop) | |
| 1557 { | |
| 1558 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText); | |
| 1559 | |
| 1560 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(gly
ph)), fScale); | |
| 1561 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking(); | |
| 1562 | |
| 1563 if (glyph.fWidth) | |
| 1564 { | |
| 1565 if (xpos) | |
| 1566 *xpos = fXPos; | |
| 1567 return fCache->findPath(glyph); | |
| 1568 } | |
| 1569 } | |
| 1570 return NULL; | |
| 1571 } | |
| OLD | NEW |