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