xref: /trunk/main/basegfx/source/inc/PolygonPoint.hxx (revision ce9c7ef7)
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