1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_BASEGFX_POLYGON_B2DPOLYGON_HXX
21 #define INCLUDED_BASEGFX_POLYGON_B2DPOLYGON_HXX
25 #include <sal/types.h>
26 #include <o3tl/cow_wrapper.hxx>
27 #include <basegfx/vector/b2enums.hxx>
28 #include <basegfx/range/b2drange.hxx>
29 #include <basegfx/basegfxdllapi.h>
44 class BASEGFX_DLLPUBLIC B2DPolygon
47 typedef o3tl::cow_wrapper
< ImplB2DPolygon
> ImplType
;
54 /// diverse constructors
56 B2DPolygon(const B2DPolygon
& rPolygon
);
57 B2DPolygon(const B2DPolygon
& rPolygon
, sal_uInt32 nIndex
, sal_uInt32 nCount
);
60 /// assignment operator
61 B2DPolygon
& operator=(const B2DPolygon
& rPolygon
);
63 /// unshare this polygon with all internally shared instances
67 bool operator==(const B2DPolygon
& rPolygon
) const;
68 bool operator!=(const B2DPolygon
& rPolygon
) const;
71 sal_uInt32
count() const;
73 /// Coordinate interface
74 basegfx::B2DPoint
getB2DPoint(sal_uInt32 nIndex
) const;
75 void setB2DPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
77 /// Coordinate insert/append
78 void insert(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rPoint
, sal_uInt32 nCount
= 1);
79 void append(const basegfx::B2DPoint
& rPoint
, sal_uInt32 nCount
);
80 void append(const basegfx::B2DPoint
& rPoint
);
81 void reserve(sal_uInt32 nCount
);
83 /// Basic ControlPoint interface
84 basegfx::B2DPoint
getPrevControlPoint(sal_uInt32 nIndex
) const;
85 basegfx::B2DPoint
getNextControlPoint(sal_uInt32 nIndex
) const;
86 void setPrevControlPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
87 void setNextControlPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
88 void setControlPoints(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rPrev
, const basegfx::B2DPoint
& rNext
);
90 /// ControlPoint resets
91 void resetPrevControlPoint(sal_uInt32 nIndex
);
92 void resetNextControlPoint(sal_uInt32 nIndex
);
93 void resetControlPoints();
95 /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point.
96 void appendBezierSegment(const basegfx::B2DPoint
& rNextControlPoint
, const basegfx::B2DPoint
& rPrevControlPoint
, const basegfx::B2DPoint
& rPoint
);
98 /// ControlPoint checks
99 bool areControlPointsUsed() const;
100 bool isPrevControlPointUsed(sal_uInt32 nIndex
) const;
101 bool isNextControlPointUsed(sal_uInt32 nIndex
) const;
102 B2VectorContinuity
getContinuityInPoint(sal_uInt32 nIndex
) const;
104 /** bezier segment access
106 This method also works when it is no bezier segment at all and will fill
107 the given B2DCubicBezier as needed.
108 In any case, the given B2DCubicBezier will be filled, if necessary with
109 the single start point (if no valid edge exists).
112 Index of the addressed edge's start point
115 The B2DCubicBezier to be filled. It's data WILL be changed.
117 void getBezierSegment(sal_uInt32 nIndex
, B2DCubicBezier
& rTarget
) const;
119 /** Default adaptive subdivision access
121 This method will return a default adapive subdivision of the polygon.
122 If the polygon does not contain any bezier curve segments, it will
125 The subdivision is created on first request and buffered, so when using
126 this subdivision You have the guarantee for fast accesses for multiple
127 usages. It is intended for tooling usage for tasks which would be hard
128 to accomplish on bezier segments (e.g. isInEpsilonRange).
130 The current default subdivision uses adaptiveSubdivideByCount with 9
131 subdivisions which gives 10 edges and 11 points per segment and is
132 usually pretty usable for processing purposes. There is no parameter
133 passing here ATM but it may be changed on demand. If needed, a TYPE
134 and PARAMETER (both defaulted) may be added to allow for switching
135 between the different kinds of subdivisiond and passing them one
138 The lifetime of the buffered subdivision is based on polygon changes.
139 When changing the polygon, it will be flushed. It is buffered at the
140 refcounted implementation class, so it will survive copy by value and
141 combinations in PolyPolygons.
144 The default (and buffered) subdivision of this polygon. It may
145 be this polygon itself when it has no bezier segments. It is guaranteed
146 to have no more bezier segments
148 B2DPolygon
getDefaultAdaptiveSubdivision() const;
150 /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon
152 A polygon may have up to three ranges:
154 (a) the range of the polygon points
155 (b) the range of the polygon points and control points
156 (c) the outer range of the subdivided bezier curve
158 Ranges (a) and (c) are produced by tools::getRange(); resp. this
159 getB2DRange(). tools::getRangeWithControlPoints handles case (b).
161 To get range (c) a simple solution would be to subdivide the polygon
162 and use getRange() on it. Since subdivision is expensive and decreases
163 the polygon quality, i added this new method. It will use a
164 methodology suggested by HDU. First, it gets the range (a).
165 Then it iterates over the bezier segments and for each it
166 first tests if the outer range of the bezier segment is already
167 contained in the result range.
169 The subdivision itself uses getAllExtremumPositions() to only
170 calculate extremum points and to expand the result accordingly.
171 Thus it calculates maximal four extremum points on the bezier
172 segment, no split is used at all.
175 The outer range of the bezier curve/polygon
177 B2DRange
getB2DRange() const;
179 /** append other 2D polygons
181 The default (nIndex ==0 && nCount == 0) will append
188 The index to the first point of rPoly to append
191 The number of points to append from rPoly, starting
192 from nIndex. If zero, as much as possibel is appended
194 void append(const B2DPolygon
& rPoly
, sal_uInt32 nIndex
= 0, sal_uInt32 nCount
= 0);
197 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
= 1);
202 /// closed state interface
203 bool isClosed() const;
204 void setClosed(bool bNew
);
206 /// flip polygon direction
209 /// test if Polygon has double points
210 bool hasDoublePoints() const;
212 /// remove double points, at the begin/end and follow-ups, too
213 void removeDoublePoints();
215 /// apply transformation given in matrix form
216 void transform(const basegfx::B2DHomMatrix
& rMatrix
);
219 // typedef for a vector of B2DPolygons
220 typedef ::std::vector
< B2DPolygon
> B2DPolygonVector
;
222 } // end of namespace basegfx
224 template< typename charT
, typename traits
>
225 inline std::basic_ostream
<charT
, traits
> & operator <<(
226 std::basic_ostream
<charT
, traits
> & stream
, const basegfx::B2DPolygon
& poly
)
228 stream
<< "<" << poly
.count() << ":";
229 for (sal_uInt32 i
= 0; i
< poly
.count(); i
++)
233 stream
<< poly
.getB2DPoint(i
);
240 #endif // INCLUDED_BASEGFX_POLYGON_B2DPOLYGON_HXX
242 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */