1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* Helper class to help with generating anonymous path elements for
8    <animateMotion> elements to use. */
9 
10 #ifndef MOZILLA_SVGMOTIONSMILPATHUTILS_H_
11 #define MOZILLA_SVGMOTIONSMILPATHUTILS_H_
12 
13 #include "mozilla/Attributes.h"
14 #include "gfxPlatform.h"
15 #include "mozilla/gfx/2D.h"
16 #include "mozilla/RefPtr.h"
17 #include "nsDebug.h"
18 #include "nsSMILParserUtils.h"
19 #include "nsStringFwd.h"
20 #include "nsTArray.h"
21 
22 class nsSVGElement;
23 
24 namespace mozilla {
25 
26 class SVGMotionSMILPathUtils {
27   typedef mozilla::gfx::DrawTarget DrawTarget;
28   typedef mozilla::gfx::Path Path;
29   typedef mozilla::gfx::PathBuilder PathBuilder;
30 
31  public:
32   // Class to assist in generating a Path, based on
33   // coordinates in the <animateMotion> from/by/to/values attributes.
34   class PathGenerator {
35    public:
PathGenerator(const nsSVGElement * aSVGElement)36     explicit PathGenerator(const nsSVGElement* aSVGElement)
37         : mSVGElement(aSVGElement), mHaveReceivedCommands(false) {
38       RefPtr<DrawTarget> drawTarget =
39           gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
40       NS_ASSERTION(
41           gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(
42               drawTarget),
43           "Should support Moz2D content drawing");
44 
45       mPathBuilder = drawTarget->CreatePathBuilder();
46     }
47 
48     // Methods for adding various path commands to output path.
49     // Note: aCoordPairStr is expected to be a whitespace and/or
50     // comma-separated x,y coordinate-pair -- see description of
51     // "the specified values for from, by, to, and values" at
52     //    http://www.w3.org/TR/SVG11/animate.html#AnimateMotionElement
53     void MoveToOrigin();
54     bool MoveToAbsolute(const nsAString& aCoordPairStr);
55     bool LineToAbsolute(const nsAString& aCoordPairStr,
56                         double& aSegmentDistance);
57     bool LineToRelative(const nsAString& aCoordPairStr,
58                         double& aSegmentDistance);
59 
60     // Accessor to let clients check if we've received any commands yet.
HaveReceivedCommands()61     inline bool HaveReceivedCommands() { return mHaveReceivedCommands; }
62     // Accessor to get the finalized path
63     already_AddRefed<Path> GetResultingPath();
64 
65    protected:
66     // Helper methods
67     bool ParseCoordinatePair(const nsAString& aStr, float& aXVal, float& aYVal);
68 
69     // Member data
70     const nsSVGElement* mSVGElement;  // context for converting to user units
71     RefPtr<PathBuilder> mPathBuilder;
72     bool mHaveReceivedCommands;
73   };
74 
75   // Class to assist in passing each subcomponent of a |values| attribute to
76   // a PathGenerator, for generating a corresponding Path.
77   class MOZ_STACK_CLASS MotionValueParser
78       : public nsSMILParserUtils::GenericValueParser {
79    public:
MotionValueParser(PathGenerator * aPathGenerator,FallibleTArray<double> * aPointDistances)80     MotionValueParser(PathGenerator* aPathGenerator,
81                       FallibleTArray<double>* aPointDistances)
82         : mPathGenerator(aPathGenerator),
83           mPointDistances(aPointDistances),
84           mDistanceSoFar(0.0) {
85       MOZ_ASSERT(mPointDistances->IsEmpty(),
86                  "expecting point distances array to start empty");
87     }
88 
89     // nsSMILParserUtils::GenericValueParser interface
90     virtual bool Parse(const nsAString& aValueStr) override;
91 
92    protected:
93     PathGenerator* mPathGenerator;
94     FallibleTArray<double>* mPointDistances;
95     double mDistanceSoFar;
96   };
97 };
98 
99 }  // namespace mozilla
100 
101 #endif  // MOZILLA_SVGMOTIONSMILPATHUTILS_H_
102