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