1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkScalerContext.h" 11#include "SkColorPriv.h" 12#include "SkDescriptor.h" 13#include "SkDraw.h" 14#include "SkFontHost.h" 15#include "SkGlyph.h" 16#include "SkMaskFilter.h" 17#include "SkMaskGamma.h" 18#include "SkOrderedReadBuffer.h" 19#include "SkPathEffect.h" 20#include "SkRasterizer.h" 21#include "SkRasterClip.h" 22#include "SkStroke.h" 23#include "SkThread.h" 24 25 26#define ComputeBWRowBytes(width) (((unsigned)(width) + 7) >> 3) 27 28void SkGlyph::toMask(SkMask* mask) const { 29 SkASSERT(mask); 30 31 mask->fImage = (uint8_t*)fImage; 32 mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight); 33 mask->fRowBytes = this->rowBytes(); 34 mask->fFormat = static_cast<SkMask::Format>(fMaskFormat); 35} 36 37size_t SkGlyph::computeImageSize() const { 38 const size_t size = this->rowBytes() * fHeight; 39 40 switch (fMaskFormat) { 41 case SkMask::k3D_Format: 42 return 3 * size; 43 default: 44 return size; 45 } 46} 47 48void SkGlyph::zeroMetrics() { 49 fAdvanceX = 0; 50 fAdvanceY = 0; 51 fWidth = 0; 52 fHeight = 0; 53 fTop = 0; 54 fLeft = 0; 55 fRsbDelta = 0; 56 fLsbDelta = 0; 57} 58 59/////////////////////////////////////////////////////////////////////////////// 60 61#ifdef SK_DEBUG 62 #define DUMP_RECx 63#endif 64 65static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) { 66 SkFlattenable* obj = NULL; 67 uint32_t len; 68 const void* data = desc->findEntry(tag, &len); 69 70 if (data) { 71 SkOrderedReadBuffer buffer(data, len); 72 obj = buffer.readFlattenable(); 73 SkASSERT(buffer.offset() == buffer.size()); 74 } 75 return obj; 76} 77 78SkScalerContext::SkScalerContext(const SkDescriptor* desc) 79 : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL))) 80 81 , fBaseGlyphCount(0) 82 83 , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_SkDescriptorTag))) 84 , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_SkDescriptorTag))) 85 , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_SkDescriptorTag))) 86 87 // Initialize based on our settings. Subclasses can also force this. 88 , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) 89 90 , fNextContext(NULL) 91 92 , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMaskPreBlend(fRec)) 93 , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec) 94 : SkMaskGamma::PreBlend()) 95{ 96#ifdef DUMP_REC 97 desc->assertChecksum(); 98 SkDebugf("SkScalarContext checksum %x count %d length %d\n", 99 desc->getChecksum(), desc->getCount(), desc->getLength()); 100 SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n", 101 rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0], 102 rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]); 103 SkDebugf(" frame %g miter %g hints %d framefill %d format %d join %d\n", 104 rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill, 105 rec->fMaskFormat, rec->fStrokeJoin); 106 SkDebugf(" pathEffect %x maskFilter %x\n", 107 desc->findEntry(kPathEffect_SkDescriptorTag, NULL), 108 desc->findEntry(kMaskFilter_SkDescriptorTag, NULL)); 109#endif 110} 111 112SkScalerContext::~SkScalerContext() { 113 SkDELETE(fNextContext); 114 115 SkSafeUnref(fPathEffect); 116 SkSafeUnref(fMaskFilter); 117 SkSafeUnref(fRasterizer); 118} 119 120static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) { 121 // fonthost will determine the next possible font to search, based 122 // on the current font in fRec. It will return NULL if ctx is our 123 // last font that can be searched (i.e. ultimate fallback font) 124#ifdef SK_BUILD_FOR_ANDROID 125 // On Android, pass entire rec structure so that clients can change fallback behavior 126 uint32_t newFontID = SkFontHost::NextLogicalFont(rec); 127#else 128 uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID); 129#endif 130 131 if (0 == newFontID) { 132 return NULL; 133 } 134 135 SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1)); 136 SkDescriptor* desc = ad.getDesc(); 137 138 desc->init(); 139 SkScalerContext::Rec* newRec = 140 (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, 141 sizeof(rec), &rec); 142 newRec->fFontID = newFontID; 143 desc->computeChecksum(); 144 145 return SkFontHost::CreateScalerContext(desc); 146} 147 148/* Return the next context, creating it if its not already created, but return 149 NULL if the fonthost says there are no more fonts to fallback to. 150 */ 151SkScalerContext* SkScalerContext::getNextContext() { 152 SkScalerContext* next = fNextContext; 153 // if next is null, then either it isn't cached yet, or we're at the 154 // end of our possible chain 155 if (NULL == next) { 156 next = allocNextContext(fRec); 157 if (NULL == next) { 158 return NULL; 159 } 160 // next's base is our base + our local count 161 next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount()); 162 // cache the answer 163 fNextContext = next; 164 } 165 return next; 166} 167 168SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, unsigned& glyphID) { 169 SkScalerContext* ctx = this; 170 for (;;) { 171 glyphID = ctx->generateCharToGlyph(uni); 172 if (glyphID) { 173 break; // found it 174 } 175 ctx = ctx->getNextContext(); 176 if (NULL == ctx) { 177 return NULL; 178 } 179 } 180 return ctx; 181} 182 183SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) { 184 unsigned glyphID = glyph.getGlyphID(); 185 SkScalerContext* ctx = this; 186 for (;;) { 187 unsigned count = ctx->getGlyphCount(); 188 if (glyphID < count) { 189 break; 190 } 191 glyphID -= count; 192 ctx = ctx->getNextContext(); 193 if (NULL == ctx) { 194// SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID()); 195 // just return the original context (this) 196 return this; 197 } 198 } 199 return ctx; 200} 201 202#ifdef SK_BUILD_FOR_ANDROID 203SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) { 204 unsigned glyphID; 205 SkScalerContext* ctx = getContextFromChar(uni, glyphID); 206 if (ctx) { 207 return ctx->fRec.fFontID; 208 } else { 209 return 0; 210 } 211} 212 213/* This loops through all available fallback contexts (if needed) until it 214 finds some context that can handle the unichar and return it. 215 216 As this is somewhat expensive operation, it should only be done on the first 217 char of a run. 218 */ 219unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) { 220 unsigned glyphID; 221 SkScalerContext* ctx = getContextFromChar(uni, glyphID); 222 if (ctx) { 223 return ctx->fBaseGlyphCount; 224 } else { 225 SkDEBUGF(("--- no context for char %x\n", uni)); 226 return this->fBaseGlyphCount; 227 } 228} 229#endif 230 231/* This loops through all available fallback contexts (if needed) until it 232 finds some context that can handle the unichar. If all fail, returns 0 233 */ 234uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) { 235 236 unsigned glyphID; 237 SkScalerContext* ctx = getContextFromChar(uni, glyphID); 238 if (!ctx) { 239 return 0; // no more contexts, return missing glyph 240 } 241 // add the ctx's base, making glyphID unique for chain of contexts 242 glyphID += ctx->fBaseGlyphCount; 243 // check for overflow of 16bits, since our glyphID cannot exceed that 244 if (glyphID > 0xFFFF) { 245 glyphID = 0; 246 } 247 return SkToU16(glyphID); 248} 249 250SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) { 251 SkScalerContext* ctx = this; 252 unsigned rangeEnd = 0; 253 do { 254 unsigned rangeStart = rangeEnd; 255 256 rangeEnd += ctx->getGlyphCount(); 257 if (rangeStart <= glyphID && glyphID < rangeEnd) { 258 return ctx->generateGlyphToChar(glyphID - rangeStart); 259 } 260 ctx = ctx->getNextContext(); 261 } while (NULL != ctx); 262 return 0; 263} 264 265void SkScalerContext::getAdvance(SkGlyph* glyph) { 266 // mark us as just having a valid advance 267 glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE; 268 // we mark the format before making the call, in case the impl 269 // internally ends up calling its generateMetrics, which is OK 270 // albeit slower than strictly necessary 271 this->getGlyphContext(*glyph)->generateAdvance(glyph); 272} 273 274void SkScalerContext::getMetrics(SkGlyph* glyph) { 275 this->getGlyphContext(*glyph)->generateMetrics(glyph); 276 277 // for now we have separate cache entries for devkerning on and off 278 // in the future we might share caches, but make our measure/draw 279 // code make the distinction. Thus we zap the values if the caller 280 // has not asked for them. 281 if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) { 282 // no devkern, so zap the fields 283 glyph->fLsbDelta = glyph->fRsbDelta = 0; 284 } 285 286 // if either dimension is empty, zap the image bounds of the glyph 287 if (0 == glyph->fWidth || 0 == glyph->fHeight) { 288 glyph->fWidth = 0; 289 glyph->fHeight = 0; 290 glyph->fTop = 0; 291 glyph->fLeft = 0; 292 glyph->fMaskFormat = 0; 293 return; 294 } 295 296 if (fGenerateImageFromPath) { 297 SkPath devPath, fillPath; 298 SkMatrix fillToDevMatrix; 299 300 this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix); 301 302 if (fRasterizer) { 303 SkMask mask; 304 305 if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL, 306 fMaskFilter, &mask, 307 SkMask::kJustComputeBounds_CreateMode)) { 308 glyph->fLeft = mask.fBounds.fLeft; 309 glyph->fTop = mask.fBounds.fTop; 310 glyph->fWidth = SkToU16(mask.fBounds.width()); 311 glyph->fHeight = SkToU16(mask.fBounds.height()); 312 } else { 313 goto SK_ERROR; 314 } 315 } else { 316 // just use devPath 317 SkIRect ir; 318 devPath.getBounds().roundOut(&ir); 319 320 if (ir.isEmpty() || !ir.is16Bit()) { 321 goto SK_ERROR; 322 } 323 glyph->fLeft = ir.fLeft; 324 glyph->fTop = ir.fTop; 325 glyph->fWidth = SkToU16(ir.width()); 326 glyph->fHeight = SkToU16(ir.height()); 327 } 328 } 329 330 if (SkMask::kARGB32_Format != glyph->fMaskFormat) { 331 glyph->fMaskFormat = fRec.fMaskFormat; 332 } 333 334 if (fMaskFilter) { 335 SkMask src, dst; 336 SkMatrix matrix; 337 338 glyph->toMask(&src); 339 fRec.getMatrixFrom2x2(&matrix); 340 341 src.fImage = NULL; // only want the bounds from the filter 342 if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) { 343 if (dst.fBounds.isEmpty() || !dst.fBounds.is16Bit()) { 344 goto SK_ERROR; 345 } 346 SkASSERT(dst.fImage == NULL); 347 glyph->fLeft = dst.fBounds.fLeft; 348 glyph->fTop = dst.fBounds.fTop; 349 glyph->fWidth = SkToU16(dst.fBounds.width()); 350 glyph->fHeight = SkToU16(dst.fBounds.height()); 351 glyph->fMaskFormat = dst.fFormat; 352 } 353 } 354 return; 355 356SK_ERROR: 357 // draw nothing 'cause we failed 358 glyph->fLeft = 0; 359 glyph->fTop = 0; 360 glyph->fWidth = 0; 361 glyph->fHeight = 0; 362 // put a valid value here, in case it was earlier set to 363 // MASK_FORMAT_JUST_ADVANCE 364 glyph->fMaskFormat = fRec.fMaskFormat; 365} 366 367 368static void applyLUTToA8Mask(const SkMask& mask, const uint8_t* lut) { 369 uint8_t* SK_RESTRICT dst = (uint8_t*)mask.fImage; 370 unsigned rowBytes = mask.fRowBytes; 371 372 for (int y = mask.fBounds.height() - 1; y >= 0; --y) { 373 for (int x = mask.fBounds.width() - 1; x >= 0; --x) { 374 dst[x] = lut[dst[x]]; 375 } 376 dst += rowBytes; 377 } 378} 379 380template<bool APPLY_PREBLEND> 381static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst, 382 const SkMaskGamma::PreBlend& maskPreBlend) { 383 SkASSERT(SkBitmap::kA8_Config == src.config()); 384 SkASSERT(SkMask::kLCD16_Format == dst.fFormat); 385 386 const int width = dst.fBounds.width(); 387 const int height = dst.fBounds.height(); 388 uint16_t* dstP = (uint16_t*)dst.fImage; 389 size_t dstRB = dst.fRowBytes; 390 391 for (int y = 0; y < height; ++y) { 392 const uint8_t* srcP = src.getAddr8(0, y); 393 for (int x = 0; x < width; ++x) { 394 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR); 395 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG); 396 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB); 397 dstP[x] = SkPack888ToRGB16(r, g, b); 398 } 399 dstP = (uint16_t*)((char*)dstP + dstRB); 400 } 401} 402 403template<bool APPLY_PREBLEND> 404static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst, 405 const SkMaskGamma::PreBlend& maskPreBlend) { 406 SkASSERT(SkBitmap::kA8_Config == src.config()); 407 SkASSERT(SkMask::kLCD32_Format == dst.fFormat); 408 409 const int width = dst.fBounds.width(); 410 const int height = dst.fBounds.height(); 411 SkPMColor* dstP = (SkPMColor*)dst.fImage; 412 size_t dstRB = dst.fRowBytes; 413 414 for (int y = 0; y < height; ++y) { 415 const uint8_t* srcP = src.getAddr8(0, y); 416 for (int x = 0; x < width; ++x) { 417 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fR); 418 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fG); 419 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*srcP++, maskPreBlend.fB); 420 dstP[x] = SkPackARGB32(0xFF, r, g, b); 421 } 422 dstP = (SkPMColor*)((char*)dstP + dstRB); 423 } 424} 425 426static void generateMask(const SkMask& mask, const SkPath& path, 427 const SkMaskGamma::PreBlend& maskPreBlend) { 428 SkBitmap::Config config; 429 SkPaint paint; 430 431 int srcW = mask.fBounds.width(); 432 int srcH = mask.fBounds.height(); 433 int dstW = srcW; 434 int dstH = srcH; 435 int dstRB = mask.fRowBytes; 436 437 SkMatrix matrix; 438 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 439 -SkIntToScalar(mask.fBounds.fTop)); 440 441 if (SkMask::kBW_Format == mask.fFormat) { 442 config = SkBitmap::kA1_Config; 443 paint.setAntiAlias(false); 444 } else { 445 config = SkBitmap::kA8_Config; 446 paint.setAntiAlias(true); 447 switch (mask.fFormat) { 448 case SkMask::kA8_Format: 449 break; 450 case SkMask::kLCD16_Format: 451 case SkMask::kLCD32_Format: 452 // TODO: trigger off LCD orientation 453 dstW *= 3; 454 matrix.postScale(SkIntToScalar(3), SK_Scalar1); 455 dstRB = 0; // signals we need a copy 456 break; 457 default: 458 SkDEBUGFAIL("unexpected mask format"); 459 } 460 } 461 462 SkRasterClip clip; 463 clip.setRect(SkIRect::MakeWH(dstW, dstH)); 464 465 SkBitmap bm; 466 bm.setConfig(config, dstW, dstH, dstRB); 467 468 if (0 == dstRB) { 469 if (!bm.allocPixels()) { 470 // can't allocate offscreen, so empty the mask and return 471 sk_bzero(mask.fImage, mask.computeImageSize()); 472 return; 473 } 474 bm.lockPixels(); 475 } else { 476 bm.setPixels(mask.fImage); 477 } 478 sk_bzero(bm.getPixels(), bm.getSafeSize()); 479 480 SkDraw draw; 481 draw.fRC = &clip; 482 draw.fClip = &clip.bwRgn(); 483 draw.fMatrix = &matrix; 484 draw.fBitmap = &bm; 485 draw.drawPath(path, paint); 486 487 switch (mask.fFormat) { 488 case SkMask::kA8_Format: 489 if (maskPreBlend.isApplicable()) { 490 applyLUTToA8Mask(mask, maskPreBlend.fG); 491 } 492 break; 493 case SkMask::kLCD16_Format: 494 if (maskPreBlend.isApplicable()) { 495 pack3xHToLCD16<true>(bm, mask, maskPreBlend); 496 } else { 497 pack3xHToLCD16<false>(bm, mask, maskPreBlend); 498 } 499 break; 500 case SkMask::kLCD32_Format: 501 if (maskPreBlend.isApplicable()) { 502 pack3xHToLCD32<true>(bm, mask, maskPreBlend); 503 } else { 504 pack3xHToLCD32<false>(bm, mask, maskPreBlend); 505 } 506 break; 507 default: 508 break; 509 } 510} 511 512void SkScalerContext::getImage(const SkGlyph& origGlyph) { 513 const SkGlyph* glyph = &origGlyph; 514 SkGlyph tmpGlyph; 515 516 if (fMaskFilter) { // restore the prefilter bounds 517 tmpGlyph.init(origGlyph.fID); 518 519 // need the original bounds, sans our maskfilter 520 SkMaskFilter* mf = fMaskFilter; 521 fMaskFilter = NULL; // temp disable 522 this->getMetrics(&tmpGlyph); 523 fMaskFilter = mf; // restore 524 525 tmpGlyph.fImage = origGlyph.fImage; 526 527 // we need the prefilter bounds to be <= filter bounds 528 SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth); 529 SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight); 530 glyph = &tmpGlyph; 531 } 532 533 if (fGenerateImageFromPath) { 534 SkPath devPath, fillPath; 535 SkMatrix fillToDevMatrix; 536 SkMask mask; 537 538 this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix); 539 glyph->toMask(&mask); 540 541 if (fRasterizer) { 542 mask.fFormat = SkMask::kA8_Format; 543 sk_bzero(glyph->fImage, mask.computeImageSize()); 544 545 if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL, 546 fMaskFilter, &mask, 547 SkMask::kJustRenderImage_CreateMode)) { 548 return; 549 } 550 if (fPreBlend.isApplicable()) { 551 applyLUTToA8Mask(mask, fPreBlend.fG); 552 } 553 } else { 554 generateMask(mask, devPath, fPreBlend); 555 } 556 } else { 557 this->getGlyphContext(*glyph)->generateImage(*glyph); 558 } 559 560 if (fMaskFilter) { 561 SkMask srcM, dstM; 562 SkMatrix matrix; 563 564 // the src glyph image shouldn't be 3D 565 SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat); 566 glyph->toMask(&srcM); 567 fRec.getMatrixFrom2x2(&matrix); 568 569 if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) { 570 int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width()); 571 int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height()); 572 int dstRB = origGlyph.rowBytes(); 573 int srcRB = dstM.fRowBytes; 574 575 const uint8_t* src = (const uint8_t*)dstM.fImage; 576 uint8_t* dst = (uint8_t*)origGlyph.fImage; 577 578 if (SkMask::k3D_Format == dstM.fFormat) { 579 // we have to copy 3 times as much 580 height *= 3; 581 } 582 583 // clean out our glyph, since it may be larger than dstM 584 //sk_bzero(dst, height * dstRB); 585 586 while (--height >= 0) { 587 memcpy(dst, src, width); 588 src += srcRB; 589 dst += dstRB; 590 } 591 SkMask::FreeImage(dstM.fImage); 592 593 if (fPreBlendForFilter.isApplicable()) { 594 applyLUTToA8Mask(srcM, fPreBlendForFilter.fG); 595 } 596 } 597 } 598} 599 600void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) { 601 this->internalGetPath(glyph, NULL, path, NULL); 602} 603 604void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, 605 SkPaint::FontMetrics* my) { 606 this->generateFontMetrics(mx, my); 607} 608 609SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) { 610 return 0; 611} 612 613/////////////////////////////////////////////////////////////////////////////// 614 615void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, 616 SkPath* devPath, SkMatrix* fillToDevMatrix) { 617 SkPath path; 618 619 this->getGlyphContext(glyph)->generatePath(glyph, &path); 620 621 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 622 SkFixed dx = glyph.getSubXFixed(); 623 SkFixed dy = glyph.getSubYFixed(); 624 if (dx | dy) { 625 path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy)); 626 } 627 } 628 629 if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { 630 // need the path in user-space, with only the point-size applied 631 // so that our stroking and effects will operate the same way they 632 // would if the user had extracted the path themself, and then 633 // called drawPath 634 SkPath localPath; 635 SkMatrix matrix, inverse; 636 637 fRec.getMatrixFrom2x2(&matrix); 638 if (!matrix.invert(&inverse)) { 639 // assume fillPath and devPath are already empty. 640 return; 641 } 642 path.transform(inverse, &localPath); 643 // now localPath is only affected by the paint settings, and not the canvas matrix 644 645 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); 646 647 if (fRec.fFrameWidth > 0) { 648 rec.setStrokeStyle(fRec.fFrameWidth, 649 SkToBool(fRec.fFlags & kFrameAndFill_Flag)); 650 // glyphs are always closed contours, so cap type is ignored, 651 // so we just pass something. 652 rec.setStrokeParams(SkPaint::kButt_Cap, 653 (SkPaint::Join)fRec.fStrokeJoin, 654 fRec.fMiterLimit); 655 } 656 657 if (fPathEffect) { 658 SkPath effectPath; 659 if (fPathEffect->filterPath(&effectPath, localPath, &rec, NULL)) { 660 localPath.swap(effectPath); 661 } 662 } 663 664 if (rec.needToApply()) { 665 SkPath strokePath; 666 if (rec.applyToPath(&strokePath, localPath)) { 667 localPath.swap(strokePath); 668 } 669 } 670 671 // now return stuff to the caller 672 if (fillToDevMatrix) { 673 *fillToDevMatrix = matrix; 674 } 675 if (devPath) { 676 localPath.transform(matrix, devPath); 677 } 678 if (fillPath) { 679 fillPath->swap(localPath); 680 } 681 } else { // nothing tricky to do 682 if (fillToDevMatrix) { 683 fillToDevMatrix->reset(); 684 } 685 if (devPath) { 686 if (fillPath == NULL) { 687 devPath->swap(path); 688 } else { 689 *devPath = path; 690 } 691 } 692 693 if (fillPath) { 694 fillPath->swap(path); 695 } 696 } 697 698 if (devPath) { 699 devPath->updateBoundsCache(); 700 } 701 if (fillPath) { 702 fillPath->updateBoundsCache(); 703 } 704} 705 706 707void SkScalerContextRec::getMatrixFrom2x2(SkMatrix* dst) const { 708 dst->setAll(fPost2x2[0][0], fPost2x2[0][1], 0, 709 fPost2x2[1][0], fPost2x2[1][1], 0, 710 0, 0, SkScalarToPersp(SK_Scalar1)); 711} 712 713void SkScalerContextRec::getLocalMatrix(SkMatrix* m) const { 714 m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize); 715 if (fPreSkewX) { 716 m->postSkew(fPreSkewX, 0); 717 } 718} 719 720void SkScalerContextRec::getSingleMatrix(SkMatrix* m) const { 721 this->getLocalMatrix(m); 722 723 // now concat the device matrix 724 SkMatrix deviceMatrix; 725 this->getMatrixFrom2x2(&deviceMatrix); 726 m->postConcat(deviceMatrix); 727} 728 729SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) { 730 SkASSERT(!matrix.hasPerspective()); 731 732 if (0 == matrix[SkMatrix::kMSkewY]) { 733 return kX_SkAxisAlignment; 734 } 735 if (0 == matrix[SkMatrix::kMScaleX]) { 736 return kY_SkAxisAlignment; 737 } 738 return kNone_SkAxisAlignment; 739} 740 741/////////////////////////////////////////////////////////////////////////////// 742 743#include "SkFontHost.h" 744 745class SkScalerContext_Empty : public SkScalerContext { 746public: 747 SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {} 748 749protected: 750 virtual unsigned generateGlyphCount() SK_OVERRIDE { 751 return 0; 752 } 753 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE { 754 return 0; 755 } 756 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE { 757 glyph->zeroMetrics(); 758 } 759 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE { 760 glyph->zeroMetrics(); 761 } 762 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE {} 763 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE {} 764 virtual void generateFontMetrics(SkPaint::FontMetrics* mx, 765 SkPaint::FontMetrics* my) SK_OVERRIDE { 766 if (mx) { 767 sk_bzero(mx, sizeof(*mx)); 768 } 769 if (my) { 770 sk_bzero(my, sizeof(*my)); 771 } 772 } 773}; 774 775extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc); 776 777SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) { 778 SkScalerContext* c = NULL; //SkCreateColorScalerContext(desc); 779 if (NULL == c) { 780 c = SkFontHost::CreateScalerContext(desc); 781 } 782 if (NULL == c) { 783 c = SkNEW_ARGS(SkScalerContext_Empty, (desc)); 784 } 785 return c; 786} 787