/src/libreoffice/vcl/source/outdev/polygon.cxx
Line | Count | Source |
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 | | |
20 | | #include <sal/types.h> |
21 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
22 | | #include <tools/poly.hxx> |
23 | | |
24 | | #include <vcl/rendercontext/AntialiasingFlags.hxx> |
25 | | #include <vcl/metaact.hxx> |
26 | | #include <vcl/virdev.hxx> |
27 | | |
28 | | #include <CoordinateMapper.hxx> |
29 | | #include <salgdi.hxx> |
30 | | |
31 | | #include <cassert> |
32 | | #include <memory> |
33 | | |
34 | 639 | #define OUTDEV_POLYPOLY_STACKBUF 32 |
35 | | |
36 | | void OutputDevice::DrawPolyPolygon( const tools::PolyPolygon& rPolyPoly ) |
37 | 514k | { |
38 | 514k | assert(!is_double_buffered_window()); |
39 | | |
40 | 514k | if( mpMetaFile ) |
41 | 20.8k | mpMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) ); |
42 | | |
43 | 514k | sal_uInt16 nPoly = rPolyPoly.Count(); |
44 | | |
45 | 514k | if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || !nPoly || ImplIsRecordLayout() ) |
46 | 30.6k | return; |
47 | | |
48 | | // we need a graphics |
49 | 483k | if ( !mpGraphics && !AcquireGraphics() ) |
50 | 0 | return; |
51 | 483k | assert(mpGraphics); |
52 | | |
53 | 483k | if ( mbInitClipRegion ) |
54 | 71 | InitClipRegion(); |
55 | | |
56 | 483k | if ( mbOutputClipped ) |
57 | 73 | return; |
58 | | |
59 | 483k | if ( mbInitLineColor ) |
60 | 154 | InitLineColor(); |
61 | | |
62 | 483k | if ( mbInitFillColor ) |
63 | 403 | InitFillColor(); |
64 | | |
65 | | // use b2dpolygon drawing if possible |
66 | 483k | if (RasterOp::OverPaint == GetRasterOp() && (IsLineColor() || IsFillColor())) |
67 | 482k | { |
68 | 482k | const basegfx::B2DHomMatrix aTransform(mpMapper->GetDeviceTransformation()); |
69 | 482k | basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon()); |
70 | | |
71 | | // ensure closed - may be asserted, will prevent buffering |
72 | 482k | if(!aB2DPolyPolygon.isClosed()) |
73 | 19.3k | { |
74 | 19.3k | aB2DPolyPolygon.setClosed(true); |
75 | 19.3k | } |
76 | | |
77 | 482k | if (IsFillColor()) |
78 | 482k | { |
79 | 482k | mpGraphics->DrawPolyPolygon( |
80 | 482k | aTransform, |
81 | 482k | aB2DPolyPolygon, |
82 | 482k | 0.0, |
83 | 482k | *this); |
84 | 482k | } |
85 | | |
86 | 482k | bool bSuccess(true); |
87 | 482k | if (IsLineColor()) |
88 | 4.35k | { |
89 | 4.35k | const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline); |
90 | | |
91 | 4.35k | for(auto const& rPolygon : std::as_const(aB2DPolyPolygon)) |
92 | 16.0k | { |
93 | 16.0k | bSuccess = mpGraphics->DrawPolyLine( |
94 | 16.0k | aTransform, |
95 | 16.0k | rPolygon, |
96 | 16.0k | 0.0, |
97 | 16.0k | 0.0, // tdf#124848 hairline |
98 | 16.0k | nullptr, // MM01 |
99 | 16.0k | basegfx::B2DLineJoin::NONE, |
100 | 16.0k | css::drawing::LineCap_BUTT, |
101 | 16.0k | basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default |
102 | 16.0k | bPixelSnapHairline, |
103 | 16.0k | *this); |
104 | 16.0k | if (!bSuccess) |
105 | 0 | break; |
106 | 16.0k | } |
107 | 4.35k | } |
108 | | |
109 | 482k | if(bSuccess) |
110 | 482k | return; |
111 | 482k | } |
112 | | |
113 | 926 | if ( nPoly == 1 ) |
114 | 297 | { |
115 | | // #100127# Map to DrawPolygon |
116 | 297 | const tools::Polygon& aPoly = rPolyPoly.GetObject( 0 ); |
117 | 297 | if( aPoly.GetSize() >= 2 ) |
118 | 295 | { |
119 | 295 | GDIMetaFile* pOldMF = mpMetaFile; |
120 | 295 | mpMetaFile = nullptr; |
121 | | |
122 | 295 | DrawPolygon( aPoly ); |
123 | | |
124 | 295 | mpMetaFile = pOldMF; |
125 | 295 | } |
126 | 297 | } |
127 | 629 | else |
128 | 629 | { |
129 | | // #100127# moved real tools::PolyPolygon draw to separate method, |
130 | | // have to call recursively, avoiding duplicate |
131 | | // ImplLogicToDevicePixel calls |
132 | 629 | ImplDrawPolyPolygon( nPoly, ImplLogicToDevicePixel( rPolyPoly ) ); |
133 | 629 | } |
134 | 926 | } |
135 | | |
136 | | void OutputDevice::DrawPolygon( const basegfx::B2DPolygon& rB2DPolygon) |
137 | 3.38k | { |
138 | 3.38k | assert(!is_double_buffered_window()); |
139 | | |
140 | | // AW: Do NOT paint empty polygons |
141 | 3.38k | if(rB2DPolygon.count()) |
142 | 3.38k | { |
143 | 3.38k | basegfx::B2DPolyPolygon aPP( rB2DPolygon ); |
144 | 3.38k | DrawPolyPolygon( aPP ); |
145 | 3.38k | } |
146 | 3.38k | } |
147 | | |
148 | | void OutputDevice::DrawPolygon( const tools::Polygon& rPoly ) |
149 | 1.15M | { |
150 | 1.15M | assert(!is_double_buffered_window()); |
151 | | |
152 | 1.15M | if( mpMetaFile ) |
153 | 1.13M | mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) ); |
154 | | |
155 | 1.15M | sal_uInt16 nPoints = rPoly.GetSize(); |
156 | | |
157 | 1.15M | if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || (nPoints < 2) || ImplIsRecordLayout() ) |
158 | 1.15M | return; |
159 | | |
160 | | // we need a graphics |
161 | 4.55k | if ( !mpGraphics && !AcquireGraphics() ) |
162 | 0 | return; |
163 | 4.55k | assert(mpGraphics); |
164 | | |
165 | 4.55k | if ( mbInitClipRegion ) |
166 | 535 | InitClipRegion(); |
167 | | |
168 | 4.55k | if ( mbOutputClipped ) |
169 | 357 | return; |
170 | | |
171 | 4.20k | if ( mbInitLineColor ) |
172 | 142 | InitLineColor(); |
173 | | |
174 | 4.20k | if ( mbInitFillColor ) |
175 | 1.14k | InitFillColor(); |
176 | | |
177 | | // use b2dpolygon drawing if possible |
178 | 4.20k | if (RasterOp::OverPaint == GetRasterOp() && (IsLineColor() || IsFillColor())) |
179 | 3.52k | { |
180 | 3.52k | const basegfx::B2DHomMatrix aTransform(mpMapper->GetDeviceTransformation()); |
181 | 3.52k | basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon()); |
182 | | |
183 | | // ensure closed - maybe assert, hinders buffering |
184 | 3.52k | if(!aB2DPolygon.isClosed()) |
185 | 2.08k | { |
186 | 2.08k | aB2DPolygon.setClosed(true); |
187 | 2.08k | } |
188 | | |
189 | 3.52k | if (IsFillColor()) |
190 | 3.21k | { |
191 | 3.21k | mpGraphics->DrawPolyPolygon( |
192 | 3.21k | aTransform, |
193 | 3.21k | basegfx::B2DPolyPolygon(aB2DPolygon), |
194 | 3.21k | 0.0, |
195 | 3.21k | *this); |
196 | 3.21k | } |
197 | | |
198 | 3.52k | bool bSuccess(true); |
199 | 3.52k | if (IsLineColor()) |
200 | 1.87k | { |
201 | 1.87k | const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline); |
202 | | |
203 | 1.87k | bSuccess = mpGraphics->DrawPolyLine( |
204 | 1.87k | aTransform, |
205 | 1.87k | aB2DPolygon, |
206 | 1.87k | 0.0, |
207 | 1.87k | 0.0, // tdf#124848 hairline |
208 | 1.87k | nullptr, // MM01 |
209 | 1.87k | basegfx::B2DLineJoin::NONE, |
210 | 1.87k | css::drawing::LineCap_BUTT, |
211 | 1.87k | basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default |
212 | 1.87k | bPixelSnapHairline, |
213 | 1.87k | *this); |
214 | 1.87k | } |
215 | | |
216 | 3.52k | if(bSuccess) |
217 | 3.52k | return; |
218 | 3.52k | } |
219 | | |
220 | 678 | tools::Polygon aPoly = ImplLogicToDevicePixel( rPoly ); |
221 | 678 | const Point* pPtAry = aPoly.GetConstPointAry(); |
222 | | |
223 | | // #100127# Forward beziers to sal, if any |
224 | 678 | if( aPoly.HasFlags() ) |
225 | 175 | { |
226 | 175 | const PolyFlags* pFlgAry = aPoly.GetConstFlagAry(); |
227 | 175 | if( !mpGraphics->DrawPolygonBezier( nPoints, pPtAry, pFlgAry, *this ) ) |
228 | 175 | { |
229 | 175 | aPoly = tools::Polygon::SubdivideBezier(aPoly); |
230 | 175 | pPtAry = aPoly.GetConstPointAry(); |
231 | 175 | mpGraphics->DrawPolygon( aPoly.GetSize(), pPtAry, *this ); |
232 | 175 | } |
233 | 175 | } |
234 | 503 | else |
235 | 503 | { |
236 | 503 | mpGraphics->DrawPolygon( nPoints, pPtAry, *this ); |
237 | 503 | } |
238 | 678 | } |
239 | | |
240 | | // Caution: This method is nearly the same as |
241 | | // OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency), |
242 | | // so when changes are made here do not forget to make changes there, too |
243 | | |
244 | | void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly ) |
245 | 4.38k | { |
246 | 4.38k | assert(!is_double_buffered_window()); |
247 | | |
248 | 4.38k | if( mpMetaFile ) |
249 | 4.38k | mpMetaFile->AddAction( new MetaPolyPolygonAction( tools::PolyPolygon( rB2DPolyPoly ) ) ); |
250 | | |
251 | | // call helper |
252 | 4.38k | ImplDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly); |
253 | 4.38k | } |
254 | | |
255 | | void OutputDevice::ImplDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly) |
256 | 4.40k | { |
257 | | // Do not paint empty PolyPolygons |
258 | 4.40k | if(!rB2DPolyPoly.count() || !IsDeviceOutputNecessary()) |
259 | 4.38k | return; |
260 | | |
261 | | // we need a graphics |
262 | 21 | if( !mpGraphics && !AcquireGraphics() ) |
263 | 0 | return; |
264 | 21 | assert(mpGraphics); |
265 | | |
266 | 21 | if( mbInitClipRegion ) |
267 | 0 | InitClipRegion(); |
268 | | |
269 | 21 | if( mbOutputClipped ) |
270 | 0 | return; |
271 | | |
272 | 21 | if( mbInitLineColor ) |
273 | 0 | InitLineColor(); |
274 | | |
275 | 21 | if( mbInitFillColor ) |
276 | 0 | InitFillColor(); |
277 | | |
278 | 21 | bool bSuccess(false); |
279 | | |
280 | 21 | if (RasterOp::OverPaint == GetRasterOp() && (IsLineColor() || IsFillColor())) |
281 | 11 | { |
282 | 11 | const basegfx::B2DHomMatrix aTransform(mpMapper->GetDeviceTransformation()); |
283 | 11 | basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly); |
284 | 11 | bSuccess = true; |
285 | | |
286 | | // ensure closed - maybe assert, hinders buffering |
287 | 11 | if(!aB2DPolyPolygon.isClosed()) |
288 | 0 | { |
289 | 0 | aB2DPolyPolygon.setClosed(true); |
290 | 0 | } |
291 | | |
292 | 11 | if (IsFillColor()) |
293 | 11 | { |
294 | 11 | mpGraphics->DrawPolyPolygon( |
295 | 11 | aTransform, |
296 | 11 | aB2DPolyPolygon, |
297 | 11 | 0.0, |
298 | 11 | *this); |
299 | 11 | } |
300 | | |
301 | 11 | if (IsLineColor()) |
302 | 0 | { |
303 | 0 | const bool bPixelSnapHairline(mnAntialiasing & AntialiasingFlags::PixelSnapHairline); |
304 | |
|
305 | 0 | for(auto const& rPolygon : std::as_const(aB2DPolyPolygon)) |
306 | 0 | { |
307 | 0 | bSuccess = mpGraphics->DrawPolyLine( |
308 | 0 | aTransform, |
309 | 0 | rPolygon, |
310 | 0 | (255 - GetLineColor().GetAlpha()) / 255.0, |
311 | 0 | 0.0, // tdf#124848 hairline |
312 | 0 | nullptr, // MM01 |
313 | 0 | basegfx::B2DLineJoin::NONE, |
314 | 0 | css::drawing::LineCap_BUTT, |
315 | 0 | basegfx::deg2rad(15.0), // not used with B2DLineJoin::NONE, but the correct default |
316 | 0 | bPixelSnapHairline, |
317 | 0 | *this); |
318 | 0 | if (!bSuccess) |
319 | 0 | break; |
320 | 0 | } |
321 | 0 | } |
322 | 11 | } |
323 | | |
324 | 21 | if (!bSuccess) |
325 | 10 | { |
326 | | // fallback to old polygon drawing if needed |
327 | 10 | const tools::PolyPolygon aToolsPolyPolygon(rB2DPolyPoly); |
328 | 10 | const tools::PolyPolygon aPixelPolyPolygon = ImplLogicToDevicePixel(aToolsPolyPolygon); |
329 | 10 | ImplDrawPolyPolygon(aPixelPolyPolygon.Count(), aPixelPolyPolygon); |
330 | 10 | } |
331 | 21 | } |
332 | | |
333 | | // #100127# Extracted from OutputDevice::DrawPolyPolygon() |
334 | | void OutputDevice::ImplDrawPolyPolygon( sal_uInt16 nPoly, const tools::PolyPolygon& rPolyPoly ) |
335 | 639 | { |
336 | | // AW: This crashes on empty PolyPolygons, avoid that |
337 | 639 | if(!nPoly) |
338 | 0 | return; |
339 | | |
340 | 639 | sal_uInt32 aStackAry1[OUTDEV_POLYPOLY_STACKBUF]; |
341 | 639 | const Point* aStackAry2[OUTDEV_POLYPOLY_STACKBUF]; |
342 | 639 | const PolyFlags* aStackAry3[OUTDEV_POLYPOLY_STACKBUF]; |
343 | 639 | sal_uInt32* pPointAry; |
344 | 639 | const Point** pPointAryAry; |
345 | 639 | const PolyFlags** pFlagAryAry; |
346 | 639 | sal_uInt16 i = 0; |
347 | 639 | sal_uInt16 j = 0; |
348 | 639 | sal_uInt16 last = 0; |
349 | 639 | bool bHaveBezier = false; |
350 | 639 | if ( nPoly > OUTDEV_POLYPOLY_STACKBUF ) |
351 | 0 | { |
352 | 0 | pPointAry = new sal_uInt32[nPoly]; |
353 | 0 | pPointAryAry = new const Point*[nPoly]; |
354 | 0 | pFlagAryAry = new const PolyFlags*[nPoly]; |
355 | 0 | } |
356 | 639 | else |
357 | 639 | { |
358 | 639 | pPointAry = aStackAry1; |
359 | 639 | pPointAryAry = aStackAry2; |
360 | 639 | pFlagAryAry = aStackAry3; |
361 | 639 | } |
362 | | |
363 | 639 | do |
364 | 2.67k | { |
365 | 2.67k | const tools::Polygon& rPoly = rPolyPoly.GetObject( i ); |
366 | 2.67k | sal_uInt16 nSize = rPoly.GetSize(); |
367 | 2.67k | if ( nSize ) |
368 | 2.67k | { |
369 | 2.67k | pPointAry[j] = nSize; |
370 | 2.67k | pPointAryAry[j] = rPoly.GetConstPointAry(); |
371 | 2.67k | pFlagAryAry[j] = rPoly.GetConstFlagAry(); |
372 | 2.67k | last = i; |
373 | | |
374 | 2.67k | if( pFlagAryAry[j] ) |
375 | 1 | bHaveBezier = true; |
376 | | |
377 | 2.67k | ++j; |
378 | 2.67k | } |
379 | 2.67k | ++i; |
380 | 2.67k | } |
381 | 2.67k | while ( i < nPoly ); |
382 | | |
383 | 639 | if ( j == 1 ) |
384 | 10 | { |
385 | | // #100127# Forward beziers to sal, if any |
386 | 10 | if( bHaveBezier ) |
387 | 1 | { |
388 | 1 | if( !mpGraphics->DrawPolygonBezier( *pPointAry, *pPointAryAry, *pFlagAryAry, *this ) ) |
389 | 1 | { |
390 | 1 | tools::Polygon aPoly = tools::Polygon::SubdivideBezier( rPolyPoly.GetObject( last ) ); |
391 | 1 | mpGraphics->DrawPolygon( aPoly.GetSize(), aPoly.GetConstPointAry(), *this ); |
392 | 1 | } |
393 | 1 | } |
394 | 9 | else |
395 | 9 | { |
396 | 9 | mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry, *this ); |
397 | 9 | } |
398 | 10 | } |
399 | 629 | else |
400 | 629 | { |
401 | | // #100127# Forward beziers to sal, if any |
402 | 629 | if( bHaveBezier ) |
403 | 0 | { |
404 | 0 | if (!mpGraphics->DrawPolyPolygonBezier(j, pPointAry, pPointAryAry, pFlagAryAry, *this)) |
405 | 0 | { |
406 | 0 | tools::PolyPolygon aPolyPoly = tools::PolyPolygon::SubdivideBezier( rPolyPoly ); |
407 | 0 | ImplDrawPolyPolygon( aPolyPoly.Count(), aPolyPoly ); |
408 | 0 | } |
409 | 0 | } |
410 | 629 | else |
411 | 629 | { |
412 | 629 | mpGraphics->DrawPolyPolygon( j, pPointAry, pPointAryAry, *this ); |
413 | 629 | } |
414 | 629 | } |
415 | | |
416 | 639 | if ( pPointAry != aStackAry1 ) |
417 | 0 | { |
418 | 0 | delete[] pPointAry; |
419 | 0 | delete[] pPointAryAry; |
420 | 0 | delete[] pFlagAryAry; |
421 | 0 | } |
422 | 639 | } |
423 | | |
424 | | void OutputDevice::ImplDrawPolygon( const tools::Polygon& rPoly, const tools::PolyPolygon* pClipPolyPoly ) |
425 | 6.01M | { |
426 | 6.01M | if( pClipPolyPoly ) |
427 | 0 | { |
428 | 0 | ImplDrawPolyPolygon( tools::PolyPolygon(rPoly), pClipPolyPoly ); |
429 | 0 | } |
430 | 6.01M | else |
431 | 6.01M | { |
432 | 6.01M | sal_uInt16 nPoints = rPoly.GetSize(); |
433 | | |
434 | 6.01M | if ( nPoints < 2 ) |
435 | 0 | return; |
436 | | |
437 | 6.01M | const Point* pPtAry = rPoly.GetConstPointAry(); |
438 | 6.01M | mpGraphics->DrawPolygon( nPoints, pPtAry, *this ); |
439 | 6.01M | } |
440 | 6.01M | } |
441 | | |
442 | | void OutputDevice::ImplDrawPolyPolygon( const tools::PolyPolygon& rPolyPoly, const tools::PolyPolygon* pClipPolyPoly ) |
443 | 199 | { |
444 | 199 | tools::PolyPolygon* pPolyPoly; |
445 | | |
446 | 199 | if( pClipPolyPoly ) |
447 | 0 | { |
448 | 0 | pPolyPoly = new tools::PolyPolygon; |
449 | 0 | rPolyPoly.GetIntersection( *pClipPolyPoly, *pPolyPoly ); |
450 | 0 | } |
451 | 199 | else |
452 | 199 | { |
453 | 199 | pPolyPoly = const_cast<tools::PolyPolygon*>(&rPolyPoly); |
454 | 199 | } |
455 | 199 | if( pPolyPoly->Count() == 1 ) |
456 | 0 | { |
457 | 0 | const tools::Polygon& rPoly = pPolyPoly->GetObject( 0 ); |
458 | 0 | sal_uInt16 nSize = rPoly.GetSize(); |
459 | |
|
460 | 0 | if( nSize >= 2 ) |
461 | 0 | { |
462 | 0 | const Point* pPtAry = rPoly.GetConstPointAry(); |
463 | 0 | mpGraphics->DrawPolygon( nSize, pPtAry, *this ); |
464 | 0 | } |
465 | 0 | } |
466 | 199 | else if( pPolyPoly->Count() ) |
467 | 199 | { |
468 | 199 | sal_uInt16 nCount = pPolyPoly->Count(); |
469 | 199 | std::unique_ptr<sal_uInt32[]> pPointAry(new sal_uInt32[nCount]); |
470 | 199 | std::unique_ptr<const Point*[]> pPointAryAry(new const Point*[nCount]); |
471 | 199 | sal_uInt16 i = 0; |
472 | 199 | do |
473 | 398 | { |
474 | 398 | const tools::Polygon& rPoly = pPolyPoly->GetObject( i ); |
475 | 398 | sal_uInt16 nSize = rPoly.GetSize(); |
476 | 398 | if ( nSize ) |
477 | 398 | { |
478 | 398 | pPointAry[i] = nSize; |
479 | 398 | pPointAryAry[i] = rPoly.GetConstPointAry(); |
480 | 398 | i++; |
481 | 398 | } |
482 | 0 | else |
483 | 0 | nCount--; |
484 | 398 | } |
485 | 398 | while( i < nCount ); |
486 | | |
487 | 199 | if( nCount == 1 ) |
488 | 0 | mpGraphics->DrawPolygon( pPointAry[0], pPointAryAry[0], *this ); |
489 | 199 | else |
490 | 199 | mpGraphics->DrawPolyPolygon( nCount, pPointAry.get(), pPointAryAry.get(), *this ); |
491 | 199 | } |
492 | | |
493 | 199 | if( pClipPolyPoly ) |
494 | 0 | delete pPolyPoly; |
495 | 199 | } |
496 | | |
497 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |