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