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