1 /* 2 * Copyright 2006-2012 The Android Open Source Project 3 * Copyright 2012 Mozilla Foundation 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 #include "SkBitmap.h" 10 #include "SkCanvas.h" 11 #include "SkColor.h" 12 #include "SkColorData.h" 13 #include "SkFDot6.h" 14 #include "SkFontHost_FreeType_common.h" 15 #include "SkPath.h" 16 17 #include <ft2build.h> 18 #include FT_FREETYPE_H 19 #include FT_BITMAP_H 20 #include FT_IMAGE_H 21 #include FT_OUTLINE_H 22 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 23 #include FT_SYNTHESIS_H 24 25 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 26 // were introduced in FreeType 2.5.0. 27 // The following may be removed once FreeType 2.5.0 is required to build. 28 #ifndef FT_LOAD_COLOR 29 # define FT_LOAD_COLOR ( 1L << 20 ) 30 # define FT_PIXEL_MODE_BGRA 7 31 #endif 32 33 //#define SK_SHOW_TEXT_BLIT_COVERAGE 34 35 #ifdef SK_DEBUG 36 const char* SkTraceFtrGetError(int e) { 37 switch ((FT_Error)e) { 38 #undef FTERRORS_H_ 39 #define FT_ERRORDEF( e, v, s ) case v: return s; 40 #define FT_ERROR_START_LIST 41 #define FT_ERROR_END_LIST 42 #include FT_ERRORS_H 43 #undef FT_ERRORDEF 44 #undef FT_ERROR_START_LIST 45 #undef FT_ERROR_END_LIST 46 default: return ""; 47 } 48 } 49 #endif // SK_DEBUG 50 51 namespace { 52 53 FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { 54 switch (format) { 55 case SkMask::kBW_Format: 56 return FT_PIXEL_MODE_MONO; 57 case SkMask::kA8_Format: 58 default: 59 return FT_PIXEL_MODE_GRAY; 60 } 61 } 62 63 /////////////////////////////////////////////////////////////////////////////// 64 65 uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) { 66 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 67 r = SkTMax(r, (U8CPU)0x40); 68 g = SkTMax(g, (U8CPU)0x40); 69 b = SkTMax(b, (U8CPU)0x40); 70 #endif 71 return SkPack888ToRGB16(r, g, b); 72 } 73 74 uint16_t grayToRGB16(U8CPU gray) { 75 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 76 gray = SkTMax(gray, (U8CPU)0x40); 77 #endif 78 return SkPack888ToRGB16(gray, gray, gray); 79 } 80 81 int bittst(const uint8_t data[], int bitOffset) { 82 SkASSERT(bitOffset >= 0); 83 int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); 84 return lowBit & 1; 85 } 86 87 /** 88 * Copies a FT_Bitmap into an SkMask with the same dimensions. 89 * 90 * FT_PIXEL_MODE_MONO 91 * FT_PIXEL_MODE_GRAY 92 * FT_PIXEL_MODE_LCD 93 * FT_PIXEL_MODE_LCD_V 94 */ 95 template<bool APPLY_PREBLEND> 96 void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR, 97 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) 98 { 99 SkASSERT(SkMask::kLCD16_Format == mask.fFormat); 100 if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) { 101 SkASSERT(mask.fBounds.width() == static_cast<int>(bitmap.width)); 102 } 103 if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) { 104 SkASSERT(mask.fBounds.height() == static_cast<int>(bitmap.rows)); 105 } 106 107 const uint8_t* src = bitmap.buffer; 108 uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage); 109 const size_t dstRB = mask.fRowBytes; 110 111 const int width = mask.fBounds.width(); 112 const int height = mask.fBounds.height(); 113 114 switch (bitmap.pixel_mode) { 115 case FT_PIXEL_MODE_MONO: 116 for (int y = height; y --> 0;) { 117 for (int x = 0; x < width; ++x) { 118 dst[x] = -bittst(src, x); 119 } 120 dst = (uint16_t*)((char*)dst + dstRB); 121 src += bitmap.pitch; 122 } 123 break; 124 case FT_PIXEL_MODE_GRAY: 125 for (int y = height; y --> 0;) { 126 for (int x = 0; x < width; ++x) { 127 dst[x] = grayToRGB16(src[x]); 128 } 129 dst = (uint16_t*)((char*)dst + dstRB); 130 src += bitmap.pitch; 131 } 132 break; 133 case FT_PIXEL_MODE_LCD: 134 SkASSERT(3 * mask.fBounds.width() == static_cast<int>(bitmap.width)); 135 for (int y = height; y --> 0;) { 136 const uint8_t* triple = src; 137 if (lcdIsBGR) { 138 for (int x = 0; x < width; x++) { 139 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR), 140 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 141 sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB)); 142 triple += 3; 143 } 144 } else { 145 for (int x = 0; x < width; x++) { 146 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR), 147 sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG), 148 sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB)); 149 triple += 3; 150 } 151 } 152 src += bitmap.pitch; 153 dst = (uint16_t*)((char*)dst + dstRB); 154 } 155 break; 156 case FT_PIXEL_MODE_LCD_V: 157 SkASSERT(3 * mask.fBounds.height() == static_cast<int>(bitmap.rows)); 158 for (int y = height; y --> 0;) { 159 const uint8_t* srcR = src; 160 const uint8_t* srcG = srcR + bitmap.pitch; 161 const uint8_t* srcB = srcG + bitmap.pitch; 162 if (lcdIsBGR) { 163 SkTSwap(srcR, srcB); 164 } 165 for (int x = 0; x < width; x++) { 166 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++, tableR), 167 sk_apply_lut_if<APPLY_PREBLEND>(*srcG++, tableG), 168 sk_apply_lut_if<APPLY_PREBLEND>(*srcB++, tableB)); 169 } 170 src += 3 * bitmap.pitch; 171 dst = (uint16_t*)((char*)dst + dstRB); 172 } 173 break; 174 default: 175 SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode)); 176 SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16"); 177 break; 178 } 179 } 180 181 /** 182 * Copies a FT_Bitmap into an SkMask with the same dimensions. 183 * 184 * Yes, No, Never Requested, Never Produced 185 * 186 * kBW kA8 k3D kARGB32 kLCD16 187 * FT_PIXEL_MODE_MONO Y Y NR N Y 188 * FT_PIXEL_MODE_GRAY N Y NR N Y 189 * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP 190 * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP 191 * FT_PIXEL_MODE_LCD NP NP NR NP NP 192 * FT_PIXEL_MODE_LCD_V NP NP NR NP NP 193 * FT_PIXEL_MODE_BGRA N N NR Y N 194 * 195 * TODO: All of these N need to be Y or otherwise ruled out. 196 */ 197 void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) { 198 SkASSERTF(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width), 199 "dstMask.fBounds.width() = %d\n" 200 "static_cast<int>(srcFTBitmap.width) = %d", 201 dstMask.fBounds.width(), 202 static_cast<int>(srcFTBitmap.width) 203 ); 204 SkASSERTF(dstMask.fBounds.height() == static_cast<int>(srcFTBitmap.rows), 205 "dstMask.fBounds.height() = %d\n" 206 "static_cast<int>(srcFTBitmap.rows) = %d", 207 dstMask.fBounds.height(), 208 static_cast<int>(srcFTBitmap.rows) 209 ); 210 211 const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer); 212 const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel_mode); 213 // FT_Bitmap::pitch is an int and allowed to be negative. 214 const int srcPitch = srcFTBitmap.pitch; 215 const size_t srcRowBytes = SkTAbs(srcPitch); 216 217 uint8_t* dst = dstMask.fImage; 218 const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat); 219 const size_t dstRowBytes = dstMask.fRowBytes; 220 221 const size_t width = srcFTBitmap.width; 222 const size_t height = srcFTBitmap.rows; 223 224 if (SkMask::kLCD16_Format == dstFormat) { 225 copyFT2LCD16<false>(srcFTBitmap, dstMask, false, nullptr, nullptr, nullptr); 226 return; 227 } 228 229 if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) || 230 (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat)) 231 { 232 size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes); 233 for (size_t y = height; y --> 0;) { 234 memcpy(dst, src, commonRowBytes); 235 src += srcPitch; 236 dst += dstRowBytes; 237 } 238 } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) { 239 for (size_t y = height; y --> 0;) { 240 uint8_t byte = 0; 241 int bits = 0; 242 const uint8_t* src_row = src; 243 uint8_t* dst_row = dst; 244 for (size_t x = width; x --> 0;) { 245 if (0 == bits) { 246 byte = *src_row++; 247 bits = 8; 248 } 249 *dst_row++ = byte & 0x80 ? 0xff : 0x00; 250 bits--; 251 byte <<= 1; 252 } 253 src += srcPitch; 254 dst += dstRowBytes; 255 } 256 } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) { 257 // FT_PIXEL_MODE_BGRA is pre-multiplied. 258 for (size_t y = height; y --> 0;) { 259 const uint8_t* src_row = src; 260 SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst); 261 for (size_t x = 0; x < width; ++x) { 262 uint8_t b = *src_row++; 263 uint8_t g = *src_row++; 264 uint8_t r = *src_row++; 265 uint8_t a = *src_row++; 266 *dst_row++ = SkPackARGB32(a, r, g, b); 267 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 268 *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE, 0x40); 269 #endif 270 } 271 src += srcPitch; 272 dst += dstRowBytes; 273 } 274 } else { 275 SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat)); 276 SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format"); 277 } 278 } 279 280 inline int convert_8_to_1(unsigned byte) { 281 SkASSERT(byte <= 0xFF); 282 // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better. 283 return (byte >> 6) != 0; 284 } 285 286 uint8_t pack_8_to_1(const uint8_t alpha[8]) { 287 unsigned bits = 0; 288 for (int i = 0; i < 8; ++i) { 289 bits <<= 1; 290 bits |= convert_8_to_1(alpha[i]); 291 } 292 return SkToU8(bits); 293 } 294 295 void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) { 296 const int height = mask.fBounds.height(); 297 const int width = mask.fBounds.width(); 298 const int octs = width >> 3; 299 const int leftOverBits = width & 7; 300 301 uint8_t* dst = mask.fImage; 302 const int dstPad = mask.fRowBytes - SkAlign8(width)/8; 303 SkASSERT(dstPad >= 0); 304 305 const int srcPad = srcRB - width; 306 SkASSERT(srcPad >= 0); 307 308 for (int y = 0; y < height; ++y) { 309 for (int i = 0; i < octs; ++i) { 310 *dst++ = pack_8_to_1(src); 311 src += 8; 312 } 313 if (leftOverBits > 0) { 314 unsigned bits = 0; 315 int shift = 7; 316 for (int i = 0; i < leftOverBits; ++i, --shift) { 317 bits |= convert_8_to_1(*src++) << shift; 318 } 319 *dst++ = bits; 320 } 321 src += srcPad; 322 dst += dstPad; 323 } 324 } 325 326 inline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) { 327 switch (colorType) { 328 case kAlpha_8_SkColorType: 329 return SkMask::kA8_Format; 330 case kN32_SkColorType: 331 return SkMask::kARGB32_Format; 332 default: 333 SkDEBUGFAIL("unsupported SkBitmap::Config"); 334 return SkMask::kA8_Format; 335 } 336 } 337 338 inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) { 339 switch (pixel_mode) { 340 case FT_PIXEL_MODE_MONO: 341 case FT_PIXEL_MODE_GRAY: 342 return kAlpha_8_SkColorType; 343 case FT_PIXEL_MODE_BGRA: 344 return kN32_SkColorType; 345 default: 346 SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); 347 return kAlpha_8_SkColorType; 348 } 349 } 350 351 inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) { 352 switch (format) { 353 case SkMask::kBW_Format: 354 case SkMask::kA8_Format: 355 case SkMask::kLCD16_Format: 356 return kAlpha_8_SkColorType; 357 case SkMask::kARGB32_Format: 358 return kN32_SkColorType; 359 default: 360 SkDEBUGFAIL("unsupported destination SkBitmap::Config"); 361 return kAlpha_8_SkColorType; 362 } 363 } 364 365 } // namespace 366 367 void SkScalerContext_FreeType_Base::generateGlyphImage( 368 FT_Face face, 369 const SkGlyph& glyph, 370 const SkMatrix& bitmapTransform) 371 { 372 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag); 373 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 374 375 switch ( face->glyph->format ) { 376 case FT_GLYPH_FORMAT_OUTLINE: { 377 FT_Outline* outline = &face->glyph->outline; 378 379 int dx = 0, dy = 0; 380 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 381 dx = SkFixedToFDot6(glyph.getSubXFixed()); 382 dy = SkFixedToFDot6(glyph.getSubYFixed()); 383 // negate dy since freetype-y-goes-up and skia-y-goes-down 384 dy = -dy; 385 } 386 387 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 388 389 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 390 FT_Outline_Translate(outline, dx, dy); 391 FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : 392 FT_RENDER_MODE_LCD); 393 if (err) { 394 SK_TRACEFTR(err, "Could not render glyph %x.", face->glyph); 395 return; 396 } 397 398 SkMask mask; 399 glyph.toMask(&mask); 400 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 401 memset(mask.fImage, 0x80, mask.fBounds.height() * mask.fRowBytes); 402 #endif 403 FT_GlyphSlotRec& ftGlyph = *face->glyph; 404 405 if (!SkIRect::Intersects(mask.fBounds, 406 SkIRect::MakeXYWH( ftGlyph.bitmap_left, 407 -ftGlyph.bitmap_top, 408 ftGlyph.bitmap.width, 409 ftGlyph.bitmap.rows))) 410 { 411 return; 412 } 413 414 // If the FT_Bitmap extent is larger, discard bits of the bitmap outside the mask. 415 // If the SkMask extent is larger, shrink mask to fit bitmap (clearing discarded). 416 unsigned char* origBuffer = ftGlyph.bitmap.buffer; 417 // First align the top left (origin). 418 if (-ftGlyph.bitmap_top < mask.fBounds.fTop) { 419 int32_t topDiff = mask.fBounds.fTop - (-ftGlyph.bitmap_top); 420 ftGlyph.bitmap.buffer += ftGlyph.bitmap.pitch * topDiff; 421 ftGlyph.bitmap.rows -= topDiff; 422 ftGlyph.bitmap_top = -mask.fBounds.fTop; 423 } 424 if (ftGlyph.bitmap_left < mask.fBounds.fLeft) { 425 int32_t leftDiff = mask.fBounds.fLeft - ftGlyph.bitmap_left; 426 ftGlyph.bitmap.buffer += leftDiff; 427 ftGlyph.bitmap.width -= leftDiff; 428 ftGlyph.bitmap_left = mask.fBounds.fLeft; 429 } 430 if (mask.fBounds.fTop < -ftGlyph.bitmap_top) { 431 mask.fImage += mask.fRowBytes * (-ftGlyph.bitmap_top - mask.fBounds.fTop); 432 mask.fBounds.fTop = -ftGlyph.bitmap_top; 433 } 434 if (mask.fBounds.fLeft < ftGlyph.bitmap_left) { 435 mask.fImage += sizeof(uint16_t) * (ftGlyph.bitmap_left - mask.fBounds.fLeft); 436 mask.fBounds.fLeft = ftGlyph.bitmap_left; 437 } 438 // Origins aligned, clean up the width and height. 439 int ftVertScale = (doVert ? 3 : 1); 440 int ftHoriScale = (doVert ? 1 : 3); 441 if (mask.fBounds.height() * ftVertScale < SkToInt(ftGlyph.bitmap.rows)) { 442 ftGlyph.bitmap.rows = mask.fBounds.height() * ftVertScale; 443 } 444 if (mask.fBounds.width() * ftHoriScale < SkToInt(ftGlyph.bitmap.width)) { 445 ftGlyph.bitmap.width = mask.fBounds.width() * ftHoriScale; 446 } 447 if (SkToInt(ftGlyph.bitmap.rows) < mask.fBounds.height() * ftVertScale) { 448 mask.fBounds.fBottom = mask.fBounds.fTop + ftGlyph.bitmap.rows / ftVertScale; 449 } 450 if (SkToInt(ftGlyph.bitmap.width) < mask.fBounds.width() * ftHoriScale) { 451 mask.fBounds.fRight = mask.fBounds.fLeft + ftGlyph.bitmap.width / ftHoriScale; 452 } 453 if (fPreBlend.isApplicable()) { 454 copyFT2LCD16<true>(ftGlyph.bitmap, mask, doBGR, 455 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 456 } else { 457 copyFT2LCD16<false>(ftGlyph.bitmap, mask, doBGR, 458 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 459 } 460 // Restore the buffer pointer so FreeType can properly free it. 461 ftGlyph.bitmap.buffer = origBuffer; 462 } else { 463 FT_BBox bbox; 464 FT_Bitmap target; 465 FT_Outline_Get_CBox(outline, &bbox); 466 /* 467 what we really want to do for subpixel is 468 offset(dx, dy) 469 compute_bounds 470 offset(bbox & !63) 471 but that is two calls to offset, so we do the following, which 472 achieves the same thing with only one offset call. 473 */ 474 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), 475 dy - ((bbox.yMin + dy) & ~63)); 476 477 target.width = glyph.fWidth; 478 target.rows = glyph.fHeight; 479 target.pitch = glyph.rowBytes(); 480 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); 481 target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat); 482 target.num_grays = 256; 483 484 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); 485 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 486 for (int y = 0; y < glyph.fHeight; ++y) { 487 for (int x = 0; x < glyph.fWidth; ++x) { 488 uint8_t& a = ((uint8_t*)glyph.fImage)[(glyph.rowBytes() * y) + x]; 489 a = SkTMax<uint8_t>(a, 0x20); 490 } 491 } 492 #endif 493 } 494 } break; 495 496 case FT_GLYPH_FORMAT_BITMAP: { 497 FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode); 498 SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 499 500 // Assume that the other formats do not exist. 501 SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode || 502 FT_PIXEL_MODE_GRAY == pixel_mode || 503 FT_PIXEL_MODE_BGRA == pixel_mode); 504 505 // These are the only formats this ScalerContext should request. 506 SkASSERT(SkMask::kBW_Format == maskFormat || 507 SkMask::kA8_Format == maskFormat || 508 SkMask::kARGB32_Format == maskFormat || 509 SkMask::kLCD16_Format == maskFormat); 510 511 // If no scaling needed, directly copy glyph bitmap. 512 if (bitmapTransform.isIdentity()) { 513 SkMask dstMask; 514 glyph.toMask(&dstMask); 515 copyFTBitmap(face->glyph->bitmap, dstMask); 516 break; 517 } 518 519 // Otherwise, scale the bitmap. 520 521 // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB) 522 SkBitmap unscaledBitmap; 523 // TODO: mark this as sRGB when the blits will be sRGB. 524 unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width, 525 face->glyph->bitmap.rows, 526 SkColorType_for_FTPixelMode(pixel_mode), 527 kPremul_SkAlphaType)); 528 529 SkMask unscaledBitmapAlias; 530 unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels()); 531 unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height()); 532 unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes(); 533 unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType()); 534 copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias); 535 536 // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD. 537 // BW requires an A8 target for resizing, which can then be down sampled. 538 // LCD should use a 4x A8 target, which will then be down sampled. 539 // For simplicity, LCD uses A8 and is replicated. 540 int bitmapRowBytes = 0; 541 if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) { 542 bitmapRowBytes = glyph.rowBytes(); 543 } 544 SkBitmap dstBitmap; 545 // TODO: mark this as sRGB when the blits will be sRGB. 546 dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight, 547 SkColorType_for_SkMaskFormat(maskFormat), 548 kPremul_SkAlphaType), 549 bitmapRowBytes); 550 if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) { 551 dstBitmap.allocPixels(); 552 } else { 553 dstBitmap.setPixels(glyph.fImage); 554 } 555 556 // Scale unscaledBitmap into dstBitmap. 557 SkCanvas canvas(dstBitmap); 558 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE 559 canvas.clear(0x33FF0000); 560 #else 561 canvas.clear(SK_ColorTRANSPARENT); 562 #endif 563 canvas.translate(-glyph.fLeft, -glyph.fTop); 564 canvas.concat(bitmapTransform); 565 canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top); 566 567 SkPaint paint; 568 // Using kMedium FilterQuality will cause mipmaps to be generated. Use 569 // kLow when the results will be roughly the same in order to avoid 570 // the mipmap generation cost. 571 // See skbug.com/6967 572 if (bitmapTransform.getMinScale() < 0.5) { 573 paint.setFilterQuality(kMedium_SkFilterQuality); 574 } else { 575 paint.setFilterQuality(kLow_SkFilterQuality); 576 } 577 canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); 578 579 // If the destination is BW or LCD, convert from A8. 580 if (SkMask::kBW_Format == maskFormat) { 581 // Copy the A8 dstBitmap into the A1 glyph.fImage. 582 SkMask dstMask; 583 glyph.toMask(&dstMask); 584 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes()); 585 } else if (SkMask::kLCD16_Format == maskFormat) { 586 // Copy the A8 dstBitmap into the LCD16 glyph.fImage. 587 uint8_t* src = dstBitmap.getAddr8(0, 0); 588 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); 589 for (int y = dstBitmap.height(); y --> 0;) { 590 for (int x = 0; x < dstBitmap.width(); ++x) { 591 dst[x] = grayToRGB16(src[x]); 592 } 593 dst = (uint16_t*)((char*)dst + glyph.rowBytes()); 594 src += dstBitmap.rowBytes(); 595 } 596 } 597 598 } break; 599 600 default: 601 SkDEBUGFAIL("unknown glyph format"); 602 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 603 return; 604 } 605 606 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, 607 // it is optional 608 #if defined(SK_GAMMA_APPLY_TO_A8) 609 if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { 610 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 611 unsigned rowBytes = glyph.rowBytes(); 612 613 for (int y = glyph.fHeight - 1; y >= 0; --y) { 614 for (int x = glyph.fWidth - 1; x >= 0; --x) { 615 dst[x] = fPreBlend.fG[dst[x]]; 616 } 617 dst += rowBytes; 618 } 619 } 620 #endif 621 } 622 623 /////////////////////////////////////////////////////////////////////////////// 624 625 namespace { 626 627 int move_proc(const FT_Vector* pt, void* ctx) { 628 SkPath* path = (SkPath*)ctx; 629 path->close(); // to close the previous contour (if any) 630 path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 631 return 0; 632 } 633 634 int line_proc(const FT_Vector* pt, void* ctx) { 635 SkPath* path = (SkPath*)ctx; 636 path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); 637 return 0; 638 } 639 640 int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1, 641 void* ctx) { 642 SkPath* path = (SkPath*)ctx; 643 path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 644 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y)); 645 return 0; 646 } 647 648 int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1, 649 const FT_Vector* pt2, void* ctx) { 650 SkPath* path = (SkPath*)ctx; 651 path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), 652 SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y), 653 SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y)); 654 return 0; 655 } 656 657 } // namespace 658 659 void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) { 660 FT_Outline_Funcs funcs; 661 662 funcs.move_to = move_proc; 663 funcs.line_to = line_proc; 664 funcs.conic_to = quad_proc; 665 funcs.cubic_to = cubic_proc; 666 funcs.shift = 0; 667 funcs.delta = 0; 668 669 FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); 670 671 if (err != 0) { 672 path->reset(); 673 return; 674 } 675 676 path->close(); 677 } 678