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