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