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