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 : 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 :
160 : void Move( long nHorzMove, long nVertMove );
161 : void Translate( const Point& rTrans );
162 : void Scale( double fScaleX, double fScaleY );
163 : void Rotate( const Point& rCenter, double fSin, double fCos );
164 : void Rotate( const Point& rCenter, sal_uInt16 nAngle10 );
165 :
166 : void Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags = POLY_NORMAL );
167 : void Insert( sal_uInt16 nPos, const Polygon& rPoly );
168 :
169 0 : const Point& operator[]( sal_uInt16 nPos ) const { return GetPoint( nPos ); }
170 : Point& operator[]( sal_uInt16 nPos );
171 :
172 : Polygon& operator=( const Polygon& rPoly );
173 : bool operator==( const Polygon& rPoly ) const;
174 : bool operator!=( const Polygon& rPoly ) const
175 : { return !(Polygon::operator==( rPoly )); }
176 : bool IsEqual( const Polygon& rPoly ) const;
177 :
178 : // streaming a Polygon does ignore PolyFlags, so use the Write Or Read
179 : // method to take care of PolyFlags
180 : TOOLS_DLLPUBLIC friend SvStream& ReadPolygon( SvStream& rIStream, Polygon& rPoly );
181 : TOOLS_DLLPUBLIC friend SvStream& WritePolygon( SvStream& rOStream, const Polygon& rPoly );
182 :
183 : void Read( SvStream& rIStream );
184 : void Write( SvStream& rOStream ) const;
185 :
186 : const Point* GetConstPointAry() const;
187 : const sal_uInt8* GetConstFlagAry() const;
188 :
189 : // convert to ::basegfx::B2DPolygon and return
190 : ::basegfx::B2DPolygon getB2DPolygon() const;
191 :
192 : // constructor to convert from ::basegfx::B2DPolygon
193 : // #i76339# made explicit
194 : explicit Polygon(const ::basegfx::B2DPolygon& rPolygon);
195 : };
196 :
197 : class TOOLS_DLLPUBLIC SAL_WARN_UNUSED PolyPolygon
198 : {
199 : private:
200 : ImplPolyPolygon* mpImplPolyPolygon;
201 :
202 : TOOLS_DLLPRIVATE void ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, sal_uIntPtr nOperation ) const;
203 : TOOLS_DLLPRIVATE void *ImplCreateArtVpath() const;
204 : TOOLS_DLLPRIVATE void ImplSetFromArtVpath( void *pVpath );
205 :
206 : public:
207 : PolyPolygon( sal_uInt16 nInitSize = 16, sal_uInt16 nResize = 16 );
208 : PolyPolygon( const Polygon& rPoly );
209 : PolyPolygon( const PolyPolygon& rPolyPoly );
210 : ~PolyPolygon();
211 :
212 : void Insert( const Polygon& rPoly, sal_uInt16 nPos = POLYPOLY_APPEND );
213 : void Remove( sal_uInt16 nPos );
214 : void Replace( const Polygon& rPoly, sal_uInt16 nPos );
215 : const Polygon& GetObject( sal_uInt16 nPos ) const;
216 :
217 : bool IsRect() const;
218 :
219 : void Clear();
220 :
221 : sal_uInt16 Count() const;
222 : Rectangle GetBoundRect() const;
223 : void Clip( const Rectangle& rRect );
224 : void Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData = NULL );
225 :
226 : /** Adaptive subdivision of polygons with curves
227 :
228 : This method adaptively subdivides bezier arcs within the
229 : polygon to straight line segments and returns the resulting
230 : polygon.
231 :
232 : @param rResult
233 : The resulting subdivided polygon
234 :
235 : @param d
236 : This parameter controls the amount of subdivision. The
237 : original curve is guaranteed to not differ by more than this
238 : amount per bezier segment from the subdivided
239 : lines. Concretely, if the polygon is in device coordinates and
240 : d equals 1.0, then the difference between the subdivided and
241 : the original polygon is guaranteed to be smaller than one
242 : pixel.
243 : */
244 : void AdaptiveSubdivide( PolyPolygon& rResult, const double d = 1.0 ) const;
245 :
246 : void GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const;
247 : void GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const;
248 :
249 : void Move( long nHorzMove, long nVertMove );
250 : void Translate( const Point& rTrans );
251 : void Scale( double fScaleX, double fScaleY );
252 : void Rotate( const Point& rCenter, double fSin, double fCos );
253 : void Rotate( const Point& rCenter, sal_uInt16 nAngle10 );
254 :
255 0 : const Polygon& operator[]( sal_uInt16 nPos ) const { return GetObject( nPos ); }
256 : Polygon& operator[]( sal_uInt16 nPos );
257 :
258 : PolyPolygon& operator=( const PolyPolygon& rPolyPoly );
259 : bool operator==( const PolyPolygon& rPolyPoly ) const;
260 : bool operator!=( const PolyPolygon& rPolyPoly ) const
261 : { return !(PolyPolygon::operator==( rPolyPoly )); }
262 :
263 : bool IsEqual( const PolyPolygon& rPolyPoly ) const;
264 :
265 : TOOLS_DLLPUBLIC friend SvStream& ReadPolyPolygon( SvStream& rIStream, PolyPolygon& rPolyPoly );
266 : TOOLS_DLLPUBLIC friend SvStream& WritePolyPolygon( SvStream& rOStream, const PolyPolygon& rPolyPoly );
267 :
268 : void Read( SvStream& rIStream );
269 : void Write( SvStream& rOStream ) const;
270 :
271 : // convert to ::basegfx::B2DPolyPolygon and return
272 : ::basegfx::B2DPolyPolygon getB2DPolyPolygon() const;
273 :
274 : // constructor to convert from ::basegfx::B2DPolyPolygon
275 : // #i76339# made explicit
276 : explicit PolyPolygon(const ::basegfx::B2DPolyPolygon& rPolyPolygon);
277 : };
278 :
279 : typedef std::vector< PolyPolygon > PolyPolyVector;
280 :
281 :
282 : template<typename charT, typename traits>
283 : inline std::basic_ostream<charT, traits> & operator <<(
284 : std::basic_ostream<charT, traits> & stream, const PolyPolygon& rPolyPoly)
285 : {
286 : if (!rPolyPoly.Count())
287 : stream << "EMPTY";
288 : for (sal_uInt16 i = 0; i < rPolyPoly.Count(); ++i)
289 : stream << "[" << i << "] " << rPolyPoly.GetObject(i);
290 : return stream;
291 : }
292 :
293 : #endif
294 :
295 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|