• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
compute_pixel_mode(SkMask::Format format)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 
packTriple(U8CPU r,U8CPU g,U8CPU b)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 
grayToRGB16(U8CPU gray)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 
bittst(const uint8_t data[],int bitOffset)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>
copyFT2LCD16(const FT_Bitmap & bitmap,const SkMask & mask,int lcdIsBGR,const uint8_t * tableR,const uint8_t * tableG,const uint8_t * tableB)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  */
copyFTBitmap(const FT_Bitmap & srcFTBitmap,SkMask & dstMask)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 
convert_8_to_1(unsigned byte)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 
pack_8_to_1(const uint8_t alpha[8])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 
packA8ToA1(const SkMask & mask,const uint8_t * src,size_t srcRB)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 
SkMaskFormat_for_SkColorType(SkColorType colorType)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 
SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode)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 
SkColorType_for_SkMaskFormat(SkMask::Format format)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 
SkTraceFTR(const char * file,unsigned long line,FT_Error err,const char * msg)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 
generateGlyphImage(FT_Face face,const SkGlyph & glyph,const SkMatrix & bitmapTransform)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 
move_proc(const FT_Vector * pt,void * ctx)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 
line_proc(const FT_Vector * pt,void * ctx)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 
quad_proc(const FT_Vector * pt0,const FT_Vector * pt1,void * ctx)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 
cubic_proc(const FT_Vector * pt0,const FT_Vector * pt1,const FT_Vector * pt2,void * ctx)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 
generateGlyphPath(FT_Face face,SkPath * path)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