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