Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/tools/source/generic/poly2.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/log.hxx>
21
#include <osl/diagnose.h>
22
#include <poly.h>
23
#include <tools/poly.hxx>
24
#include <tools/debug.hxx>
25
#include <tools/stream.hxx>
26
#include <tools/vcompat.hxx>
27
#include <tools/gen.hxx>
28
#include <basegfx/polygon/b2dpolypolygon.hxx>
29
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
30
#include <basegfx/polygon/b2dpolygonclipper.hxx>
31
32
namespace tools {
33
34
PolyPolygon::PolyPolygon( sal_uInt16 nInitSize )
35
1.01M
    : mpImplPolyPolygon( ImplPolyPolygon( nInitSize ) )
36
1.01M
{
37
1.01M
}
38
39
PolyPolygon::PolyPolygon( const tools::Polygon& rPoly )
40
22.5k
    : mpImplPolyPolygon( rPoly )
41
22.5k
{
42
22.5k
}
43
PolyPolygon::PolyPolygon( const tools::Rectangle& rRect )
44
0
    : mpImplPolyPolygon( tools::Polygon(rRect) )
45
0
{
46
0
}
47
48
PolyPolygon::PolyPolygon( const tools::PolyPolygon& rPolyPoly )
49
1.12M
    : mpImplPolyPolygon( rPolyPoly.mpImplPolyPolygon )
50
1.12M
{
51
1.12M
}
52
53
PolyPolygon::PolyPolygon( tools::PolyPolygon&& rPolyPoly ) noexcept
54
86.9k
    : mpImplPolyPolygon( std::move(rPolyPoly.mpImplPolyPolygon) )
55
86.9k
{
56
86.9k
}
57
58
PolyPolygon::~PolyPolygon()
59
2.47M
{
60
2.47M
}
61
62
void PolyPolygon::Insert( const tools::Polygon& rPoly, sal_uInt16 nPos )
63
437k
{
64
437k
    assert ( mpImplPolyPolygon->mvPolyAry.size() < MAX_POLYGONS );
65
66
437k
    if ( nPos > mpImplPolyPolygon->mvPolyAry.size() )
67
437k
        nPos = mpImplPolyPolygon->mvPolyAry.size();
68
69
437k
    mpImplPolyPolygon->mvPolyAry.insert(mpImplPolyPolygon->mvPolyAry.begin() + nPos, rPoly);
70
437k
}
71
72
void PolyPolygon::Remove( sal_uInt16 nPos )
73
6.79k
{
74
6.79k
    assert(nPos < Count() && "PolyPolygon::Remove(): nPos >= nSize");
75
76
6.79k
    mpImplPolyPolygon->mvPolyAry.erase(mpImplPolyPolygon->mvPolyAry.begin() + nPos);
77
6.79k
}
78
79
void PolyPolygon::Replace( const tools::Polygon& rPoly, sal_uInt16 nPos )
80
1.14M
{
81
1.14M
    assert(nPos < Count() && "PolyPolygon::Replace(): nPos >= nSize");
82
83
1.14M
    mpImplPolyPolygon->mvPolyAry[nPos] = rPoly;
84
1.14M
}
85
86
const tools::Polygon& PolyPolygon::GetObject( sal_uInt16 nPos ) const
87
3.36M
{
88
3.36M
    assert(nPos < Count() && "PolyPolygon::GetObject(): nPos >= nSize");
89
90
3.36M
    return mpImplPolyPolygon->mvPolyAry[nPos];
91
3.36M
}
92
93
bool PolyPolygon::IsRect() const
94
22.1k
{
95
22.1k
    bool bIsRect = false;
96
22.1k
    if ( Count() == 1 )
97
17.3k
        bIsRect = mpImplPolyPolygon->mvPolyAry[ 0 ].IsRect();
98
22.1k
    return bIsRect;
99
22.1k
}
100
101
void PolyPolygon::Clear()
102
508k
{
103
508k
    mpImplPolyPolygon->mvPolyAry.clear();
104
508k
}
105
106
void PolyPolygon::Optimize( PolyOptimizeFlags nOptimizeFlags )
107
1.37k
{
108
1.37k
    if(!(bool(nOptimizeFlags) && Count()))
109
0
        return;
110
111
    // #115630# ImplDrawHatch does not work with beziers included in the polypolygon, take care of that
112
1.37k
    bool bIsCurve(false);
113
114
2.99k
    for(sal_uInt16 a(0); !bIsCurve && a < Count(); a++)
115
1.61k
    {
116
1.61k
        if((*this)[a].HasFlags())
117
0
        {
118
0
            bIsCurve = true;
119
0
        }
120
1.61k
    }
121
122
1.37k
    if(bIsCurve)
123
0
    {
124
0
        OSL_ENSURE(false, "Optimize does *not* support curves, falling back to AdaptiveSubdivide()...");
125
0
        tools::PolyPolygon aPolyPoly;
126
127
0
        AdaptiveSubdivide(aPolyPoly);
128
0
        aPolyPoly.Optimize(nOptimizeFlags);
129
0
        *this = std::move(aPolyPoly);
130
0
    }
131
1.37k
    else
132
1.37k
    {
133
1.37k
        double      fArea;
134
1.37k
        const bool  bEdges = ( nOptimizeFlags & PolyOptimizeFlags::EDGES ) == PolyOptimizeFlags::EDGES;
135
1.37k
        sal_uInt16      nPercent = 0;
136
137
1.37k
        if( bEdges )
138
0
        {
139
0
            const tools::Rectangle aBound( GetBoundRect() );
140
141
0
            fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
142
0
            nPercent = 50;
143
0
            nOptimizeFlags &= ~PolyOptimizeFlags::EDGES;
144
0
        }
145
146
        // Optimize polygons
147
2.99k
        for( sal_uInt16 i = 0, nPolyCount = mpImplPolyPolygon->mvPolyAry.size(); i < nPolyCount; i++ )
148
1.61k
        {
149
1.61k
            if( bEdges )
150
0
            {
151
0
                mpImplPolyPolygon->mvPolyAry[ i ].Optimize( PolyOptimizeFlags::NO_SAME );
152
0
                tools::Polygon::ImplReduceEdges( mpImplPolyPolygon->mvPolyAry[ i ], fArea, nPercent );
153
0
            }
154
155
1.61k
            if( bool(nOptimizeFlags) )
156
1.61k
                mpImplPolyPolygon->mvPolyAry[ i ].Optimize( nOptimizeFlags );
157
1.61k
        }
158
1.37k
    }
159
1.37k
}
160
161
void PolyPolygon::AdaptiveSubdivide( tools::PolyPolygon& rResult ) const
162
1.59k
{
163
1.59k
    rResult.Clear();
164
165
1.59k
    tools::Polygon aPolygon;
166
167
3.77k
    for( size_t i = 0; i < mpImplPolyPolygon->mvPolyAry.size(); i++ )
168
2.18k
    {
169
2.18k
        mpImplPolyPolygon->mvPolyAry[ i ].AdaptiveSubdivide( aPolygon, 1.0 );
170
2.18k
        rResult.Insert( aPolygon );
171
2.18k
    }
172
1.59k
}
173
174
tools::PolyPolygon PolyPolygon::SubdivideBezier( const tools::PolyPolygon& rPolyPoly )
175
14.9k
{
176
14.9k
    sal_uInt16 i, nPolys = rPolyPoly.Count();
177
14.9k
    tools::PolyPolygon aPolyPoly( nPolys );
178
44.7k
    for( i=0; i<nPolys; ++i )
179
29.8k
        aPolyPoly.Insert( tools::Polygon::SubdivideBezier( rPolyPoly.GetObject(i) ) );
180
181
14.9k
    return aPolyPoly;
182
14.9k
}
183
184
185
void PolyPolygon::GetIntersection( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const
186
0
{
187
0
    ImplDoOperation( rPolyPoly, rResult, PolyClipOp::INTERSECT );
188
0
}
189
190
void PolyPolygon::GetUnion( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const
191
0
{
192
0
    ImplDoOperation( rPolyPoly, rResult, PolyClipOp::UNION );
193
0
}
194
195
void PolyPolygon::ImplDoOperation( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult, PolyClipOp nOperation ) const
196
0
{
197
    // Convert to B2DPolyPolygon, temporarily. It might be
198
    // advantageous in the future, to have a tools::PolyPolygon adaptor that
199
    // just simulates a B2DPolyPolygon here...
200
0
    basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
201
0
    basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
202
203
    // normalize the two polypolygons before. Force properly oriented
204
    // polygons.
205
0
    aMergePolyPolygonA = basegfx::utils::prepareForPolygonOperation( aMergePolyPolygonA );
206
0
    aMergePolyPolygonB = basegfx::utils::prepareForPolygonOperation( aMergePolyPolygonB );
207
208
0
    switch( nOperation )
209
0
    {
210
        // All code extracted from svx/source/svdraw/svedtv2.cxx
211
212
0
        case PolyClipOp::UNION:
213
0
        {
214
            // merge A and B (OR)
215
0
            aMergePolyPolygonA = basegfx::utils::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
216
0
            break;
217
0
        }
218
219
0
        default:
220
0
        case PolyClipOp::INTERSECT:
221
0
        {
222
            // cut poly 1 against polys 2..n (AND)
223
0
            aMergePolyPolygonA = basegfx::utils::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
224
0
            break;
225
0
        }
226
0
    }
227
228
0
    rResult = tools::PolyPolygon( aMergePolyPolygonA );
229
0
}
230
231
sal_uInt16 PolyPolygon::Count() const
232
9.44M
{
233
9.44M
    return mpImplPolyPolygon->mvPolyAry.size();
234
9.44M
}
235
236
void PolyPolygon::Move( tools::Long nHorzMove, tools::Long nVertMove )
237
805k
{
238
    // Required for DrawEngine
239
805k
    if( nHorzMove || nVertMove )
240
804k
    {
241
        // move points
242
804k
        sal_uInt16 nPolyCount = mpImplPolyPolygon->mvPolyAry.size();
243
2.69M
        for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
244
1.89M
            mpImplPolyPolygon->mvPolyAry[i].Move( nHorzMove, nVertMove );
245
804k
    }
246
805k
}
247
248
void PolyPolygon::Translate( const Point& rTrans )
249
0
{
250
    // move points
251
0
    for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mvPolyAry.size(); i < nCount; i++ )
252
0
        mpImplPolyPolygon->mvPolyAry[ i ].Translate( rTrans );
253
0
}
254
255
void PolyPolygon::Scale( double fScaleX, double fScaleY )
256
140
{
257
    // Move points
258
140
    for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mvPolyAry.size(); i < nCount; i++ )
259
0
        mpImplPolyPolygon->mvPolyAry[ i ].Scale( fScaleX, fScaleY );
260
140
}
261
262
void PolyPolygon::Rotate( const Point& rCenter, Degree10 nAngle10 )
263
0
{
264
0
    nAngle10 %= 3600_deg10;
265
266
0
    if( nAngle10 )
267
0
    {
268
0
        const double fAngle = toRadians(nAngle10);
269
0
        Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
270
0
    }
271
0
}
272
273
void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
274
0
{
275
    // move points
276
0
    for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mvPolyAry.size(); i < nCount; i++ )
277
0
        mpImplPolyPolygon->mvPolyAry[ i ].Rotate( rCenter, fSin, fCos );
278
0
}
279
280
void PolyPolygon::Clip( const tools::Rectangle& rRect )
281
5.42k
{
282
5.42k
    sal_uInt16 nPolyCount = mpImplPolyPolygon->mvPolyAry.size();
283
5.42k
    sal_uInt16 i;
284
285
5.42k
    if ( !nPolyCount )
286
28
        return;
287
288
    // If there are bezier curves involved, Polygon::Clip() is broken.
289
    // Use a temporary B2DPolyPolygon for the clipping.
290
21.1k
    for ( i = 0; i < nPolyCount; i++ )
291
15.7k
    {
292
15.7k
        if(mpImplPolyPolygon->mvPolyAry[i].HasFlags())
293
0
        {
294
0
            const basegfx::B2DPolyPolygon aPoly(
295
0
                basegfx::utils::clipPolyPolygonOnRange(
296
0
                    getB2DPolyPolygon(),
297
0
                    basegfx::B2DRange(
298
0
                        rRect.Left(),
299
0
                        rRect.Top(),
300
0
                        rRect.Right() + 1,
301
0
                        rRect.Bottom() + 1),
302
0
                    true,
303
0
                    false));
304
0
            *this = PolyPolygon( aPoly );
305
0
            return;
306
0
        }
307
15.7k
    }
308
309
    // Clip every polygon, deleting the empty ones
310
21.1k
    for ( i = 0; i < nPolyCount; i++ )
311
15.7k
        mpImplPolyPolygon->mvPolyAry[i].Clip( rRect );
312
21.1k
    while ( nPolyCount )
313
15.7k
    {
314
15.7k
        if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
315
6.79k
            Remove( nPolyCount-1 );
316
15.7k
        nPolyCount--;
317
15.7k
    }
318
5.39k
}
319
320
tools::Rectangle PolyPolygon::GetBoundRect() const
321
62.2k
{
322
62.2k
    tools::Long    nXMin=0, nXMax=0, nYMin=0, nYMax=0;
323
62.2k
    bool    bFirst = true;
324
62.2k
    sal_uInt16  nPolyCount = mpImplPolyPolygon->mvPolyAry.size();
325
326
716k
    for ( sal_uInt16 n = 0; n < nPolyCount; n++ )
327
653k
    {
328
653k
        const tools::Polygon*  pPoly = &mpImplPolyPolygon->mvPolyAry[n];
329
653k
        const Point*    pAry = pPoly->GetConstPointAry();
330
653k
        sal_uInt16          nPointCount = pPoly->GetSize();
331
332
4.49M
        for ( sal_uInt16 i = 0; i < nPointCount; i++ )
333
3.83M
        {
334
3.83M
            const Point* pPt = &pAry[ i ];
335
336
3.83M
            if ( bFirst )
337
42.5k
            {
338
42.5k
                nXMin = nXMax = pPt->X();
339
42.5k
                nYMin = nYMax = pPt->Y();
340
42.5k
                bFirst = false;
341
42.5k
            }
342
3.79M
            else
343
3.79M
            {
344
3.79M
                if ( pPt->X() < nXMin )
345
25.0k
                    nXMin = pPt->X();
346
3.79M
                if ( pPt->X() > nXMax )
347
54.2k
                    nXMax = pPt->X();
348
3.79M
                if ( pPt->Y() < nYMin )
349
30.9k
                    nYMin = pPt->Y();
350
3.79M
                if ( pPt->Y() > nYMax )
351
31.1k
                    nYMax = pPt->Y();
352
3.79M
            }
353
3.83M
        }
354
653k
    }
355
356
62.2k
    if ( !bFirst )
357
42.5k
        return tools::Rectangle( nXMin, nYMin, nXMax, nYMax );
358
19.6k
    else
359
19.6k
        return tools::Rectangle();
360
62.2k
}
361
362
Polygon& PolyPolygon::operator[]( sal_uInt16 nPos )
363
345k
{
364
345k
    assert(nPos < Count() && "PolyPolygon::[](): nPos >= nSize");
365
366
345k
    return mpImplPolyPolygon->mvPolyAry[nPos];
367
345k
}
368
369
PolyPolygon& PolyPolygon::operator=( const tools::PolyPolygon& rPolyPoly )
370
155k
{
371
155k
    mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
372
155k
    return *this;
373
155k
}
374
375
PolyPolygon& PolyPolygon::operator=( tools::PolyPolygon&& rPolyPoly ) noexcept
376
24.6k
{
377
24.6k
    mpImplPolyPolygon = std::move(rPolyPoly.mpImplPolyPolygon);
378
24.6k
    return *this;
379
24.6k
}
380
381
bool PolyPolygon::operator==( const tools::PolyPolygon& rPolyPoly ) const
382
2
{
383
2
    return rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon;
384
2
}
385
386
SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly )
387
29.6k
{
388
29.6k
    sal_uInt16 nPolyCount(0);
389
390
    // Read number of polygons
391
29.6k
    rIStream.ReadUInt16( nPolyCount );
392
393
29.6k
    const size_t nMinRecordSize = sizeof(sal_uInt16);
394
29.6k
    const size_t nMaxRecords = rIStream.remainingSize() / nMinRecordSize;
395
29.6k
    if (nPolyCount > nMaxRecords)
396
424
    {
397
424
        SAL_WARN("tools", "Parsing error: " << nMaxRecords <<
398
424
                 " max possible entries, but " << nPolyCount << " claimed, truncating");
399
424
        nPolyCount = nMaxRecords;
400
424
    }
401
402
29.6k
    if( nPolyCount )
403
13.7k
    {
404
13.7k
        rPolyPoly.mpImplPolyPolygon->mvPolyAry.reserve(nPolyCount);
405
406
13.7k
        tools::Polygon aTempPoly;
407
394k
        for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
408
380k
        {
409
380k
            ReadPolygon( rIStream, aTempPoly );
410
380k
            if (aTempPoly.GetSize() == 0)
411
348k
            {
412
348k
                SAL_WARN("tools", "Parsing error: polygon with 0 points, ignoring");
413
348k
                continue;
414
348k
            }
415
31.5k
            rPolyPoly.mpImplPolyPolygon->mvPolyAry.push_back(aTempPoly);
416
31.5k
        }
417
13.7k
    }
418
15.8k
    else
419
15.8k
        rPolyPoly = tools::PolyPolygon();
420
421
29.6k
    return rIStream;
422
29.6k
}
423
424
SvStream& WritePolyPolygon( SvStream& rOStream, const tools::PolyPolygon& rPolyPoly )
425
0
{
426
    // Write number of polygons
427
0
    sal_uInt16 nPolyCount = rPolyPoly.mpImplPolyPolygon->mvPolyAry.size();
428
0
    rOStream.WriteUInt16( nPolyCount );
429
430
    // output polygons
431
0
    for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
432
0
        WritePolygon( rOStream, rPolyPoly.mpImplPolyPolygon->mvPolyAry[i] );
433
434
0
    return rOStream;
435
0
}
436
437
void PolyPolygon::Read( SvStream& rIStream )
438
8.63k
{
439
8.63k
    VersionCompatRead aCompat(rIStream);
440
441
8.63k
    sal_uInt16 nPolyCount(0);
442
443
    // Read number of polygons
444
8.63k
    rIStream.ReadUInt16( nPolyCount );
445
446
8.63k
    const size_t nMinRecordSize = sizeof(sal_uInt16);
447
8.63k
    const size_t nMaxRecords = rIStream.remainingSize() / nMinRecordSize;
448
8.63k
    if (nPolyCount > nMaxRecords)
449
0
    {
450
0
        SAL_WARN("tools", "Parsing error: " << nMaxRecords <<
451
0
                 " max possible entries, but " << nPolyCount << " claimed, truncating");
452
0
        nPolyCount = nMaxRecords;
453
0
    }
454
455
8.63k
    if( nPolyCount )
456
0
    {
457
0
        mpImplPolyPolygon->mvPolyAry.clear();
458
459
0
        for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
460
0
        {
461
0
            tools::Polygon aTempPoly;
462
0
            aTempPoly.ImplRead( rIStream );
463
0
            mpImplPolyPolygon->mvPolyAry.emplace_back( aTempPoly );
464
0
        }
465
0
    }
466
8.63k
    else
467
8.63k
        *this = tools::PolyPolygon();
468
8.63k
}
469
470
void PolyPolygon::Write( SvStream& rOStream ) const
471
17.4k
{
472
17.4k
    VersionCompatWrite aCompat(rOStream, 1);
473
474
    // Write number of polygons
475
17.4k
    sal_uInt16 nPolyCount = mpImplPolyPolygon->mvPolyAry.size();
476
17.4k
    rOStream.WriteUInt16( nPolyCount );
477
478
    // Output polygons
479
23.9k
    for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
480
6.55k
        mpImplPolyPolygon->mvPolyAry[i].ImplWrite( rOStream );
481
17.4k
}
482
483
// convert to basegfx::B2DPolyPolygon and return
484
basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
485
935k
{
486
935k
    basegfx::B2DPolyPolygon aRetval;
487
488
2.37M
    for(size_t a(0); a < mpImplPolyPolygon->mvPolyAry.size(); a++)
489
1.43M
    {
490
1.43M
        tools::Polygon const & rCandidate = mpImplPolyPolygon->mvPolyAry[a];
491
1.43M
        aRetval.append(rCandidate.getB2DPolygon());
492
1.43M
    }
493
494
935k
    return aRetval;
495
935k
}
496
497
// constructor to convert from basegfx::B2DPolyPolygon
498
PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
499
225k
    : mpImplPolyPolygon(rPolyPolygon)
500
225k
{
501
225k
}
502
503
PolyPolygon::iterator PolyPolygon::begin()
504
0
{
505
0
    return mpImplPolyPolygon->begin();
506
0
}
507
508
PolyPolygon::iterator PolyPolygon::end()
509
0
{
510
0
    return mpImplPolyPolygon->end();
511
0
}
512
513
PolyPolygon::const_iterator PolyPolygon::begin() const
514
6.44k
{
515
6.44k
    return mpImplPolyPolygon->begin();
516
6.44k
}
517
518
PolyPolygon::const_iterator PolyPolygon::end() const
519
6.44k
{
520
6.44k
    return mpImplPolyPolygon->end();
521
6.44k
}
522
523
} /* namespace tools */
524
525
ImplPolyPolygon::ImplPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
526
225k
{
527
225k
    const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
528
225k
    DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
529
225k
        "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
530
531
225k
    if ( nCount )
532
216k
    {
533
216k
        mvPolyAry.resize( nCount );
534
535
436k
        for(sal_uInt16 a(0); a < nCount; a++)
536
219k
        {
537
219k
            const basegfx::B2DPolygon& aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
538
219k
            mvPolyAry[a] = tools::Polygon( aCandidate );
539
219k
        }
540
216k
    }
541
8.99k
    else
542
8.99k
       mvPolyAry.reserve(16);
543
225k
}
544
545
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */