Bug 1325319 - Implement isPointInFill() and isPointInStroke() for SVGGeometryElement r=longsonr,bzbarsky

Differential Revision: https://phabricator.services.mozilla.com/D33592

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-06-19 21:14:55 +00:00
Родитель 5cab43f3ff
Коммит 00989decc6
7 изменённых файлов: 70 добавлений и 140 удалений

Просмотреть файл

@ -15,6 +15,7 @@
#include "SVGEllipseElement.h"
#include "SVGGeometryProperty.h"
#include "SVGRectElement.h"
#include "mozilla/dom/DOMPointBinding.h"
#include "mozilla/dom/SVGLengthBinding.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/RefPtr.h"
@ -114,6 +115,18 @@ already_AddRefed<Path> SVGGeometryElement::GetOrBuildPathForMeasuring() {
return GetOrBuildPath(drawTarget, fillRule);
}
// This helper is currently identical to GetOrBuildPathForMeasuring.
// We keep it a separate method because for length measuring purpose,
// fillRule isn't really needed. Derived class (e.g. SVGPathElement)
// may override GetOrBuildPathForMeasuring() to ignore fillRule. And
// GetOrBuildPathForMeasuring() itself may be modified in the future.
already_AddRefed<Path> SVGGeometryElement::GetOrBuildPathForHitTest() {
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
FillRule fillRule = mCachedPath ? mCachedPath->GetFillRule() : GetFillRule();
return GetOrBuildPath(drawTarget, fillRule);
}
bool SVGGeometryElement::IsGeometryChangedViaCSS(
ComputedStyle const& aNewStyle, ComputedStyle const& aOldStyle) const {
if (IsSVGElement(nsGkAtoms::rect)) {
@ -153,6 +166,54 @@ FillRule SVGGeometryElement::GetFillRule() {
return fillRule;
}
static Point GetPointFrom(const DOMPointInit& aPoint) {
return Point(aPoint.mX, aPoint.mY);
}
bool SVGGeometryElement::IsPointInFill(const DOMPointInit& aPoint) {
auto point = GetPointFrom(aPoint);
RefPtr<Path> path = GetOrBuildPathForHitTest();
if (!path) {
return false;
}
return path->ContainsPoint(point, {});
}
bool SVGGeometryElement::IsPointInStroke(const DOMPointInit& aPoint) {
auto point = GetPointFrom(aPoint);
RefPtr<Path> path = GetOrBuildPathForHitTest();
if (!path) {
return false;
}
bool res = false;
SVGGeometryProperty::DoForComputedStyle(this, [&](const ComputedStyle* s) {
// Per spec, we should take vector-effect into account.
if (s->StyleSVGReset()->HasNonScalingStroke()) {
auto mat = SVGContentUtils::GetCTM(this, true);
if (mat.HasNonTranslation()) {
// We have non-scaling-stroke as well as a non-translation transform.
// We should transform the path first then apply the stroke on the
// transformed path to preserve the stroke-width.
RefPtr<PathBuilder> builder = path->TransformedCopyToBuilder(mat);
path = builder->Finish();
point = mat.TransformPoint(point);
}
}
SVGContentUtils::AutoStrokeOptions strokeOptions;
SVGContentUtils::GetStrokeOptions(&strokeOptions, this, s, nullptr);
res = path->StrokeContainsPoint(strokeOptions, point, {});
});
return res;
}
float SVGGeometryElement::GetTotalLength() {
RefPtr<Path> flat = GetOrBuildPathForMeasuring();
return flat ? flat->ComputeLength() : 0.f;

Просмотреть файл

@ -216,6 +216,8 @@ class SVGGeometryElement : public SVGGeometryElementBase {
// WebIDL
already_AddRefed<DOMSVGAnimatedNumber> PathLength();
bool IsPointInFill(const DOMPointInit& aPoint);
bool IsPointInStroke(const DOMPointInit& aPoint);
float GetTotalLength();
already_AddRefed<nsISVGPoint> GetPointAtLength(float distance,
ErrorResult& rv);
@ -227,6 +229,9 @@ class SVGGeometryElement : public SVGGeometryElementBase {
SVGAnimatedNumber mPathLength;
static NumberInfo sNumberInfo;
mutable RefPtr<Path> mCachedPath;
private:
already_AddRefed<Path> GetOrBuildPathForHitTest();
};
} // namespace dom

Просмотреть файл

@ -14,6 +14,9 @@ interface SVGGeometryElement : SVGGraphicsElement {
[SameObject]
readonly attribute SVGAnimatedNumber pathLength;
boolean isPointInFill(optional DOMPointInit point);
boolean isPointInStroke(optional DOMPointInit point);
float getTotalLength();
[NewObject, Throws]
SVGPoint getPointAtLength(float distance);

Просмотреть файл

@ -5,12 +5,6 @@
[SVGElement interface: attribute correspondingUseElement]
expected: FAIL
[SVGGeometryElement interface: operation isPointInFill(DOMPointInit)]
expected: FAIL
[SVGGeometryElement interface: operation isPointInStroke(DOMPointInit)]
expected: FAIL
[SVGAnimatedRect interface: objects.svg.viewBox must inherit property "baseVal" with the proper type]
expected: FAIL
@ -260,126 +254,42 @@
[SVGTransform interface: objects.svg.createSVGTransform() must inherit property "matrix" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.path must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.path with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.path must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.path with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.path must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.path must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.rect must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.rect with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.rect must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.rect with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.rect must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.rect must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.circle must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.circle with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.circle must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.circle with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.circle must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.circle must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.ellipse must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.ellipse with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.ellipse must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.ellipse with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.ellipse must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.ellipse must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.line must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.line with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.line must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.line with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.line must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.line must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.polyline must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.polyline with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.polyline must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.polyline with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.polyline must inherit property "correspondingElement" with the proper type]
expected: FAIL
[SVGElement interface: objects.polyline must inherit property "correspondingUseElement" with the proper type]
expected: FAIL
[SVGGeometryElement interface: objects.polygon must inherit property "isPointInFill(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInFill(DOMPointInit) on objects.polygon with too few arguments must throw TypeError]
expected: FAIL
[SVGGeometryElement interface: objects.polygon must inherit property "isPointInStroke(DOMPointInit)" with the proper type]
expected: FAIL
[SVGGeometryElement interface: calling isPointInStroke(DOMPointInit) on objects.polygon with too few arguments must throw TypeError]
expected: FAIL
[SVGElement interface: objects.polygon must inherit property "correspondingElement" with the proper type]
expected: FAIL

Просмотреть файл

@ -1,19 +1,4 @@
[SVGGeometryElement.isPointInFill-01.svg]
[SVGGeometryElement.prototype.isPointInFill, 'visibility' and 'pointer-events' have no effect.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInFill, 'fill-rule'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInFill, non-finite argument.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInFill, no arguments.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInFill, 'clip-rule' never overrides 'fill-rule'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInFill, functional test.]
expected: FAIL

Просмотреть файл

@ -1,37 +1,3 @@
[SVGGeometryElement.isPointInStroke-01.svg]
[SVGGeometryElement.prototype.isPointInStroke, 'visibility' and 'pointer-events' have no effect.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'vector-effect' have no effect.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, no arguments.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'pathLength'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, functional test.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'stroke-miterlimit'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'stroke-dasharray'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'stroke-linecap'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'stroke-linejoin'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, non-finite argument.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'stroke-dashoffset'.]
expected: FAIL
[SVGGeometryElement.prototype.isPointInStroke, 'vector-effect'.]
expected: FAIL

Просмотреть файл

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400"
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400"
xmlns:h="http://www.w3.org/1999/xhtml">
<title>SVGGeometryElement.prototype.isPointInStroke</title>
<metadata>

До

Ширина:  |  Высота:  |  Размер: 7.6 KiB

После

Ширина:  |  Высота:  |  Размер: 7.6 KiB