1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
25 #define _BGFX_POLYGON_B2DPOLYGON_HXX
26 
27 #include <sal/types.h>
28 #include <o3tl/cow_wrapper.hxx>
29 #include <basegfx/vector/b2enums.hxx>
30 #include <basegfx/range/b2drange.hxx>
31 
32 //////////////////////////////////////////////////////////////////////////////
33 // predeclarations
34 class ImplB2DPolygon;
35 
36 namespace basegfx
37 {
38 	class B2DPolygon;
39 	class B2DPoint;
40 	class B2DVector;
41 	class B2DHomMatrix;
42     class B2DCubicBezier;
43 } // end of namespace basegfx
44 
45 //////////////////////////////////////////////////////////////////////////////
46 
47 namespace basegfx
48 {
49 	class B2DPolygon
50 	{
51     public:
52         typedef o3tl::cow_wrapper< ImplB2DPolygon > ImplType;
53 
54 	private:
55 		// internal data.
56         ImplType                                    mpPolygon;
57 
58 	public:
59 		/// diverse constructors
60 		B2DPolygon();
61 		B2DPolygon(const B2DPolygon& rPolygon);
62 		B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount);
63 		~B2DPolygon();
64 
65 		/// assignment operator
66 		B2DPolygon& operator=(const B2DPolygon& rPolygon);
67 
68         /// unshare this polygon with all internally shared instances
69         void makeUnique();
70 
71 		/// compare operators
72 		bool operator==(const B2DPolygon& rPolygon) const;
73 		bool operator!=(const B2DPolygon& rPolygon) const;
74 
75 		/// member count
76 		sal_uInt32 count() const;
77 
78 		/// Coordinate interface
79         basegfx::B2DPoint getB2DPoint(sal_uInt32 nIndex) const;
80 		void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
81 
82 		/// Coordinate insert/append
83 		void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount = 1);
84 		void append(const basegfx::B2DPoint& rPoint, sal_uInt32 nCount);
85 		void append(const basegfx::B2DPoint& rPoint);
86 		void reserve(sal_uInt32 nCount);
87 
88 		/// Basic ControlPoint interface
89 		basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const;
90 		basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const;
91 		void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
92 		void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
93 		void setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext);
94 
95 		/// ControlPoint resets
96 		void resetPrevControlPoint(sal_uInt32 nIndex);
97 		void resetNextControlPoint(sal_uInt32 nIndex);
98 		void resetControlPoints(sal_uInt32 nIndex);
99 		void resetControlPoints();
100 
101 		/// Bezier segment append with control points. The current last polygon point is implicitly taken as start point.
102 		void appendBezierSegment(const basegfx::B2DPoint& rNextControlPoint, const basegfx::B2DPoint& rPrevControlPoint, const basegfx::B2DPoint& rPoint);
103 
104 		/// ControlPoint checks
105 		bool areControlPointsUsed() const;
106 		bool isPrevControlPointUsed(sal_uInt32 nIndex) const;
107 		bool isNextControlPointUsed(sal_uInt32 nIndex) const;
108 		B2VectorContinuity getContinuityInPoint(sal_uInt32 nIndex) const;
109 
110         /** check edge for being a bezier segment
111 
112             This test the existance of control vectors, but do not apply
113             testAndSolveTrivialBezier() to the bezier segment, so it is still useful
114             to do so.
115             Since it can use internal data representations, it is faster
116             than using getBezierSegment() and applying isBezier() on it.
117 
118             @param nIndex
119             Index of the addressed edge's start point
120 
121             @return
122             true if edge exists and at least one control vector is used
123         */
124         bool isBezierSegment(sal_uInt32 nIndex) const;
125 
126         /** bezier segment access
127 
128             This method also works when it is no bezier segment at all and will fill
129             the given B2DCubicBezier as needed.
130             In any case, the given B2DCubicBezier will be filled, if necessary with
131             the single start point (if no valid edge exists).
132 
133             @param nIndex
134             Index of the addressed edge's start point
135 
136             @param rTarget
137             The B2DCubicBezier to be filled. It's data WILL be changed.
138         */
139         void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const;
140 
141 		/** Default adaptive subdivision access
142 
143 			This method will return a default adapive subdivision of the polygon.
144 			If the polygon does not contain any bezier curve segments, it will
145 			just return itself.
146 
147 			The subdivision is created on first request and buffered, so when using
148 			this subdivision You have the guarantee for fast accesses for multiple
149 			usages. It is intended for tooling usage for tasks which would be hard
150 			to accomplish on bezier segments (e.g. isInEpsilonRange).
151 
152 			The current default subdivision uses adaptiveSubdivideByCount with 9
153 			subdivisions which gives 10 edges and 11 points per segment and is
154 			usually pretty usable for processing purposes. There is no parameter
155 			passing here ATM but it may be changed on demand. If needed, a TYPE
156 			and PARAMETER (both defaulted) may be added to allow for switching
157 			between the different kinds of subdivisiond and passing them one
158 			parameter.
159 
160 			The lifetime of the buffered subdivision is based on polygon changes.
161 			When changing the polygon, it will be flushed. It is buffered at the
162 			refcounted implementation class, so it will survive copy by value and
163 			combinations in PolyPolygons.
164 
165 			@return
166 			The default (and buffered) subdivision of this polygon. It may
167 			be this polygon itself when it has no bezier segments. It is guaranteed
168 			to have no more bezier segments
169 		*/
170         B2DPolygon getDefaultAdaptiveSubdivision() const;
171 
172         /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon
173 
174 			A polygon may have up to three ranges:
175 
176 			(a) the range of the polygon points
177 			(b) the range of the polygon points and control points
178 			(c) the outer range of the subdivided bezier curve
179 
180 			Ranges (a) and (c) are produced by tools::getRange(); resp. this
181             getB2DRange(). tools::getRangeWithControlPoints handles case (b).
182 
183 			To get range (c) a simple solution would be to subdivide the polygon
184 			and use getRange() on it. Since subdivision is expensive and decreases
185 			the polygon quality, i added this new method. It will use a
186 			methodology suggested by HDU. First, it gets the range (a).
187 			Then it iterates over the bezier segments and for each it
188 			first tests if the outer range of the bezier segment is already
189 			contained in the result range.
190 
191 			The subdivision itself uses getAllExtremumPositions() to only
192 			calculate extremum points and to expand the result accordingly.
193 			Thus it calculates maximal four extremum points on the bezier
194 			segment, no split is used at all.
195 
196 			@return
197 			The outer range of the bezier curve/polygon
198         */
199         B2DRange getB2DRange() const;
200 
201 		/** insert other 2D polygons
202 
203 			The default (with nIndex2 == 0 && nCount == 0) inserts the whole
204 			rPoly at position nIndex
205 
206 			@param nIndex
207 			Target index for points to be inserted
208 
209 			@param rPoly
210 			The source for new points
211 
212 			@param nIndex2
213 			The index to the first source point into rPoly
214 
215 			@param nCount
216 			How many points to add from rPoly to this polygon. Null
217 			means to copy all (starting from nIndex2)
218 		*/
219 		void insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2 = 0, sal_uInt32 nCount = 0);
220 
221 		/** append other 2D polygons
222 
223 			The default (nIndex ==0 && nCount == 0) will append
224 			the whole rPoly
225 
226 			@param rPoly
227 			The source polygon
228 
229 			@param nIndex
230 			The index to the first point of rPoly to append
231 
232 			@param nCount
233 			The number of points to append from rPoly, starting
234 			from nIndex. If zero, as much as possibel is appended
235 		*/
236 		void append(const B2DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0);
237 
238 		/// remove points
239 		void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1);
240 
241 		/// clear all points
242 		void clear();
243 
244 		/// closed state interface
245 		bool isClosed() const;
246 		void setClosed(bool bNew);
247 
248 		/// flip polygon direction
249 		void flip();
250 
251 		/// test if Polygon has double points
252 		bool hasDoublePoints() const;
253 
254 		/// remove double points, at the begin/end and follow-ups, too
255 		void removeDoublePoints();
256 
257 		/// apply transformation given in matrix form
258 		void transform(const basegfx::B2DHomMatrix& rMatrix);
259 
260         // point iterators (same iterator validity conditions as for vector)
261         const B2DPoint* begin() const;
262         const B2DPoint* end() const;
263         B2DPoint* begin();
264         B2DPoint* end();
265 	};
266 
267     // typedef for a vector of B2DPolygons
268     typedef ::std::vector< B2DPolygon > B2DPolygonVector;
269 
270 } // end of namespace basegfx
271 
272 //////////////////////////////////////////////////////////////////////////////
273 
274 #endif /* _BGFX_POLYGON_B2DPOLYGON_HXX */
275