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" |
| 10 #include "SkCanvas.h" |
| 11 #include "SkColor.h" |
9 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
10 #include "SkFDot6.h" | 13 #include "SkFDot6.h" |
11 #include "SkFontHost_FreeType_common.h" | 14 #include "SkFontHost_FreeType_common.h" |
12 #include "SkPath.h" | 15 #include "SkPath.h" |
13 | 16 |
14 #include <ft2build.h> | 17 #include <ft2build.h> |
| 18 #include FT_FREETYPE_H |
| 19 #include FT_BITMAP_H |
| 20 #include FT_IMAGE_H |
15 #include FT_OUTLINE_H | 21 #include FT_OUTLINE_H |
16 #include FT_BITMAP_H | |
17 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. | 22 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. |
18 #include FT_SYNTHESIS_H | 23 #include FT_SYNTHESIS_H |
19 | 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 |
20 static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { | 35 static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { |
21 switch (format) { | 36 switch (format) { |
22 case SkMask::kBW_Format: | 37 case SkMask::kBW_Format: |
23 return FT_PIXEL_MODE_MONO; | 38 return FT_PIXEL_MODE_MONO; |
24 case SkMask::kA8_Format: | 39 case SkMask::kA8_Format: |
25 default: | 40 default: |
26 return FT_PIXEL_MODE_GRAY; | 41 return FT_PIXEL_MODE_GRAY; |
27 } | 42 } |
28 } | 43 } |
29 | 44 |
30 /////////////////////////////////////////////////////////////////////////////// | 45 /////////////////////////////////////////////////////////////////////////////// |
31 | 46 |
32 static uint16_t packTriple(unsigned r, unsigned g, unsigned b) { | 47 static uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) { |
33 return SkPackRGB16(r >> 3, g >> 2, b >> 3); | 48 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE |
| 49 r = SkTMax(r, (U8CPU)0x40); |
| 50 g = SkTMax(g, (U8CPU)0x40); |
| 51 b = SkTMax(b, (U8CPU)0x40); |
| 52 #endif |
| 53 return SkPack888ToRGB16(r, g, b); |
34 } | 54 } |
35 | 55 |
36 static uint16_t grayToRGB16(U8CPU gray) { | 56 static uint16_t grayToRGB16(U8CPU gray) { |
37 SkASSERT(gray <= 255); | 57 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE |
38 return SkPackRGB16(gray >> 3, gray >> 2, gray >> 3); | 58 gray = SkTMax(gray, (U8CPU)0x40); |
| 59 #endif |
| 60 return SkPack888ToRGB16(gray, gray, gray); |
39 } | 61 } |
40 | 62 |
41 static int bittst(const uint8_t data[], int bitOffset) { | 63 static int bittst(const uint8_t data[], int bitOffset) { |
42 SkASSERT(bitOffset >= 0); | 64 SkASSERT(bitOffset >= 0); |
43 int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); | 65 int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); |
44 return lowBit & 1; | 66 return lowBit & 1; |
45 } | 67 } |
46 | 68 |
| 69 /** |
| 70 * Copies a FT_Bitmap into an SkMask with the same dimensions. |
| 71 * |
| 72 * FT_PIXEL_MODE_MONO |
| 73 * FT_PIXEL_MODE_GRAY |
| 74 * FT_PIXEL_MODE_LCD |
| 75 * FT_PIXEL_MODE_LCD_V |
| 76 */ |
47 template<bool APPLY_PREBLEND> | 77 template<bool APPLY_PREBLEND> |
48 static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap, | 78 static void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsB
GR, |
49 int lcdIsBGR, bool lcdIsVert, const uint8_t* tableR, | 79 const uint8_t* tableR, const uint8_t* tableG, const uin
t8_t* tableB) |
50 const uint8_t* tableG, const uint8_t* tableB) { | 80 { |
51 if (lcdIsVert) { | 81 SkASSERT(SkMask::kLCD16_Format == mask.fFormat); |
52 SkASSERT(3 * glyph.fHeight == bitmap.rows); | 82 if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) { |
53 } else { | 83 SkASSERT(mask.fBounds.width() == bitmap.width); |
54 SkASSERT(glyph.fHeight == bitmap.rows); | 84 } |
55 } | 85 if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) { |
56 | 86 SkASSERT(mask.fBounds.height() == bitmap.rows); |
57 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); | 87 } |
58 const size_t dstRB = glyph.rowBytes(); | 88 |
59 const int width = glyph.fWidth; | |
60 const uint8_t* src = bitmap.buffer; | 89 const uint8_t* src = bitmap.buffer; |
| 90 uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage); |
| 91 const size_t dstRB = mask.fRowBytes; |
| 92 |
| 93 const int width = mask.fBounds.width(); |
| 94 const int height = mask.fBounds.height(); |
61 | 95 |
62 switch (bitmap.pixel_mode) { | 96 switch (bitmap.pixel_mode) { |
63 case FT_PIXEL_MODE_MONO: { | 97 case FT_PIXEL_MODE_MONO: |
64 for (int y = 0; y < glyph.fHeight; ++y) { | 98 for (int y = height; y --> 0;) { |
65 for (int x = 0; x < width; ++x) { | 99 for (int x = 0; x < width; ++x) { |
66 dst[x] = -bittst(src, x); | 100 dst[x] = -bittst(src, x); |
67 } | 101 } |
68 dst = (uint16_t*)((char*)dst + dstRB); | 102 dst = (uint16_t*)((char*)dst + dstRB); |
69 src += bitmap.pitch; | 103 src += bitmap.pitch; |
70 } | 104 } |
71 } break; | 105 break; |
72 case FT_PIXEL_MODE_GRAY: { | 106 case FT_PIXEL_MODE_GRAY: |
73 for (int y = 0; y < glyph.fHeight; ++y) { | 107 for (int y = height; y --> 0;) { |
74 for (int x = 0; x < width; ++x) { | 108 for (int x = 0; x < width; ++x) { |
75 dst[x] = grayToRGB16(src[x]); | 109 dst[x] = grayToRGB16(src[x]); |
76 } | 110 } |
77 dst = (uint16_t*)((char*)dst + dstRB); | 111 dst = (uint16_t*)((char*)dst + dstRB); |
78 src += bitmap.pitch; | 112 src += bitmap.pitch; |
79 } | 113 } |
80 } break; | 114 break; |
81 default: { | 115 case FT_PIXEL_MODE_LCD: |
82 SkASSERT(lcdIsVert || (glyph.fWidth * 3 == bitmap.width)); | 116 SkASSERT(3 * mask.fBounds.width() == bitmap.width); |
83 for (int y = 0; y < glyph.fHeight; y++) { | 117 for (int y = height; y --> 0;) { |
84 if (lcdIsVert) { // vertical stripes | 118 const uint8_t* triple = src; |
85 const uint8_t* srcR = src; | 119 if (lcdIsBGR) { |
86 const uint8_t* srcG = srcR + bitmap.pitch; | 120 for (int x = 0; x < width; x++) { |
87 const uint8_t* srcB = srcG + bitmap.pitch; | 121 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(trip
le[2], tableR), |
88 if (lcdIsBGR) { | 122 sk_apply_lut_if<APPLY_PREBLEND>(trip
le[1], tableG), |
89 SkTSwap(srcR, srcB); | 123 sk_apply_lut_if<APPLY_PREBLEND>(trip
le[0], tableB)); |
| 124 triple += 3; |
90 } | 125 } |
| 126 } else { |
91 for (int x = 0; x < width; x++) { | 127 for (int x = 0; x < width; x++) { |
92 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*src
R++, tableR), | 128 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(trip
le[0], tableR), |
93 sk_apply_lut_if<APPLY_PREBLEND>(*src
G++, tableG), | 129 sk_apply_lut_if<APPLY_PREBLEND>(trip
le[1], tableG), |
94 sk_apply_lut_if<APPLY_PREBLEND>(*src
B++, tableB)); | 130 sk_apply_lut_if<APPLY_PREBLEND>(trip
le[2], tableB)); |
| 131 triple += 3; |
95 } | 132 } |
96 src += 3 * bitmap.pitch; | 133 } |
97 } else { // horizontal stripes | 134 src += bitmap.pitch; |
98 const uint8_t* triple = src; | 135 dst = (uint16_t*)((char*)dst + dstRB); |
99 if (lcdIsBGR) { | 136 } |
100 for (int x = 0; x < width; x++) { | 137 break; |
101 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(
triple[2], tableR), | 138 case FT_PIXEL_MODE_LCD_V: |
102 sk_apply_lut_if<APPLY_PREBLEND>(
triple[1], tableG), | 139 SkASSERT(3 * mask.fBounds.height() == bitmap.rows); |
103 sk_apply_lut_if<APPLY_PREBLEND>(
triple[0], tableB)); | 140 for (int y = height; y --> 0;) { |
104 triple += 3; | 141 const uint8_t* srcR = src; |
105 } | 142 const uint8_t* srcG = srcR + bitmap.pitch; |
106 } else { | 143 const uint8_t* srcB = srcG + bitmap.pitch; |
107 for (int x = 0; x < width; x++) { | 144 if (lcdIsBGR) { |
108 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(
triple[0], tableR), | 145 SkTSwap(srcR, srcB); |
109 sk_apply_lut_if<APPLY_PREBLEND>(
triple[1], tableG), | 146 } |
110 sk_apply_lut_if<APPLY_PREBLEND>(
triple[2], tableB)); | 147 for (int x = 0; x < width; x++) { |
111 triple += 3; | 148 dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(*srcR++,
tableR), |
112 } | 149 sk_apply_lut_if<APPLY_PREBLEND>(*srcG++,
tableG), |
113 } | 150 sk_apply_lut_if<APPLY_PREBLEND>(*srcB++,
tableB)); |
114 src += bitmap.pitch; | 151 } |
115 } | 152 src += 3 * bitmap.pitch; |
116 dst = (uint16_t*)((char*)dst + dstRB); | 153 dst = (uint16_t*)((char*)dst + dstRB); |
117 } | 154 } |
118 } break; | 155 break; |
| 156 default: |
| 157 SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode)); |
| 158 SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16"); |
| 159 break; |
| 160 } |
| 161 } |
| 162 |
| 163 /** |
| 164 * Copies a FT_Bitmap into an SkMask with the same dimensions. |
| 165 * |
| 166 * Yes, No, Never Requested, Never Produced |
| 167 * |
| 168 * kBW kA8 k3D kARGB32 kLCD16 kLCD32 |
| 169 * FT_PIXEL_MODE_MONO Y Y NR N Y NR |
| 170 * FT_PIXEL_MODE_GRAY N Y NR N Y NR |
| 171 * FT_PIXEL_MODE_GRAY2 NP NP NR NP NP NR |
| 172 * FT_PIXEL_MODE_GRAY4 NP NP NR NP NP NR |
| 173 * FT_PIXEL_MODE_LCD NP NP NR NP NP NR |
| 174 * FT_PIXEL_MODE_LCD_V NP NP NR NP NP NR |
| 175 * FT_PIXEL_MODE_BGRA N N NR Y N NR |
| 176 * |
| 177 * TODO: All of these N need to be Y or otherwise ruled out. |
| 178 */ |
| 179 static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) { |
| 180 SkASSERT(dstMask.fBounds.width() == srcFTBitmap.width); |
| 181 SkASSERT(dstMask.fBounds.height() == srcFTBitmap.rows); |
| 182 |
| 183 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); |
| 185 // FT_Bitmap::pitch is an int and allowed to be negative. |
| 186 const int srcPitch = srcFTBitmap.pitch; |
| 187 const size_t srcRowBytes = SkTAbs(srcPitch); |
| 188 |
| 189 uint8_t* dst = dstMask.fImage; |
| 190 const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat
); |
| 191 const size_t dstRowBytes = dstMask.fRowBytes; |
| 192 |
| 193 const size_t width = srcFTBitmap.width; |
| 194 const size_t height = srcFTBitmap.rows; |
| 195 |
| 196 if (SkMask::kLCD16_Format == dstFormat) { |
| 197 copyFT2LCD16<false>(srcFTBitmap, dstMask, false, NULL, NULL, NULL); |
| 198 return; |
| 199 } |
| 200 |
| 201 if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) || |
| 202 (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat)) |
| 203 { |
| 204 size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes); |
| 205 for (size_t y = height; y --> 0;) { |
| 206 memcpy(dst, src, commonRowBytes); |
| 207 src += srcPitch; |
| 208 dst += dstRowBytes; |
| 209 } |
| 210 } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstForma
t) { |
| 211 for (size_t y = height; y --> 0;) { |
| 212 uint8_t byte = 0; |
| 213 int bits = 0; |
| 214 const uint8_t* src_row = src; |
| 215 uint8_t* dst_row = dst; |
| 216 for (size_t x = width; x --> 0;) { |
| 217 if (0 == bits) { |
| 218 byte = *src_row++; |
| 219 bits = 8; |
| 220 } |
| 221 *dst_row++ = byte & 0x80 ? 0xff : 0x00; |
| 222 bits--; |
| 223 byte <<= 1; |
| 224 } |
| 225 src += srcPitch; |
| 226 dst += dstRowBytes; |
| 227 } |
| 228 } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstF
ormat) { |
| 229 // FT_PIXEL_MODE_BGRA is pre-multiplied. |
| 230 for (size_t y = height; y --> 0;) { |
| 231 const uint8_t* src_row = src; |
| 232 SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst); |
| 233 for (size_t x = 0; x < width; ++x) { |
| 234 uint8_t b = *src_row++; |
| 235 uint8_t g = *src_row++; |
| 236 uint8_t r = *src_row++; |
| 237 uint8_t a = *src_row++; |
| 238 *dst_row++ = SkPackARGB32(a, r, g, b); |
| 239 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE |
| 240 *(dst_row-1) = SkFourByteInterp256(*(dst_row-1), SK_ColorWHITE,
0x40); |
| 241 #endif |
| 242 } |
| 243 src += srcPitch; |
| 244 dst += dstRowBytes; |
| 245 } |
| 246 } else { |
| 247 SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat)
); |
| 248 SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format
"); |
| 249 } |
| 250 } |
| 251 |
| 252 static inline int convert_8_to_1(unsigned byte) { |
| 253 SkASSERT(byte <= 0xFF); |
| 254 // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in genera
l looks better. |
| 255 return (byte >> 6) != 0; |
| 256 } |
| 257 |
| 258 static uint8_t pack_8_to_1(const uint8_t alpha[8]) { |
| 259 unsigned bits = 0; |
| 260 for (int i = 0; i < 8; ++i) { |
| 261 bits <<= 1; |
| 262 bits |= convert_8_to_1(alpha[i]); |
| 263 } |
| 264 return SkToU8(bits); |
| 265 } |
| 266 |
| 267 static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) { |
| 268 const int height = mask.fBounds.height(); |
| 269 const int width = mask.fBounds.width(); |
| 270 const int octs = width >> 3; |
| 271 const int leftOverBits = width & 7; |
| 272 |
| 273 uint8_t* dst = mask.fImage; |
| 274 const int dstPad = mask.fRowBytes - SkAlign8(width)/8; |
| 275 SkASSERT(dstPad >= 0); |
| 276 |
| 277 const int srcPad = srcRB - width; |
| 278 SkASSERT(srcPad >= 0); |
| 279 |
| 280 for (int y = 0; y < height; ++y) { |
| 281 for (int i = 0; i < octs; ++i) { |
| 282 *dst++ = pack_8_to_1(src); |
| 283 src += 8; |
| 284 } |
| 285 if (leftOverBits > 0) { |
| 286 unsigned bits = 0; |
| 287 int shift = 7; |
| 288 for (int i = 0; i < leftOverBits; ++i, --shift) { |
| 289 bits |= convert_8_to_1(*src++) << shift; |
| 290 } |
| 291 *dst++ = bits; |
| 292 } |
| 293 src += srcPad; |
| 294 dst += dstPad; |
| 295 } |
| 296 } |
| 297 |
| 298 inline SkMask::Format SkMaskFormat_for_SkBitmapConfig(SkBitmap::Config config) { |
| 299 switch (config) { |
| 300 case SkBitmap::kA8_Config: |
| 301 return SkMask::kA8_Format; |
| 302 case SkBitmap::kARGB_8888_Config: |
| 303 return SkMask::kARGB32_Format; |
| 304 default: |
| 305 SkDEBUGFAIL("unsupported SkBitmap::Config"); |
| 306 return SkMask::kA8_Format; |
| 307 } |
| 308 } |
| 309 |
| 310 inline SkBitmap::Config SkBitmapConfig_for_FTPixelMode(FT_Pixel_Mode pixel_mode)
{ |
| 311 switch (pixel_mode) { |
| 312 case FT_PIXEL_MODE_MONO: |
| 313 case FT_PIXEL_MODE_GRAY: |
| 314 return SkBitmap::kA8_Config; |
| 315 case FT_PIXEL_MODE_BGRA: |
| 316 return SkBitmap::kARGB_8888_Config; |
| 317 default: |
| 318 SkDEBUGFAIL("unsupported FT_PIXEL_MODE"); |
| 319 return SkBitmap::kA8_Config; |
| 320 } |
| 321 } |
| 322 |
| 323 inline SkBitmap::Config SkBitmapConfig_for_SkMaskFormat(SkMask::Format format) { |
| 324 switch (format) { |
| 325 case SkMask::kBW_Format: |
| 326 case SkMask::kA8_Format: |
| 327 case SkMask::kLCD16_Format: |
| 328 return SkBitmap::kA8_Config; |
| 329 case SkMask::kARGB32_Format: |
| 330 return SkBitmap::kARGB_8888_Config; |
| 331 default: |
| 332 SkDEBUGFAIL("unsupported destination SkBitmap::Config"); |
| 333 return SkBitmap::kA8_Config; |
119 } | 334 } |
120 } | 335 } |
121 | 336 |
122 void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
ph& glyph) { | 337 void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
ph& glyph) { |
123 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Fla
g); | 338 const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Fla
g); |
124 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Fl
ag); | 339 const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Fl
ag); |
125 | 340 |
126 switch ( face->glyph->format ) { | 341 switch ( face->glyph->format ) { |
127 case FT_GLYPH_FORMAT_OUTLINE: { | 342 case FT_GLYPH_FORMAT_OUTLINE: { |
128 FT_Outline* outline = &face->glyph->outline; | 343 FT_Outline* outline = &face->glyph->outline; |
129 FT_BBox bbox; | 344 FT_BBox bbox; |
130 FT_Bitmap target; | 345 FT_Bitmap target; |
131 | 346 |
132 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) { | 347 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && |
| 348 !(face->style_flags & FT_STYLE_FLAG_BOLD)) { |
133 emboldenOutline(face, outline); | 349 emboldenOutline(face, outline); |
134 } | 350 } |
135 | 351 |
136 int dx = 0, dy = 0; | 352 int dx = 0, dy = 0; |
137 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { | 353 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { |
138 dx = SkFixedToFDot6(glyph.getSubXFixed()); | 354 dx = SkFixedToFDot6(glyph.getSubXFixed()); |
139 dy = SkFixedToFDot6(glyph.getSubYFixed()); | 355 dy = SkFixedToFDot6(glyph.getSubYFixed()); |
140 // negate dy since freetype-y-goes-up and skia-y-goes-down | 356 // negate dy since freetype-y-goes-up and skia-y-goes-down |
141 dy = -dy; | 357 dy = -dy; |
142 } | 358 } |
143 FT_Outline_Get_CBox(outline, &bbox); | 359 FT_Outline_Get_CBox(outline, &bbox); |
144 /* | 360 /* |
145 what we really want to do for subpixel is | 361 what we really want to do for subpixel is |
146 offset(dx, dy) | 362 offset(dx, dy) |
147 compute_bounds | 363 compute_bounds |
148 offset(bbox & !63) | 364 offset(bbox & !63) |
149 but that is two calls to offset, so we do the following, which | 365 but that is two calls to offset, so we do the following, which |
150 achieves the same thing with only one offset call. | 366 achieves the same thing with only one offset call. |
151 */ | 367 */ |
152 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), | 368 FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), |
153 dy - ((bbox.yMin + dy) & ~63)); | 369 dy - ((bbox.yMin + dy) & ~63)); |
154 | 370 |
155 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { | 371 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { |
156 FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_
RENDER_MODE_LCD); | 372 FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_
RENDER_MODE_LCD); |
| 373 SkMask mask; |
| 374 glyph.toMask(&mask); |
157 if (fPreBlend.isApplicable()) { | 375 if (fPreBlend.isApplicable()) { |
158 copyFT2LCD16<true>(glyph, face->glyph->bitmap, doBGR, doVert
, | 376 copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR, |
159 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB)
; | 377 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB)
; |
160 } else { | 378 } else { |
161 copyFT2LCD16<false>(glyph, face->glyph->bitmap, doBGR, doVer
t, | 379 copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR, |
162 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB
); | 380 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB
); |
163 } | 381 } |
164 } else { | 382 } else { |
165 target.width = glyph.fWidth; | 383 target.width = glyph.fWidth; |
166 target.rows = glyph.fHeight; | 384 target.rows = glyph.fHeight; |
167 target.pitch = glyph.rowBytes(); | 385 target.pitch = glyph.rowBytes(); |
168 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); | 386 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage); |
169 target.pixel_mode = compute_pixel_mode( | 387 target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMa
skFormat); |
170 (SkMask::Format)fRec.fMaskFormat
); | |
171 target.num_grays = 256; | 388 target.num_grays = 256; |
172 | 389 |
173 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); | 390 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); |
174 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); | 391 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); |
175 } | 392 } |
176 } break; | 393 } break; |
177 | 394 |
178 case FT_GLYPH_FORMAT_BITMAP: { | 395 case FT_GLYPH_FORMAT_BITMAP: { |
179 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) { | 396 FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->b
itmap.pixel_mode); |
| 397 SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskF
ormat); |
| 398 |
| 399 // Assume that the other formats do not exist. |
| 400 SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode || |
| 401 FT_PIXEL_MODE_GRAY == pixel_mode || |
| 402 FT_PIXEL_MODE_BGRA == pixel_mode); |
| 403 |
| 404 // These are the only formats this ScalerContext should request. |
| 405 SkASSERT(SkMask::kBW_Format == maskFormat || |
| 406 SkMask::kA8_Format == maskFormat || |
| 407 SkMask::kARGB32_Format == maskFormat || |
| 408 SkMask::kLCD16_Format == maskFormat); |
| 409 |
| 410 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag && |
| 411 !(face->style_flags & FT_STYLE_FLAG_BOLD)) |
| 412 { |
180 FT_GlyphSlot_Own_Bitmap(face->glyph); | 413 FT_GlyphSlot_Own_Bitmap(face->glyph); |
181 FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, k
BitmapEmboldenStrength, 0); | 414 FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, |
| 415 kBitmapEmboldenStrength, 0); |
182 } | 416 } |
183 SkASSERT_CONTINUE(glyph.fWidth == face->glyph->bitmap.width); | |
184 SkASSERT_CONTINUE(glyph.fHeight == face->glyph->bitmap.rows); | |
185 SkASSERT_CONTINUE(glyph.fTop == -face->glyph->bitmap_top); | |
186 SkASSERT_CONTINUE(glyph.fLeft == face->glyph->bitmap_left); | |
187 | 417 |
188 const uint8_t* src = (const uint8_t*)face->glyph->bitmap.buffer; | 418 // If no scaling needed, directly copy glyph bitmap. |
189 uint8_t* dst = (uint8_t*)glyph.fImage; | 419 if (glyph.fWidth == face->glyph->bitmap.width && |
| 420 glyph.fHeight == face->glyph->bitmap.rows && |
| 421 glyph.fTop == -face->glyph->bitmap_top && |
| 422 glyph.fLeft == face->glyph->bitmap_left) |
| 423 { |
| 424 SkMask dstMask; |
| 425 glyph.toMask(&dstMask); |
| 426 copyFTBitmap(face->glyph->bitmap, dstMask); |
| 427 break; |
| 428 } |
190 | 429 |
191 if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY || | 430 // Otherwise, scale the bitmap. |
192 (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && | |
193 glyph.fMaskFormat == SkMask::kBW_Format)) { | |
194 unsigned srcRowBytes = face->glyph->bitmap.pitch; | |
195 unsigned dstRowBytes = glyph.rowBytes(); | |
196 unsigned minRowBytes = SkMin32(srcRowBytes, dstRowBytes); | |
197 unsigned extraRowBytes = dstRowBytes - minRowBytes; | |
198 | 431 |
199 for (int y = face->glyph->bitmap.rows - 1; y >= 0; --y) { | 432 // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB) |
200 memcpy(dst, src, minRowBytes); | 433 SkBitmap unscaledBitmap; |
201 memset(dst + minRowBytes, 0, extraRowBytes); | 434 unscaledBitmap.setConfig(SkBitmapConfig_for_FTPixelMode(pixel_mode), |
202 src += srcRowBytes; | 435 face->glyph->bitmap.width, face->glyph->bit
map.rows); |
203 dst += dstRowBytes; | 436 unscaledBitmap.allocPixels(); |
| 437 |
| 438 SkMask unscaledBitmapAlias; |
| 439 unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitm
ap.getPixels()); |
| 440 unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscal
edBitmap.height()); |
| 441 unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes(); |
| 442 unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkBitmapConfig(unscal
edBitmap.config()); |
| 443 copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias); |
| 444 |
| 445 // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW
or LCD. |
| 446 // BW requires an A8 target for resizing, which can then be down sam
pled. |
| 447 // LCD should use a 4x A8 target, which will then be down sampled. |
| 448 // For simplicity, LCD uses A8 and is replicated. |
| 449 int bitmapRowBytes = 0; |
| 450 if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != mas
kFormat) { |
| 451 bitmapRowBytes = glyph.rowBytes(); |
| 452 } |
| 453 SkBitmap dstBitmap; |
| 454 dstBitmap.setConfig(SkBitmapConfig_for_SkMaskFormat(maskFormat), |
| 455 glyph.fWidth, glyph.fHeight, bitmapRowBytes); |
| 456 if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == mas
kFormat) { |
| 457 dstBitmap.allocPixels(); |
| 458 } else { |
| 459 dstBitmap.setPixels(glyph.fImage); |
| 460 } |
| 461 |
| 462 // Scale unscaledBitmap into dstBitmap. |
| 463 SkCanvas canvas(dstBitmap); |
| 464 canvas.clear(SK_ColorTRANSPARENT); |
| 465 canvas.scale(SkIntToScalar(glyph.fWidth) / SkIntToScalar(face->glyph
->bitmap.width), |
| 466 SkIntToScalar(glyph.fHeight) / SkIntToScalar(face->glyp
h->bitmap.rows)); |
| 467 SkPaint paint; |
| 468 paint.setFilterLevel(SkPaint::kLow_FilterLevel); |
| 469 canvas.drawBitmap(unscaledBitmap, 0, 0, &paint); |
| 470 |
| 471 // If the destination is BW or LCD, convert from A8. |
| 472 if (SkMask::kBW_Format == maskFormat) { |
| 473 // Copy the A8 dstBitmap into the A1 glyph.fImage. |
| 474 SkMask dstMask; |
| 475 glyph.toMask(&dstMask); |
| 476 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes
()); |
| 477 } else if (SkMask::kLCD16_Format == maskFormat) { |
| 478 // Copy the A8 dstBitmap into the LCD16 glyph.fImage. |
| 479 uint8_t* src = dstBitmap.getAddr8(0, 0); |
| 480 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage); |
| 481 for (int y = dstBitmap.height(); y --> 0;) { |
| 482 for (int x = 0; x < dstBitmap.width(); ++x) { |
| 483 dst[x] = grayToRGB16(src[x]); |
| 484 } |
| 485 dst = (uint16_t*)((char*)dst + glyph.rowBytes()); |
| 486 src += dstBitmap.rowBytes(); |
204 } | 487 } |
205 } else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && | 488 } |
206 glyph.fMaskFormat == SkMask::kA8_Format) { | |
207 for (int y = 0; y < face->glyph->bitmap.rows; ++y) { | |
208 uint8_t byte = 0; | |
209 int bits = 0; | |
210 const uint8_t* src_row = src; | |
211 uint8_t* dst_row = dst; | |
212 | 489 |
213 for (int x = 0; x < face->glyph->bitmap.width; ++x) { | |
214 if (!bits) { | |
215 byte = *src_row++; | |
216 bits = 8; | |
217 } | |
218 | |
219 *dst_row++ = byte & 0x80 ? 0xff : 0; | |
220 bits--; | |
221 byte <<= 1; | |
222 } | |
223 | |
224 src += face->glyph->bitmap.pitch; | |
225 dst += glyph.rowBytes(); | |
226 } | |
227 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { | |
228 if (fPreBlend.isApplicable()) { | |
229 copyFT2LCD16<true>(glyph, face->glyph->bitmap, doBGR, doVert
, | |
230 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB)
; | |
231 } else { | |
232 copyFT2LCD16<false>(glyph, face->glyph->bitmap, doBGR, doVer
t, | |
233 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB
); | |
234 } | |
235 } else { | |
236 SkDEBUGFAIL("unknown glyph bitmap transform needed"); | |
237 } | |
238 } break; | 490 } break; |
239 | 491 |
240 default: | 492 default: |
241 SkDEBUGFAIL("unknown glyph format"); | 493 SkDEBUGFAIL("unknown glyph format"); |
242 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); | 494 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); |
243 return; | 495 return; |
244 } | 496 } |
245 | 497 |
246 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, | 498 // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, |
247 // it is optional | 499 // it is optional |
248 #if defined(SK_GAMMA_APPLY_TO_A8) | 500 #if defined(SK_GAMMA_APPLY_TO_A8) |
249 if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { | 501 if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { |
250 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; | 502 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; |
251 unsigned rowBytes = glyph.rowBytes(); | 503 unsigned rowBytes = glyph.rowBytes(); |
252 | 504 |
253 for (int y = glyph.fHeight - 1; y >= 0; --y) { | 505 for (int y = glyph.fHeight - 1; y >= 0; --y) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 path->close(); | 570 path->close(); |
319 } | 571 } |
320 | 572 |
321 void SkScalerContext_FreeType_Base::emboldenOutline(FT_Face face, FT_Outline* ou
tline) | 573 void SkScalerContext_FreeType_Base::emboldenOutline(FT_Face face, FT_Outline* ou
tline) |
322 { | 574 { |
323 FT_Pos strength; | 575 FT_Pos strength; |
324 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) | 576 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) |
325 / 24; | 577 / 24; |
326 FT_Outline_Embolden(outline, strength); | 578 FT_Outline_Embolden(outline, strength); |
327 } | 579 } |
OLD | NEW |