Bug 1066670: Deal with a failed brush creation by drawing transparent black. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Sun, 14 Sep 2014 23:51:34 +0200
changeset 718 4dbb4dba171a
parent 717 df63dbdce3b2
child 719 d166b9e0320d
push id274
push userbschouten@mozilla.com
push dateTue, 23 Sep 2014 16:10:56 +0000
reviewersjrmuizel
bugs1066670
Bug 1066670: Deal with a failed brush creation by drawing transparent black. r=jrmuizel
DrawTargetD2D.cpp
DrawTargetD2D1.cpp
DrawTargetD2D1.h
--- a/DrawTargetD2D.cpp
+++ b/DrawTargetD2D.cpp
@@ -2690,16 +2690,17 @@ DrawTargetD2D::factory()
   }
 
   D2D1_FACTORY_OPTIONS options;
 #ifdef _DEBUG
   options.debugLevel = D2D1_DEBUG_LEVEL_WARNING;
 #else
   options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
 #endif
+  //options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
 
   HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
                                 __uuidof(ID2D1Factory),
                                 &options,
                                 (void**)&mFactory);
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create Direct2D factory.";
--- a/DrawTargetD2D1.cpp
+++ b/DrawTargetD2D1.cpp
@@ -664,16 +664,21 @@ DrawTargetD2D1::CreatePathBuilder(FillRu
   }
 
   return new PathBuilderD2D(sink, path, aFillRule);
 }
 
 TemporaryRef<GradientStops>
 DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const
 {
+  if (aNumStops == 0) {
+    gfxWarning() << *this << ": Failed to create GradientStopCollection with no stops.";
+    return nullptr;
+  }
+
   D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops];
 
   for (uint32_t i = 0; i < aNumStops; i++) {
     stops[i].position = rawStops[i].offset;
     stops[i].color = D2DColor(rawStops[i].color);
   }
 
   RefPtr<ID2D1GradientStopCollection> stopCollection;
@@ -1103,16 +1108,24 @@ DrawTargetD2D1::PopClipsFromDC(ID2D1Devi
       aDC->PopLayer();
     } else {
       aDC->PopAxisAlignedClip();
     }
   }
 }
 
 TemporaryRef<ID2D1Brush>
+DrawTargetD2D1::CreateTransparentBlackBrush()
+{
+  RefPtr<ID2D1SolidColorBrush> brush;
+  mDC->CreateSolidColorBrush(D2D1::ColorF(0, 0), byRef(brush));
+  return brush;
+}
+
+TemporaryRef<ID2D1Brush>
 DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
 {
   if (!IsPatternSupportedByD2D(aPattern)) {
     RefPtr<ID2D1SolidColorBrush> colBrush;
     mDC->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), byRef(colBrush));
     return colBrush.forget();
   }
 
@@ -1129,17 +1142,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
     RefPtr<ID2D1LinearGradientBrush> gradBrush;
     const LinearGradientPattern *pat =
       static_cast<const LinearGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
-      return nullptr;
+      return CreateTransparentBlackBrush();
     }
 
     if (pat->mBegin == pat->mEnd) {
       RefPtr<ID2D1SolidColorBrush> colBrush;
       uint32_t stopCount = stops->mStopCollection->GetGradientStopCount();
       vector<D2D1_GRADIENT_STOP> d2dStops(stopCount);
       stops->mStopCollection->GetGradientStops(&d2dStops.front(), stopCount);
       mDC->CreateSolidColorBrush(d2dStops.back().color,
@@ -1159,17 +1172,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
     RefPtr<ID2D1RadialGradientBrush> gradBrush;
     const RadialGradientPattern *pat =
       static_cast<const RadialGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
-      return nullptr;
+      return CreateTransparentBlackBrush();
     }
 
     // This will not be a complex radial gradient brush.
     mDC->CreateRadialGradientBrush(
       D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2),
                                           D2DPoint(pat->mCenter1 - pat->mCenter2),
                                           pat->mRadius2, pat->mRadius2),
       D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
@@ -1179,17 +1192,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
     return gradBrush.forget();
   }
   if (aPattern.GetType() == PatternType::SURFACE) {
     const SurfacePattern *pat =
       static_cast<const SurfacePattern*>(&aPattern);
 
     if (!pat->mSurface) {
       gfxDebug() << "No source surface specified for surface pattern";
-      return nullptr;
+      return CreateTransparentBlackBrush();
     }
 
     D2D1_RECT_F samplingBounds;
     if (!pat->mSamplingRect.IsEmpty()) {
       samplingBounds = D2DRect(pat->mSamplingRect);
     } else {
       samplingBounds = D2D1::RectF(0, 0,
                                    Float(pat->mSurface->GetSize().width),
@@ -1206,17 +1219,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
                                                      D2DExtend(pat->mExtendMode),
                                                      D2DInterpolationMode(pat->mFilter)),
                           D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
                           byRef(imageBrush));
     return imageBrush.forget();
   }
 
   gfxWarning() << "Invalid pattern type detected.";
-  return nullptr;
+  return CreateTransparentBlackBrush();
 }
 
 TemporaryRef<ID2D1Image>
 DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
                                    ExtendMode aExtendMode)
 {
   RefPtr<ID2D1Image> image;
 
--- a/DrawTargetD2D1.h
+++ b/DrawTargetD2D1.h
@@ -178,16 +178,17 @@ private:
   TemporaryRef<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
 
   bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
 
   void PopAllClips();
   void PushClipsToDC(ID2D1DeviceContext *aDC);
   void PopClipsFromDC(ID2D1DeviceContext *aDC);
 
+  TemporaryRef<ID2D1Brush> CreateTransparentBlackBrush();
   TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
 
   void PushD2DLayer(ID2D1DeviceContext *aDC, ID2D1Geometry *aGeometry, const D2D1_MATRIX_3X2_F &aTransform);
 
   IntSize mSize;
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11Texture2D> mTexture;