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