LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/ports - SkFontHost_FreeType_common.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 46 303 15.2 %
Date: 2017-07-14 16:53:18 Functions: 3 20 15.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
      38           0 :     switch (format) {
      39             :         case SkMask::kBW_Format:
      40           0 :             return FT_PIXEL_MODE_MONO;
      41             :         case SkMask::kA8_Format:
      42             :         default:
      43           0 :             return FT_PIXEL_MODE_GRAY;
      44             :     }
      45             : }
      46             : 
      47             : ///////////////////////////////////////////////////////////////////////////////
      48             : 
      49       17191 : 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       17191 :     return SkPack888ToRGB16(r, g, b);
      56             : }
      57             : 
      58           0 : uint16_t grayToRGB16(U8CPU gray) {
      59             : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
      60             :     gray = SkTMax(gray, (U8CPU)0x40);
      61             : #endif
      62           0 :     return SkPack888ToRGB16(gray, gray, gray);
      63             : }
      64             : 
      65           0 : int bittst(const uint8_t data[], int bitOffset) {
      66           0 :     SkASSERT(bitOffset >= 0);
      67           0 :     int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7);
      68           0 :     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          58 : 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          58 :     SkASSERT(SkMask::kLCD16_Format == mask.fFormat);
      84          58 :     if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) {
      85           0 :         SkASSERT(mask.fBounds.width() == static_cast<int>(bitmap.width));
      86             :     }
      87          58 :     if (FT_PIXEL_MODE_LCD_V != bitmap.pixel_mode) {
      88          58 :         SkASSERT(mask.fBounds.height() == static_cast<int>(bitmap.rows));
      89             :     }
      90             : 
      91          58 :     const uint8_t* src = bitmap.buffer;
      92          58 :     uint16_t* dst = reinterpret_cast<uint16_t*>(mask.fImage);
      93          58 :     const size_t dstRB = mask.fRowBytes;
      94             : 
      95          58 :     const int width = mask.fBounds.width();
      96          58 :     const int height = mask.fBounds.height();
      97             : 
      98          58 :     switch (bitmap.pixel_mode) {
      99             :         case FT_PIXEL_MODE_MONO:
     100           0 :             for (int y = height; y --> 0;) {
     101           0 :                 for (int x = 0; x < width; ++x) {
     102           0 :                     dst[x] = -bittst(src, x);
     103             :                 }
     104           0 :                 dst = (uint16_t*)((char*)dst + dstRB);
     105           0 :                 src += bitmap.pitch;
     106             :             }
     107           0 :             break;
     108             :         case FT_PIXEL_MODE_GRAY:
     109           0 :             for (int y = height; y --> 0;) {
     110           0 :                 for (int x = 0; x < width; ++x) {
     111           0 :                     dst[x] = grayToRGB16(src[x]);
     112             :                 }
     113           0 :                 dst = (uint16_t*)((char*)dst + dstRB);
     114           0 :                 src += bitmap.pitch;
     115             :             }
     116           0 :             break;
     117             :         case FT_PIXEL_MODE_LCD:
     118          58 :             SkASSERT(3 * mask.fBounds.width() == static_cast<int>(bitmap.width));
     119        1104 :             for (int y = height; y --> 0;) {
     120        1046 :                 const uint8_t* triple = src;
     121        1046 :                 if (lcdIsBGR) {
     122           0 :                     for (int x = 0; x < width; x++) {
     123           0 :                         dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableR),
     124           0 :                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
     125           0 :                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableB));
     126           0 :                         triple += 3;
     127             :                     }
     128             :                 } else {
     129       18237 :                     for (int x = 0; x < width; x++) {
     130       51573 :                         dst[x] = packTriple(sk_apply_lut_if<APPLY_PREBLEND>(triple[0], tableR),
     131       17191 :                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[1], tableG),
     132       17191 :                                             sk_apply_lut_if<APPLY_PREBLEND>(triple[2], tableB));
     133       17191 :                         triple += 3;
     134             :                     }
     135             :                 }
     136        1046 :                 src += bitmap.pitch;
     137        1046 :                 dst = (uint16_t*)((char*)dst + dstRB);
     138             :             }
     139          58 :             break;
     140             :         case FT_PIXEL_MODE_LCD_V:
     141           0 :             SkASSERT(3 * mask.fBounds.height() == static_cast<int>(bitmap.rows));
     142           0 :             for (int y = height; y --> 0;) {
     143           0 :                 const uint8_t* srcR = src;
     144           0 :                 const uint8_t* srcG = srcR + bitmap.pitch;
     145           0 :                 const uint8_t* srcB = srcG + bitmap.pitch;
     146           0 :                 if (lcdIsBGR) {
     147           0 :                     SkTSwap(srcR, srcB);
     148             :                 }
     149           0 :                 for (int x = 0; x < width; x++) {
     150           0 :                     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           0 :                 src += 3 * bitmap.pitch;
     155           0 :                 dst = (uint16_t*)((char*)dst + dstRB);
     156             :             }
     157           0 :             break;
     158             :         default:
     159           0 :             SkDEBUGF(("FT_Pixel_Mode %d", bitmap.pixel_mode));
     160           0 :             SkDEBUGFAIL("unsupported FT_Pixel_Mode for LCD16");
     161           0 :             break;
     162             :     }
     163          58 : }
     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           0 : void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
     182           0 :     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           0 :     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           0 :     const uint8_t* src = reinterpret_cast<const uint8_t*>(srcFTBitmap.buffer);
     196           0 :     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           0 :     const int srcPitch = srcFTBitmap.pitch;
     199           0 :     const size_t srcRowBytes = SkTAbs(srcPitch);
     200             : 
     201           0 :     uint8_t* dst = dstMask.fImage;
     202           0 :     const SkMask::Format dstFormat = static_cast<SkMask::Format>(dstMask.fFormat);
     203           0 :     const size_t dstRowBytes = dstMask.fRowBytes;
     204             : 
     205           0 :     const size_t width = srcFTBitmap.width;
     206           0 :     const size_t height = srcFTBitmap.rows;
     207             : 
     208           0 :     if (SkMask::kLCD16_Format == dstFormat) {
     209           0 :         copyFT2LCD16<false>(srcFTBitmap, dstMask, false, nullptr, nullptr, nullptr);
     210           0 :         return;
     211             :     }
     212             : 
     213           0 :     if ((FT_PIXEL_MODE_MONO == srcFormat && SkMask::kBW_Format == dstFormat) ||
     214           0 :         (FT_PIXEL_MODE_GRAY == srcFormat && SkMask::kA8_Format == dstFormat))
     215             :     {
     216           0 :         size_t commonRowBytes = SkTMin(srcRowBytes, dstRowBytes);
     217           0 :         for (size_t y = height; y --> 0;) {
     218           0 :             memcpy(dst, src, commonRowBytes);
     219           0 :             src += srcPitch;
     220           0 :             dst += dstRowBytes;
     221           0 :         }
     222           0 :     } else if (FT_PIXEL_MODE_MONO == srcFormat && SkMask::kA8_Format == dstFormat) {
     223           0 :         for (size_t y = height; y --> 0;) {
     224           0 :             uint8_t byte = 0;
     225           0 :             int bits = 0;
     226           0 :             const uint8_t* src_row = src;
     227           0 :             uint8_t* dst_row = dst;
     228           0 :             for (size_t x = width; x --> 0;) {
     229           0 :                 if (0 == bits) {
     230           0 :                     byte = *src_row++;
     231           0 :                     bits = 8;
     232             :                 }
     233           0 :                 *dst_row++ = byte & 0x80 ? 0xff : 0x00;
     234           0 :                 bits--;
     235           0 :                 byte <<= 1;
     236             :             }
     237           0 :             src += srcPitch;
     238           0 :             dst += dstRowBytes;
     239           0 :         }
     240           0 :     } else if (FT_PIXEL_MODE_BGRA == srcFormat && SkMask::kARGB32_Format == dstFormat) {
     241             :         // FT_PIXEL_MODE_BGRA is pre-multiplied.
     242           0 :         for (size_t y = height; y --> 0;) {
     243           0 :             const uint8_t* src_row = src;
     244           0 :             SkPMColor* dst_row = reinterpret_cast<SkPMColor*>(dst);
     245           0 :             for (size_t x = 0; x < width; ++x) {
     246           0 :                 uint8_t b = *src_row++;
     247           0 :                 uint8_t g = *src_row++;
     248           0 :                 uint8_t r = *src_row++;
     249           0 :                 uint8_t a = *src_row++;
     250           0 :                 *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           0 :             src += srcPitch;
     256           0 :             dst += dstRowBytes;
     257           0 :         }
     258             :     } else {
     259           0 :         SkDEBUGF(("FT_Pixel_Mode %d, SkMask::Format %d\n", srcFormat, dstFormat));
     260           0 :         SkDEBUGFAIL("unsupported combination of FT_Pixel_Mode and SkMask::Format");
     261             :     }
     262             : }
     263             : 
     264           0 : inline int convert_8_to_1(unsigned byte) {
     265           0 :     SkASSERT(byte <= 0xFF);
     266             :     // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better.
     267           0 :     return (byte >> 6) != 0;
     268             : }
     269             : 
     270           0 : uint8_t pack_8_to_1(const uint8_t alpha[8]) {
     271           0 :     unsigned bits = 0;
     272           0 :     for (int i = 0; i < 8; ++i) {
     273           0 :         bits <<= 1;
     274           0 :         bits |= convert_8_to_1(alpha[i]);
     275             :     }
     276           0 :     return SkToU8(bits);
     277             : }
     278             : 
     279           0 : void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
     280           0 :     const int height = mask.fBounds.height();
     281           0 :     const int width = mask.fBounds.width();
     282           0 :     const int octs = width >> 3;
     283           0 :     const int leftOverBits = width & 7;
     284             : 
     285           0 :     uint8_t* dst = mask.fImage;
     286           0 :     const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
     287           0 :     SkASSERT(dstPad >= 0);
     288             : 
     289           0 :     const int srcPad = srcRB - width;
     290           0 :     SkASSERT(srcPad >= 0);
     291             : 
     292           0 :     for (int y = 0; y < height; ++y) {
     293           0 :         for (int i = 0; i < octs; ++i) {
     294           0 :             *dst++ = pack_8_to_1(src);
     295           0 :             src += 8;
     296             :         }
     297           0 :         if (leftOverBits > 0) {
     298           0 :             unsigned bits = 0;
     299           0 :             int shift = 7;
     300           0 :             for (int i = 0; i < leftOverBits; ++i, --shift) {
     301           0 :                 bits |= convert_8_to_1(*src++) << shift;
     302             :             }
     303           0 :             *dst++ = bits;
     304             :         }
     305           0 :         src += srcPad;
     306           0 :         dst += dstPad;
     307             :     }
     308           0 : }
     309             : 
     310           0 : inline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) {
     311           0 :     switch (colorType) {
     312             :         case kAlpha_8_SkColorType:
     313           0 :             return SkMask::kA8_Format;
     314             :         case kN32_SkColorType:
     315           0 :             return SkMask::kARGB32_Format;
     316             :         default:
     317           0 :             SkDEBUGFAIL("unsupported SkBitmap::Config");
     318           0 :             return SkMask::kA8_Format;
     319             :     }
     320             : }
     321             : 
     322           0 : inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
     323           0 :     switch (pixel_mode) {
     324             :         case FT_PIXEL_MODE_MONO:
     325             :         case FT_PIXEL_MODE_GRAY:
     326           0 :             return kAlpha_8_SkColorType;
     327             :         case FT_PIXEL_MODE_BGRA:
     328           0 :             return kN32_SkColorType;
     329             :         default:
     330           0 :             SkDEBUGFAIL("unsupported FT_PIXEL_MODE");
     331           0 :             return kAlpha_8_SkColorType;
     332             :     }
     333             : }
     334             : 
     335           0 : inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) {
     336           0 :     switch (format) {
     337             :         case SkMask::kBW_Format:
     338             :         case SkMask::kA8_Format:
     339             :         case SkMask::kLCD16_Format:
     340           0 :             return kAlpha_8_SkColorType;
     341             :         case SkMask::kARGB32_Format:
     342           0 :             return kN32_SkColorType;
     343             :         default:
     344           0 :             SkDEBUGFAIL("unsupported destination SkBitmap::Config");
     345           0 :             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           0 : void SkTraceFTR(const char* file, unsigned long line, FT_Error err, const char* msg) {
     367           0 :     SkString s;
     368           0 :     s.printf("%s:%lu:1: error: 0x%x ", file, line, err);
     369           0 :     if (0 <= err && (unsigned)err < SK_ARRAY_COUNT(sk_ft_errors)) {
     370           0 :         s.appendf("%s '%s' ", sk_ft_errors[err].err_code, sk_ft_errors[err].err_msg);
     371             :     } else {
     372           0 :         s.appendf("<unknown> ");
     373             :     }
     374           0 :     if (msg) {
     375           0 :         s.appendf("%s", msg);
     376             :     }
     377           0 :     SkDebugf("%s\n", s.c_str());
     378           0 : }
     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          58 : void SkScalerContext_FreeType_Base::generateGlyphImage(
     388             :     FT_Face face,
     389             :     const SkGlyph& glyph,
     390             :     const SkMatrix& bitmapTransform)
     391             : {
     392          58 :     const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
     393          58 :     const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
     394             : 
     395          58 :     switch ( face->glyph->format ) {
     396             :         case FT_GLYPH_FORMAT_OUTLINE: {
     397          58 :             FT_Outline* outline = &face->glyph->outline;
     398             :             FT_BBox     bbox;
     399             :             FT_Bitmap   target;
     400             : 
     401          58 :             int dx = 0, dy = 0;
     402          58 :             if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
     403           0 :                 dx = SkFixedToFDot6(glyph.getSubXFixed());
     404           0 :                 dy = SkFixedToFDot6(glyph.getSubYFixed());
     405             :                 // negate dy since freetype-y-goes-up and skia-y-goes-down
     406           0 :                 dy = -dy;
     407             :             }
     408          58 :             FT_Outline_Get_CBox(outline, &bbox);
     409             :             /*
     410             :                 what we really want to do for subpixel is
     411             :                     offset(dx, dy)
     412             :                     compute_bounds
     413             :                     offset(bbox & !63)
     414             :                 but that is two calls to offset, so we do the following, which
     415             :                 achieves the same thing with only one offset call.
     416             :             */
     417         116 :             FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63),
     418         116 :                                           dy - ((bbox.yMin + dy) & ~63));
     419             : 
     420          58 :             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
     421          58 :                 FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
     422          58 :                                                                      FT_RENDER_MODE_LCD);
     423          58 :                 if (err) {
     424           0 :                     SK_TRACEFTR(err, "Could not render glyph.");
     425           0 :                     sk_bzero(glyph.fImage, glyph.computeImageSize());
     426           0 :                     return;
     427             :                 }
     428          58 :                 SkMask mask;
     429          58 :                 glyph.toMask(&mask);
     430          58 :                 if (fPreBlend.isApplicable()) {
     431           0 :                     copyFT2LCD16<true>(face->glyph->bitmap, mask, doBGR,
     432           0 :                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
     433             :                 } else {
     434          58 :                     copyFT2LCD16<false>(face->glyph->bitmap, mask, doBGR,
     435         116 :                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
     436             :                 }
     437             :             } else {
     438           0 :                 target.width = glyph.fWidth;
     439           0 :                 target.rows = glyph.fHeight;
     440           0 :                 target.pitch = glyph.rowBytes();
     441           0 :                 target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
     442           0 :                 target.pixel_mode = compute_pixel_mode( (SkMask::Format)fRec.fMaskFormat);
     443           0 :                 target.num_grays = 256;
     444             : 
     445           0 :                 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
     446           0 :                 FT_Outline_Get_Bitmap(face->glyph->library, outline, &target);
     447             :             }
     448          58 :         } break;
     449             : 
     450             :         case FT_GLYPH_FORMAT_BITMAP: {
     451           0 :             FT_Pixel_Mode pixel_mode = static_cast<FT_Pixel_Mode>(face->glyph->bitmap.pixel_mode);
     452           0 :             SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
     453             : 
     454             :             // Assume that the other formats do not exist.
     455           0 :             SkASSERT(FT_PIXEL_MODE_MONO == pixel_mode ||
     456             :                      FT_PIXEL_MODE_GRAY == pixel_mode ||
     457             :                      FT_PIXEL_MODE_BGRA == pixel_mode);
     458             : 
     459             :             // These are the only formats this ScalerContext should request.
     460           0 :             SkASSERT(SkMask::kBW_Format == maskFormat ||
     461             :                      SkMask::kA8_Format == maskFormat ||
     462             :                      SkMask::kARGB32_Format == maskFormat ||
     463             :                      SkMask::kLCD16_Format == maskFormat);
     464             : 
     465             :             // If no scaling needed, directly copy glyph bitmap.
     466           0 :             if (bitmapTransform.isIdentity()) {
     467           0 :                 SkMask dstMask;
     468           0 :                 glyph.toMask(&dstMask);
     469           0 :                 copyFTBitmap(face->glyph->bitmap, dstMask);
     470           0 :                 break;
     471             :             }
     472             : 
     473             :             // Otherwise, scale the bitmap.
     474             : 
     475             :             // Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
     476           0 :             SkBitmap unscaledBitmap;
     477             :             // TODO: mark this as sRGB when the blits will be sRGB.
     478           0 :             unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
     479           0 :                                                          face->glyph->bitmap.rows,
     480             :                                                          SkColorType_for_FTPixelMode(pixel_mode),
     481           0 :                                                          kPremul_SkAlphaType));
     482             : 
     483           0 :             SkMask unscaledBitmapAlias;
     484           0 :             unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
     485           0 :             unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height());
     486           0 :             unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
     487           0 :             unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
     488           0 :             copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
     489             : 
     490             :             // Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
     491             :             // BW requires an A8 target for resizing, which can then be down sampled.
     492             :             // LCD should use a 4x A8 target, which will then be down sampled.
     493             :             // For simplicity, LCD uses A8 and is replicated.
     494           0 :             int bitmapRowBytes = 0;
     495           0 :             if (SkMask::kBW_Format != maskFormat && SkMask::kLCD16_Format != maskFormat) {
     496           0 :                 bitmapRowBytes = glyph.rowBytes();
     497             :             }
     498           0 :             SkBitmap dstBitmap;
     499             :             // TODO: mark this as sRGB when the blits will be sRGB.
     500           0 :             dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
     501             :                                                 SkColorType_for_SkMaskFormat(maskFormat),
     502             :                                                 kPremul_SkAlphaType),
     503           0 :                               bitmapRowBytes);
     504           0 :             if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
     505           0 :                 dstBitmap.allocPixels();
     506             :             } else {
     507           0 :                 dstBitmap.setPixels(glyph.fImage);
     508             :             }
     509             : 
     510             :             // Scale unscaledBitmap into dstBitmap.
     511           0 :             SkCanvas canvas(dstBitmap);
     512             : #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
     513             :             canvas.clear(0x33FF0000);
     514             : #else
     515           0 :             canvas.clear(SK_ColorTRANSPARENT);
     516             : #endif
     517           0 :             canvas.translate(-glyph.fLeft, -glyph.fTop);
     518           0 :             canvas.concat(bitmapTransform);
     519           0 :             canvas.translate(face->glyph->bitmap_left, -face->glyph->bitmap_top);
     520             : 
     521           0 :             SkPaint paint;
     522           0 :             paint.setFilterQuality(kMedium_SkFilterQuality);
     523           0 :             canvas.drawBitmap(unscaledBitmap, 0, 0, &paint);
     524             : 
     525             :             // If the destination is BW or LCD, convert from A8.
     526           0 :             if (SkMask::kBW_Format == maskFormat) {
     527             :                 // Copy the A8 dstBitmap into the A1 glyph.fImage.
     528           0 :                 SkMask dstMask;
     529           0 :                 glyph.toMask(&dstMask);
     530           0 :                 packA8ToA1(dstMask, dstBitmap.getAddr8(0, 0), dstBitmap.rowBytes());
     531           0 :             } else if (SkMask::kLCD16_Format == maskFormat) {
     532             :                 // Copy the A8 dstBitmap into the LCD16 glyph.fImage.
     533           0 :                 uint8_t* src = dstBitmap.getAddr8(0, 0);
     534           0 :                 uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
     535           0 :                 for (int y = dstBitmap.height(); y --> 0;) {
     536           0 :                     for (int x = 0; x < dstBitmap.width(); ++x) {
     537           0 :                         dst[x] = grayToRGB16(src[x]);
     538             :                     }
     539           0 :                     dst = (uint16_t*)((char*)dst + glyph.rowBytes());
     540           0 :                     src += dstBitmap.rowBytes();
     541             :                 }
     542             :             }
     543             : 
     544           0 :         } break;
     545             : 
     546             :         default:
     547           0 :             SkDEBUGFAIL("unknown glyph format");
     548           0 :             memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
     549           0 :             return;
     550             :     }
     551             : 
     552             : // We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum,
     553             : // it is optional
     554             : #if defined(SK_GAMMA_APPLY_TO_A8)
     555             :     if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) {
     556             :         uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage;
     557             :         unsigned rowBytes = glyph.rowBytes();
     558             : 
     559             :         for (int y = glyph.fHeight - 1; y >= 0; --y) {
     560             :             for (int x = glyph.fWidth - 1; x >= 0; --x) {
     561             :                 dst[x] = fPreBlend.fG[dst[x]];
     562             :             }
     563             :             dst += rowBytes;
     564             :         }
     565             :     }
     566             : #endif
     567             : }
     568             : 
     569             : ///////////////////////////////////////////////////////////////////////////////
     570             : 
     571             : namespace {
     572             : 
     573           0 : int move_proc(const FT_Vector* pt, void* ctx) {
     574           0 :     SkPath* path = (SkPath*)ctx;
     575           0 :     path->close();  // to close the previous contour (if any)
     576           0 :     path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
     577           0 :     return 0;
     578             : }
     579             : 
     580           0 : int line_proc(const FT_Vector* pt, void* ctx) {
     581           0 :     SkPath* path = (SkPath*)ctx;
     582           0 :     path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
     583           0 :     return 0;
     584             : }
     585             : 
     586           0 : int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
     587             :                      void* ctx) {
     588           0 :     SkPath* path = (SkPath*)ctx;
     589           0 :     path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
     590           0 :                  SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
     591           0 :     return 0;
     592             : }
     593             : 
     594           0 : int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
     595             :                       const FT_Vector* pt2, void* ctx) {
     596           0 :     SkPath* path = (SkPath*)ctx;
     597           0 :     path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
     598           0 :                   SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
     599           0 :                   SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y));
     600           0 :     return 0;
     601             : }
     602             : 
     603             : }  // namespace
     604             : 
     605           0 : void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
     606             :     FT_Outline_Funcs    funcs;
     607             : 
     608           0 :     funcs.move_to   = move_proc;
     609           0 :     funcs.line_to   = line_proc;
     610           0 :     funcs.conic_to  = quad_proc;
     611           0 :     funcs.cubic_to  = cubic_proc;
     612           0 :     funcs.shift     = 0;
     613           0 :     funcs.delta     = 0;
     614             : 
     615           0 :     FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path);
     616             : 
     617           0 :     if (err != 0) {
     618           0 :         path->reset();
     619           0 :         return;
     620             :     }
     621             : 
     622           0 :     path->close();
     623             : }

Generated by: LCOV version 1.13