Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(812)

Side by Side Diff: src/ports/SkFontHost_FreeType_common.cpp

Issue 23684041: improve bitmap font support (FreeType only) (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Correct selection logic, remove debug code. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« gm/coloremoji.cpp ('K') | « src/ports/SkFontHost_FreeType.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 }
OLDNEW
« gm/coloremoji.cpp ('K') | « src/ports/SkFontHost_FreeType.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698