--- 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
*/