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