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