Bug 927892 - Also calculate bounds for canvas operations when a filter is used. r=Bas
authorMarkus Stange <mstange@themasta.com>
Tue, 23 Sep 2014 17:47:19 -0400
changeset 230138 ef9e17516cbcbd8e144be6f37c335813a1badf90
parent 230137 24a838f90b5c1619432f478d0b9e3a89a9b0b864
child 230139 e633da2eea486bdb816f6eb1668dc23164ba2f63
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs927892
milestone35.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 927892 - Also calculate bounds for canvas operations when a filter is used. r=Bas
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasRenderingContext2D.h
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2020,17 +2020,17 @@ CanvasRenderingContext2D::FillRect(doubl
         }
       }
     }
   }
 
   mgfx::Rect bounds;
 
   EnsureTarget();
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds = mgfx::Rect(x, y, w, h);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     FillRect(mgfx::Rect(x, y, w, h),
              CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
              DrawOptions(state.globalAlpha, UsedOperation()));
@@ -2050,17 +2050,17 @@ CanvasRenderingContext2D::StrokeRect(dou
     return;
   }
 
   EnsureTarget();
   if (!IsTargetValid()) {
     return;
   }
 
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
                         w + state.lineWidth, h + state.lineWidth);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   if (!h) {
     CapStyle cap = CapStyle::BUTT;
     if (state.lineJoin == JoinStyle::ROUND) {
@@ -2127,17 +2127,17 @@ CanvasRenderingContext2D::Fill(const Can
   EnsureUserSpacePath(winding);
 
   if (!mPath) {
     return;
   }
 
   mgfx::Rect bounds;
 
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds = mPath->GetBounds(mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Fill(mPath, CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   Redraw();
@@ -2150,17 +2150,17 @@ void CanvasRenderingContext2D::Fill(cons
   RefPtr<gfx::Path> gfxpath = path.GetPath(winding, mTarget);
 
   if (!gfxpath) {
     return;
   }
 
   mgfx::Rect bounds;
 
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds = gfxpath->GetBounds(mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Fill(gfxpath, CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   Redraw();
@@ -2178,17 +2178,17 @@ CanvasRenderingContext2D::Stroke()
   const ContextState &state = CurrentState();
 
   StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
                               state.lineCap, state.miterLimit,
                               state.dash.Length(), state.dash.Elements(),
                               state.dashOffset);
 
   mgfx::Rect bounds;
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds =
       mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Stroke(mPath, CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
@@ -2209,17 +2209,17 @@ CanvasRenderingContext2D::Stroke(const C
   const ContextState &state = CurrentState();
 
   StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
                               state.lineCap, state.miterLimit,
                               state.dash.Length(), state.dash.Elements(),
                               state.dashOffset);
 
   mgfx::Rect bounds;
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds =
       gfxpath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Stroke(gfxpath, CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
@@ -3117,17 +3117,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
       *aWidth = 0;
     }
     return NS_OK;
   }
 
   const ContextState &state = CurrentState();
 
   // This is only needed to know if we can know the drawing bounding box easily.
-  bool doDrawShadow = NeedToDrawShadow();
+  bool doCalculateBounds = NeedToCalculateBounds();
 
   CanvasBidiProcessor processor;
 
   GetAppUnitsValues(&processor.mAppUnitsPerDevPixel, nullptr);
   processor.mPt = gfxPoint(aX, aY);
   processor.mThebes =
     new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
 
@@ -3136,17 +3136,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
   // to avoid creating a target if it's only being used to measure text sizes.
   if (mTarget) {
     Matrix matrix = mTarget->GetTransform();
     processor.mThebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21, matrix._22, matrix._31, matrix._32));
   }
   processor.mCtx = this;
   processor.mOp = aOp;
   processor.mBoundingBox = gfxRect(0, 0, 0, 0);
-  processor.mDoMeasureBoundingBox = doDrawShadow || !mIsEntireFrameInvalid;
+  processor.mDoMeasureBoundingBox = doCalculateBounds || !mIsEntireFrameInvalid;
   processor.mState = &CurrentState();
   processor.mFontgrp = currentFontStyle;
 
   nscoord totalWidthCoord;
 
   // calls bidi algo twice since it needs the full text width and the
   // bounding boxes before rendering anything
   nsBidi bidiEngine;
@@ -3261,17 +3261,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
                                     0,
                                     nullptr,
                                     &bidiEngine);
 
 
   mTarget->SetTransform(oldTransform);
 
   if (aOp == CanvasRenderingContext2D::TextDrawOperation::FILL &&
-      !doDrawShadow) {
+      !doCalculateBounds) {
     RedrawUser(boundingBox);
     return NS_OK;
   }
 
   Redraw();
   return NS_OK;
 }
 
@@ -3674,17 +3674,17 @@ CanvasRenderingContext2D::DrawImage(cons
 
   if (CurrentState().imageSmoothingEnabled)
     filter = mgfx::Filter::LINEAR;
   else
     filter = mgfx::Filter::POINT;
 
   mgfx::Rect bounds;
 
-  if (NeedToDrawShadow()) {
+  if (NeedToCalculateBounds()) {
     bounds = mgfx::Rect(dx, dy, dw, dh);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   if (srcSurf) {
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       DrawSurface(srcSurf,
                   mgfx::Rect(dx, dy, dw, dh),
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -852,16 +852,21 @@ protected:
     * drawn with a filter.
     */
   bool NeedToApplyFilter()
   {
     const ContextState& state = CurrentState();
     return state.filter.mPrimitives.Length() > 0;
   }
 
+  bool NeedToCalculateBounds()
+  {
+    return NeedToDrawShadow() || NeedToApplyFilter();
+  }
+
   mozilla::gfx::CompositionOp UsedOperation()
   {
     if (NeedToDrawShadow()) {
       // In this case the shadow rendering will use the operator.
       return mozilla::gfx::CompositionOp::OP_OVER;
     }
 
     return CurrentState().op;