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