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 possibel 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