Bug 1318573 - (Part 8) Move CanvasDrawPath to BasicRenderingContext2D. r?mstange draft
authorKevin Chen <kechen@mozilla.com>
Fri, 17 Feb 2017 15:23:25 +0800
changeset 499861 22802c0b8e7a1d6fa1573b4acc51b3d640118180
parent 499860 a3527a8ca53169907930220284368bedf1e9b810
child 499862 4caf7dd998e12aa359732ea2a5fd582f0c2e6671
push id49564
push userbmo:kechen@mozilla.com
push dateThu, 16 Mar 2017 09:50:15 +0000
reviewersmstange
bugs1318573
milestone54.0a1
Bug 1318573 - (Part 8) Move CanvasDrawPath to BasicRenderingContext2D. r?mstange MozReview-Commit-ID: AuUUARBeLxK
dom/canvas/BasicRenderingContext2D.cpp
dom/canvas/BasicRenderingContext2D.h
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasRenderingContext2D.h
--- a/dom/canvas/BasicRenderingContext2D.cpp
+++ b/dom/canvas/BasicRenderingContext2D.cpp
@@ -11,23 +11,26 @@
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/ImageBitmap.h"
 #include "nsContentUtils.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsPrintfCString.h"
 #include "nsStyleUtil.h"
 
+using mozilla::CanvasUtils::FloatValidate;
 using mozilla::gfx::AntialiasMode;
 using mozilla::gfx::CapStyle;
 using mozilla::gfx::Color;
 using mozilla::gfx::DrawOptions;
 using mozilla::gfx::ExtendMode;
+using mozilla::gfx::FillRule;
 using mozilla::gfx::JoinStyle;
 using mozilla::gfx::IntSize;
+using mozilla::gfx::Path;
 using mozilla::gfx::SamplingFilter;
 using mozilla::gfx::SourceSurface;
 using mozilla::gfx::StrokeOptions;
 using mozilla::gfx::ToDeviceColor;
 
 namespace mozilla {
 namespace dom{
 
@@ -745,16 +748,239 @@ BasicRenderingContext2D::StrokeRect(doub
   Redraw();
 }
 
 //
 // path bits
 //
 
 void
+BasicRenderingContext2D::BeginPath()
+{
+  mPath = nullptr;
+  mPathBuilder = nullptr;
+  mDSPathBuilder = nullptr;
+  mPathTransformWillUpdate = false;
+}
+
+void
+BasicRenderingContext2D::Fill(const CanvasWindingRule& aWinding)
+{
+  EnsureUserSpacePath(aWinding);
+
+  if (!mPath) {
+    return;
+  }
+
+  gfx::Rect bounds;
+
+  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();
+}
+
+void BasicRenderingContext2D::Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding)
+{
+  EnsureTarget();
+
+  RefPtr<gfx::Path> gfxpath = aPath.GetPath(aWinding, mTarget);
+
+  if (!gfxpath) {
+    return;
+  }
+
+  gfx::Rect bounds;
+
+  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();
+}
+
+void
+BasicRenderingContext2D::Stroke()
+{
+  EnsureUserSpacePath();
+
+  if (!mPath) {
+    return;
+  }
+
+  const ContextState &state = CurrentState();
+
+  StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
+                              state.lineCap, state.miterLimit,
+                              state.dash.Length(), state.dash.Elements(),
+                              state.dashOffset);
+
+  gfx::Rect bounds;
+  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()));
+
+  Redraw();
+}
+
+void
+BasicRenderingContext2D::Stroke(const CanvasPath& aPath)
+{
+  EnsureTarget();
+
+  RefPtr<gfx::Path> gfxpath = aPath.GetPath(CanvasWindingRule::Nonzero, mTarget);
+
+  if (!gfxpath) {
+    return;
+  }
+
+  const ContextState &state = CurrentState();
+
+  StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
+                              state.lineCap, state.miterLimit,
+                              state.dash.Length(), state.dash.Elements(),
+                              state.dashOffset);
+
+  gfx::Rect bounds;
+  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()));
+
+  Redraw();
+}
+
+void
+BasicRenderingContext2D::Clip(const CanvasWindingRule& aWinding)
+{
+  EnsureUserSpacePath(aWinding);
+
+  if (!mPath) {
+    return;
+  }
+
+  mTarget->PushClip(mPath);
+  CurrentState().clipsAndTransforms.AppendElement(ClipState(mPath));
+}
+
+void
+BasicRenderingContext2D::Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding)
+{
+  EnsureTarget();
+
+  RefPtr<gfx::Path> gfxpath = aPath.GetPath(aWinding, mTarget);
+
+  if (!gfxpath) {
+    return;
+  }
+
+  mTarget->PushClip(gfxpath);
+  CurrentState().clipsAndTransforms.AppendElement(ClipState(gfxpath));
+}
+
+bool
+BasicRenderingContext2D::IsPointInPath(double aX, double aY, const CanvasWindingRule& aWinding)
+{
+  if (!FloatValidate(aX, aY)) {
+    return false;
+  }
+
+  EnsureUserSpacePath(aWinding);
+  if (!mPath) {
+    return false;
+  }
+
+  if (mPathTransformWillUpdate) {
+    return mPath->ContainsPoint(Point(aX, aY), mPathToDS);
+  }
+
+  return mPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
+}
+
+bool BasicRenderingContext2D::IsPointInPath(const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding)
+{
+  if (!FloatValidate(aX, aY)) {
+    return false;
+  }
+
+  EnsureTarget();
+  RefPtr<gfx::Path> tempPath = aPath.GetPath(aWinding, mTarget);
+
+  return tempPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
+}
+
+bool
+BasicRenderingContext2D::IsPointInStroke(double aX, double aY)
+{
+  if (!FloatValidate(aX, aY)) {
+    return false;
+  }
+
+  EnsureUserSpacePath();
+  if (!mPath) {
+    return false;
+  }
+
+  const ContextState &state = CurrentState();
+
+  StrokeOptions strokeOptions(state.lineWidth,
+                              state.lineJoin,
+                              state.lineCap,
+                              state.miterLimit,
+                              state.dash.Length(),
+                              state.dash.Elements(),
+                              state.dashOffset);
+
+  if (mPathTransformWillUpdate) {
+    return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mPathToDS);
+  }
+  return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mTarget->GetTransform());
+}
+
+bool BasicRenderingContext2D::IsPointInStroke(const CanvasPath& aPath, double aX, double aY)
+{
+  if (!FloatValidate(aX, aY)) {
+    return false;
+  }
+
+  EnsureTarget();
+  RefPtr<gfx::Path> tempPath = aPath.GetPath(CanvasWindingRule::Nonzero, mTarget);
+
+  const ContextState &state = CurrentState();
+
+  StrokeOptions strokeOptions(state.lineWidth,
+                              state.lineJoin,
+                              state.lineCap,
+                              state.miterLimit,
+                              state.dash.Length(),
+                              state.dash.Elements(),
+                              state.dashOffset);
+
+  return tempPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mTarget->GetTransform());
+}
+
+void
 BasicRenderingContext2D::TransformWillUpdate()
 {
   EnsureTarget();
 
   // Store the matrix that would transform the current path to device
   // space.
   if (mPath || mPathBuilder) {
     if (!mPathTransformWillUpdate) {
@@ -763,16 +989,68 @@ BasicRenderingContext2D::TransformWillUp
       // transform the current mPath into device space.
       // We should leave it alone.
       mPathToDS = mTarget->GetTransform();
     }
     mPathTransformWillUpdate = true;
   }
 }
 
+void
+BasicRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& aWinding)
+{
+  FillRule fillRule = CurrentState().fillRule;
+  if (aWinding == CanvasWindingRule::Evenodd)
+    fillRule = FillRule::FILL_EVEN_ODD;
+
+  EnsureTarget();
+
+  if (!mPath && !mPathBuilder && !mDSPathBuilder) {
+    mPathBuilder = mTarget->CreatePathBuilder(fillRule);
+  }
+
+  if (mPathBuilder) {
+    mPath = mPathBuilder->Finish();
+    mPathBuilder = nullptr;
+  }
+
+  if (mPath &&
+      mPathTransformWillUpdate) {
+    mDSPathBuilder =
+      mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
+    mPath = nullptr;
+    mPathTransformWillUpdate = false;
+  }
+
+  if (mDSPathBuilder) {
+    RefPtr<Path> dsPath;
+    dsPath = mDSPathBuilder->Finish();
+    mDSPathBuilder = nullptr;
+
+    Matrix inverse = mTarget->GetTransform();
+    if (!inverse.Invert()) {
+      NS_WARNING("Could not invert transform");
+      return;
+    }
+
+    mPathBuilder =
+      dsPath->TransformedCopyToBuilder(inverse, fillRule);
+    mPath = mPathBuilder->Finish();
+    mPathBuilder = nullptr;
+  }
+
+  if (mPath && mPath->GetFillRule() != fillRule) {
+    mPathBuilder = mPath->CopyToBuilder(fillRule);
+    mPath = mPathBuilder->Finish();
+    mPathBuilder = nullptr;
+  }
+
+  NS_ASSERTION(mPath, "mPath should exist");
+}
+
 Pattern&
 CanvasGeneralPattern::ForStyle(BasicRenderingContext2D* aCtx,
                                BasicRenderingContext2D::Style aStyle,
                                DrawTarget* aRT)
 {
   // This should only be called once or the mPattern destructor will
   // not be executed.
   NS_ASSERTION(!mPattern.GetPattern(), "ForStyle() should only be called once on CanvasGeneralPattern!");
--- a/dom/canvas/BasicRenderingContext2D.h
+++ b/dom/canvas/BasicRenderingContext2D.h
@@ -204,16 +204,31 @@ public:
   //
   // CanvasRect
   //
   void ClearRect(double aX, double aY, double aW, double aH);
   void FillRect(double aX, double aY, double aW, double aH);
   void StrokeRect(double aX, double aY, double aW, double aH);
 
   //
+  // CanvasDrawPath
+  //
+  void BeginPath();
+  void Fill(const CanvasWindingRule& aWinding);
+  void Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
+  void Stroke();
+  void Stroke(const CanvasPath& aPath);
+  void Clip(const CanvasWindingRule& aWinding);
+  void Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
+  bool IsPointInPath(double aX, double aY, const CanvasWindingRule& aWinding);
+  bool IsPointInPath(const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding);
+  bool IsPointInStroke(double aX, double aY);
+  bool IsPointInStroke(const CanvasPath& aPath, double aX, double aY);
+
+  //
   // CanvasDrawImage
   //
   virtual void DrawImage(const CanvasImageSource& aImage,
                          double aDx,
                          double aDy,
                          mozilla::ErrorResult& aError) = 0;
   virtual void DrawImage(const CanvasImageSource& aImage,
                          double aDx,
@@ -508,16 +523,42 @@ protected:
     *
     * mPath is always in user-space.
     */
   RefPtr<mozilla::gfx::Path> mPath;
   RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
   bool mPathTransformWillUpdate;
   Matrix mPathToDS;
 
+  /**
+    * We also have a device space pathbuilder. The reason for this is as
+    * follows, when a path is being built, but the transform changes, we
+    * can no longer keep a single path in userspace, considering there's
+    * several 'user spaces' now. We therefore transform the current path
+    * into device space, and add all operations to this path in device
+    * space.
+    *
+    * When then finally executing a render, the Azure drawing API expects
+    * the path to be in userspace. We could then set an identity transform
+    * on the DrawTarget and do all drawing in device space. This is
+    * undesirable because it requires transforming patterns, gradients,
+    * clips, etc. into device space and it would not work for stroking.
+    * What we do instead is convert the path back to user space when it is
+    * drawn, and draw it with the current transform. This makes all drawing
+    * occur correctly.
+    *
+    * There's never both a device space path builder and a user space path
+    * builder present at the same time. There is also never a path and a
+    * path builder present at the same time. When writing proceeds on an
+    * existing path the Path is cleared and a new builder is created.
+    *
+    * mPath is always in user-space.
+    */
+  RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
+
 protected:
   virtual HTMLCanvasElement* GetCanvasElement() = 0;
 
   virtual bool AlreadyShutDown() const = 0;
 
   /**
    * Create the backing surfacing, if it doesn't exist. If there is an error
    * in creating the target then it will put sErrorTarget in place. If there
@@ -610,16 +651,19 @@ protected:
     * drawn with a filter.
     */
   virtual bool NeedToApplyFilter() = 0;
 
   bool NeedToCalculateBounds()
   {
     return NeedToDrawShadow() || NeedToApplyFilter();
   }
+
+  // Ensures a path in UserSpace is available.
+  void EnsureUserSpacePath(const CanvasWindingRule& aWinding = CanvasWindingRule::Nonzero);
 };
 
  NS_DEFINE_STATIC_IID_ACCESSOR(BasicRenderingContext2D,
                                NS_BASICRENDERINGCONTEXT2D_IID)
 
 // This class is named 'GeneralCanvasPattern' instead of just
 // 'GeneralPattern' to keep Windows PGO builds from confusing the
 // GeneralPattern class in gfxContext.cpp with this one.
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -53,17 +53,16 @@
 #include "gfxBlur.h"
 #include "gfxPrefs.h"
 
 #include "nsFrameLoader.h"
 #include "nsBidi.h"
 #include "nsBidiPresUtils.h"
 #include "Layers.h"
 #include "LayerUserData.h"
-#include "CanvasUtils.h"
 #include "nsIMemoryReporter.h"
 #include "CanvasImageCache.h"
 
 #include <algorithm>
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/Conversions.h"
@@ -2004,130 +2003,16 @@ CanvasRenderingContext2D::UpdateFilter()
       CurrentState().filterAdditionalImages);
   CurrentState().filterSourceGraphicTainted = sourceGraphicIsTainted;
 }
 
 //
 // path bits
 //
 
-void
-CanvasRenderingContext2D::BeginPath()
-{
-  mPath = nullptr;
-  mPathBuilder = nullptr;
-  mDSPathBuilder = nullptr;
-  mPathTransformWillUpdate = false;
-}
-
-void
-CanvasRenderingContext2D::Fill(const CanvasWindingRule& aWinding)
-{
-  EnsureUserSpacePath(aWinding);
-
-  if (!mPath) {
-    return;
-  }
-
-  gfx::Rect bounds;
-
-  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();
-}
-
-void CanvasRenderingContext2D::Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding)
-{
-  EnsureTarget();
-
-  RefPtr<gfx::Path> gfxpath = aPath.GetPath(aWinding, mTarget);
-
-  if (!gfxpath) {
-    return;
-  }
-
-  gfx::Rect bounds;
-
-  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();
-}
-
-void
-CanvasRenderingContext2D::Stroke()
-{
-  EnsureUserSpacePath();
-
-  if (!mPath) {
-    return;
-  }
-
-  const ContextState &state = CurrentState();
-
-  StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
-                              state.lineCap, state.miterLimit,
-                              state.dash.Length(), state.dash.Elements(),
-                              state.dashOffset);
-
-  gfx::Rect bounds;
-  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()));
-
-  Redraw();
-}
-
-void
-CanvasRenderingContext2D::Stroke(const CanvasPath& aPath)
-{
-  EnsureTarget();
-
-  RefPtr<gfx::Path> gfxpath = aPath.GetPath(CanvasWindingRule::Nonzero, mTarget);
-
-  if (!gfxpath) {
-    return;
-  }
-
-  const ContextState &state = CurrentState();
-
-  StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
-                              state.lineCap, state.miterLimit,
-                              state.dash.Length(), state.dash.Elements(),
-                              state.dashOffset);
-
-  gfx::Rect bounds;
-  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()));
-
-  Redraw();
-}
-
 void CanvasRenderingContext2D::DrawFocusIfNeeded(mozilla::dom::Element& aElement,
                                                  ErrorResult& aRv)
 {
   EnsureUserSpacePath();
 
   if (!mPath) {
     return;
   }
@@ -2193,44 +2078,16 @@ bool CanvasRenderingContext2D::DrawCusto
       }
     }
   }
 
   return false;
 }
 
 void
-CanvasRenderingContext2D::Clip(const CanvasWindingRule& aWinding)
-{
-  EnsureUserSpacePath(aWinding);
-
-  if (!mPath) {
-    return;
-  }
-
-  mTarget->PushClip(mPath);
-  CurrentState().clipsAndTransforms.AppendElement(ClipState(mPath));
-}
-
-void
-CanvasRenderingContext2D::Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding)
-{
-  EnsureTarget();
-
-  RefPtr<gfx::Path> gfxpath = aPath.GetPath(aWinding, mTarget);
-
-  if (!gfxpath) {
-    return;
-  }
-
-  mTarget->PushClip(gfxpath);
-  CurrentState().clipsAndTransforms.AppendElement(ClipState(gfxpath));
-}
-
-void
 CanvasRenderingContext2D::ArcTo(double aX1, double aY1, double aX2,
                                 double aY2, double aRadius,
                                 ErrorResult& aError)
 {
   if (aRadius < 0) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
@@ -2385,68 +2242,16 @@ CanvasRenderingContext2D::EnsureWritable
   } else {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPathTransformWillUpdate = false;
     mPath = nullptr;
   }
 }
 
-void
-CanvasRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& aWinding)
-{
-  FillRule fillRule = CurrentState().fillRule;
-  if (aWinding == CanvasWindingRule::Evenodd)
-    fillRule = FillRule::FILL_EVEN_ODD;
-
-  EnsureTarget();
-
-  if (!mPath && !mPathBuilder && !mDSPathBuilder) {
-    mPathBuilder = mTarget->CreatePathBuilder(fillRule);
-  }
-
-  if (mPathBuilder) {
-    mPath = mPathBuilder->Finish();
-    mPathBuilder = nullptr;
-  }
-
-  if (mPath &&
-      mPathTransformWillUpdate) {
-    mDSPathBuilder =
-      mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
-    mPath = nullptr;
-    mPathTransformWillUpdate = false;
-  }
-
-  if (mDSPathBuilder) {
-    RefPtr<Path> dsPath;
-    dsPath = mDSPathBuilder->Finish();
-    mDSPathBuilder = nullptr;
-
-    Matrix inverse = mTarget->GetTransform();
-    if (!inverse.Invert()) {
-      NS_WARNING("Could not invert transform");
-      return;
-    }
-
-    mPathBuilder =
-      dsPath->TransformedCopyToBuilder(inverse, fillRule);
-    mPath = mPathBuilder->Finish();
-    mPathBuilder = nullptr;
-  }
-
-  if (mPath && mPath->GetFillRule() != fillRule) {
-    mPathBuilder = mPath->CopyToBuilder(fillRule);
-    mPath = mPathBuilder->Finish();
-    mPathBuilder = nullptr;
-  }
-
-  NS_ASSERTION(mPath, "mPath should exist");
-}
-
 //
 // text
 //
 
 void
 CanvasRenderingContext2D::SetFont(const nsAString& aFont,
                                   ErrorResult& aError)
 {
@@ -3404,97 +3209,16 @@ CanvasRenderingContext2D::SetLineDashOff
   CurrentState().dashOffset = aOffset;
 }
 
 double
 CanvasRenderingContext2D::LineDashOffset() const {
   return CurrentState().dashOffset;
 }
 
-bool
-CanvasRenderingContext2D::IsPointInPath(double aX, double aY, const CanvasWindingRule& aWinding)
-{
-  if (!FloatValidate(aX, aY)) {
-    return false;
-  }
-
-  EnsureUserSpacePath(aWinding);
-  if (!mPath) {
-    return false;
-  }
-
-  if (mPathTransformWillUpdate) {
-    return mPath->ContainsPoint(Point(aX, aY), mPathToDS);
-  }
-
-  return mPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
-}
-
-bool CanvasRenderingContext2D::IsPointInPath(const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding)
-{
-  if (!FloatValidate(aX, aY)) {
-    return false;
-  }
-
-  EnsureTarget();
-  RefPtr<gfx::Path> tempPath = aPath.GetPath(aWinding, mTarget);
-
-  return tempPath->ContainsPoint(Point(aX, aY), mTarget->GetTransform());
-}
-
-bool
-CanvasRenderingContext2D::IsPointInStroke(double aX, double aY)
-{
-  if (!FloatValidate(aX, aY)) {
-    return false;
-  }
-
-  EnsureUserSpacePath();
-  if (!mPath) {
-    return false;
-  }
-
-  const ContextState &state = CurrentState();
-
-  StrokeOptions strokeOptions(state.lineWidth,
-                              state.lineJoin,
-                              state.lineCap,
-                              state.miterLimit,
-                              state.dash.Length(),
-                              state.dash.Elements(),
-                              state.dashOffset);
-
-  if (mPathTransformWillUpdate) {
-    return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mPathToDS);
-  }
-  return mPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mTarget->GetTransform());
-}
-
-bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& aPath, double aX, double aY)
-{
-  if (!FloatValidate(aX, aY)) {
-    return false;
-  }
-
-  EnsureTarget();
-  RefPtr<gfx::Path> tempPath = aPath.GetPath(CanvasWindingRule::Nonzero, mTarget);
-
-  const ContextState &state = CurrentState();
-
-  StrokeOptions strokeOptions(state.lineWidth,
-                              state.lineJoin,
-                              state.lineCap,
-                              state.miterLimit,
-                              state.dash.Length(),
-                              state.dash.Elements(),
-                              state.dashOffset);
-
-  return tempPath->StrokeContainsPoint(strokeOptions, Point(aX, aY), mTarget->GetTransform());
-}
-
 // Returns a surface that contains only the part needed to draw aSourceRect.
 // On entry, aSourceRect is relative to aSurface, and on return aSourceRect is
 // relative to the returned surface.
 static already_AddRefed<SourceSurface>
 ExtractSubrect(SourceSurface* aSurface, gfx::Rect* aSourceRect, DrawTarget* aTargetDT)
 {
   gfx::Rect roundedOutSourceRect = *aSourceRect;
   roundedOutSourceRect.RoundOut();
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -75,29 +75,18 @@ public:
   }
 
   void GetFilter(nsAString& aFilter)
   {
     aFilter = CurrentState().filterString;
   }
 
   void SetFilter(const nsAString& aFilter, mozilla::ErrorResult& aError);
-  void BeginPath();
-  void Fill(const CanvasWindingRule& aWinding);
-  void Fill(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
-  void Stroke();
-  void Stroke(const CanvasPath& aPath);
   void DrawFocusIfNeeded(mozilla::dom::Element& aElement, ErrorResult& aRv);
   bool DrawCustomFocusRing(mozilla::dom::Element& aElement);
-  void Clip(const CanvasWindingRule& aWinding);
-  void Clip(const CanvasPath& aPath, const CanvasWindingRule& aWinding);
-  bool IsPointInPath(double aX, double aY, const CanvasWindingRule& aWinding);
-  bool IsPointInPath(const CanvasPath& aPath, double aX, double aY, const CanvasWindingRule& aWinding);
-  bool IsPointInStroke(double aX, double aY);
-  bool IsPointInStroke(const CanvasPath& aPath, double aX, double aY);
   void FillText(const nsAString& aText, double aX, double aY,
                 const Optional<double>& aMaxWidth,
                 mozilla::ErrorResult& aError);
   void StrokeText(const nsAString& aText, double aX, double aY,
                   const Optional<double>& aMaxWidth,
                   mozilla::ErrorResult& aError);
   TextMetrics*
     MeasureText(const nsAString& aRawText, mozilla::ErrorResult& aError);
@@ -466,19 +455,16 @@ protected:
 
   /* This function ensures there is a writable pathbuilder available, this
    * pathbuilder may be working in user space or in device space or
    * device space.
    * After calling this function mPathTransformWillUpdate will be false
    */
   void EnsureWritablePath();
 
-  // Ensures a path in UserSpace is available.
-  void EnsureUserSpacePath(const CanvasWindingRule& aWinding = CanvasWindingRule::Nonzero);
-
   // Report the fillRule has changed.
   void FillRuleChanged();
 
   /**
    * Create the backing surfacing, if it doesn't exist. If there is an error
    * in creating the target then it will put sErrorTarget in place. If there
    * is in turn an error in creating the sErrorTarget then they would both
    * be null so IsTargetValid() would still return null.
@@ -638,42 +624,16 @@ protected:
   /**
    * Flag to avoid unnecessary surface copies to FrameCaptureListeners in the
    * case when the canvas is not currently being drawn into and not rendered
    * but canvas capturing is still ongoing.
    */
   bool mIsCapturedFrameInvalid;
 
   /**
-    * We also have a device space pathbuilder. The reason for this is as
-    * follows, when a path is being built, but the transform changes, we
-    * can no longer keep a single path in userspace, considering there's
-    * several 'user spaces' now. We therefore transform the current path
-    * into device space, and add all operations to this path in device
-    * space.
-    *
-    * When then finally executing a render, the Azure drawing API expects
-    * the path to be in userspace. We could then set an identity transform
-    * on the DrawTarget and do all drawing in device space. This is
-    * undesirable because it requires transforming patterns, gradients,
-    * clips, etc. into device space and it would not work for stroking.
-    * What we do instead is convert the path back to user space when it is
-    * drawn, and draw it with the current transform. This makes all drawing
-    * occur correctly.
-    *
-    * There's never both a device space path builder and a user space path
-    * builder present at the same time. There is also never a path and a
-    * path builder present at the same time. When writing proceeds on an
-    * existing path the Path is cleared and a new builder is created.
-    *
-    * mPath is always in user-space.
-    */
-  RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
-
-  /**
     * Number of times we've invalidated before calling redraw
     */
   uint32_t mInvalidateCount;
   static const uint32_t kCanvasMaxInvalidateCount = 100;
 
   /**
     * State information for hit regions
     */