зеркало из https://github.com/mozilla/gecko-dev.git
Bug 930577 - Convert much of the SVG code for calculating path lengths and position at an offset along a path to Moz2D. r=heycam
This commit is contained in:
Родитель
0b523bd06b
Коммит
986088b126
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/dom/SVGAnimationElement.h"
|
||||
#include "mozilla/dom/SVGPathElement.h" // for nsSVGPathList
|
||||
#include "mozilla/dom/SVGMPathElement.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsSMILParserUtils.h"
|
||||
|
@ -15,9 +16,10 @@
|
|||
#include "SVGMotionSMILType.h"
|
||||
#include "SVGMotionSMILPathUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
using namespace dom;
|
||||
namespace mozilla {
|
||||
|
||||
SVGMotionSMILAnimationFunction::SVGMotionSMILAnimationFunction()
|
||||
: mRotateType(eRotateType_Explicit),
|
||||
|
@ -227,7 +229,8 @@ SVGMotionSMILAnimationFunction::
|
|||
bool ok =
|
||||
path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices);
|
||||
if (ok && mPathVertices.Length()) {
|
||||
mPath = pathElem->GetPath(gfxMatrix());
|
||||
RefPtr<Path> path = pathElem->GetPathForLengthOrPositionMeasuring();
|
||||
mPath = new gfxPath(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +255,8 @@ SVGMotionSMILAnimationFunction::RebuildPathAndVerticesFromPathAttr()
|
|||
return;
|
||||
}
|
||||
|
||||
mPath = path.ToPath(gfxMatrix());
|
||||
RefPtr<Path> moz2dpath = path.ToPathForLengthOrPositionMeasuring();
|
||||
mPath = new gfxPath(moz2dpath);
|
||||
bool ok = path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices);
|
||||
if (!ok || !mPathVertices.Length()) {
|
||||
mPath = nullptr;
|
||||
|
|
|
@ -806,17 +806,18 @@ SVGPathData::ConstructPath(gfxContext *aCtx) const
|
|||
MAYBE_APPROXIMATE_ZERO_LENGTH_SUBPATH_SQUARE_CAPS;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
SVGPathData::ToPath(const gfxMatrix& aMatrix) const
|
||||
TemporaryRef<Path>
|
||||
SVGPathData::ToPathForLengthOrPositionMeasuring() const
|
||||
{
|
||||
nsRefPtr<gfxContext> tmpCtx =
|
||||
new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
|
||||
// Since the path that we return will not be used for painting it doesn't
|
||||
// matter what we pass to BuildPath as aFillRule. Hawever, we do want to
|
||||
// pass something other than NS_STYLE_STROKE_LINECAP_SQUARE as aStrokeLineCap
|
||||
// to avoid the insertion of extra little lines (by
|
||||
// ApproximateZeroLengthSubpathSquareCaps), in which case the value that we
|
||||
// pass as aStrokeWidth doesn't matter (since it's only used to determine the
|
||||
// length of those extra little lines).
|
||||
|
||||
tmpCtx->SetMatrix(aMatrix);
|
||||
ConstructPath(tmpCtx);
|
||||
tmpCtx->IdentityMatrix();
|
||||
|
||||
return tmpCtx->CopyPath();
|
||||
return BuildPath(FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 0);
|
||||
}
|
||||
|
||||
static double
|
||||
|
|
|
@ -159,8 +159,12 @@ public:
|
|||
*/
|
||||
bool GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aArray) const;
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
ToPath(const gfxMatrix& aMatrix) const;
|
||||
/**
|
||||
* This returns a path without the extra little line segments that
|
||||
* ApproximateZeroLengthSubpathSquareCaps can insert if we have square-caps.
|
||||
* See the comment for that function for more info on that.
|
||||
*/
|
||||
TemporaryRef<Path> ToPathForLengthOrPositionMeasuring() const;
|
||||
|
||||
void ConstructPath(gfxContext *aCtx) const;
|
||||
TemporaryRef<Path> BuildPath(FillRule aFillRule,
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include "DOMSVGPathSegList.h"
|
||||
#include "DOMSVGPoint.h"
|
||||
#include "gfxPath.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/dom/SVGPathElementBinding.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
@ -59,25 +61,27 @@ SVGPathElement::PathLength()
|
|||
float
|
||||
SVGPathElement::GetTotalLength(ErrorResult& rv)
|
||||
{
|
||||
nsRefPtr<gfxPath> flat = GetPath(gfxMatrix());
|
||||
RefPtr<Path> flat = GetPathForLengthOrPositionMeasuring();
|
||||
|
||||
if (!flat) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
return flat->GetLength();
|
||||
return flat->ComputeLength();
|
||||
}
|
||||
|
||||
already_AddRefed<nsISVGPoint>
|
||||
SVGPathElement::GetPointAtLength(float distance, ErrorResult& rv)
|
||||
{
|
||||
nsRefPtr<gfxPath> flat = GetPath(gfxMatrix());
|
||||
if (!flat) {
|
||||
RefPtr<Path> path = GetPathForLengthOrPositionMeasuring();
|
||||
if (!path) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxPath> flat = new gfxPath(path);
|
||||
|
||||
float totalLength = flat->GetLength();
|
||||
if (mPathLength.IsExplicitlySet()) {
|
||||
float pathLength = mPathLength.GetAnimValue();
|
||||
|
@ -298,10 +302,10 @@ SVGPathElement::IsAttributeMapped(const nsIAtom* name) const
|
|||
SVGPathElementBase::IsAttributeMapped(name);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
SVGPathElement::GetPath(const gfxMatrix &aMatrix)
|
||||
TemporaryRef<Path>
|
||||
SVGPathElement::GetPathForLengthOrPositionMeasuring()
|
||||
{
|
||||
return mD.GetAnimValue().ToPath(aMatrix);
|
||||
return mD.GetAnimValue().ToPathForLengthOrPositionMeasuring();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -340,16 +344,22 @@ SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
|
|||
if (mPathLength.IsExplicitlySet()) {
|
||||
float authorsPathLengthEstimate = mPathLength.GetAnimValue();
|
||||
if (authorsPathLengthEstimate > 0) {
|
||||
gfxMatrix matrix;
|
||||
RefPtr<Path> path = GetPathForLengthOrPositionMeasuring();
|
||||
|
||||
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.
|
||||
matrix = PrependLocalTransformsTo(matrix);
|
||||
gfxMatrix matrix = PrependLocalTransformsTo(gfxMatrix());
|
||||
if (!matrix.IsIdentity()) {
|
||||
RefPtr<PathBuilder> builder =
|
||||
path->TransformedCopyToBuilder(ToMatrix(matrix));
|
||||
path = builder->Finish();
|
||||
}
|
||||
}
|
||||
nsRefPtr<gfxPath> path = GetPath(matrix);
|
||||
|
||||
if (path) {
|
||||
return path->GetLength() / authorsPathLengthEstimate;
|
||||
return path->ComputeLength() / authorsPathLengthEstimate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef mozilla_dom_SVGPathElement_h
|
||||
#define mozilla_dom_SVGPathElement_h
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsSVGNumber2.h"
|
||||
#include "nsSVGPathGeometryElement.h"
|
||||
#include "SVGAnimatedPathSegList.h"
|
||||
|
@ -28,6 +30,8 @@ class SVGPathElement MOZ_FINAL : public SVGPathElementBase
|
|||
{
|
||||
friend class nsSVGPathFrame;
|
||||
|
||||
typedef mozilla::gfx::Path Path;
|
||||
|
||||
protected:
|
||||
friend nsresult (::NS_NewSVGPathElement(nsIContent **aResult,
|
||||
already_AddRefed<nsINodeInfo> aNodeInfo));
|
||||
|
@ -49,7 +53,13 @@ public:
|
|||
virtual void ConstructPath(gfxContext *aCtx) MOZ_OVERRIDE;
|
||||
virtual TemporaryRef<Path> BuildPath() MOZ_OVERRIDE;
|
||||
|
||||
virtual already_AddRefed<gfxPath> GetPath(const gfxMatrix &aMatrix) MOZ_OVERRIDE;
|
||||
/**
|
||||
* This returns a path without the extra little line segments that
|
||||
* ApproximateZeroLengthSubpathSquareCaps can insert if we have square-caps.
|
||||
* See the comment for that function for more info on that.
|
||||
*/
|
||||
virtual TemporaryRef<Path>
|
||||
GetPathForLengthOrPositionMeasuring() MOZ_OVERRIDE;
|
||||
|
||||
// nsIContent interface
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
|
|
@ -60,8 +60,8 @@ nsSVGPathGeometryElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
|
|||
{
|
||||
}
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
nsSVGPathGeometryElement::GetPath(const gfxMatrix &aMatrix)
|
||||
TemporaryRef<Path>
|
||||
nsSVGPathGeometryElement::GetPathForLengthOrPositionMeasuring()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
*/
|
||||
virtual mozilla::TemporaryRef<Path> BuildPath() = 0;
|
||||
|
||||
virtual already_AddRefed<gfxPath> GetPath(const gfxMatrix &aMatrix);
|
||||
virtual mozilla::TemporaryRef<Path> GetPathForLengthOrPositionMeasuring();
|
||||
|
||||
/**
|
||||
* Returns a PathBuilder object created using the current computed value of
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "gfxContext.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "nsBidiPresUtils.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "SVGLengthList.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
struct CharacterPosition {
|
||||
gfxPoint pos;
|
||||
|
@ -739,15 +741,17 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
|
|||
nsSVGTextPathFrame *textPath = FindTextPathParent();
|
||||
|
||||
if (textPath) {
|
||||
nsRefPtr<gfxPath> data = textPath->GetPath();
|
||||
RefPtr<Path> path = textPath->GetPath();
|
||||
|
||||
// textPath frame, but invalid target
|
||||
if (!data)
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
if (!aCharacterPositions->SetLength(strLength))
|
||||
return false;
|
||||
|
||||
nsRefPtr<gfxPath> data = new gfxPath(path);
|
||||
|
||||
gfxFloat pathScale = textPath->GetOffsetScale();
|
||||
|
||||
CharacterPosition *cp = aCharacterPositions->Elements();
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
|
||||
// Keep others in (case-insensitive) order:
|
||||
#include "DOMSVGPoint.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxFont.h"
|
||||
#include "gfxSkipChars.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "LookAndFeel.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsCaret.h"
|
||||
|
@ -47,6 +49,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
// ============================================================================
|
||||
// Utility functions
|
||||
|
@ -4715,16 +4718,25 @@ nsSVGTextFrame2::GetTextPathPathFrame(nsIFrame* aTextPathFrame)
|
|||
return property->GetReferencedFrame(nsGkAtoms::svgPathGeometryFrame, nullptr);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
TemporaryRef<Path>
|
||||
nsSVGTextFrame2::GetTextPath(nsIFrame* aTextPathFrame)
|
||||
{
|
||||
nsIFrame *path = GetTextPathPathFrame(aTextPathFrame);
|
||||
nsIFrame *pathFrame = GetTextPathPathFrame(aTextPathFrame);
|
||||
|
||||
if (path) {
|
||||
if (pathFrame) {
|
||||
nsSVGPathGeometryElement *element =
|
||||
static_cast<nsSVGPathGeometryElement*>(path->GetContent());
|
||||
static_cast<nsSVGPathGeometryElement*>(pathFrame->GetContent());
|
||||
|
||||
return element->GetPath(element->PrependLocalTransformsTo(gfxMatrix()));
|
||||
RefPtr<Path> path = element->GetPathForLengthOrPositionMeasuring();
|
||||
|
||||
gfxMatrix matrix = element->PrependLocalTransformsTo(gfxMatrix());
|
||||
if (!matrix.IsIdentity()) {
|
||||
RefPtr<PathBuilder> builder =
|
||||
path->TransformedCopyToBuilder(ToMatrix(matrix));
|
||||
path = builder->Finish();
|
||||
}
|
||||
|
||||
return path.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4749,10 +4761,10 @@ nsSVGTextFrame2::GetStartOffset(nsIFrame* aTextPathFrame)
|
|||
&tp->mLengthAttributes[dom::SVGTextPathElement::STARTOFFSET];
|
||||
|
||||
if (length->IsPercentage()) {
|
||||
nsRefPtr<gfxPath> data = GetTextPath(aTextPathFrame);
|
||||
RefPtr<Path> data = GetTextPath(aTextPathFrame);
|
||||
return data ?
|
||||
length->GetAnimValInSpecifiedUnits() * data->GetLength() / 100.0 :
|
||||
0.0;
|
||||
length->GetAnimValInSpecifiedUnits() * data->ComputeLength() / 100.0 :
|
||||
0.0;
|
||||
}
|
||||
return length->GetAnimValue(tp) * GetOffsetScale(aTextPathFrame);
|
||||
}
|
||||
|
@ -4772,7 +4784,8 @@ nsSVGTextFrame2::DoTextPathLayout()
|
|||
}
|
||||
|
||||
// Get the path itself.
|
||||
nsRefPtr<gfxPath> data = GetTextPath(textPathFrame);
|
||||
RefPtr<Path> path = GetTextPath(textPathFrame);
|
||||
nsRefPtr<gfxPath> data = new gfxPath(path);
|
||||
if (!data) {
|
||||
it.AdvancePastCurrentTextPathFrame();
|
||||
continue;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#define NS_SVGTEXTFRAME2_H
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxSVGGlyphs.h"
|
||||
|
@ -251,6 +253,7 @@ class nsSVGTextFrame2 : public nsSVGTextFrame2Base
|
|||
friend class MutationObserver;
|
||||
friend class nsDisplaySVGText;
|
||||
|
||||
typedef mozilla::gfx::Path Path;
|
||||
typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
|
||||
|
||||
protected:
|
||||
|
@ -585,7 +588,7 @@ private:
|
|||
|
||||
// Methods to get information for a <textPath> frame.
|
||||
nsIFrame* GetTextPathPathFrame(nsIFrame* aTextPathFrame);
|
||||
already_AddRefed<gfxPath> GetTextPath(nsIFrame* aTextPathFrame);
|
||||
mozilla::TemporaryRef<Path> GetTextPath(nsIFrame* aTextPathFrame);
|
||||
gfxFloat GetOffsetScale(nsIFrame* aTextPathFrame);
|
||||
gfxFloat GetStartOffset(nsIFrame* aTextPathFrame);
|
||||
|
||||
|
|
|
@ -7,16 +7,19 @@
|
|||
#include "nsSVGTextPathFrame.h"
|
||||
|
||||
// Keep others in (case-insensitive) order:
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPath.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsSVGLength2.h"
|
||||
#include "mozilla/dom/SVGPathElement.h"
|
||||
#include "mozilla/dom/SVGTextPathElement.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "SVGLengthList.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
@ -111,16 +114,25 @@ nsSVGTextPathFrame::GetPathFrame()
|
|||
return frame && frame->GetContent()->Tag() == nsGkAtoms::path ? frame : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxPath>
|
||||
TemporaryRef<Path>
|
||||
nsSVGTextPathFrame::GetPath()
|
||||
{
|
||||
nsIFrame *path = GetPathFrame();
|
||||
nsIFrame *pathFrame = GetPathFrame();
|
||||
|
||||
if (path) {
|
||||
if (pathFrame) {
|
||||
nsSVGPathGeometryElement *element =
|
||||
static_cast<nsSVGPathGeometryElement*>(path->GetContent());
|
||||
static_cast<nsSVGPathGeometryElement*>(pathFrame->GetContent());
|
||||
|
||||
return element->GetPath(element->PrependLocalTransformsTo(gfxMatrix()));
|
||||
RefPtr<Path> path = element->GetPathForLengthOrPositionMeasuring();
|
||||
|
||||
gfxMatrix matrix = element->PrependLocalTransformsTo(gfxMatrix());
|
||||
if (!matrix.IsIdentity()) {
|
||||
RefPtr<PathBuilder> builder =
|
||||
path->TransformedCopyToBuilder(ToMatrix(matrix));
|
||||
path = builder->Finish();
|
||||
}
|
||||
|
||||
return path.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -132,8 +144,8 @@ nsSVGTextPathFrame::GetStartOffset()
|
|||
nsSVGLength2 *length = &tp->mLengthAttributes[SVGTextPathElement::STARTOFFSET];
|
||||
|
||||
if (length->IsPercentage()) {
|
||||
nsRefPtr<gfxPath> data = GetPath();
|
||||
return data ? (length->GetAnimValInSpecifiedUnits() * data->GetLength() / 100.0) : 0.0;
|
||||
RefPtr<Path> path = GetPath();
|
||||
return path ? (length->GetAnimValInSpecifiedUnits() * path->ComputeLength() / 100.0) : 0.0;
|
||||
}
|
||||
return length->GetAnimValue(tp) * GetOffsetScale();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#define NSSVGTEXTPATHFRAME_H
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFrame.h"
|
||||
|
@ -30,6 +32,7 @@ typedef nsSVGTSpanFrame nsSVGTextPathFrameBase;
|
|||
|
||||
class nsSVGTextPathFrame : public nsSVGTextPathFrameBase
|
||||
{
|
||||
typedef mozilla::gfx::Path Path;
|
||||
typedef mozilla::SVGNumberList SVGNumberList;
|
||||
|
||||
friend nsIFrame*
|
||||
|
@ -65,7 +68,7 @@ public:
|
|||
#endif
|
||||
|
||||
// nsSVGTextPathFrame methods:
|
||||
already_AddRefed<gfxPath> GetPath();
|
||||
mozilla::TemporaryRef<Path> GetPath();
|
||||
nsIFrame *GetPathFrame();
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче