Check and report FreeType error.
authorBen Wagner <bungeman@google.com>
Thu, 10 Nov 2016 21:14:52 +0000 (16:14 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 10 Nov 2016 22:16:27 +0000 (22:16 +0000)
BUG=chromium:648959

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4685

Change-Id: Ibc3cd5ddf37926accf1b7bf0959668510de903a8
Reviewed-on: https://skia-review.googlesource.com/4685
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Ben Wagner <bungeman@google.com>

src/ports/SkFontHost_FreeType_common.cpp

index 26e02fd..9df7268 100644 (file)
@@ -32,7 +32,9 @@
 
 //#define SK_SHOW_TEXT_BLIT_COVERAGE
 
-static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
+namespace {
+
+FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
     switch (format) {
         case SkMask::kBW_Format:
             return FT_PIXEL_MODE_MONO;
@@ -44,7 +46,7 @@ static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
+uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
     r = SkTMax(r, (U8CPU)0x40);
     g = SkTMax(g, (U8CPU)0x40);
@@ -53,14 +55,14 @@ static uint16_t packTriple(U8CPU r, U8CPU g, U8CPU b) {
     return SkPack888ToRGB16(r, g, b);
 }
 
-static uint16_t grayToRGB16(U8CPU gray) {
+uint16_t grayToRGB16(U8CPU gray) {
 #ifdef SK_SHOW_TEXT_BLIT_COVERAGE
     gray = SkTMax(gray, (U8CPU)0x40);
 #endif
     return SkPack888ToRGB16(gray, gray, gray);
 }
 
-static int bittst(const uint8_t data[], int bitOffset) {
+int bittst(const uint8_t data[], int bitOffset) {
     SkASSERT(bitOffset >= 0);
     int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7);
     return lowBit & 1;
@@ -75,8 +77,8 @@ static int bittst(const uint8_t data[], int bitOffset) {
  *  FT_PIXEL_MODE_LCD_V
  */
 template<bool APPLY_PREBLEND>
-static void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR,
-                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB)
+void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsBGR,
+                  const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB)
 {
     SkASSERT(SkMask::kLCD16_Format == mask.fFormat);
     if (FT_PIXEL_MODE_LCD != bitmap.pixel_mode) {
@@ -176,7 +178,7 @@ static void copyFT2LCD16(const FT_Bitmap& bitmap, const SkMask& mask, int lcdIsB
  *
  *  TODO: All of these N need to be Y or otherwise ruled out.
  */
-static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
+void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
     SkASSERTF(dstMask.fBounds.width() == static_cast<int>(srcFTBitmap.width),
               "dstMask.fBounds.width() = %d\n"
               "static_cast<int>(srcFTBitmap.width) = %d",
@@ -259,13 +261,13 @@ static void copyFTBitmap(const FT_Bitmap& srcFTBitmap, SkMask& dstMask) {
     }
 }
 
-static inline int convert_8_to_1(unsigned byte) {
+inline int convert_8_to_1(unsigned byte) {
     SkASSERT(byte <= 0xFF);
     // Arbitrary decision that making the cutoff at 1/4 instead of 1/2 in general looks better.
     return (byte >> 6) != 0;
 }
 
-static uint8_t pack_8_to_1(const uint8_t alpha[8]) {
+uint8_t pack_8_to_1(const uint8_t alpha[8]) {
     unsigned bits = 0;
     for (int i = 0; i < 8; ++i) {
         bits <<= 1;
@@ -274,7 +276,7 @@ static uint8_t pack_8_to_1(const uint8_t alpha[8]) {
     return SkToU8(bits);
 }
 
-static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
+void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
     const int height = mask.fBounds.height();
     const int width = mask.fBounds.width();
     const int octs = width >> 3;
@@ -344,6 +346,44 @@ inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) {
     }
 }
 
+#ifdef SK_DEBUG
+
+#  define SK_STRING(X) SK_STRING_IMPL(X)
+#  define SK_STRING_IMPL(X) #X
+
+#  undef __FTERRORS_H__
+#  define FT_ERROR_START_LIST
+#  define FT_ERRORDEF(e, v, s)  { SK_STRING(e), s },
+#  define FT_ERROR_END_LIST
+
+const struct {
+  const char* err_code;
+  const char* err_msg;
+} sk_ft_errors[] = {
+#  include FT_ERRORS_H
+};
+
+void SkTraceFTR(const char* file, unsigned long line, FT_Error err, const char* msg) {
+    SkString s;
+    s.printf("%s:%lu:1: error: 0x%x ", file, line, err);
+    if (0 <= err && (unsigned)err < SK_ARRAY_COUNT(sk_ft_errors)) {
+        s.appendf("%s '%s' ", sk_ft_errors[err].err_code, sk_ft_errors[err].err_msg);
+    } else {
+        s.appendf("<unknown> ");
+    }
+    if (msg) {
+        s.appendf("%s", msg);
+    }
+    SkDebugf("%s\n", s.c_str());
+}
+
+#  define SK_TRACEFTR(_err, _msg) SkTraceFTR(__FILE__, __LINE__, _err, _msg)
+#else
+#  define SK_TRACEFTR(_err, _msg) sk_ignore_unused_variable(_err)
+#endif
+
+}  // namespace
+
 void SkScalerContext_FreeType_Base::generateGlyphImage(
     FT_Face face,
     const SkGlyph& glyph,
@@ -378,7 +418,13 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(
                                           dy - ((bbox.yMin + dy) & ~63));
 
             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
-                FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD);
+                FT_Error err = FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V :
+                                                                     FT_RENDER_MODE_LCD);
+                if (err) {
+                    SK_TRACEFTR(err, "Could not render glyph.");
+                    sk_bzero(glyph.fImage, glyph.computeImageSize());
+                    return;
+                }
                 SkMask mask;
                 glyph.toMask(&mask);
                 if (fPreBlend.isApplicable()) {
@@ -522,20 +568,22 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static int move_proc(const FT_Vector* pt, void* ctx) {
+namespace {
+
+int move_proc(const FT_Vector* pt, void* ctx) {
     SkPath* path = (SkPath*)ctx;
     path->close();  // to close the previous contour (if any)
     path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
     return 0;
 }
 
-static int line_proc(const FT_Vector* pt, void* ctx) {
+int line_proc(const FT_Vector* pt, void* ctx) {
     SkPath* path = (SkPath*)ctx;
     path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y));
     return 0;
 }
 
-static int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
+int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
                      void* ctx) {
     SkPath* path = (SkPath*)ctx;
     path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
@@ -543,7 +591,7 @@ static int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
     return 0;
 }
 
-static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
+int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
                       const FT_Vector* pt2, void* ctx) {
     SkPath* path = (SkPath*)ctx;
     path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
@@ -552,9 +600,9 @@ static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
     return 0;
 }
 
-void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
-                                                      SkPath* path)
-{
+}  // namespace
+
+void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
     FT_Outline_Funcs    funcs;
 
     funcs.move_to   = move_proc;