Bug 781731 - Fix shadow surface extents so they aren't double padded; r=roc
authorAnthony Jones <ajones@mozilla.com>
Mon, 27 Aug 2012 11:32:14 +0200
changeset 105583 4041007e49cd37f4fa1018bbda066c8cc158e2a9
parent 105582 ddff99db5f7c61f3a58eadde82541bf0235d5a3a
child 105584 aec0729913fee9e86cf3d7aff9315382f963b5ec
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersroc
bugs781731
milestone17.0a1
Bug 781731 - Fix shadow surface extents so they aren't double padded; r=roc
gfx/2d/Blur.cpp
gfx/2d/Blur.h
gfx/2d/DrawTargetCairo.cpp
--- a/gfx/2d/Blur.cpp
+++ b/gfx/2d/Blur.cpp
@@ -325,17 +325,18 @@ RoundUpToMultipleOf4(int32_t aVal)
 
 AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
                            const IntSize& aSpreadRadius,
                            const IntSize& aBlurRadius,
                            const Rect* aDirtyRect,
                            const Rect* aSkipRect)
  : mSpreadRadius(aSpreadRadius),
    mBlurRadius(aBlurRadius),
-   mData(nullptr)
+   mData(nullptr),
+   mFreeData(true)
 {
   Rect rect(aRect);
   rect.Inflate(Size(aBlurRadius + aSpreadRadius));
   rect.RoundOut();
 
   if (aDirtyRect) {
     // If we get passed a dirty rect from layout, we can minimize the
     // shadow size and make painting faster.
@@ -379,19 +380,35 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& a
                                sizeof(unsigned char);
     if (size.isValid()) {
       mData = static_cast<unsigned char*>(malloc(size.value()));
       memset(mData, 0, size.value());
     }
   }
 }
 
+AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData,
+                           const Rect& aRect,
+                           int8_t aStride,
+                           float aSigma)
+  : mSpreadRadius(),
+    mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))),
+    mData(aData),
+    mFreeData(false),
+    mStride(aStride),
+    mRect(aRect.x, aRect.y, aRect.width, aRect.height)
+{
+}
+
+
 AlphaBoxBlur::~AlphaBoxBlur()
 {
-  free(mData);
+  if (mFreeData) {
+    delete mData;
+  }
 }
 
 unsigned char*
 AlphaBoxBlur::GetData()
 {
   return mData;
 }
 
--- a/gfx/2d/Blur.h
+++ b/gfx/2d/Blur.h
@@ -52,16 +52,21 @@ public:
    *   speed reasons. It is safe to pass nullptr here.
    */
   AlphaBoxBlur(const Rect& aRect,
                const IntSize& aSpreadRadius,
                const IntSize& aBlurRadius,
                const Rect* aDirtyRect,
                const Rect* aSkipRect);
 
+  AlphaBoxBlur(uint8_t* aData,
+               const Rect& aRect,
+               int8_t aStride,
+               float aSigma);
+
   ~AlphaBoxBlur();
 
   /**
    * Return the pointer to memory allocated by the constructor for the 8-bit
    * alpha surface you need to be blurred. After you draw to this surface, call
    * Blur(), below, to have its contents blurred.
    */
   unsigned char* GetData();
@@ -130,17 +135,22 @@ private:
   /**
    * The blur radius, in pixels.
    */
   IntSize mBlurRadius;
 
   /**
    * A pointer to the backing 8-bit alpha surface.
    */
-  unsigned char* mData;
+  uint8_t* mData;
+
+  /**
+   * True if we need to dispose the data.
+   */
+  bool mFreeData;
 
   /**
    * The stride of the data contained in mData.
    */
   int32_t mStride;
 
   /**
    * Whether mDirtyRect contains valid data.
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -382,53 +382,43 @@ DrawTargetCairo::DrawSurfaceWithShadow(S
                                        const Point &aOffset,
                                        Float aSigma,
                                        CompositionOp aOperator)
 {
   if (aSurface->GetType() != SURFACE_CAIRO) {
     return;
   }
 
-  WillChange();
-
   Float width = aSurface->GetSize().width;
   Float height = aSurface->GetSize().height;
-  Rect extents(0, 0, width, height);
-
-  AlphaBoxBlur blur(extents, IntSize(0, 0),
-                    AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)),
-                    nullptr, nullptr);
-  if (!blur.GetData()) {
-    return;
-  }
-
-  IntSize blursize = blur.GetSize();
-  cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
-                                                                  CAIRO_FORMAT_A8,
-                                                                  blursize.width,
-                                                                  blursize.height,
-                                                                  blur.GetStride());
-
-  ClearSurfaceForUnboundedSource(aOperator);
-  
-  // Draw the source surface into the surface we're going to blur.
+ 
   SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
   cairo_surface_t* surf = source->GetSurface();
+ 
+  cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8,
+                                                         width,
+                                                         height);
 
   cairo_t* ctx = cairo_create(blursurf);
   cairo_set_source_surface(ctx, surf, 0, 0);
-  IntRect blurrect = blur.GetRect();
   cairo_new_path(ctx);
-  cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height);
+  cairo_rectangle(ctx, 0, 0, width, height);
   cairo_fill(ctx);
   cairo_destroy(ctx);
+ 
+  Rect extents(0, 0, width, height);
+  AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf),
+                    extents,
+                    cairo_image_surface_get_stride(blursurf),
+                    aSigma);
+  blur.Blur();
 
-  // Blur the result, then use that blurred result as a mask to draw the shadow
-  // colour to the surface.
-  blur.Blur();
+  WillChange();
+  ClearSurfaceForUnboundedSource(aOperator);
+  
   cairo_save(mContext);
   cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
 
   if (OperatorAffectsUncoveredAreas(aOperator) ||
       aOperator == OP_SOURCE){
     cairo_push_group(mContext);