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