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