Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #ifndef INCLUDED_TOOLS_POLY_HXX
20 : #define INCLUDED_TOOLS_POLY_HXX
21 :
22 : #include <tools/toolsdllapi.h>
23 : #include <tools/gen.hxx>
24 : #include <tools/debug.hxx>
25 :
26 : #include <vector>
27 :
28 : #define POLY_APPEND (0xFFFF)
29 : #define POLYPOLY_APPEND (0xFFFF)
30 :
31 : #define POLY_OPTIMIZE_NONE 0x00000000UL
32 : #define POLY_OPTIMIZE_OPEN 0x00000001UL
33 : #define POLY_OPTIMIZE_CLOSE 0x00000002UL
34 : #define POLY_OPTIMIZE_NO_SAME 0x00000004UL
35 : #define POLY_OPTIMIZE_REDUCE 0x00000008UL
36 : #define POLY_OPTIMIZE_EDGES 0x00000010UL
37 :
38 : enum PolyStyle
39 : {
40 : POLY_ARC = 1,
41 : POLY_PIE = 2,
42 : POLY_CHORD = 3
43 : };
44 :
45 : #ifndef ENUM_POLYFLAGS_DECLARED
46 : #define ENUM_POLYFLAGS_DECLARED
47 : enum PolyFlags
48 : {
49 : POLY_NORMAL,
50 : POLY_SMOOTH,
51 : POLY_CONTROL,
52 : POLY_SYMMTR
53 : };
54 : #endif
55 :
56 : class SAL_WARN_UNUSED PolyOptimizeData
57 : {
58 : private:
59 :
60 : enum DataType { DATA_NONE = 0, DATA_ABSOLUT = 1, DATA_PERCENT = 2 };
61 : DataType eType;
62 : union { sal_uIntPtr mnAbsolut; sal_uInt16 mnPercent; };
63 :
64 : public:
65 : PolyOptimizeData() : eType( DATA_NONE ) {}
66 : PolyOptimizeData( sal_uIntPtr nAbsolut ) : eType( DATA_ABSOLUT ), mnAbsolut( nAbsolut ) {}
67 : PolyOptimizeData( sal_uInt16 nPercent ) : eType( DATA_PERCENT ), mnPercent( nPercent ) {}
68 :
69 0 : sal_uIntPtr GetAbsValue() const { (void) eType; DBG_ASSERT( eType == DATA_ABSOLUT, "Wrong data type" ); return mnAbsolut; }
70 0 : sal_uInt16 GetPercentValue() const { (void) eType; DBG_ASSERT( eType == DATA_PERCENT, "Wrong data type" ); return mnPercent; }
71 : };
72 :
73 : class SvStream;
74 : class ImplPolygon;
75 : class ImplPolyPolygon;
76 : namespace tools { class PolyPolygon; }
77 :
78 : namespace basegfx
79 : {
80 : class B2DPolygon;
81 : class B2DPolyPolygon;
82 : }
83 :
84 : class TOOLS_DLLPUBLIC SAL_WARN_UNUSED Polygon
85 : {
86 : private:
87 : ImplPolygon* mpImplPolygon;
88 :
89 : TOOLS_DLLPRIVATE inline void ImplMakeUnique();
90 :
91 : public:
92 : static void ImplReduceEdges( Polygon& rPoly, const double& rArea, sal_uInt16 nPercent );
93 : void ImplRead( SvStream& rIStream );
94 : void ImplWrite( SvStream& rOStream ) const;
95 :
96 : public:
97 : Polygon();
98 : Polygon( sal_uInt16 nSize );
99 : Polygon( sal_uInt16 nPoints, const Point* pPtAry,
100 : const sal_uInt8* pFlagAry = NULL );
101 : Polygon( const Rectangle& rRect );
102 : Polygon( const Rectangle& rRect,
103 : sal_uIntPtr nHorzRound, sal_uIntPtr nVertRound );
104 : Polygon( const Point& rCenter,
105 : long nRadX, long nRadY,
106 : sal_uInt16 nPoints = 0 );
107 : Polygon( const Rectangle& rBound,
108 : const Point& rStart, const Point& rEnd,
109 : PolyStyle ePolyStyle = POLY_ARC,
110 : bool bWholeCircle = false );
111 : Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
112 : const Point& rBezPt2, const Point& rCtrlPt2,
113 : sal_uInt16 nPoints = 0 );
114 :
115 : Polygon( const Polygon& rPoly );
116 : ~Polygon();
117 :
118 : void SetPoint( const Point& rPt, sal_uInt16 nPos );
119 : const Point& GetPoint( sal_uInt16 nPos ) const;
120 :
121 : void SetFlags( sal_uInt16 nPos, PolyFlags eFlags );
122 : PolyFlags GetFlags( sal_uInt16 nPos ) const;
123 : bool HasFlags() const;
124 :
125 : bool IsRect() const;
126 :
127 : void SetSize( sal_uInt16 nNewSize );
128 : sal_uInt16 GetSize() const;
129 :
130 : void Clear();
131 :
132 : Rectangle GetBoundRect() const;
133 : double GetSignedArea() const;
134 : bool IsInside( const Point& rPt ) const;
135 : bool IsRightOrientated() const;
136 : double CalcDistance( sal_uInt16 nPt1, sal_uInt16 nPt2 );
137 : void Clip( const Rectangle& rRect, bool bPolygon = true );
138 : void Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData = NULL );
139 :
140 : /** Adaptive subdivision of polygons with curves
141 :
142 : This method adaptively subdivides bezier arcs within the
143 : polygon to straight line segments and returns the resulting
144 : polygon.
145 :
146 : @param rResult
147 : The resulting subdivided polygon
148 :
149 : @param d
150 : This parameter controls the amount of subdivision. The
151 : original curve is guaranteed to not differ by more than this
152 : amount per bezier segment from the subdivided
153 : lines. Concretely, if the polygon is in device coordinates and
154 : d equals 1.0, then the difference between the subdivided and
155 : the original polygon is guaranteed to be smaller than one
156 : pixel.
157 : */
158 : void AdaptiveSubdivide( Polygon& rResult, const double d = 1.0 ) const;
159 : static Polygon SubdivideBezier( const Polygon& rPoly );
160 :
161 : void Move( long nHorzMove, long nVertMove );
162 : void Translate( const Point& rTrans );
163 : void Scale( double fScaleX, double fScaleY );
164 : void Rotate( const Point& rCenter, double fSin, double fCos );
165 : void Rotate( const Point& rCenter, sal_uInt16 nAngle10 );
166 :
167 : void Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags = POLY_NORMAL );
168 : void Insert( sal_uInt16 nPos, const Polygon& rPoly );
169 :
170 861067 : const Point& operator[]( sal_uInt16 nPos ) const { return GetPoint( nPos ); }
171 : Point& operator[]( sal_uInt16 nPos );
172 :
173 : Polygon& operator=( const Polygon& rPoly );
174 : bool operator==( const Polygon& rPoly ) const;
175 : bool operator!=( const Polygon& rPoly ) const
176 : { return !(Polygon::operator==( rPoly )); }
177 : bool IsEqual( const Polygon& rPoly ) const;
178 :
179 : // streaming a Polygon does ignore PolyFlags, so use the Write Or Read
180 : // method to take care of PolyFlags
181 : TOOLS_DLLPUBLIC friend SvStream& ReadPolygon( SvStream& rIStream, Polygon& rPoly );
182 : TOOLS_DLLPUBLIC friend SvStream& WritePolygon( SvStream& rOStream, const Polygon& rPoly );
183 :
184 : void Read( SvStream& rIStream );
185 : void Write( SvStream& rOStream ) const;
186 :
187 : const Point* GetConstPointAry() const;
188 : const sal_uInt8* GetConstFlagAry() const;
189 :
190 : // convert to ::basegfx::B2DPolygon and return
191 : ::basegfx::B2DPolygon getB2DPolygon() const;
192 :
193 : // constructor to convert from ::basegfx::B2DPolygon
194 : // #i76339# made explicit
195 : explicit Polygon(const ::basegfx::B2DPolygon& rPolygon);
196 : };
197 :
198 : namespace tools {
199 :
200 : class TOOLS_DLLPUBLIC SAL_WARN_UNUSED PolyPolygon
201 : {
202 : private:
203 : ImplPolyPolygon* mpImplPolyPolygon;
204 :
205 : TOOLS_DLLPRIVATE void ImplDoOperation( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult, sal_uIntPtr nOperation ) const;
206 : TOOLS_DLLPRIVATE void *ImplCreateArtVpath() const;
207 : TOOLS_DLLPRIVATE void ImplSetFromArtVpath( void *pVpath );
208 :
209 : public:
210 : PolyPolygon( sal_uInt16 nInitSize = 16, sal_uInt16 nResize = 16 );
211 : PolyPolygon( const Polygon& rPoly );
212 : PolyPolygon( const tools::PolyPolygon& rPolyPoly );
213 : ~PolyPolygon();
214 :
215 : void Insert( const Polygon& rPoly, sal_uInt16 nPos = POLYPOLY_APPEND );
216 : void Remove( sal_uInt16 nPos );
217 : void Replace( const Polygon& rPoly, sal_uInt16 nPos );
218 : const Polygon& GetObject( sal_uInt16 nPos ) const;
219 :
220 : bool IsRect() const;
221 :
222 : void Clear();
223 :
224 : sal_uInt16 Count() const;
225 : Rectangle GetBoundRect() const;
226 : void Clip( const Rectangle& rRect );
227 : void Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData = NULL );
228 :
229 : /** Adaptive subdivision of polygons with curves
230 :
231 : This method adaptively subdivides bezier arcs within the
232 : polygon to straight line segments and returns the resulting
233 : polygon.
234 :
235 : @param rResult
236 : The resulting subdivided polygon
237 :
238 : @param d
239 : This parameter controls the amount of subdivision. The
240 : original curve is guaranteed to not differ by more than this
241 : amount per bezier segment from the subdivided
242 : lines. Concretely, if the polygon is in device coordinates and
243 : d equals 1.0, then the difference between the subdivided and
244 : the original polygon is guaranteed to be smaller than one
245 : pixel.
246 : */
247 : void AdaptiveSubdivide( tools::PolyPolygon& rResult, const double d = 1.0 ) const;
248 : static tools::PolyPolygon SubdivideBezier( const tools::PolyPolygon& rPolyPoly );
249 :
250 : void GetIntersection( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const;
251 : void GetUnion( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const;
252 :
253 : void Move( long nHorzMove, long nVertMove );
254 : void Translate( const Point& rTrans );
255 : void Scale( double fScaleX, double fScaleY );
256 : void Rotate( const Point& rCenter, double fSin, double fCos );
257 : void Rotate( const Point& rCenter, sal_uInt16 nAngle10 );
258 :
259 277825 : const Polygon& operator[]( sal_uInt16 nPos ) const { return GetObject( nPos ); }
260 : Polygon& operator[]( sal_uInt16 nPos );
261 :
262 : tools::PolyPolygon& operator=( const tools::PolyPolygon& rPolyPoly );
263 : bool operator==( const tools::PolyPolygon& rPolyPoly ) const;
264 : bool operator!=( const tools::PolyPolygon& rPolyPoly ) const
265 : { return !(PolyPolygon::operator==( rPolyPoly )); }
266 :
267 : bool IsEqual( const tools::PolyPolygon& rPolyPoly ) const;
268 :
269 : TOOLS_DLLPUBLIC friend SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly );
270 : TOOLS_DLLPUBLIC friend SvStream& WritePolyPolygon( SvStream& rOStream, const tools::PolyPolygon& rPolyPoly );
271 :
272 : void Read( SvStream& rIStream );
273 : void Write( SvStream& rOStream ) const;
274 :
275 : // convert to ::basegfx::B2DPolyPolygon and return
276 : ::basegfx::B2DPolyPolygon getB2DPolyPolygon() const;
277 :
278 : // constructor to convert from ::basegfx::B2DPolyPolygon
279 : // #i76339# made explicit
280 : explicit PolyPolygon(const ::basegfx::B2DPolyPolygon& rPolyPolygon);
281 : };
282 :
283 : } /* namespace tools */
284 :
285 : typedef std::vector< tools::PolyPolygon > PolyPolyVector;
286 :
287 :
288 : template<typename charT, typename traits>
289 : inline std::basic_ostream<charT, traits> & operator <<(
290 : std::basic_ostream<charT, traits> & stream, const tools::PolyPolygon& rPolyPoly)
291 : {
292 : if (!rPolyPoly.Count())
293 : stream << "EMPTY";
294 : for (sal_uInt16 i = 0; i < rPolyPoly.Count(); ++i)
295 : stream << "[" << i << "] " << rPolyPoly.GetObject(i);
296 : return stream;
297 : }
298 :
299 : #endif
300 :
301 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|