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