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