xref: /trunk/main/basegfx/source/inc/PolygonPoint.hxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _POLYGON_POINT_HXX
29 #define _POLYGON_POINT_HXX
30 
31 #include <vector>
32 
33 //////////////////////////////////////////////////////////////////////////////
34 
35 template < class Point > class SimplePointEntry
36 {
37     Point                                           maPoint;
38 
39 public:
40     SimplePointEntry()
41     :   maPoint(Point::getEmptyPoint())
42     {
43     }
44 
45     SimplePointEntry(const Point& rInitPoint)
46     :   maPoint(rInitPoint)
47     {
48     }
49 
50     const Point& getPoint() const
51     {
52         return maPoint;
53     }
54 
55     void setPoint(const Point& rValue)
56     {
57         maPoint = rValue;
58     }
59 
60     bool operator==(const SimplePointEntry& rEntry) const
61     {
62         return (maPoint == rEntry.maPoint);
63     }
64 };
65 
66 //////////////////////////////////////////////////////////////////////////////
67 
68 template < class Vector > class SimpleBezierEntry
69 {
70     Vector                                          maBackward;
71     Vector                                          maForward;
72 
73 public:
74     SimpleBezierEntry()
75     :   maBackward(Vector::getEmptyVector()),
76         maForward(Vector::getEmptyVector())
77     {
78     }
79 
80     SimpleBezierEntry(const Vector& rInitBackward, const Vector& rInitForward)
81     :   maBackward(rInitBackward),
82         maForward(rInitForward)
83     {
84     }
85 
86     const Vector& getBackwardVector() const
87     {
88         return maBackward;
89     }
90 
91     void setBackwardVector(const Vector& rValue)
92     {
93         maBackward = rValue;
94     }
95 
96     const Vector& getForwardVector() const
97     {
98         return maForward;
99     }
100 
101     void setForwardVector(const Vector& rValue)
102     {
103         maForward = rValue;
104     }
105 
106     bool isBezierNeeded()
107     {
108         if(maBackward != Vector::getEmptyVector() || maForward != Vector::getEmptyVector())
109             return true;
110         return false;
111     }
112 
113     bool operator==(const SimpleBezierEntry& rEntry) const
114     {
115         return ((maBackward == rEntry.maBackward) && (maForward == rEntry.maForward));
116     }
117 
118     void doInvertForFlip()
119     {
120         maBackward = -maBackward;
121         maForward = -maForward;
122     }
123 };
124 
125 //////////////////////////////////////////////////////////////////////////////
126 
127 template < class Point, class Vector > class PolygonPointList
128 {
129     typedef SimplePointEntry< Point > LocalSimplePointEntry;
130     typedef SimpleBezierEntry< Vector > LocalSimpleBezierEntry;
131     typedef ::std::vector< LocalSimplePointEntry > SimplePointVector;
132     typedef ::std::vector< LocalSimpleBezierEntry > SimpleBezierVector;
133 
134     sal_uInt32                                      mnBezierCount;
135     SimplePointVector                               maPoints;
136     SimpleBezierVector*                             mpVectors;
137 
138     unsigned                                        mbIsClosed : 1;
139 
140     void implTryToReduceToPointVector()
141     {
142         if(!mnBezierCount && mpVectors)
143         {
144             delete mpVectors;
145             mpVectors = 0L;
146         }
147     }
148 
149 public:
150     bool isBezier() const
151     {
152         return bool(mnBezierCount);
153     }
154 
155     bool isClosed() const
156     {
157         return bool(mbIsClosed);
158     }
159 
160     void setClosed(bool bNew)
161     {
162         mbIsClosed = bNew;
163     }
164 
165     sal_uInt32 count() const
166     {
167         return maPoints.size();
168     }
169 
170     PolygonPointList()
171     :   mnBezierCount(0L),
172         mpVectors(0L),
173         mbIsClosed(false)
174     {
175         // complete initialization with defaults
176     }
177 
178     PolygonPointList(const PolygonPointList& rSource)
179     :   mnBezierCount(0L),
180         maPoints(rSource.maPoints),
181         mpVectors(0L),
182         mbIsClosed(rSource.mbIsClosed)
183     {
184         // complete initialization using copy
185         if(rSource.mpVectors && rSource.mnBezierCount)
186         {
187             mpVectors = new SimpleBezierVector(*rSource.mpVectors);
188             mnBezierCount = rSource.mnBezierCount;
189         }
190     }
191 
192     PolygonPointList(const PolygonPointList& rSource, sal_uInt32 nIndex, sal_uInt32 nCount)
193     :   mnBezierCount(0L),
194         maPoints(nCount),
195         mpVectors(0L),
196         mbIsClosed(rSource.mbIsClosed)
197     {
198         // complete initialization using partly copy
199         if(nCount)
200         {
201             // copy point data
202             {
203                 SimplePointVector::const_iterator aStart(rSource.maPoints.begin());
204                 aStart += nIndex;
205                 SimplePointVector::const_iterator aEnd(aStart);
206                 aEnd += nCount;
207                 maPoints.insert(0L, aStart, aEnd);
208             }
209 
210             // copy bezier data
211             if(rSource.mpVectors && rSource.mnBezierCount)
212             {
213                 mpVectors = new SimpleBezierVector();
214                 mpVectors->reserve(nCount);
215 
216                 SimpleBezierVector::iterator aStart(mpVectors->begin());
217                 aStart += nIndex;
218                 SimpleBezierVector::iterator aEnd(aStart);
219                 aEnd += nCount;
220 
221                 for( ; aStart != aEnd; ++aStart )
222                 {
223                     if(aStart->IsBezierNeeded())
224                     {
225                         mnBezierCount++;
226                     }
227 
228                     mpVectors->push_back(*aStart);
229                 }
230 
231                 // maybe vectors are not needed anymore, try to reduce memory footprint
232                 implTryToReduceToPointVector();
233             }
234         }
235     }
236 
237     ~PolygonPointList()
238     {
239         if(mpVectors)
240         {
241             delete mpVectors;
242         }
243     }
244 
245     bool isEqual(const PolygonPointList& rPointList) const
246     {
247         // same point count?
248         if(maPoints.size() != rPointList.maPoints.size())
249             return false;
250 
251         // if zero points the polys are equal
252         if(!maPoints.size())
253             return true;
254 
255         // if bezier count used it needs to be equal
256         if(mnBezierCount != rPointList.mnBezierCount)
257             return false;
258 
259         // compare point content
260         if(maPoints != rPointList.maPoints)
261             return false;
262 
263         // beziercounts are equal: if it's zero, we are done
264         if(!mnBezierCount)
265             return true;
266 
267         // beziercounts are equal and not zero; compare them
268         OSL_ENSURE(0L != mpVectors, "Error: Bezier list needs to exist here(!)");
269         OSL_ENSURE(0L != rPointList.mpVectors, "Error: Bezier list needs to exist here(!)");
270 
271         return (*mpVectors == *rPointList.mpVectors);
272     }
273 
274     const Point& getPoint(sal_uInt32 nIndex) const
275     {
276         return maPoints[nIndex].getPoint();
277     }
278 
279     void setPoint(sal_uInt32 nIndex, const Point& rValue)
280     {
281         maPoints[nIndex].setPoint(rValue);
282     }
283 
284     const Vector& getBackwardVector(sal_uInt32 nIndex) const
285     {
286         if(mpVectors)
287             return ((*mpVectors)[nIndex]).getBackwardVector();
288         else
289             return Vector::getEmptyVector();
290     }
291 
292     void setBackwardVector(sal_uInt32 nIndex, const Vector& rValue)
293     {
294         if(mpVectors)
295         {
296             LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex];
297             bool bBezierNeededBefore(rDest.isBezierNeeded());
298             ((*mpVectors)[nIndex]).setBackwardVector(rValue);
299             bool bBezierNeededAfter(rDest.isBezierNeeded());
300 
301             if(bBezierNeededBefore != bBezierNeededAfter)
302             {
303                 if(bBezierNeededAfter)
304                     mnBezierCount++;
305                 else
306                     mnBezierCount--;
307             }
308         }
309         else
310         {
311             bool bEmptyVector(rValue == Vector::getEmptyVector());
312 
313             if(bEmptyVector)
314                 return;
315 
316             mpVectors = new SimpleBezierVector(maPoints.size());
317             ((*mpVectors)[nIndex]).setBackwardVector(rValue);
318             mnBezierCount++;
319         }
320     }
321 
322     const Vector& getForwardVector(sal_uInt32 nIndex) const
323     {
324         if(mpVectors)
325             return ((*mpVectors)[nIndex]).getForwardVector();
326         else
327             return Vector::getEmptyVector();
328     }
329 
330     void setForwardVector(sal_uInt32 nIndex, const Vector& rValue)
331     {
332         if(mpVectors)
333         {
334             LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex];
335             bool bBezierNeededBefore(rDest.isBezierNeeded());
336             ((*mpVectors)[nIndex]).setForwardVector(rValue);
337             bool bBezierNeededAfter(rDest.isBezierNeeded());
338 
339             if(bBezierNeededBefore != bBezierNeededAfter)
340             {
341                 if(bBezierNeededAfter)
342                     mnBezierCount++;
343                 else
344                     mnBezierCount--;
345             }
346         }
347         else
348         {
349             bool bEmptyVector(rValue == Vector::getEmptyVector());
350 
351             if(bEmptyVector)
352                 return;
353 
354             mpVectors = new SimpleBezierVector(maPoints.size());
355             ((*mpVectors)[nIndex]).setForwardVector(rValue);
356             mnBezierCount++;
357         }
358     }
359 
360     void insert(sal_uInt32 nIndex, const Point& rPoint, sal_uInt32 nCount)
361     {
362         if(nCount)
363         {
364             // maybe vectors are not needed anymore, try to reduce memory footprint
365             implTryToReduceToPointVector();
366 
367             // add nCount copies of rPoint
368             {
369                 LocalSimplePointEntry aNode(rPoint);
370                 SimplePointVector::iterator aIndex(maPoints.begin());
371                 aIndex += nIndex;
372                 maPoints.insert(aIndex, nCount, aNode);
373             }
374 
375             // add nCount empty entries to keep indices synchronized
376             if(mpVectors)
377             {
378                 LocalSimpleBezierEntry aNode;
379                 SimpleBezierVector::iterator aIndex(mpVectors->begin());
380                 aIndex += nIndex;
381                 mpVectors->insert(aIndex, nCount, aNode);
382             }
383         }
384     }
385 
386     void insert(sal_uInt32 nIndex, const PolygonPointList& rSource)
387     {
388         const sal_uInt32 nCount(rSource.maPoints.size());
389 
390         if(nCount)
391         {
392             // instert point data
393             {
394                 SimplePointVector::iterator aIndex(maPoints.begin());
395                 aIndex += nIndex;
396 
397                 SimplePointVector::const_iterator aStart(rSource.maPoints.begin());
398                 SimplePointVector::const_iterator aEnd(rSource.maPoints.end());
399 
400                 maPoints.insert(aIndex, aStart, aEnd);
401             }
402 
403             // insert bezier data
404             if(rSource.mpVectors && rSource.mnBezierCount)
405             {
406                 SimpleBezierVector::iterator aIndex(mpVectors->begin());
407                 aIndex += nIndex;
408 
409                 SimpleBezierVector::iterator aStart(rSource.mpVectors->begin());
410                 SimpleBezierVector::iterator aEnd(rSource.mpVectors->end());
411 
412                 if(!mpVectors)
413                 {
414                     mpVectors = new SimpleBezierVector(maPoints.size() - nCount);
415                 }
416 
417                 mpVectors->insert(aIndex, aStart, aEnd);
418 
419                 mnBezierCount += rSource.mnBezierCount;
420             }
421             else
422             {
423                 // maybe vectors are not needed anymore, try to reduce memory footprint
424                 implTryToReduceToPointVector();
425 
426                 // add nCount empty entries to keep indices synchronized
427                 if(mpVectors)
428                 {
429                     LocalSimpleBezierEntry aNode;
430                     SimpleBezierVector::iterator aIndex(mpVectors->begin());
431                     aIndex += nIndex;
432                     mpVectors->insert(aIndex, nCount, aNode);
433                 }
434             }
435         }
436     }
437 
438     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
439     {
440         if(nCount)
441         {
442             // maybe vectors are not needed anymore, try to reduce memory footprint
443             implTryToReduceToPointVector();
444 
445             // remove point data
446             {
447                 SimplePointVector::iterator aStart(maPoints.begin());
448                 aStart += nIndex;
449                 const SimplePointVector::iterator aEnd(aStart + nCount);
450 
451                 maPoints.erase(aStart, aEnd);
452             }
453 
454             // remove bezier data
455             if(mpVectors)
456             {
457                 SimpleBezierVector::iterator aStart(mpVectors->begin());
458                 aStart += nIndex;
459                 const SimpleBezierVector::iterator aEnd(aStart + nCount);
460 
461                 // take care for correct mnBezierCount BEFORE erase
462                 if(mnBezierCount)
463                 {
464                     SimpleBezierVector::iterator aTestIter(aStart);
465 
466                     for( ; mnBezierCount && aTestIter != aEnd; ++aTestIter)
467                     {
468                         if(aTestIter->isBezierNeeded())
469                             mnBezierCount--;
470                     }
471                 }
472 
473                 if(mnBezierCount)
474                 {
475                     // erase nodes
476                     mpVectors->erase(aStart, aEnd);
477                 }
478                 else
479                 {
480                     // try to reduce, maybe 0L == mnBezierCount
481                     implTryToReduceToPointVector();
482                 }
483             }
484         }
485     }
486 
487     void flip()
488     {
489         if(maPoints.size() > 1)
490         {
491             // maybe vectors are not needed anymore, try to reduce memory footprint
492             implTryToReduceToPointVector();
493 
494             // calculate half size
495             const sal_uInt32 nHalfSize(maPoints.size() >> 1L);
496 
497             // flip point data
498             {
499                 SimplePointVector::iterator aStart(maPoints.begin());
500                 SimplePointVector::iterator aEnd(maPoints.end());
501 
502                 for(sal_uInt32 a(0); a < nHalfSize; a++)
503                 {
504                     LocalSimplePointEntry aTemp = *aStart;
505                     *aStart++ = *aEnd;
506                     *aEnd-- = aTemp;
507                 }
508             }
509 
510             // flip bezier data
511             if(mpVectors)
512             {
513                 SimpleBezierVector::iterator aStart(mpVectors->begin());
514                 SimpleBezierVector::iterator aEnd(mpVectors->end());
515 
516                 for(sal_uInt32 a(0); a < nHalfSize; a++)
517                 {
518                     LocalSimpleBezierEntry aTemp = *aStart;
519                     aTemp.doInvertForFlip();
520                     *aStart = *aEnd;
521                     aStart->doInvertForFlip();
522                     aStart++;
523                     *aEnd-- = aTemp;
524                 }
525 
526                 // also flip vectors of middle point (if existing)
527                 if(maPoints.size() % 2)
528                 {
529                     (*mpVectors)[nHalfSize].doInvertForFlip();
530                 }
531             }
532         }
533     }
534 };
535 
536 //////////////////////////////////////////////////////////////////////////////
537 
538 #endif _POLYGON_POINT_HXX
539