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