Bug 1288872 - verify cairo_scaled_font creation succeeds in SkFontHost_cairo. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Fri, 22 Jul 2016 21:23:56 -0400
changeset 348537 0a819a2a98f684748b9fe59363ec3f994e16f4a0
parent 348536 f9ecbe4d60f8cfd3dbb496a494b176e36c570719
child 348538 d8af5416b0627e13948a3e400ba0e9f152a5ee48
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1288872
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1288872 - verify cairo_scaled_font creation succeeds in SkFontHost_cairo. r=mchang MozReview-Commit-ID: JKRiyQgi9Y2
dom/canvas/crashtests/1288872-1.html
dom/canvas/crashtests/crashtests.list
gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
new file mode 100644
--- /dev/null
+++ b/dom/canvas/crashtests/1288872-1.html
@@ -0,0 +1,6 @@
+<canvas id='id0'></canvas>
+<script>
+var c=document.getElementById('id0').getContext('2d');
+c.transform(1,0,1,0,0,0);
+c.fillText('A',0,53);
+</script>
\ No newline at end of file
--- a/dom/canvas/crashtests/crashtests.list
+++ b/dom/canvas/crashtests/crashtests.list
@@ -25,8 +25,10 @@ load 1183363.html
 load 1190705.html
 load 1223740-1.html
 load 1225381-1.html
 skip-if(azureCairo) load 1229983-1.html
 load 1229932-1.html
 load 1244850-1.html
 load 1246775-1.html
 skip-if(d2d) load 1287515-1.html
+load 1288872-1.html
+
--- a/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
@@ -84,16 +84,20 @@ template<> struct SkTUnref<FcPattern> {
 };
 
 class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base {
 public:
     SkScalerContext_CairoFT(SkTypeface* typeface, const SkDescriptor* desc,
                             cairo_font_face_t* fontFace, FcPattern* pattern);
     virtual ~SkScalerContext_CairoFT();
 
+    bool isValid() const {
+        return fScaledFont != nullptr;
+    }
+
 protected:
     virtual unsigned generateGlyphCount() override;
     virtual uint16_t generateCharToGlyph(SkUnichar uniChar) override;
     virtual void generateAdvance(SkGlyph* glyph) override;
     virtual void generateMetrics(SkGlyph* glyph) override;
     virtual void generateImage(const SkGlyph& glyph) override;
     virtual void generatePath(const SkGlyph& glyph, SkPath* path) override;
     virtual void generateFontMetrics(SkPaint::FontMetrics* metrics) override;
@@ -183,18 +187,24 @@ public:
                                      const uint32_t*, uint32_t) const override
     {
         SkDEBUGCODE(SkDebugf("SkCairoFTTypeface::onGetAdvancedTypefaceMetrics unimplemented\n"));
         return nullptr;
     }
 
     virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const override
     {
-        return new SkScalerContext_CairoFT(const_cast<SkCairoFTTypeface*>(this), desc,
-                                           fFontFace, fPattern);
+        SkScalerContext_CairoFT* ctx =
+            new SkScalerContext_CairoFT(const_cast<SkCairoFTTypeface*>(this), desc,
+                                        fFontFace, fPattern);
+        if (!ctx->isValid()) {
+            delete ctx;
+            return nullptr;
+        }
+        return ctx;
     }
 
     virtual void onFilterRec(SkScalerContextRec* rec) const override
     {
         // No subpixel AA unless enabled in Fontconfig.
         if (!fPattern && isLCD(*rec)) {
             rec->fMaskFormat = SkMask::kA8_Format;
         }
@@ -521,17 +531,17 @@ bool SkScalerContext_CairoFT::computeSha
     double minor = major != 0.0 ? fabs(det) / major : 0.0;
     // Limit scales to be above 1pt.
     major = SkTMax(major, 1.0);
     minor = SkTMax(minor, 1.0);
 
     // If the font is not scalable, then choose the best available size.
     CairoLockedFTFace faceLock(fScaledFont);
     FT_Face face = faceLock.getFace();
-    if (!FT_IS_SCALABLE(face)) {
+    if (face && !FT_IS_SCALABLE(face)) {
         double bestDist = DBL_MAX;
         FT_Int bestSize = -1;
         for (FT_Int i = 0; i < face->num_fixed_sizes; i++) {
             // Distance is positive if strike is larger than desired size,
             // or negative if smaller. If previously a found smaller strike,
             // then prefer a larger strike. Otherwise, minimize distance.
             double dist = face->available_sizes[i].y_ppem / 64.0 - minor;
             if (bestDist < 0 ? dist >= bestDist : fabs(dist) <= bestDist) {