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