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