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