SVGPathSegUtils.h (4323B)
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 #ifndef DOM_SVG_SVGPATHSEGUTILS_H_ 8 #define DOM_SVG_SVGPATHSEGUTILS_H_ 9 10 #include "mozilla/Span.h" 11 #include "mozilla/gfx/Point.h" 12 #include "mozilla/gfx/Rect.h" 13 14 namespace mozilla { 15 16 // Position 17 template <typename H, typename V> 18 struct StyleGenericPosition; 19 20 // Command Endpoint 21 template <typename Position, typename LP> 22 struct StyleCommandEndPoint; 23 template <typename T> 24 using StyleEndPoint = StyleCommandEndPoint<StyleGenericPosition<T, T>, T>; 25 26 // Control Point 27 template <typename Position, typename LP> 28 struct StyleControlPoint; 29 template <typename T> 30 using StyleCurveControlPoint = StyleControlPoint<StyleGenericPosition<T, T>, T>; 31 32 // Shape Command 33 template <typename Angle, typename Position, typename LP> 34 struct StyleGenericShapeCommand; 35 using StylePathCommand = 36 StyleGenericShapeCommand<float, StyleGenericPosition<float, float>, float>; 37 38 /** 39 * Code that works with path segments can use an instance of this class to 40 * store/provide information about the start of the current subpath and the 41 * last path segment (if any). 42 */ 43 struct SVGPathTraversalState { 44 using Point = gfx::Point; 45 46 enum TraversalMode { eUpdateAll, eUpdateOnlyStartAndCurrentPos }; 47 48 SVGPathTraversalState() 49 : start(0.0, 0.0), 50 pos(0.0, 0.0), 51 cp1(0.0, 0.0), 52 cp2(0.0, 0.0), 53 length(0.0), 54 mode(eUpdateAll) {} 55 56 bool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; } 57 58 Point start; // start point of current sub path (reset each moveto) 59 60 Point pos; // current position (end point of previous segment) 61 62 Point cp1; // quadratic control point - if the previous segment was a 63 // quadratic bezier curve then this is set to the absolute 64 // position of its control point, otherwise its set to pos 65 66 Point cp2; // cubic control point - if the previous segment was a cubic 67 // bezier curve then this is set to the absolute position of 68 // its second control point, otherwise it's set to pos 69 70 float length; // accumulated path length 71 72 TraversalMode mode; // indicates what to track while traversing a path 73 }; 74 75 /** 76 * This class is just a collection of static methods - it doesn't have any data 77 * members, and it's not possible to create instances of this class. This class 78 * exists purely as a convenient place to gather together a bunch of methods 79 * related to manipulating and answering questions about path segments. 80 * Internally we represent path segments purely as an array of floats. See the 81 * comment documenting SVGPathData for more info on that. 82 * 83 * The DOM wrapper classes for encoded path segments (data contained in 84 * instances of SVGPathData) is DOMSVGPathSeg and its sub-classes. Note that 85 * there are multiple different DOM classes for path segs - one for each of the 86 * 19 SVG 1.1 segment types. 87 */ 88 class SVGPathSegUtils { 89 private: 90 SVGPathSegUtils() = default; // private to prevent instances 91 92 public: 93 /** 94 * Traverse the given path segment and update the SVGPathTraversalState 95 * object. This is identical to the above one but accepts StylePathCommand. 96 */ 97 static void TraversePathSegment(const StylePathCommand&, 98 SVGPathTraversalState&); 99 }; 100 101 /// Detect whether the path represents a rectangle (for both filling AND 102 /// stroking) and if so returns it. 103 /// 104 /// This is typically useful for google slides which has many of these rectangle 105 /// shaped paths. It handles the same scenarios as skia's 106 /// SkPathPriv::IsRectContour which it is inspired from, including zero-length 107 /// edges and multiple points on edges of the rectangle, and doesn't attempt to 108 /// detect flat curves (that could easily be added but the expectation is that 109 /// since skia doesn't fast path it we're not likely to run into it in 110 /// practice). 111 /// 112 /// We could implement something similar for polygons. 113 Maybe<gfx::Rect> SVGPathToAxisAlignedRect(Span<const StylePathCommand>); 114 115 } // namespace mozilla 116 117 #endif // DOM_SVG_SVGPATHSEGUTILS_H_