Bug 1325320 part 3 - move GetPathLengthScale to SVGGeometryElement and convert callers of SVGPathElement methods to work on the base SVGGeometryElement class and work for all shapes, not just paths r=dholbert

This commit is contained in:
Robert Longson 2018-03-13 19:52:03 +00:00
parent 6c45419ff3
commit 797f6cb1a6
8 changed files with 68 additions and 59 deletions

View File

@ -422,7 +422,9 @@ public:
/** animation elements */ /** animation elements */
eANIMATION = 1 << 10, eANIMATION = 1 << 10,
/** filter elements that implement SVGFilterPrimitiveStandardAttributes */ /** filter elements that implement SVGFilterPrimitiveStandardAttributes */
eFILTER = 1 << 11 eFILTER = 1 << 11,
/** SVGGeometryElement */
eSHAPE = 1 << 12
}; };
/** /**

View File

@ -104,9 +104,9 @@ GetStrokeDashData(SVGContentUtils::AutoStrokeOptions* aStrokeOptions,
if (dashArrayLength <= 0) { if (dashArrayLength <= 0) {
return eContinuousStroke; return eContinuousStroke;
} }
if (aElement->IsSVGElement(nsGkAtoms::path)) { if (aElement->IsNodeOfType(nsINode::eSHAPE)) {
pathScale = static_cast<SVGPathElement*>(aElement)-> pathScale = static_cast<SVGGeometryElement*>(aElement)->
GetPathLengthScale(SVGPathElement::eForStroking); GetPathLengthScale(SVGGeometryElement::eForStroking);
if (pathScale <= 0) { if (pathScale <= 0) {
return eContinuousStroke; return eContinuousStroke;
} }

View File

@ -54,6 +54,12 @@ SVGGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
aNotify); aNotify);
} }
bool
SVGGeometryElement::IsNodeOfType(uint32_t aFlags) const
{
return !(aFlags & ~eSHAPE);
}
bool bool
SVGGeometryElement::AttributeDefinesGeometry(const nsAtom *aName) SVGGeometryElement::AttributeDefinesGeometry(const nsAtom *aName)
{ {
@ -176,6 +182,37 @@ SVGGeometryElement::GetPointAtLength(float distance, ErrorResult& rv)
return point.forget(); return point.forget();
} }
float
SVGGeometryElement::GetPathLengthScale(PathLengthScaleForType aFor)
{
MOZ_ASSERT(aFor == eForTextPath || aFor == eForStroking,
"Unknown enum");
if (mPathLength.IsExplicitlySet()) {
float authorsPathLengthEstimate = mPathLength.GetAnimValue();
if (authorsPathLengthEstimate > 0) {
RefPtr<Path> path = GetOrBuildPathForMeasuring();
if (!path) {
// The path is empty or invalid so its length must be zero and
// we know that 0 / authorsPathLengthEstimate = 0.
return 0.0;
}
if (aFor == eForTextPath) {
// For textPath, a transform on the referenced path affects the
// textPath layout, so when calculating the actual path length
// we need to take that into account.
gfxMatrix matrix = PrependLocalTransformsTo(gfxMatrix());
if (!matrix.IsIdentity()) {
RefPtr<PathBuilder> builder =
path->TransformedCopyToBuilder(ToMatrix(matrix));
path = builder->Finish();
}
}
return path->ComputeLength() / authorsPathLengthEstimate;
}
}
return 1.0;
}
already_AddRefed<SVGAnimatedNumber> already_AddRefed<SVGAnimatedNumber>
SVGGeometryElement::PathLength() SVGGeometryElement::PathLength()
{ {

View File

@ -56,6 +56,7 @@ public:
const nsAttrValue* aOldValue, const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal, nsIPrincipal* aSubjectPrincipal,
bool aNotify) override; bool aNotify) override;
bool IsNodeOfType(uint32_t aFlags) const override;
/** /**
* Causes this element to discard any Path object that GetOrBuildPath may * Causes this element to discard any Path object that GetOrBuildPath may
@ -207,6 +208,18 @@ public:
*/ */
FillRule GetFillRule(); FillRule GetFillRule();
enum PathLengthScaleForType {
eForTextPath,
eForStroking
};
/**
* Gets the ratio of the actual element's length to the content author's
* estimated length (as provided by the element's 'pathLength' attribute).
* This is used to scale stroke dashing, and to scale offsets along a textPath.
*/
float GetPathLengthScale(PathLengthScaleForType aFor);
// WebIDL // WebIDL
already_AddRefed<SVGAnimatedNumber> PathLength(); already_AddRefed<SVGAnimatedNumber> PathLength();
float GetTotalLength(); float GetTotalLength();

View File

@ -285,37 +285,6 @@ SVGPathElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
mD.GetAnimValue().GetMarkerPositioningData(aMarks); mD.GetAnimValue().GetMarkerPositioningData(aMarks);
} }
float
SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
{
MOZ_ASSERT(aFor == eForTextPath || aFor == eForStroking,
"Unknown enum");
if (mPathLength.IsExplicitlySet()) {
float authorsPathLengthEstimate = mPathLength.GetAnimValue();
if (authorsPathLengthEstimate > 0) {
RefPtr<Path> path = GetOrBuildPathForMeasuring();
if (!path) {
// The path is empty or invalid so its length must be zero and
// we know that 0 / authorsPathLengthEstimate = 0.
return 0.0;
}
if (aFor == eForTextPath) {
// For textPath, a transform on the referenced path affects the
// textPath layout, so when calculating the actual path length
// we need to take that into account.
gfxMatrix matrix = PrependLocalTransformsTo(gfxMatrix());
if (!matrix.IsIdentity()) {
RefPtr<PathBuilder> builder =
path->TransformedCopyToBuilder(ToMatrix(matrix));
path = builder->Finish();
}
}
return path->ComputeLength() / authorsPathLengthEstimate;
}
}
return 1.0;
}
already_AddRefed<Path> already_AddRefed<Path>
SVGPathElement::BuildPath(PathBuilder* aBuilder) SVGPathElement::BuildPath(PathBuilder* aBuilder)
{ {

View File

@ -68,18 +68,6 @@ public:
return nsGkAtoms::d; return nsGkAtoms::d;
} }
enum PathLengthScaleForType {
eForTextPath,
eForStroking
};
/**
* Gets the ratio of the actual path length to the content author's estimated
* length (as provided by the <path> element's 'pathLength' attribute). This
* is used to scale stroke dashing, and to scale offsets along a textPath.
*/
float GetPathLengthScale(PathLengthScaleForType aFor);
// WebIDL // WebIDL
uint32_t GetPathSegAtLength(float distance); uint32_t GetPathSegAtLength(float distance);
already_AddRefed<DOMSVGPathSegClosePath> CreateSVGPathSegClosePath(); already_AddRefed<DOMSVGPathSegClosePath> CreateSVGPathSegClosePath();

View File

@ -42,7 +42,7 @@
#include "SVGContextPaint.h" #include "SVGContextPaint.h"
#include "SVGLengthList.h" #include "SVGLengthList.h"
#include "SVGNumberList.h" #include "SVGNumberList.h"
#include "SVGPathElement.h" #include "SVGGeometryElement.h"
#include "SVGTextPathElement.h" #include "SVGTextPathElement.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsFrameSelection.h" #include "nsFrameSelection.h"
@ -4987,8 +4987,8 @@ SVGTextFrame::AdjustPositionsForClusters()
} }
} }
SVGPathElement* SVGGeometryElement*
SVGTextFrame::GetTextPathPathElement(nsIFrame* aTextPathFrame) SVGTextFrame::GetTextPathGeometryElement(nsIFrame* aTextPathFrame)
{ {
nsSVGTextPathProperty *property = nsSVGTextPathProperty *property =
aTextPathFrame->GetProperty(SVGObserverUtils::HrefAsTextPathProperty()); aTextPathFrame->GetProperty(SVGObserverUtils::HrefAsTextPathProperty());
@ -5023,14 +5023,14 @@ SVGTextFrame::GetTextPathPathElement(nsIFrame* aTextPathFrame)
} }
Element* element = property->GetReferencedElement(); Element* element = property->GetReferencedElement();
return (element && element->IsSVGElement(nsGkAtoms::path)) ? return (element && element->IsNodeOfType(nsINode::eSHAPE)) ?
static_cast<SVGPathElement*>(element) : nullptr; static_cast<SVGGeometryElement*>(element) : nullptr;
} }
already_AddRefed<Path> already_AddRefed<Path>
SVGTextFrame::GetTextPath(nsIFrame* aTextPathFrame) SVGTextFrame::GetTextPath(nsIFrame* aTextPathFrame)
{ {
SVGPathElement* element = GetTextPathPathElement(aTextPathFrame); SVGGeometryElement* element = GetTextPathGeometryElement(aTextPathFrame);
if (!element) { if (!element) {
return nullptr; return nullptr;
} }
@ -5053,11 +5053,11 @@ SVGTextFrame::GetTextPath(nsIFrame* aTextPathFrame)
gfxFloat gfxFloat
SVGTextFrame::GetOffsetScale(nsIFrame* aTextPathFrame) SVGTextFrame::GetOffsetScale(nsIFrame* aTextPathFrame)
{ {
SVGPathElement* pathElement = GetTextPathPathElement(aTextPathFrame); SVGGeometryElement* element = GetTextPathGeometryElement(aTextPathFrame);
if (!pathElement) if (!element)
return 1.0; return 1.0;
return pathElement->GetPathLengthScale(dom::SVGPathElement::eForTextPath); return element->GetPathLengthScale(dom::SVGGeometryElement::eForTextPath);
} }
gfxFloat gfxFloat

View File

@ -34,7 +34,7 @@ class TextRenderedRunIterator;
namespace dom { namespace dom {
class SVGIRect; class SVGIRect;
class SVGPathElement; class SVGGeometryElement;
} // namespace dom } // namespace dom
/** /**
@ -538,8 +538,8 @@ private:
bool ShouldRenderAsPath(nsTextFrame* aFrame, bool& aShouldPaintSVGGlyphs); bool ShouldRenderAsPath(nsTextFrame* aFrame, bool& aShouldPaintSVGGlyphs);
// Methods to get information for a <textPath> frame. // Methods to get information for a <textPath> frame.
mozilla::dom::SVGPathElement* mozilla::dom::SVGGeometryElement*
GetTextPathPathElement(nsIFrame* aTextPathFrame); GetTextPathGeometryElement(nsIFrame* aTextPathFrame);
already_AddRefed<Path> GetTextPath(nsIFrame* aTextPathFrame); already_AddRefed<Path> GetTextPath(nsIFrame* aTextPathFrame);
gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame); gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame);
gfxFloat GetStartOffset(nsIFrame* aTextPathFrame); gfxFloat GetStartOffset(nsIFrame* aTextPathFrame);