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
26 #include <sal/types.h>
27 #include <o3tl/cow_wrapper.hxx>
28 #include <basegfx/vector/b2enums.hxx>
29 #include <basegfx/basegfxdllapi.h>
39 class SystemDependentData
;
40 class SystemDependentDataManager
;
41 typedef std::shared_ptr
<SystemDependentData
> SystemDependentData_SharedPtr
;
46 class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC B2DPolygon
49 typedef o3tl::cow_wrapper
< ImplB2DPolygon
> ImplType
;
56 /// diverse constructors
58 B2DPolygon(const B2DPolygon
& rPolygon
);
59 B2DPolygon(B2DPolygon
&& rPolygon
);
60 B2DPolygon(const B2DPolygon
& rPolygon
, sal_uInt32 nIndex
, sal_uInt32 nCount
);
61 B2DPolygon(std::initializer_list
<basegfx::B2DPoint
> rPoints
);
65 /// assignment operator
66 B2DPolygon
& operator=(const B2DPolygon
& rPolygon
);
67 B2DPolygon
& operator=(B2DPolygon
&& rPolygon
);
69 /// unshare this polygon with all internally shared instances
73 bool operator==(const B2DPolygon
& rPolygon
) const;
74 bool operator!=(const B2DPolygon
& rPolygon
) const;
77 sal_uInt32
count() const;
79 /// Coordinate interface
80 basegfx::B2DPoint
const & getB2DPoint(sal_uInt32 nIndex
) const;
81 void setB2DPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
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
);
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
);
96 /// ControlPoint resets
97 void resetPrevControlPoint(sal_uInt32 nIndex
);
98 void resetNextControlPoint(sal_uInt32 nIndex
);
99 void resetControlPoints();
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
);
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;
110 /** bezier segment access
112 This method also works when it is no bezier segment at all and will fill
113 the given B2DCubicBezier as needed.
114 In any case, the given B2DCubicBezier will be filled, if necessary with
115 the single start point (if no valid edge exists).
118 Index of the addressed edge's start point
121 The B2DCubicBezier to be filled. It's data WILL be changed.
123 void getBezierSegment(sal_uInt32 nIndex
, B2DCubicBezier
& rTarget
) const;
125 /** Default adaptive subdivision access
127 This method will return a default adaptive subdivision of the polygon.
128 If the polygon does not contain any bezier curve segments, it will
131 The subdivision is created on first request and buffered, so when using
132 this subdivision You have the guarantee for fast accesses for multiple
133 usages. It is intended for tooling usage for tasks which would be hard
134 to accomplish on bezier segments (e.g. isInEpsilonRange).
136 The current default subdivision uses adaptiveSubdivideByCount with 9
137 subdivisions which gives 10 edges and 11 points per segment and is
138 usually pretty usable for processing purposes. There is no parameter
139 passing here ATM but it may be changed on demand. If needed, a TYPE
140 and PARAMETER (both defaulted) may be added to allow for switching
141 between the different kinds of subdivisioned and passing them one
144 The lifetime of the buffered subdivision is based on polygon changes.
145 When changing the polygon, it will be flushed. It is buffered at the
146 refcounted implementation class, so it will survive copy by value and
147 combinations in PolyPolygons.
150 The default (and buffered) subdivision of this polygon. It may
151 be this polygon itself when it has no bezier segments. It is guaranteed
152 to have no more bezier segments
154 B2DPolygon
const & getDefaultAdaptiveSubdivision() const;
156 /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon
158 A polygon may have up to three ranges:
160 (a) the range of the polygon points
161 (b) the range of the polygon points and control points
162 (c) the outer range of the subdivided bezier curve
164 Ranges (a) and (c) are produced by tools::getRange(); resp. this
165 getB2DRange(). tools::getRangeWithControlPoints handles case (b).
167 To get range (c) a simple solution would be to subdivide the polygon
168 and use getRange() on it. Since subdivision is expensive and decreases
169 the polygon quality, i added this new method. It will use a
170 methodology suggested by HDU. First, it gets the range (a).
171 Then it iterates over the bezier segments and for each it
172 first tests if the outer range of the bezier segment is already
173 contained in the result range.
175 The subdivision itself uses getAllExtremumPositions() to only
176 calculate extremum points and to expand the result accordingly.
177 Thus it calculates maximal four extremum points on the bezier
178 segment, no split is used at all.
181 The outer range of the bezier curve/polygon
183 B2DRange
const & getB2DRange() const;
185 /** append other 2D polygons
187 The default (nIndex ==0 && nCount == 0) will append
194 The index to the first point of rPoly to append
197 The number of points to append from rPoly, starting
198 from nIndex. If zero, as much as possibel is appended
200 void append(const B2DPolygon
& rPoly
, sal_uInt32 nIndex
= 0, sal_uInt32 nCount
= 0);
203 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
= 1);
208 /// closed state interface
209 bool isClosed() const;
210 void setClosed(bool bNew
);
212 /// flip polygon direction
215 /// test if Polygon has double points
216 bool hasDoublePoints() const;
218 /// remove double points, at the begin/end and follow-ups, too
219 void removeDoublePoints();
221 /// apply transformation given in matrix form
222 void transform(const basegfx::B2DHomMatrix
& rMatrix
);
224 // exclusive management op's for SystemDependentData at B2DPolygon
226 std::shared_ptr
<T
> getSystemDependentData() const
228 return std::static_pointer_cast
<T
>(getSystemDependantDataInternal(typeid(T
).hash_code()));
231 template<class T
, class... Args
>
232 std::shared_ptr
<T
> addOrReplaceSystemDependentData(SystemDependentDataManager
& manager
, Args
&&... args
) const
234 std::shared_ptr
<T
> r
= std::make_shared
<T
>(manager
, std::forward
<Args
>(args
)...);
235 basegfx::SystemDependentData_SharedPtr
r2(r
);
236 addOrReplaceSystemDependentDataInternal(r2
);
241 void addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr
& rData
) const;
242 SystemDependentData_SharedPtr
getSystemDependantDataInternal(size_t hash_code
) const;
245 // typedef for a vector of B2DPolygons
246 typedef ::std::vector
< B2DPolygon
> B2DPolygonVector
;
248 template< typename charT
, typename traits
>
249 inline std::basic_ostream
<charT
, traits
> & operator <<(
250 std::basic_ostream
<charT
, traits
> & stream
, const B2DPolygon
& poly
)
252 stream
<< "<" << poly
.count() << ":";
253 for (sal_uInt32 i
= 0; i
< poly
.count(); i
++)
257 stream
<< poly
.getB2DPoint(i
);
264 } // end of namespace basegfx
266 #endif // INCLUDED_BASEGFX_POLYGON_B2DPOLYGON_HXX
268 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */