OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006-2012 The Android Open Source Project | 2 * Copyright 2006-2012 The Android Open Source Project |
3 * Copyright 2012 Mozilla Foundation | 3 * Copyright 2012 Mozilla Foundation |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 * FT_PIXEL_MODE_GRAY N Y NR N Y | 170 * FT_PIXEL_MODE_GRAY N Y NR N Y |
171 * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP | 171 * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP |
172 * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP | 172 * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP |
173 * FT_PIXEL_MODE_LCD NP NP NR NP NP | 173 * FT_PIXEL_MODE_LCD NP NP NR NP NP |
174 * FT_PIXEL_MODE_LCD_V NP NP NR NP NP | 174 * FT_PIXEL_MODE_LCD_V NP NP NR NP NP |
175 * FT_PIXEL_MODE_BGRA N N NR Y N | 175 * FT_PIXEL_MODE_BGRA N N NR Y N |
176 * | 176 * |
177 * TODO: All of these N need to be Y or otherwise ruled out. | 177 * TODO: All of these N need to be Y or otherwise ruled out. |
178 */ | 178 */ |
179 static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) { | 179 static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) { |
180 SkASSERT(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width)); | 180 SkASSERTF(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width), |
181 SkASSERT(dstMask.fBounds.height() == static_cast<int>(srcFTBitmap.rows)); | 181 "dstMask.fBounds.width() = %d\n" |
| 182 "static_cast<int>(srcFTBitmap.width) = %d", |
| 183 dstMask.fBounds.width(), |
| 184 static_cast<int>(srcFTBitmap.width) |
| 185 ); |
| 186 SkASSERTF(dstMask.fBounds.height() == static_cast<int>(srcFTBitmap.rows), |
| 187 "dstMask.fBounds.height() = %d\n" |
| 188 "static_cast<int>(srcFTBitmap.rows) = %d", |
| 189 dstMask.fBounds.height(), |
| 190 static_cast<int>(srcFTBitmap.rows) |
| 191 ); |
182 | 192 |
183 const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer); | 193 const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer); |
184 const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel
_mode); | 194 const FT_Pixel_Mode srcFormat = static_cast<FT_Pixel_Mode>(srcFTBitmap.pixel
_mode); |
185 // FT_Bitmap::pitch is an int and allowed to be negative. | 195 // FT_Bitmap::pitch is an int and allowed to be negative. |
186 const int srcPitch = srcFTBitmap.pitch; | 196 const int srcPitch = srcFTBitmap.pitch; |
187 const size_t srcRowBytes = SkTAbs(srcPitch); | 197 const size_t srcRowBytes = SkTAbs(srcPitch); |
188 | 198 |
189 uint8_t* dst = dstMask.fImage; | 199 uint8_t* dst = dstMask.fImage; |
190 const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat
); | 200 const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat
); |
191 const size_t dstRowBytes = dstMask.fRowBytes; | 201 const size_t dstRowBytes = dstMask.fRowBytes; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 case SkMask::kLCD16_Format: | 337 case SkMask::kLCD16_Format: |
328 return kAlpha_8_SkColorType; | 338 return kAlpha_8_SkColorType; |
329 case SkMask::kARGB32_Format: | 339 case SkMask::kARGB32_Format: |
330 return kN32_SkColorType; | 340 return kN32_SkColorType; |
331 default: | 341 default: |
332 SkDEBUGFAIL("unsupported destination SkBitmap::Config"); | 342 SkDEBUGFAIL("unsupported destination SkBitmap::Config"); |
333 return kAlpha_8_SkColorType; | 343 return kAlpha_8_SkColorType; |
334 } | 344 } |
335 } | 345 } |
336 | 346 |
337 void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
ph& glyph) { | 347 void SkScalerContext_FreeType_Base::generateGlyphImage( |
| 348 FT_Face face, |
| 349 const SkGlyph& glyph, |
| 350 const SkMatrix& bitmapTransform) |
| 351 { |
338 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Fla
g); | 352 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Fla
g); |
339 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Fl
ag); | 353 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Fl
ag); |
340 | 354 |
341 switch ( face->glyph->format ) { | 355 switch ( face->glyph->format ) { |
342 case FT_GLYPH_FORMAT_OUTLINE: { | 356 case FT_GLYPH_FORMAT_OUTLINE: { |
343 FT_Outline* outline = &face->glyph->outline; | 357 FT_Outline* outline = &face->glyph->outline; |
344 FT_BBox bbox; | 358 FT_BBox bbox; |
345 FT_Bitmap target; | 359 FT_Bitmap target; |
346 | 360 |
347 int dx = 0, dy = 0; | 361 int dx = 0, dy = 0; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode || | 409 SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode || |
396 FT_PIXEL_MODE_GRAY == pixel_mode || | 410 FT_PIXEL_MODE_GRAY == pixel_mode || |
397 FT_PIXEL_MODE_BGRA == pixel_mode); | 411 FT_PIXEL_MODE_BGRA == pixel_mode); |
398 | 412 |
399 // These are the only formats this ScalerContext should request. | 413 // These are the only formats this ScalerContext should request. |
400 SkASSERT(SkMask::kBW_Format == maskFormat || | 414 SkASSERT(SkMask::kBW_Format == maskFormat || |
401 SkMask::kA8_Format == maskFormat || | 415 SkMask::kA8_Format == maskFormat || |
402 SkMask::kARGB32_Format == maskFormat || | 416 SkMask::kARGB32_Format == maskFormat || |
403 SkMask::kLCD16_Format == maskFormat); | 417 SkMask::kLCD16_Format == maskFormat); |
404 | 418 |
405 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && | |
406 !(face->style_flags & FT_STYLE_FLAG_BOLD)) | |
407 { | |
408 FT_GlyphSlot_Own_Bitmap(face->glyph); | |
409 FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, | |
410 kBitmapEmboldenStrength, 0); | |
411 } | |
412 | |
413 // If no scaling needed, directly copy glyph bitmap. | 419 // If no scaling needed, directly copy glyph bitmap. |
414 if (glyph.fWidth == face->glyph->bitmap.width && | 420 if (bitmapTransform.isIdentity()) { |
415 glyph.fHeight == face->glyph->bitmap.rows && | |
416 glyph.fTop == -face->glyph->bitmap_top && | |
417 glyph.fLeft == face->glyph->bitmap_left) | |
418 { | |
419 SkMask dstMask; | 421 SkMask dstMask; |
420 glyph.toMask(&dstMask); | 422 glyph.toMask(&dstMask); |
421 copyFTBitmap(face->glyph->bitmap, dstMask); | 423 copyFTBitmap(face->glyph->bitmap, dstMask); |
422 break; | 424 break; |
423 } | 425 } |
424 | 426 |
425 // Otherwise, scale the bitmap. | 427 // Otherwise, scale the bitmap. |
426 | 428 |
427 // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB) | 429 // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB) |
428 SkBitmap unscaledBitmap; | 430 SkBitmap unscaledBitmap; |
| 431 // TODO: mark this as sRGB when the blits will be sRGB. |
429 unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.wid
th, | 432 unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.wid
th, |
430 face->glyph->bitmap.row
s, | 433 face->glyph->bitmap.row
s, |
431 SkColorType_for_FTPixel
Mode(pixel_mode), | 434 SkColorType_for_FTPixel
Mode(pixel_mode), |
432 kPremul_SkAlphaType)); | 435 kPremul_SkAlphaType)); |
433 | 436 |
434 SkMask unscaledBitmapAlias; | 437 SkMask unscaledBitmapAlias; |
435 unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitm
ap.getPixels()); | 438 unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitm
ap.getPixels()); |
436 unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscal
edBitmap.height()); | 439 unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscal
edBitmap.height()); |
437 unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes(); | 440 unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes(); |
438 unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledB
itmap.colorType()); | 441 unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledB
itmap.colorType()); |
439 copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias); | 442 copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias); |
440 | 443 |
441 // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW
or LCD. | 444 // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW
or LCD. |
442 // BW requires an A8 target for resizing, which can then be down sam
pled. | 445 // BW requires an A8 target for resizing, which can then be down sam
pled. |
443 // LCD should use a 4x A8 target, which will then be down sampled. | 446 // LCD should use a 4x A8 target, which will then be down sampled. |
444 // For simplicity, LCD uses A8 and is replicated. | 447 // For simplicity, LCD uses A8 and is replicated. |
445 int bitmapRowBytes = 0; | 448 int bitmapRowBytes = 0; |
446 if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != mas
kFormat) { | 449 if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != mas
kFormat) { |
447 bitmapRowBytes = glyph.rowBytes(); | 450 bitmapRowBytes = glyph.rowBytes(); |
448 } | 451 } |
449 SkBitmap dstBitmap; | 452 SkBitmap dstBitmap; |
| 453 // TODO: mark this as sRGB when the blits will be sRGB. |
450 dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight, | 454 dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight, |
451 SkColorType_for_SkMaskFormat(mas
kFormat), | 455 SkColorType_for_SkMaskFormat(mas
kFormat), |
452 kPremul_SkAlphaType), | 456 kPremul_SkAlphaType), |
453 bitmapRowBytes); | 457 bitmapRowBytes); |
454 if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == mas
kFormat) { | 458 if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == mas
kFormat) { |
455 dstBitmap.allocPixels(); | 459 dstBitmap.allocPixels(); |
456 } else { | 460 } else { |
457 dstBitmap.setPixels(glyph.fImage); | 461 dstBitmap.setPixels(glyph.fImage); |
458 } | 462 } |
459 | 463 |
460 // Scale unscaledBitmap into dstBitmap. | 464 // Scale unscaledBitmap into dstBitmap. |
461 SkCanvas canvas(dstBitmap); | 465 SkCanvas canvas(dstBitmap); |
| 466 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE |
| 467 canvas.clear(0x33FF0000); |
| 468 #else |
462 canvas.clear(SK_ColorTRANSPARENT); | 469 canvas.clear(SK_ColorTRANSPARENT); |
463 canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph
->bitmap.width), | 470 #endif |
464 SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyp
h->bitmap.rows)); | 471 canvas.translate(-glyph.fLeft, -glyph.fTop); |
| 472 canvas.concat(bitmapTransform); |
| 473 canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top)
; |
| 474 |
465 SkPaint paint; | 475 SkPaint paint; |
466 paint.setFilterQuality(kMedium_SkFilterQuality); | 476 paint.setFilterQuality(kMedium_SkFilterQuality); |
467 canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); | 477 canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); |
468 | 478 |
469 // If the destination is BW or LCD, convert from A8. | 479 // If the destination is BW or LCD, convert from A8. |
470 if (SkMask::kBW_Format == maskFormat) { | 480 if (SkMask::kBW_Format == maskFormat) { |
471 // Copy the A8 dstBitmap into the A1 glyph.fImage. | 481 // Copy the A8 dstBitmap into the A1 glyph.fImage. |
472 SkMask dstMask; | 482 SkMask dstMask; |
473 glyph.toMask(&dstMask); | 483 glyph.toMask(&dstMask); |
474 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes
()); | 484 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes
()); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 | 566 |
557 FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); | 567 FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); |
558 | 568 |
559 if (err != 0) { | 569 if (err != 0) { |
560 path->reset(); | 570 path->reset(); |
561 return; | 571 return; |
562 } | 572 } |
563 | 573 |
564 path->close(); | 574 path->close(); |
565 } | 575 } |
OLD | NEW |