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