Line data Source code
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 :
21 : #include <stdlib.h>
22 : #include <vcl/bmpacc.hxx>
23 : #include <tools/poly.hxx>
24 : #include <vcl/gdimtf.hxx>
25 : #include <vcl/metaact.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/wrkwin.hxx>
28 : #include <vcl/virdev.hxx>
29 : #include <impvect.hxx>
30 :
31 : // -----------
32 : // - Defines -
33 : // -----------
34 :
35 : #define VECT_POLY_MAX 8192
36 :
37 : // -----------------------------------------------------------------------------
38 :
39 : #define VECT_FREE_INDEX 0
40 : #define VECT_CONT_INDEX 1
41 : #define VECT_DONE_INDEX 2
42 :
43 : // -----------------------------------------------------------------------------
44 :
45 : #define VECT_POLY_INLINE_INNER 1UL
46 : #define VECT_POLY_INLINE_OUTER 2UL
47 : #define VECT_POLY_OUTLINE_INNER 4UL
48 : #define VECT_POLY_OUTLINE_OUTER 8UL
49 :
50 : // -----------------------------------------------------------------------------
51 :
52 : #define VECT_MAP( _def_pIn, _def_pOut, _def_nVal ) _def_pOut[_def_nVal]=(_def_pIn[_def_nVal]=((_def_nVal)*4L)+1L)+5L;
53 : #define BACK_MAP( _def_nVal ) ((((_def_nVal)+2)>>2)-1)
54 : #define VECT_PROGRESS( _def_pProgress, _def_nVal ) if(_def_pProgress&&_def_pProgress->IsSet())(_def_pProgress->Call((void*)_def_nVal));
55 :
56 : // -----------
57 : // - statics -
58 : // -----------
59 :
60 : struct ChainMove { long nDX; long nDY; };
61 :
62 : static ChainMove aImplMove[ 8 ] = {
63 : { 1L, 0L },
64 : { 0L, -1L },
65 : { -1L, 0L },
66 : { 0L, 1L },
67 : { 1L, -1L },
68 : { -1, -1L },
69 : { -1L, 1L },
70 : { 1L, 1L }
71 : };
72 :
73 : static ChainMove aImplMoveInner[ 8 ] = {
74 : { 0L, 1L },
75 : { 1L, 0L },
76 : { 0L, -1L },
77 : { -1L, 0L },
78 : { 0L, 1L },
79 : { 1L, 0L },
80 : { 0L, -1L },
81 : { -1L, 0L }
82 : };
83 :
84 : static ChainMove aImplMoveOuter[ 8 ] = {
85 : { 0L, -1L },
86 : { -1L, 0L },
87 : { 0L, 1L },
88 : { 1L, 0L },
89 : { -1L, 0L },
90 : { 0L, 1L },
91 : { 1L, 0L },
92 : { 0L, -1L }
93 : };
94 :
95 : // ----------------
96 : // - ImplColorSet -
97 : // ----------------
98 :
99 : struct ImplColorSet
100 : {
101 : BitmapColor maColor;
102 : sal_uInt16 mnIndex;
103 : sal_Bool mbSet;
104 :
105 : sal_Bool operator<( const ImplColorSet& rSet ) const;
106 : sal_Bool operator>( const ImplColorSet& rSet ) const;
107 : };
108 :
109 : // ----------------------------------------------------------------------------
110 :
111 : inline sal_Bool ImplColorSet::operator<( const ImplColorSet& rSet ) const
112 : {
113 : return( mbSet && ( !rSet.mbSet || ( maColor.GetLuminance() > rSet.maColor.GetLuminance() ) ) );
114 : }
115 :
116 : // ----------------------------------------------------------------------------
117 :
118 : inline sal_Bool ImplColorSet::operator>( const ImplColorSet& rSet ) const
119 : {
120 : return( !mbSet || ( rSet.mbSet && maColor.GetLuminance() < rSet.maColor.GetLuminance() ) );
121 : }
122 :
123 : // ----------------------------------------------------------------------------
124 :
125 0 : extern "C" int SAL_CALL ImplColorSetCmpFnc( const void* p1, const void* p2 )
126 : {
127 0 : ImplColorSet* pSet1 = (ImplColorSet*) p1;
128 0 : ImplColorSet* pSet2 = (ImplColorSet*) p2;
129 : int nRet;
130 :
131 0 : if( pSet1->mbSet && pSet2->mbSet )
132 : {
133 0 : const sal_uInt8 cLum1 = pSet1->maColor.GetLuminance();
134 0 : const sal_uInt8 cLum2 = pSet2->maColor.GetLuminance();
135 0 : nRet = ( ( cLum1 > cLum2 ) ? -1 : ( ( cLum1 == cLum2 ) ? 0 : 1 ) );
136 : }
137 0 : else if( pSet1->mbSet )
138 0 : nRet = -1;
139 0 : else if( pSet2->mbSet )
140 0 : nRet = 1;
141 : else
142 0 : nRet = 0;
143 :
144 0 : return nRet;
145 : }
146 :
147 : // ------------------
148 : // - ImplPointArray -
149 : // ------------------
150 :
151 : class ImplPointArray
152 : {
153 : Point* mpArray;
154 : sal_uLong mnSize;
155 : sal_uLong mnRealSize;
156 :
157 : public:
158 :
159 : ImplPointArray();
160 : ~ImplPointArray();
161 :
162 : void ImplSetSize( sal_uLong nSize );
163 :
164 0 : sal_uLong ImplGetRealSize() const { return mnRealSize; }
165 0 : void ImplSetRealSize( sal_uLong nRealSize ) { mnRealSize = nRealSize; }
166 :
167 : inline Point& operator[]( sal_uLong nPos );
168 : inline const Point& operator[]( sal_uLong nPos ) const;
169 :
170 : void ImplCreatePoly( Polygon& rPoly ) const;
171 : };
172 :
173 : // -----------------------------------------------------------------------------
174 :
175 0 : ImplPointArray::ImplPointArray() :
176 : mpArray ( NULL ),
177 : mnSize ( 0UL ),
178 0 : mnRealSize ( 0UL )
179 :
180 : {
181 0 : }
182 :
183 : // -----------------------------------------------------------------------------
184 :
185 0 : ImplPointArray::~ImplPointArray()
186 : {
187 0 : if( mpArray )
188 0 : rtl_freeMemory( mpArray );
189 0 : }
190 :
191 : // -----------------------------------------------------------------------------
192 :
193 0 : void ImplPointArray::ImplSetSize( sal_uLong nSize )
194 : {
195 0 : const sal_uLong nTotal = nSize * sizeof( Point );
196 :
197 0 : mnSize = nSize;
198 0 : mnRealSize = 0UL;
199 :
200 0 : if( mpArray )
201 0 : rtl_freeMemory( mpArray );
202 :
203 0 : mpArray = (Point*) rtl_allocateMemory( nTotal );
204 0 : memset( (HPBYTE) mpArray, 0, nTotal );
205 0 : }
206 :
207 : // -----------------------------------------------------------------------------
208 :
209 0 : inline Point& ImplPointArray::operator[]( sal_uLong nPos )
210 : {
211 : DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
212 0 : return mpArray[ nPos ];
213 : }
214 :
215 : // -----------------------------------------------------------------------------
216 :
217 0 : inline const Point& ImplPointArray::operator[]( sal_uLong nPos ) const
218 : {
219 : DBG_ASSERT( nPos < mnSize, "ImplPointArray::operator[]: nPos out of range!" );
220 0 : return mpArray[ nPos ];
221 : }
222 :
223 : // -----------------------------------------------------------------------------
224 :
225 0 : void ImplPointArray::ImplCreatePoly( Polygon& rPoly ) const
226 : {
227 0 : rPoly = Polygon( sal::static_int_cast<sal_uInt16>(mnRealSize), mpArray );
228 0 : }
229 :
230 : // ---------------
231 : // - ImplVectMap -
232 : // ---------------
233 :
234 : class ImplVectMap
235 : {
236 : private:
237 :
238 : Scanline mpBuf;
239 : Scanline* mpScan;
240 : long mnWidth;
241 : long mnHeight;
242 :
243 : ImplVectMap() {};
244 :
245 : public:
246 :
247 : ImplVectMap( long nWidth, long nHeight );
248 : ~ImplVectMap();
249 :
250 35 : inline long Width() const { return mnWidth; }
251 35 : inline long Height() const { return mnHeight; }
252 :
253 : inline void Set( long nY, long nX, sal_uInt8 cVal );
254 : inline sal_uInt8 Get( long nY, long nX ) const;
255 :
256 : inline sal_Bool IsFree( long nY, long nX ) const;
257 : inline sal_Bool IsCont( long nY, long nX ) const;
258 : inline sal_Bool IsDone( long nY, long nX ) const;
259 :
260 : };
261 :
262 : // -----------------------------------------------------------------------------
263 :
264 35 : ImplVectMap::ImplVectMap( long nWidth, long nHeight ) :
265 : mnWidth ( nWidth ),
266 35 : mnHeight( nHeight )
267 : {
268 35 : const long nWidthAl = ( nWidth >> 2L ) + 1L;
269 35 : const long nSize = nWidthAl * nHeight;
270 35 : Scanline pTmp = mpBuf = (Scanline) rtl_allocateMemory( nSize );
271 :
272 35 : memset( mpBuf, 0, nSize );
273 35 : mpScan = (Scanline*) rtl_allocateMemory( nHeight * sizeof( Scanline ) );
274 :
275 19847 : for( long nY = 0L; nY < nHeight; pTmp += nWidthAl )
276 19812 : mpScan[ nY++ ] = pTmp;
277 35 : }
278 :
279 : // -----------------------------------------------------------------------------
280 :
281 :
282 35 : ImplVectMap::~ImplVectMap()
283 : {
284 35 : rtl_freeMemory( mpBuf );
285 35 : rtl_freeMemory( mpScan );
286 35 : }
287 :
288 : // -----------------------------------------------------------------------------
289 :
290 0 : inline void ImplVectMap::Set( long nY, long nX, sal_uInt8 cVal )
291 : {
292 0 : const sal_uInt8 cShift = sal::static_int_cast<sal_uInt8>(6 - ( ( nX & 3 ) << 1 ));
293 0 : ( ( mpScan[ nY ][ nX >> 2 ] ) &= ~( 3 << cShift ) ) |= ( cVal << cShift );
294 0 : }
295 :
296 : // -----------------------------------------------------------------------------
297 :
298 12221472 : inline sal_uInt8 ImplVectMap::Get( long nY, long nX ) const
299 : {
300 12221472 : return sal::static_int_cast<sal_uInt8>( ( ( mpScan[ nY ][ nX >> 2 ] ) >> ( 6 - ( ( nX & 3 ) << 1 ) ) ) & 3 );
301 : }
302 :
303 : // -----------------------------------------------------------------------------
304 :
305 12221472 : inline sal_Bool ImplVectMap::IsFree( long nY, long nX ) const
306 : {
307 12221472 : return( VECT_FREE_INDEX == Get( nY, nX ) );
308 : }
309 :
310 : // -----------------------------------------------------------------------------
311 :
312 0 : inline sal_Bool ImplVectMap::IsCont( long nY, long nX ) const
313 : {
314 0 : return( VECT_CONT_INDEX == Get( nY, nX ) );
315 : }
316 :
317 : // -----------------------------------------------------------------------------
318 :
319 0 : inline sal_Bool ImplVectMap::IsDone( long nY, long nX ) const
320 : {
321 0 : return( VECT_DONE_INDEX == Get( nY, nX ) );
322 : }
323 :
324 : // -------------
325 : // - ImplChain -
326 : // -------------
327 :
328 : class ImplChain
329 : {
330 : private:
331 :
332 : Polygon maPoly;
333 : Point maStartPt;
334 : sal_uLong mnArraySize;
335 : sal_uLong mnCount;
336 : long mnResize;
337 : sal_uInt8* mpCodes;
338 :
339 : void ImplGetSpace();
340 :
341 : void ImplCreate();
342 : void ImplCreateInner();
343 : void ImplCreateOuter();
344 : void ImplPostProcess( const ImplPointArray& rArr );
345 :
346 : public:
347 :
348 : ImplChain( sal_uLong nInitCount = 1024UL, long nResize = -1L );
349 : ~ImplChain();
350 :
351 : void ImplBeginAdd( const Point& rStartPt );
352 : inline void ImplAdd( sal_uInt8 nCode );
353 : void ImplEndAdd( sal_uLong nTypeFlag );
354 :
355 0 : const Polygon& ImplGetPoly() const { return maPoly; }
356 : };
357 :
358 : // -----------------------------------------------------------------------------
359 :
360 0 : ImplChain::ImplChain( sal_uLong nInitCount, long nResize ) :
361 : mnArraySize ( nInitCount ),
362 : mnCount ( 0UL ),
363 0 : mnResize ( nResize )
364 : {
365 : DBG_ASSERT( nInitCount && nResize, "ImplChain::ImplChain(): invalid parameters!" );
366 0 : mpCodes = new sal_uInt8[ mnArraySize ];
367 0 : }
368 :
369 : // -----------------------------------------------------------------------------
370 :
371 0 : ImplChain::~ImplChain()
372 : {
373 0 : delete[] mpCodes;
374 0 : }
375 :
376 : // -----------------------------------------------------------------------------
377 :
378 0 : void ImplChain::ImplGetSpace()
379 : {
380 0 : const sal_uLong nOldArraySize = mnArraySize;
381 : sal_uInt8* pNewCodes;
382 :
383 0 : mnArraySize = ( mnResize < 0L ) ? ( mnArraySize << 1UL ) : ( mnArraySize + (sal_uLong) mnResize );
384 0 : pNewCodes = new sal_uInt8[ mnArraySize ];
385 0 : memcpy( pNewCodes, mpCodes, nOldArraySize );
386 0 : delete[] mpCodes;
387 0 : mpCodes = pNewCodes;
388 0 : }
389 :
390 : // -----------------------------------------------------------------------------
391 :
392 0 : void ImplChain::ImplBeginAdd( const Point& rStartPt )
393 : {
394 0 : maPoly = Polygon();
395 0 : maStartPt = rStartPt;
396 0 : mnCount = 0UL;
397 0 : }
398 :
399 : // -----------------------------------------------------------------------------
400 :
401 0 : inline void ImplChain::ImplAdd( sal_uInt8 nCode )
402 : {
403 0 : if( mnCount == mnArraySize )
404 0 : ImplGetSpace();
405 :
406 0 : mpCodes[ mnCount++ ] = nCode;
407 0 : }
408 :
409 : // -----------------------------------------------------------------------------
410 :
411 0 : void ImplChain::ImplEndAdd( sal_uLong nFlag )
412 : {
413 0 : if( mnCount )
414 : {
415 0 : ImplPointArray aArr;
416 :
417 0 : if( nFlag & VECT_POLY_INLINE_INNER )
418 : {
419 : long nFirstX, nFirstY;
420 : long nLastX, nLastY;
421 :
422 0 : nFirstX = nLastX = maStartPt.X();
423 0 : nFirstY = nLastY = maStartPt.Y();
424 0 : aArr.ImplSetSize( mnCount << 1 );
425 :
426 : sal_uInt16 i, nPolyPos;
427 0 : for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
428 : {
429 0 : const sal_uInt8 cMove = mpCodes[ i ];
430 0 : const sal_uInt8 cNextMove = mpCodes[ i + 1 ];
431 0 : const ChainMove& rMove = aImplMove[ cMove ];
432 0 : const ChainMove& rMoveInner = aImplMoveInner[ cMove ];
433 : // Point& rPt = aArr[ nPolyPos ];
434 0 : sal_Bool bDone = sal_True;
435 :
436 0 : nLastX += rMove.nDX;
437 0 : nLastY += rMove.nDY;
438 :
439 0 : if( cMove < 4 )
440 : {
441 0 : if( ( cMove == 0 && cNextMove == 3 ) ||
442 : ( cMove == 3 && cNextMove == 2 ) ||
443 : ( cMove == 2 && cNextMove == 1 ) ||
444 : ( cMove == 1 && cNextMove == 0 ) )
445 : {
446 : }
447 0 : else if( cMove == 2 && cNextMove == 3 )
448 : {
449 0 : aArr[ nPolyPos ].X() = nLastX;
450 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
451 :
452 0 : aArr[ nPolyPos ].X() = nLastX - 1;
453 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
454 :
455 0 : aArr[ nPolyPos ].X() = nLastX - 1;
456 0 : aArr[ nPolyPos++ ].Y() = nLastY;
457 : }
458 0 : else if( cMove == 3 && cNextMove == 0 )
459 : {
460 0 : aArr[ nPolyPos ].X() = nLastX - 1;
461 0 : aArr[ nPolyPos++ ].Y() = nLastY;
462 :
463 0 : aArr[ nPolyPos ].X() = nLastX - 1;
464 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
465 :
466 0 : aArr[ nPolyPos ].X() = nLastX;
467 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
468 : }
469 0 : else if( cMove == 0 && cNextMove == 1 )
470 : {
471 0 : aArr[ nPolyPos ].X() = nLastX;
472 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
473 :
474 0 : aArr[ nPolyPos ].X() = nLastX + 1;
475 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
476 :
477 0 : aArr[ nPolyPos ].X() = nLastX + 1;
478 0 : aArr[ nPolyPos++ ].Y() = nLastY;
479 : }
480 0 : else if( cMove == 1 && cNextMove == 2 )
481 : {
482 0 : aArr[ nPolyPos ].X() = nLastX + 1;
483 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
484 :
485 0 : aArr[ nPolyPos ].X() = nLastX + 1;
486 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
487 :
488 0 : aArr[ nPolyPos ].X() = nLastX;
489 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
490 : }
491 : else
492 0 : bDone = sal_False;
493 : }
494 0 : else if( cMove == 7 && cNextMove == 0 )
495 : {
496 0 : aArr[ nPolyPos ].X() = nLastX - 1;
497 0 : aArr[ nPolyPos++ ].Y() = nLastY;
498 :
499 0 : aArr[ nPolyPos ].X() = nLastX;
500 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
501 : }
502 0 : else if( cMove == 4 && cNextMove == 1 )
503 : {
504 0 : aArr[ nPolyPos ].X() = nLastX;
505 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
506 :
507 0 : aArr[ nPolyPos ].X() = nLastX + 1;
508 0 : aArr[ nPolyPos++ ].Y() = nLastY;
509 : }
510 : else
511 0 : bDone = sal_False;
512 :
513 0 : if( !bDone )
514 : {
515 0 : aArr[ nPolyPos ].X() = nLastX + rMoveInner.nDX;
516 0 : aArr[ nPolyPos++ ].Y() = nLastY + rMoveInner.nDY;
517 : }
518 : }
519 :
520 0 : aArr[ nPolyPos ].X() = nFirstX + 1L;
521 0 : aArr[ nPolyPos++ ].Y() = nFirstY + 1L;
522 0 : aArr.ImplSetRealSize( nPolyPos );
523 : }
524 0 : else if( nFlag & VECT_POLY_INLINE_OUTER )
525 : {
526 : long nFirstX, nFirstY;
527 : long nLastX, nLastY;
528 :
529 0 : nFirstX = nLastX = maStartPt.X();
530 0 : nFirstY = nLastY = maStartPt.Y();
531 0 : aArr.ImplSetSize( mnCount << 1 );
532 :
533 : sal_uInt16 i, nPolyPos;
534 0 : for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ )
535 : {
536 0 : const sal_uInt8 cMove = mpCodes[ i ];
537 0 : const sal_uInt8 cNextMove = mpCodes[ i + 1 ];
538 0 : const ChainMove& rMove = aImplMove[ cMove ];
539 0 : const ChainMove& rMoveOuter = aImplMoveOuter[ cMove ];
540 : // Point& rPt = aArr[ nPolyPos ];
541 0 : sal_Bool bDone = sal_True;
542 :
543 0 : nLastX += rMove.nDX;
544 0 : nLastY += rMove.nDY;
545 :
546 0 : if( cMove < 4 )
547 : {
548 0 : if( ( cMove == 0 && cNextMove == 1 ) ||
549 : ( cMove == 1 && cNextMove == 2 ) ||
550 : ( cMove == 2 && cNextMove == 3 ) ||
551 : ( cMove == 3 && cNextMove == 0 ) )
552 : {
553 : }
554 0 : else if( cMove == 0 && cNextMove == 3 )
555 : {
556 0 : aArr[ nPolyPos ].X() = nLastX;
557 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
558 :
559 0 : aArr[ nPolyPos ].X() = nLastX + 1;
560 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
561 :
562 0 : aArr[ nPolyPos ].X() = nLastX + 1;
563 0 : aArr[ nPolyPos++ ].Y() = nLastY;
564 : }
565 0 : else if( cMove == 3 && cNextMove == 2 )
566 : {
567 0 : aArr[ nPolyPos ].X() = nLastX + 1;
568 0 : aArr[ nPolyPos++ ].Y() = nLastY;
569 :
570 0 : aArr[ nPolyPos ].X() = nLastX + 1;
571 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
572 :
573 0 : aArr[ nPolyPos ].X() = nLastX;
574 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
575 : }
576 0 : else if( cMove == 2 && cNextMove == 1 )
577 : {
578 0 : aArr[ nPolyPos ].X() = nLastX;
579 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
580 :
581 0 : aArr[ nPolyPos ].X() = nLastX - 1;
582 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
583 :
584 0 : aArr[ nPolyPos ].X() = nLastX - 1;
585 0 : aArr[ nPolyPos++ ].Y() = nLastY;
586 : }
587 0 : else if( cMove == 1 && cNextMove == 0 )
588 : {
589 0 : aArr[ nPolyPos ].X() = nLastX - 1;
590 0 : aArr[ nPolyPos++ ].Y() = nLastY;
591 :
592 0 : aArr[ nPolyPos ].X() = nLastX - 1;
593 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
594 :
595 0 : aArr[ nPolyPos ].X() = nLastX;
596 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
597 : }
598 : else
599 0 : bDone = sal_False;
600 : }
601 0 : else if( cMove == 7 && cNextMove == 3 )
602 : {
603 0 : aArr[ nPolyPos ].X() = nLastX;
604 0 : aArr[ nPolyPos++ ].Y() = nLastY - 1;
605 :
606 0 : aArr[ nPolyPos ].X() = nLastX + 1;
607 0 : aArr[ nPolyPos++ ].Y() = nLastY;
608 : }
609 0 : else if( cMove == 6 && cNextMove == 2 )
610 : {
611 0 : aArr[ nPolyPos ].X() = nLastX + 1;
612 0 : aArr[ nPolyPos++ ].Y() = nLastY;
613 :
614 0 : aArr[ nPolyPos ].X() = nLastX;
615 0 : aArr[ nPolyPos++ ].Y() = nLastY + 1;
616 : }
617 : else
618 0 : bDone = sal_False;
619 :
620 0 : if( !bDone )
621 : {
622 0 : aArr[ nPolyPos ].X() = nLastX + rMoveOuter.nDX;
623 0 : aArr[ nPolyPos++ ].Y() = nLastY + rMoveOuter.nDY;
624 : }
625 : }
626 :
627 0 : aArr[ nPolyPos ].X() = nFirstX - 1L;
628 0 : aArr[ nPolyPos++ ].Y() = nFirstY - 1L;
629 0 : aArr.ImplSetRealSize( nPolyPos );
630 : }
631 : else
632 : {
633 0 : long nLastX = maStartPt.X(), nLastY = maStartPt.Y();
634 :
635 0 : aArr.ImplSetSize( mnCount + 1 );
636 0 : aArr[ 0 ] = Point( nLastX, nLastY );
637 :
638 0 : for( sal_uLong i = 0; i < mnCount; )
639 : {
640 0 : const ChainMove& rMove = aImplMove[ mpCodes[ i ] ];
641 0 : aArr[ ++i ] = Point( nLastX += rMove.nDX, nLastY += rMove.nDY );
642 : }
643 :
644 0 : aArr.ImplSetRealSize( mnCount + 1 );
645 : }
646 :
647 0 : ImplPostProcess( aArr );
648 : }
649 : else
650 0 : maPoly.SetSize( 0 );
651 0 : }
652 :
653 : // -----------------------------------------------------------------------------
654 :
655 0 : void ImplChain::ImplPostProcess( const ImplPointArray& rArr )
656 : {
657 0 : ImplPointArray aNewArr1;
658 0 : ImplPointArray aNewArr2;
659 : Point* pLast;
660 : Point* pLeast;
661 : sal_uLong nNewPos;
662 0 : sal_uLong nCount = rArr.ImplGetRealSize();
663 : sal_uLong n;
664 :
665 : // pass 1
666 0 : aNewArr1.ImplSetSize( nCount );
667 0 : pLast = &( aNewArr1[ 0 ] );
668 0 : pLast->X() = BACK_MAP( rArr[ 0 ].X() );
669 0 : pLast->Y() = BACK_MAP( rArr[ 0 ].Y() );
670 :
671 0 : for( n = nNewPos = 1; n < nCount; )
672 : {
673 0 : const Point& rPt = rArr[ n++ ];
674 0 : const long nX = BACK_MAP( rPt.X() );
675 0 : const long nY = BACK_MAP( rPt.Y() );
676 :
677 0 : if( nX != pLast->X() || nY != pLast->Y() )
678 : {
679 0 : pLast = pLeast = &( aNewArr1[ nNewPos++ ] );
680 0 : pLeast->X() = nX;
681 0 : pLeast->Y() = nY;
682 : }
683 : }
684 :
685 0 : aNewArr1.ImplSetRealSize( nCount = nNewPos );
686 :
687 : // pass 2
688 0 : aNewArr2.ImplSetSize( nCount );
689 0 : pLast = &( aNewArr2[ 0 ] );
690 0 : *pLast = aNewArr1[ 0 ];
691 :
692 0 : for( n = nNewPos = 1; n < nCount; )
693 : {
694 0 : pLeast = &( aNewArr1[ n++ ] );
695 :
696 0 : if( pLeast->X() == pLast->X() )
697 : {
698 0 : while( n < nCount && aNewArr1[ n ].X() == pLast->X() )
699 0 : pLeast = &( aNewArr1[ n++ ] );
700 : }
701 0 : else if( pLeast->Y() == pLast->Y() )
702 : {
703 0 : while( n < nCount && aNewArr1[ n ].Y() == pLast->Y() )
704 0 : pLeast = &( aNewArr1[ n++ ] );
705 : }
706 :
707 0 : aNewArr2[ nNewPos++ ] = *( pLast = pLeast );
708 : }
709 :
710 0 : aNewArr2.ImplSetRealSize( nNewPos );
711 0 : aNewArr2.ImplCreatePoly( maPoly );
712 0 : }
713 :
714 : // ------------------
715 : // - ImplVectorizer -
716 : // ------------------
717 :
718 35 : ImplVectorizer::ImplVectorizer()
719 : {
720 35 : }
721 :
722 : // -----------------------------------------------------------------------------
723 :
724 35 : ImplVectorizer::~ImplVectorizer()
725 : {
726 35 : }
727 :
728 : // -----------------------------------------------------------------------------
729 :
730 0 : sal_Bool ImplVectorizer::ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf,
731 : sal_uInt8 cReduce, sal_uLong nFlags, const Link* pProgress )
732 : {
733 0 : sal_Bool bRet = sal_False;
734 :
735 0 : VECT_PROGRESS( pProgress, 0 );
736 :
737 0 : Bitmap* pBmp = new Bitmap( rColorBmp );
738 0 : BitmapReadAccess* pRAcc = pBmp->AcquireReadAccess();
739 :
740 0 : if( pRAcc )
741 : {
742 0 : PolyPolygon aPolyPoly;
743 0 : double fPercent = 0.0;
744 0 : double fPercentStep_2 = 0.0;
745 0 : const long nWidth = pRAcc->Width();
746 0 : const long nHeight = pRAcc->Height();
747 0 : const sal_uInt16 nColorCount = pRAcc->GetPaletteEntryCount();
748 : sal_uInt16 n;
749 0 : ImplColorSet* pColorSet = (ImplColorSet*) new sal_uInt8[ 256 * sizeof( ImplColorSet ) ];
750 :
751 0 : memset( pColorSet, 0, 256 * sizeof( ImplColorSet ) );
752 0 : rMtf.Clear();
753 :
754 : // get used palette colors and sort them from light to dark colors
755 0 : for( n = 0; n < nColorCount; n++ )
756 : {
757 0 : pColorSet[ n ].mnIndex = n;
758 0 : pColorSet[ n ].maColor = pRAcc->GetPaletteColor( n );
759 : }
760 :
761 0 : for( long nY = 0L; nY < nHeight; nY++ )
762 0 : for( long nX = 0L; nX < nWidth; nX++ )
763 0 : pColorSet[ pRAcc->GetPixel( nY, nX ).GetIndex() ].mbSet = 1;
764 :
765 0 : qsort( pColorSet, 256, sizeof( ImplColorSet ), ImplColorSetCmpFnc );
766 :
767 0 : for( n = 0; n < 256; n++ )
768 0 : if( !pColorSet[ n ].mbSet )
769 0 : break;
770 :
771 0 : if( n )
772 0 : fPercentStep_2 = 45.0 / n;
773 :
774 0 : VECT_PROGRESS( pProgress, FRound( fPercent += 10.0 ) );
775 :
776 0 : for( sal_uInt16 i = 0; i < n; i++ )
777 : {
778 0 : const BitmapColor aBmpCol( pRAcc->GetPaletteColor( pColorSet[ i ].mnIndex ) );
779 0 : const Color aFindColor( aBmpCol.GetRed(), aBmpCol.GetGreen(), aBmpCol.GetBlue() );
780 : // const sal_uInt8 cLum = aFindColor.GetLuminance();
781 0 : ImplVectMap* pMap = ImplExpand( pRAcc, aFindColor );
782 :
783 0 : VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
784 :
785 0 : if( pMap )
786 : {
787 0 : aPolyPoly.Clear();
788 0 : ImplCalculate( pMap, aPolyPoly, cReduce, nFlags );
789 0 : delete pMap;
790 :
791 0 : if( aPolyPoly.Count() )
792 : {
793 0 : ImplLimitPolyPoly( aPolyPoly );
794 :
795 0 : if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
796 0 : aPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
797 :
798 0 : if( aPolyPoly.Count() )
799 : {
800 0 : rMtf.AddAction( new MetaLineColorAction( aFindColor, sal_True ) );
801 0 : rMtf.AddAction( new MetaFillColorAction( aFindColor, sal_True ) );
802 0 : rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
803 : }
804 : }
805 : }
806 :
807 0 : VECT_PROGRESS( pProgress, FRound( fPercent += fPercentStep_2 ) );
808 0 : }
809 :
810 0 : delete[] (sal_uInt8*) pColorSet;
811 :
812 0 : if( rMtf.GetActionSize() )
813 : {
814 0 : MapMode aMap( MAP_100TH_MM );
815 0 : VirtualDevice aVDev;
816 0 : const Size aLogSize1( aVDev.PixelToLogic( Size( 1, 1 ), aMap ) );
817 :
818 0 : rMtf.SetPrefMapMode( aMap );
819 0 : rMtf.SetPrefSize( Size( nWidth + 2, nHeight + 2 ) );
820 0 : rMtf.Move( 1, 1 );
821 0 : rMtf.Scale( aLogSize1.Width(), aLogSize1.Height() );
822 0 : bRet = sal_True;
823 0 : }
824 : }
825 :
826 0 : pBmp->ReleaseAccess( pRAcc );
827 0 : delete pBmp;
828 0 : VECT_PROGRESS( pProgress, 100 );
829 :
830 0 : return bRet;
831 : }
832 :
833 : // -----------------------------------------------------------------------------
834 :
835 35 : sal_Bool ImplVectorizer::ImplVectorize( const Bitmap& rMonoBmp,
836 : PolyPolygon& rPolyPoly,
837 : sal_uLong nFlags, const Link* pProgress )
838 : {
839 35 : Bitmap* pBmp = new Bitmap( rMonoBmp );
840 : BitmapReadAccess* pRAcc;
841 : ImplVectMap* pMap;
842 35 : sal_Bool bRet = sal_False;
843 :
844 35 : VECT_PROGRESS( pProgress, 10 );
845 :
846 35 : if( pBmp->GetBitCount() > 1 )
847 0 : pBmp->Convert( BMP_CONVERSION_1BIT_THRESHOLD );
848 :
849 35 : VECT_PROGRESS( pProgress, 30 );
850 :
851 35 : pRAcc = pBmp->AcquireReadAccess();
852 35 : pMap = ImplExpand( pRAcc, COL_BLACK );
853 35 : pBmp->ReleaseAccess( pRAcc );
854 35 : delete pBmp;
855 :
856 35 : VECT_PROGRESS( pProgress, 60 );
857 :
858 35 : if( pMap )
859 : {
860 35 : rPolyPoly.Clear();
861 35 : ImplCalculate( pMap, rPolyPoly, 0, nFlags );
862 35 : delete pMap;
863 35 : ImplLimitPolyPoly( rPolyPoly );
864 :
865 35 : if( nFlags & BMP_VECTORIZE_REDUCE_EDGES )
866 35 : rPolyPoly.Optimize( POLY_OPTIMIZE_EDGES );
867 :
868 : // #i14895#:setting the correct direction for polygons
869 : // that represent holes and non-holes; non-hole polygons
870 : // need to have a right orientation, holes need to have a
871 : // left orientation in order to be treated correctly by
872 : // several external tools like Flash viewers
873 35 : sal_Int32 nFirstPoly = -1;
874 35 : sal_uInt16 nCurPoly( 0 ), nCount( rPolyPoly.Count() );
875 :
876 35 : for( ; nCurPoly < nCount; ++nCurPoly )
877 : {
878 0 : const Polygon& rPoly = rPolyPoly.GetObject( nCurPoly );
879 0 : const sal_uInt16 nSize( rPoly.GetSize() );
880 0 : sal_uInt16 nDepth( 0 ), i( 0 );
881 0 : const bool bRight( rPoly.IsRightOrientated() );
882 :
883 0 : for( ; i < nCount; ++i )
884 0 : if( ( i != nCurPoly ) && rPolyPoly.GetObject( i ).IsInside( rPoly[ 0 ] ) )
885 0 : ++nDepth;
886 :
887 0 : const bool bHole( ( nDepth & 0x0001 ) == 1 );
888 :
889 0 : if( nSize && ( ( !bRight && !bHole ) || ( bRight && bHole ) ) )
890 : {
891 0 : Polygon aNewPoly( nSize );
892 0 : sal_uInt16 nPrim( 0 ), nSec( nSize - 1 );
893 :
894 0 : if( rPoly.HasFlags() )
895 : {
896 0 : while( nPrim < nSize )
897 : {
898 0 : aNewPoly.SetPoint( rPoly.GetPoint( nSec ), nPrim );
899 0 : aNewPoly.SetFlags( nPrim++, rPoly.GetFlags( nSec-- ) );
900 : }
901 : }
902 : else
903 0 : while( nPrim < nSize )
904 0 : aNewPoly.SetPoint( rPoly.GetPoint( nSec-- ), nPrim++ );
905 :
906 0 : rPolyPoly.Replace( aNewPoly, nCurPoly );
907 : }
908 :
909 0 : if( ( 0 == nDepth ) && ( -1 == nFirstPoly ) )
910 0 : nFirstPoly = nCurPoly;
911 : }
912 :
913 : // put outmost polygon to the front
914 35 : if( nFirstPoly > 0 )
915 : {
916 0 : const Polygon aFirst( rPolyPoly.GetObject( static_cast< sal_uInt16 >( nFirstPoly ) ) );
917 :
918 0 : rPolyPoly.Remove( static_cast< sal_uInt16 >( nFirstPoly ) );
919 0 : rPolyPoly.Insert( aFirst, 0 );
920 : }
921 :
922 35 : bRet = sal_True;
923 : }
924 :
925 35 : VECT_PROGRESS( pProgress, 100 );
926 :
927 35 : return bRet;
928 : }
929 :
930 : // -----------------------------------------------------------------------------
931 :
932 35 : void ImplVectorizer::ImplLimitPolyPoly( PolyPolygon& rPolyPoly )
933 : {
934 35 : if( rPolyPoly.Count() > VECT_POLY_MAX )
935 : {
936 0 : PolyPolygon aNewPolyPoly;
937 0 : long nReduce = 0;
938 : sal_uInt16 nNewCount;
939 :
940 0 : do
941 : {
942 0 : aNewPolyPoly.Clear();
943 0 : nReduce++;
944 :
945 0 : for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
946 : {
947 0 : const Rectangle aBound( rPolyPoly[ i ].GetBoundRect() );
948 :
949 0 : if( aBound.GetWidth() > nReduce && aBound.GetHeight() > nReduce )
950 : {
951 0 : if( rPolyPoly[ i ].GetSize() )
952 0 : aNewPolyPoly.Insert( rPolyPoly[ i ] );
953 : }
954 : }
955 :
956 0 : nNewCount = aNewPolyPoly.Count();
957 : }
958 : while( nNewCount > VECT_POLY_MAX );
959 :
960 0 : rPolyPoly = aNewPolyPoly;
961 : }
962 35 : }
963 :
964 : // -----------------------------------------------------------------------------
965 :
966 35 : ImplVectMap* ImplVectorizer::ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor )
967 : {
968 35 : ImplVectMap* pMap = NULL;
969 :
970 35 : if( pRAcc && pRAcc->Width() && pRAcc->Height() )
971 : {
972 35 : const long nOldWidth = pRAcc->Width();
973 35 : const long nOldHeight = pRAcc->Height();
974 35 : const long nNewWidth = ( nOldWidth << 2L ) + 4L;
975 35 : const long nNewHeight = ( nOldHeight << 2L ) + 4L;
976 35 : const BitmapColor aTest( pRAcc->GetBestMatchingColor( rColor ) );
977 35 : long* pMapIn = new long[ Max( nOldWidth, nOldHeight ) ];
978 35 : long* pMapOut = new long[ Max( nOldWidth, nOldHeight ) ];
979 : long nX, nY, nTmpX, nTmpY;
980 :
981 35 : pMap = new ImplVectMap( nNewWidth, nNewHeight );
982 :
983 5390 : for( nX = 0L; nX < nOldWidth; nX++ )
984 5355 : VECT_MAP( pMapIn, pMapOut, nX );
985 :
986 4953 : for( nY = 0L, nTmpY = 5L; nY < nOldHeight; nY++, nTmpY += 4L )
987 : {
988 763370 : for( nX = 0L; nX < nOldWidth; )
989 : {
990 753534 : if( pRAcc->GetPixel( nY, nX ) == aTest )
991 : {
992 0 : nTmpX = pMapIn[ nX++ ];
993 0 : nTmpY -= 3L;
994 :
995 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
996 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
997 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
998 0 : pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
999 :
1000 0 : while( nX < nOldWidth && pRAcc->GetPixel( nY, nX ) == aTest )
1001 0 : nX++;
1002 :
1003 0 : nTmpX = pMapOut[ nX - 1L ];
1004 0 : nTmpY -= 3L;
1005 :
1006 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
1007 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
1008 0 : pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX );
1009 0 : pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
1010 : }
1011 : else
1012 753534 : nX++;
1013 : }
1014 : }
1015 :
1016 4953 : for( nY = 0L; nY < nOldHeight; nY++ )
1017 4918 : VECT_MAP( pMapIn, pMapOut, nY );
1018 :
1019 5390 : for( nX = 0L, nTmpX = 5L; nX < nOldWidth; nX++, nTmpX += 4L )
1020 : {
1021 764244 : for( nY = 0L; nY < nOldHeight; )
1022 : {
1023 753534 : if( pRAcc->GetPixel( nY, nX ) == aTest )
1024 : {
1025 0 : nTmpX -= 3L;
1026 0 : nTmpY = pMapIn[ nY++ ];
1027 :
1028 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1029 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1030 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1031 0 : pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
1032 :
1033 0 : while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest )
1034 0 : nY++;
1035 :
1036 0 : nTmpX -= 3L;
1037 0 : nTmpY = pMapOut[ nY - 1L ];
1038 :
1039 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1040 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1041 0 : pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX );
1042 0 : pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX );
1043 : }
1044 : else
1045 753534 : nY++;
1046 : }
1047 : }
1048 :
1049 : // cleanup
1050 35 : delete[] pMapIn;
1051 35 : delete[] pMapOut;
1052 : }
1053 :
1054 35 : return pMap;
1055 : }
1056 :
1057 : // -----------------------------------------------------------------------------
1058 :
1059 35 : void ImplVectorizer::ImplCalculate( ImplVectMap* pMap, PolyPolygon& rPolyPoly, sal_uInt8 cReduce, sal_uLong nFlags )
1060 : {
1061 35 : const long nWidth = pMap->Width(), nHeight= pMap->Height();
1062 :
1063 19847 : for( long nY = 0L; nY < nHeight; nY++ )
1064 : {
1065 19812 : long nX = 0L;
1066 19812 : sal_Bool bInner = sal_True;
1067 :
1068 39624 : while( nX < nWidth )
1069 : {
1070 : // skip free
1071 12261096 : while( ( nX < nWidth ) && pMap->IsFree( nY, nX ) )
1072 12221472 : nX++;
1073 :
1074 19812 : if( nX == nWidth )
1075 19812 : break;
1076 :
1077 0 : if( pMap->IsCont( nY, nX ) )
1078 : {
1079 : // new contour
1080 0 : ImplChain aChain;
1081 0 : const Point aStartPt( nX++, nY );
1082 :
1083 : // get chain code
1084 0 : aChain.ImplBeginAdd( aStartPt );
1085 0 : ImplGetChain( pMap, aStartPt, aChain );
1086 :
1087 0 : if( nFlags & BMP_VECTORIZE_INNER )
1088 0 : aChain.ImplEndAdd( bInner ? VECT_POLY_INLINE_INNER : VECT_POLY_INLINE_OUTER );
1089 : else
1090 0 : aChain.ImplEndAdd( bInner ? VECT_POLY_OUTLINE_INNER : VECT_POLY_OUTLINE_OUTER );
1091 :
1092 0 : const Polygon& rPoly = aChain.ImplGetPoly();
1093 :
1094 0 : if( rPoly.GetSize() > 2 )
1095 : {
1096 0 : if( cReduce )
1097 : {
1098 0 : const Rectangle aBound( rPoly.GetBoundRect() );
1099 :
1100 0 : if( aBound.GetWidth() > cReduce && aBound.GetHeight() > cReduce )
1101 0 : rPolyPoly.Insert( rPoly );
1102 : }
1103 : else
1104 0 : rPolyPoly.Insert( rPoly );
1105 : }
1106 :
1107 : // skip rest of detected contour
1108 0 : while( pMap->IsCont( nY, nX ) )
1109 0 : nX++;
1110 : }
1111 : else
1112 : {
1113 : // process done segment
1114 0 : const long nStartSegX = nX++;
1115 :
1116 0 : while( pMap->IsDone( nY, nX ) )
1117 0 : nX++;
1118 :
1119 0 : if( ( ( nX - nStartSegX ) == 1L ) || ( ImplIsUp( pMap, nY, nStartSegX ) != ImplIsUp( pMap, nY, nX - 1L ) ) )
1120 0 : bInner = !bInner;
1121 : }
1122 : }
1123 : }
1124 35 : }
1125 :
1126 : // -----------------------------------------------------------------------------
1127 :
1128 0 : sal_Bool ImplVectorizer::ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain )
1129 : {
1130 0 : long nActX = rStartPt.X();
1131 0 : long nActY = rStartPt.Y();
1132 : long nTryX;
1133 : long nTryY;
1134 : sal_uLong nFound;
1135 0 : sal_uLong nLastDir = 0UL;
1136 : sal_uLong nDir;
1137 :
1138 0 : do
1139 : {
1140 0 : nFound = 0UL;
1141 :
1142 : // first try last direction
1143 0 : nTryX = nActX + aImplMove[ nLastDir ].nDX;
1144 0 : nTryY = nActY + aImplMove[ nLastDir ].nDY;
1145 :
1146 0 : if( pMap->IsCont( nTryY, nTryX ) )
1147 : {
1148 0 : rChain.ImplAdd( (sal_uInt8) nLastDir );
1149 0 : pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
1150 0 : nFound = 1UL;
1151 : }
1152 : else
1153 : {
1154 : // try other directions
1155 0 : for( nDir = 0UL; nDir < 8UL; nDir++ )
1156 : {
1157 : // we already tried nLastDir
1158 0 : if( nDir != nLastDir )
1159 : {
1160 0 : nTryX = nActX + aImplMove[ nDir ].nDX;
1161 0 : nTryY = nActY + aImplMove[ nDir ].nDY;
1162 :
1163 0 : if( pMap->IsCont( nTryY, nTryX ) )
1164 : {
1165 0 : rChain.ImplAdd( (sal_uInt8) nDir );
1166 0 : pMap->Set( nActY = nTryY, nActX = nTryX, VECT_DONE_INDEX );
1167 0 : nFound = 1UL;
1168 0 : nLastDir = nDir;
1169 0 : break;
1170 : }
1171 : }
1172 : }
1173 : }
1174 : }
1175 : while( nFound );
1176 :
1177 0 : return sal_True;
1178 : }
1179 :
1180 : // -----------------------------------------------------------------------------
1181 :
1182 0 : sal_Bool ImplVectorizer::ImplIsUp( ImplVectMap* pMap, long nY, long nX ) const
1183 : {
1184 0 : if( pMap->IsDone( nY - 1L, nX ) )
1185 0 : return sal_True;
1186 0 : else if( pMap->IsDone( nY + 1L, nX ) )
1187 0 : return sal_False;
1188 0 : else if( pMap->IsDone( nY - 1L, nX - 1L ) || pMap->IsDone( nY - 1L, nX + 1L ) )
1189 0 : return sal_True;
1190 : else
1191 0 : return sal_False;
1192 : }
1193 :
1194 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|