File: | home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx |
Warning: | line 251, column 47 Dereference of undefined pointer value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | #include <sal/log.hxx> | |||
21 | #include <vcl/bitmapaccess.hxx> | |||
22 | #include <tools/link.hxx> | |||
23 | #include <tools/poly.hxx> | |||
24 | #include <tools/helpers.hxx> | |||
25 | #include <vcl/gdimtf.hxx> | |||
26 | #include <vcl/metaact.hxx> | |||
27 | #include <vcl/virdev.hxx> | |||
28 | #include "impvect.hxx" | |||
29 | #include <array> | |||
30 | #include <memory> | |||
31 | ||||
32 | #define VECT_POLY_MAX8192 8192 | |||
33 | ||||
34 | #define VECT_FREE_INDEX0 0 | |||
35 | #define VECT_CONT_INDEX1 1 | |||
36 | #define VECT_DONE_INDEX2 2 | |||
37 | ||||
38 | #define VECT_POLY_INLINE_INNER1UL 1UL | |||
39 | #define VECT_POLY_INLINE_OUTER2UL 2UL | |||
40 | #define VECT_POLY_OUTLINE_INNER4UL 4UL | |||
41 | #define VECT_POLY_OUTLINE_OUTER8UL 8UL | |||
42 | ||||
43 | static void VECT_MAP( const std::unique_ptr<long []> & pMapIn, const std::unique_ptr<long []>& pMapOut, long nVal ) | |||
44 | { | |||
45 | pMapIn[nVal] = (nVal * 4) + 1; | |||
46 | pMapOut[nVal] = pMapIn[nVal] + 5; | |||
47 | } | |||
48 | static constexpr long BACK_MAP( long _def_nVal ) | |||
49 | { | |||
50 | return ((_def_nVal + 2) >> 2) - 1; | |||
51 | } | |||
52 | static void VECT_PROGRESS( const Link<long, void>* pProgress, long _def_nVal ) | |||
53 | { | |||
54 | if(pProgress) | |||
55 | pProgress->Call(_def_nVal); | |||
56 | } | |||
57 | ||||
58 | namespace { | |||
59 | ||||
60 | class ImplVectMap; | |||
61 | class ImplChain; | |||
62 | ||||
63 | } | |||
64 | ||||
65 | namespace ImplVectorizer | |||
66 | { | |||
67 | static ImplVectMap* ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor ); | |||
68 | static void ImplCalculate( ImplVectMap* pMap, tools::PolyPolygon& rPolyPoly, sal_uInt8 cReduce ); | |||
69 | static bool ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain ); | |||
70 | static bool ImplIsUp( ImplVectMap const * pMap, long nY, long nX ); | |||
71 | static void ImplLimitPolyPoly( tools::PolyPolygon& rPolyPoly ); | |||
72 | } | |||
73 | ||||
74 | namespace { | |||
75 | ||||
76 | struct ChainMove { long nDX; long nDY; }; | |||
77 | ||||
78 | } | |||
79 | ||||
80 | const ChainMove aImplMove[ 8 ] = { | |||
81 | { 1, 0 }, | |||
82 | { 0, -1 }, | |||
83 | { -1, 0 }, | |||
84 | { 0, 1 }, | |||
85 | { 1, -1 }, | |||
86 | { -1, -1 }, | |||
87 | { -1, 1 }, | |||
88 | { 1, 1 } | |||
89 | }; | |||
90 | ||||
91 | const ChainMove aImplMoveInner[ 8 ] = { | |||
92 | { 0, 1 }, | |||
93 | { 1, 0 }, | |||
94 | { 0, -1 }, | |||
95 | { -1, 0 }, | |||
96 | { 0, 1 }, | |||
97 | { 1, 0 }, | |||
98 | { 0, -1 }, | |||
99 | { -1, 0 } | |||
100 | }; | |||
101 | ||||
102 | const ChainMove aImplMoveOuter[ 8 ] = { | |||
103 | { 0, -1 }, | |||
104 | { -1, 0 }, | |||
105 | { 0, 1 }, | |||
106 | { 1, 0 }, | |||
107 | { -1, 0 }, | |||
108 | { 0, 1 }, | |||
109 | { 1, 0 }, | |||
110 | { 0, -1 } | |||
111 | }; | |||
112 | ||||
113 | namespace { | |||
114 | ||||
115 | struct ImplColorSet | |||
116 | { | |||
117 | BitmapColor maColor; | |||
118 | sal_uInt16 mnIndex = 0; | |||
119 | bool mbSet = false; | |||
120 | }; | |||
121 | ||||
122 | } | |||
123 | ||||
124 | static bool ImplColorSetCmpFnc( const ImplColorSet& lhs, const ImplColorSet& rhs) | |||
125 | { | |||
126 | if( lhs.mbSet && rhs.mbSet ) | |||
127 | { | |||
128 | const sal_uInt8 cLum1 = lhs.maColor.GetLuminance(); | |||
129 | const sal_uInt8 cLum2 = rhs.maColor.GetLuminance(); | |||
130 | return cLum1 < cLum2; | |||
131 | } | |||
132 | return lhs.mbSet > rhs.mbSet; | |||
133 | } | |||
134 | ||||
135 | namespace { | |||
136 | ||||
137 | class ImplPointArray | |||
138 | { | |||
139 | std::unique_ptr<Point[]> mpArray; | |||
140 | sal_uLong mnSize; | |||
141 | sal_uLong mnRealSize; | |||
142 | ||||
143 | public: | |||
144 | ||||
145 | ImplPointArray(); | |||
146 | ||||
147 | void ImplSetSize( sal_uLong nSize ); | |||
148 | sal_uLong ImplGetRealSize() const { return mnRealSize; } | |||
149 | void ImplSetRealSize( sal_uLong nRealSize ) { mnRealSize = nRealSize; } | |||
150 | void ImplCreatePoly( tools::Polygon& rPoly ) const; | |||
151 | ||||
152 | inline Point& operator[]( sal_uLong nPos ); | |||
153 | inline const Point& operator[]( sal_uLong nPos ) const; | |||
154 | ||||
155 | }; | |||
156 | ||||
157 | } | |||
158 | ||||
159 | ImplPointArray::ImplPointArray() : | |||
160 | mnSize ( 0 ), | |||
161 | mnRealSize ( 0 ) | |||
162 | ||||
163 | { | |||
164 | } | |||
165 | ||||
166 | void ImplPointArray::ImplSetSize( sal_uLong nSize ) | |||
167 | { | |||
168 | const sal_uLong nTotal = nSize * sizeof( Point ); | |||
169 | ||||
170 | mnSize = nSize; | |||
171 | mnRealSize = 0; | |||
172 | ||||
173 | mpArray = std::make_unique<Point[]>( nTotal ); | |||
174 | } | |||
175 | ||||
176 | inline Point& ImplPointArray::operator[]( sal_uLong nPos ) | |||
177 | { | |||
178 | SAL_WARN_IF( nPos >= mnSize, "vcl", "ImplPointArray::operator[]: nPos out of range!" )do { if (true && (nPos >= mnSize)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "178" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "ImplPointArray::operator[]: nPos out of range!"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "178" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "ImplPointArray::operator[]: nPos out of range!") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "178" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "ImplPointArray::operator[]: nPos out of range!"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "178" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
179 | return mpArray[ nPos ]; | |||
180 | } | |||
181 | ||||
182 | inline const Point& ImplPointArray::operator[]( sal_uLong nPos ) const | |||
183 | { | |||
184 | SAL_WARN_IF( nPos >= mnSize, "vcl", "ImplPointArray::operator[]: nPos out of range!" )do { if (true && (nPos >= mnSize)) { switch (sal_detail_log_report (::SAL_DETAIL_LOG_LEVEL_WARN, "vcl")) { case SAL_DETAIL_LOG_ACTION_IGNORE : break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail ::getResult( ::sal::detail::StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "184" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "ImplPointArray::operator[]: nPos out of range!"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "184" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "ImplPointArray::operator[]: nPos out of range!") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl" ), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "184" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "ImplPointArray::operator[]: nPos out of range!" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "ImplPointArray::operator[]: nPos out of range!"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/impvect.cxx" ":" "184" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
185 | return mpArray[ nPos ]; | |||
186 | } | |||
187 | ||||
188 | void ImplPointArray::ImplCreatePoly( tools::Polygon& rPoly ) const | |||
189 | { | |||
190 | rPoly = tools::Polygon( sal::static_int_cast<sal_uInt16>(mnRealSize), mpArray.get() ); | |||
191 | } | |||
192 | ||||
193 | namespace { | |||
194 | ||||
195 | class ImplVectMap | |||
196 | { | |||
197 | private: | |||
198 | ||||
199 | Scanline mpBuf; | |||
200 | Scanline* mpScan; | |||
201 | long mnWidth; | |||
202 | long mnHeight; | |||
203 | ||||
204 | public: | |||
205 | ||||
206 | ImplVectMap( long nWidth, long nHeight ); | |||
207 | ~ImplVectMap(); | |||
208 | ||||
209 | long Width() const { return mnWidth; } | |||
210 | long Height() const { return mnHeight; } | |||
211 | ||||
212 | inline void Set( long nY, long nX, sal_uInt8 cVal ); | |||
213 | inline sal_uInt8 Get( long nY, long nX ) const; | |||
214 | ||||
215 | inline bool IsFree( long nY, long nX ) const; | |||
216 | inline bool IsCont( long nY, long nX ) const; | |||
217 | inline bool IsDone( long nY, long nX ) const; | |||
218 | ||||
219 | }; | |||
220 | ||||
221 | } | |||
222 | ||||
223 | ImplVectMap::ImplVectMap( long nWidth, long nHeight ) : | |||
224 | mpBuf ( static_cast<Scanline>(rtl_allocateZeroMemory(nWidth * nHeight)) ), | |||
225 | mpScan ( static_cast<Scanline*>(std::malloc(nHeight * sizeof(Scanline))) ), | |||
226 | mnWidth ( nWidth ), | |||
227 | mnHeight( nHeight ) | |||
228 | { | |||
229 | const long nWidthAl = ( nWidth >> 2 ) + 1; | |||
230 | Scanline pTmp = mpBuf; | |||
231 | ||||
232 | for( long nY = 0; nY < nHeight; pTmp += nWidthAl ) | |||
233 | mpScan[ nY++ ] = pTmp; | |||
234 | } | |||
235 | ||||
236 | ImplVectMap::~ImplVectMap() | |||
237 | { | |||
238 | std::free( mpBuf ); | |||
239 | std::free( mpScan ); | |||
240 | } | |||
241 | ||||
242 | inline void ImplVectMap::Set( long nY, long nX, sal_uInt8 cVal ) | |||
243 | { | |||
244 | const sal_uInt8 cShift = sal::static_int_cast<sal_uInt8>(6 - ( ( nX & 3 ) << 1 )); | |||
245 | auto & rPixel = mpScan[ nY ][ nX >> 2 ]; | |||
246 | rPixel = (rPixel & ~( 3 << cShift ) ) | ( cVal << cShift ); | |||
247 | } | |||
248 | ||||
249 | inline sal_uInt8 ImplVectMap::Get( long nY, long nX ) const | |||
250 | { | |||
251 | return sal::static_int_cast<sal_uInt8>( ( ( mpScan[ nY ][ nX >> 2 ] ) >> ( 6 - ( ( nX & 3 ) << 1 ) ) ) & 3 ); | |||
| ||||
252 | } | |||
253 | ||||
254 | inline bool ImplVectMap::IsFree( long nY, long nX ) const | |||
255 | { | |||
256 | return( VECT_FREE_INDEX0 == Get( nY, nX ) ); | |||
257 | } | |||
258 | ||||
259 | inline bool ImplVectMap::IsCont( long nY, long nX ) const | |||
260 | { | |||
261 | return( VECT_CONT_INDEX1 == Get( nY, nX ) ); | |||
262 | } | |||
263 | ||||
264 | inline bool ImplVectMap::IsDone( long nY, long nX ) const | |||
265 | { | |||
266 | return( VECT_DONE_INDEX2 == Get( nY, nX ) ); | |||
267 | } | |||
268 | ||||
269 | namespace { | |||
270 | ||||
271 | class ImplChain | |||
272 | { | |||
273 | private: | |||
274 | ||||
275 | tools::Polygon maPoly; | |||
276 | Point maStartPt; | |||
277 | sal_uLong mnArraySize; | |||
278 | sal_uLong mnCount; | |||
279 | std::unique_ptr<sal_uInt8[]> | |||
280 | mpCodes; | |||
281 | ||||
282 | void ImplGetSpace(); | |||
283 | ||||
284 | void ImplPostProcess( const ImplPointArray& rArr ); | |||
285 | ||||
286 | ImplChain(const ImplChain&) = delete; | |||
287 | ImplChain& operator=(const ImplChain&) = delete; | |||
288 | ||||
289 | public: | |||
290 | ||||
291 | ImplChain(); | |||
292 | ||||
293 | void ImplBeginAdd( const Point& rStartPt ); | |||
294 | inline void ImplAdd( sal_uInt8 nCode ); | |||
295 | void ImplEndAdd( sal_uLong nTypeFlag ); | |||
296 | ||||
297 | const tools::Polygon& ImplGetPoly() const { return maPoly; } | |||
298 | }; | |||
299 | ||||
300 | } | |||
301 | ||||
302 | ImplChain::ImplChain() : | |||
303 | mnArraySize ( 1024 ), | |||
304 | mnCount ( 0 ), | |||
305 | mpCodes ( new sal_uInt8[mnArraySize] ) | |||
306 | { | |||
307 | } | |||
308 | ||||
309 | void ImplChain::ImplGetSpace() | |||
310 | { | |||
311 | const sal_uLong nOldArraySize = mnArraySize; | |||
312 | sal_uInt8* pNewCodes; | |||
313 | ||||
314 | mnArraySize = mnArraySize << 1; | |||
315 | pNewCodes = new sal_uInt8[ mnArraySize ]; | |||
316 | memcpy( pNewCodes, mpCodes.get(), nOldArraySize ); | |||
317 | mpCodes.reset( pNewCodes ); | |||
318 | } | |||
319 | ||||
320 | void ImplChain::ImplBeginAdd( const Point& rStartPt ) | |||
321 | { | |||
322 | maPoly = tools::Polygon(); | |||
323 | maStartPt = rStartPt; | |||
324 | mnCount = 0; | |||
325 | } | |||
326 | ||||
327 | inline void ImplChain::ImplAdd( sal_uInt8 nCode ) | |||
328 | { | |||
329 | if( mnCount == mnArraySize ) | |||
330 | ImplGetSpace(); | |||
331 | ||||
332 | mpCodes[ mnCount++ ] = nCode; | |||
333 | } | |||
334 | ||||
335 | void ImplChain::ImplEndAdd( sal_uLong nFlag ) | |||
336 | { | |||
337 | if( mnCount ) | |||
338 | { | |||
339 | ImplPointArray aArr; | |||
340 | ||||
341 | if( nFlag & VECT_POLY_INLINE_INNER1UL ) | |||
342 | { | |||
343 | long nFirstX, nFirstY; | |||
344 | long nLastX, nLastY; | |||
345 | ||||
346 | nFirstX = nLastX = maStartPt.X(); | |||
347 | nFirstY = nLastY = maStartPt.Y(); | |||
348 | aArr.ImplSetSize( mnCount << 1 ); | |||
349 | ||||
350 | sal_uInt16 nPolyPos; | |||
351 | sal_uLong i; | |||
352 | for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ ) | |||
353 | { | |||
354 | const sal_uInt8 cMove = mpCodes[ i ]; | |||
355 | const sal_uInt8 cNextMove = mpCodes[ i + 1 ]; | |||
356 | const ChainMove& rMove = aImplMove[ cMove ]; | |||
357 | const ChainMove& rMoveInner = aImplMoveInner[ cMove ]; | |||
358 | // Point& rPt = aArr[ nPolyPos ]; | |||
359 | bool bDone = true; | |||
360 | ||||
361 | nLastX += rMove.nDX; | |||
362 | nLastY += rMove.nDY; | |||
363 | ||||
364 | if( cMove < 4 ) | |||
365 | { | |||
366 | if( ( cMove == 0 && cNextMove == 3 ) || | |||
367 | ( cMove == 3 && cNextMove == 2 ) || | |||
368 | ( cMove == 2 && cNextMove == 1 ) || | |||
369 | ( cMove == 1 && cNextMove == 0 ) ) | |||
370 | { | |||
371 | } | |||
372 | else if( cMove == 2 && cNextMove == 3 ) | |||
373 | { | |||
374 | aArr[ nPolyPos ].setX( nLastX ); | |||
375 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
376 | ||||
377 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
378 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
379 | ||||
380 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
381 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
382 | } | |||
383 | else if( cMove == 3 && cNextMove == 0 ) | |||
384 | { | |||
385 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
386 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
387 | ||||
388 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
389 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
390 | ||||
391 | aArr[ nPolyPos ].setX( nLastX ); | |||
392 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
393 | } | |||
394 | else if( cMove == 0 && cNextMove == 1 ) | |||
395 | { | |||
396 | aArr[ nPolyPos ].setX( nLastX ); | |||
397 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
398 | ||||
399 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
400 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
401 | ||||
402 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
403 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
404 | } | |||
405 | else if( cMove == 1 && cNextMove == 2 ) | |||
406 | { | |||
407 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
408 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
409 | ||||
410 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
411 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
412 | ||||
413 | aArr[ nPolyPos ].setX( nLastX ); | |||
414 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
415 | } | |||
416 | else | |||
417 | bDone = false; | |||
418 | } | |||
419 | else if( cMove == 7 && cNextMove == 0 ) | |||
420 | { | |||
421 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
422 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
423 | ||||
424 | aArr[ nPolyPos ].setX( nLastX ); | |||
425 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
426 | } | |||
427 | else if( cMove == 4 && cNextMove == 1 ) | |||
428 | { | |||
429 | aArr[ nPolyPos ].setX( nLastX ); | |||
430 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
431 | ||||
432 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
433 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
434 | } | |||
435 | else | |||
436 | bDone = false; | |||
437 | ||||
438 | if( !bDone ) | |||
439 | { | |||
440 | aArr[ nPolyPos ].setX( nLastX + rMoveInner.nDX ); | |||
441 | aArr[ nPolyPos++ ].setY( nLastY + rMoveInner.nDY ); | |||
442 | } | |||
443 | } | |||
444 | ||||
445 | aArr[ nPolyPos ].setX( nFirstX + 1 ); | |||
446 | aArr[ nPolyPos++ ].setY( nFirstY + 1 ); | |||
447 | aArr.ImplSetRealSize( nPolyPos ); | |||
448 | } | |||
449 | else if( nFlag & VECT_POLY_INLINE_OUTER2UL ) | |||
450 | { | |||
451 | long nFirstX, nFirstY; | |||
452 | long nLastX, nLastY; | |||
453 | ||||
454 | nFirstX = nLastX = maStartPt.X(); | |||
455 | nFirstY = nLastY = maStartPt.Y(); | |||
456 | aArr.ImplSetSize( mnCount << 1 ); | |||
457 | ||||
458 | sal_uInt16 nPolyPos; | |||
459 | sal_uLong i; | |||
460 | for( i = 0, nPolyPos = 0; i < ( mnCount - 1 ); i++ ) | |||
461 | { | |||
462 | const sal_uInt8 cMove = mpCodes[ i ]; | |||
463 | const sal_uInt8 cNextMove = mpCodes[ i + 1 ]; | |||
464 | const ChainMove& rMove = aImplMove[ cMove ]; | |||
465 | const ChainMove& rMoveOuter = aImplMoveOuter[ cMove ]; | |||
466 | // Point& rPt = aArr[ nPolyPos ]; | |||
467 | bool bDone = true; | |||
468 | ||||
469 | nLastX += rMove.nDX; | |||
470 | nLastY += rMove.nDY; | |||
471 | ||||
472 | if( cMove < 4 ) | |||
473 | { | |||
474 | if( ( cMove == 0 && cNextMove == 1 ) || | |||
475 | ( cMove == 1 && cNextMove == 2 ) || | |||
476 | ( cMove == 2 && cNextMove == 3 ) || | |||
477 | ( cMove == 3 && cNextMove == 0 ) ) | |||
478 | { | |||
479 | } | |||
480 | else if( cMove == 0 && cNextMove == 3 ) | |||
481 | { | |||
482 | aArr[ nPolyPos ].setX( nLastX ); | |||
483 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
484 | ||||
485 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
486 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
487 | ||||
488 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
489 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
490 | } | |||
491 | else if( cMove == 3 && cNextMove == 2 ) | |||
492 | { | |||
493 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
494 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
495 | ||||
496 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
497 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
498 | ||||
499 | aArr[ nPolyPos ].setX( nLastX ); | |||
500 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
501 | } | |||
502 | else if( cMove == 2 && cNextMove == 1 ) | |||
503 | { | |||
504 | aArr[ nPolyPos ].setX( nLastX ); | |||
505 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
506 | ||||
507 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
508 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
509 | ||||
510 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
511 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
512 | } | |||
513 | else if( cMove == 1 && cNextMove == 0 ) | |||
514 | { | |||
515 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
516 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
517 | ||||
518 | aArr[ nPolyPos ].setX( nLastX - 1 ); | |||
519 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
520 | ||||
521 | aArr[ nPolyPos ].setX( nLastX ); | |||
522 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
523 | } | |||
524 | else | |||
525 | bDone = false; | |||
526 | } | |||
527 | else if( cMove == 7 && cNextMove == 3 ) | |||
528 | { | |||
529 | aArr[ nPolyPos ].setX( nLastX ); | |||
530 | aArr[ nPolyPos++ ].setY( nLastY - 1 ); | |||
531 | ||||
532 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
533 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
534 | } | |||
535 | else if( cMove == 6 && cNextMove == 2 ) | |||
536 | { | |||
537 | aArr[ nPolyPos ].setX( nLastX + 1 ); | |||
538 | aArr[ nPolyPos++ ].setY( nLastY ); | |||
539 | ||||
540 | aArr[ nPolyPos ].setX( nLastX ); | |||
541 | aArr[ nPolyPos++ ].setY( nLastY + 1 ); | |||
542 | } | |||
543 | else | |||
544 | bDone = false; | |||
545 | ||||
546 | if( !bDone ) | |||
547 | { | |||
548 | aArr[ nPolyPos ].setX( nLastX + rMoveOuter.nDX ); | |||
549 | aArr[ nPolyPos++ ].setY( nLastY + rMoveOuter.nDY ); | |||
550 | } | |||
551 | } | |||
552 | ||||
553 | aArr[ nPolyPos ].setX( nFirstX - 1 ); | |||
554 | aArr[ nPolyPos++ ].setY( nFirstY - 1 ); | |||
555 | aArr.ImplSetRealSize( nPolyPos ); | |||
556 | } | |||
557 | else | |||
558 | { | |||
559 | long nLastX = maStartPt.X(), nLastY = maStartPt.Y(); | |||
560 | ||||
561 | aArr.ImplSetSize( mnCount + 1 ); | |||
562 | aArr[ 0 ] = Point( nLastX, nLastY ); | |||
563 | ||||
564 | for( sal_uLong i = 0; i < mnCount; ) | |||
565 | { | |||
566 | const ChainMove& rMove = aImplMove[ mpCodes[ i ] ]; | |||
567 | nLastX += rMove.nDX; | |||
568 | nLastY += rMove.nDY; | |||
569 | aArr[ ++i ] = Point( nLastX, nLastY ); | |||
570 | } | |||
571 | ||||
572 | aArr.ImplSetRealSize( mnCount + 1 ); | |||
573 | } | |||
574 | ||||
575 | ImplPostProcess( aArr ); | |||
576 | } | |||
577 | else | |||
578 | maPoly.SetSize( 0 ); | |||
579 | } | |||
580 | ||||
581 | void ImplChain::ImplPostProcess( const ImplPointArray& rArr ) | |||
582 | { | |||
583 | ImplPointArray aNewArr1; | |||
584 | ImplPointArray aNewArr2; | |||
585 | Point* pLast; | |||
586 | Point* pLeast; | |||
587 | sal_uLong nNewPos; | |||
588 | sal_uLong nCount = rArr.ImplGetRealSize(); | |||
589 | sal_uLong n; | |||
590 | ||||
591 | // pass 1 | |||
592 | aNewArr1.ImplSetSize( nCount ); | |||
593 | pLast = &( aNewArr1[ 0 ] ); | |||
594 | pLast->setX( BACK_MAP( rArr[ 0 ].X() ) ); | |||
595 | pLast->setY( BACK_MAP( rArr[ 0 ].Y() ) ); | |||
596 | ||||
597 | for( n = nNewPos = 1; n < nCount; ) | |||
598 | { | |||
599 | const Point& rPt = rArr[ n++ ]; | |||
600 | const long nX = BACK_MAP( rPt.X() ); | |||
601 | const long nY = BACK_MAP( rPt.Y() ); | |||
602 | ||||
603 | if( nX != pLast->X() || nY != pLast->Y() ) | |||
604 | { | |||
605 | pLast = pLeast = &( aNewArr1[ nNewPos++ ] ); | |||
606 | pLeast->setX( nX ); | |||
607 | pLeast->setY( nY ); | |||
608 | } | |||
609 | } | |||
610 | ||||
611 | nCount = nNewPos; | |||
612 | aNewArr1.ImplSetRealSize( nCount ); | |||
613 | ||||
614 | // pass 2 | |||
615 | aNewArr2.ImplSetSize( nCount ); | |||
616 | pLast = &( aNewArr2[ 0 ] ); | |||
617 | *pLast = aNewArr1[ 0 ]; | |||
618 | ||||
619 | for( n = nNewPos = 1; n < nCount; ) | |||
620 | { | |||
621 | pLeast = &( aNewArr1[ n++ ] ); | |||
622 | ||||
623 | if( pLeast->X() == pLast->X() ) | |||
624 | { | |||
625 | while( n < nCount && aNewArr1[ n ].X() == pLast->X() ) | |||
626 | pLeast = &( aNewArr1[ n++ ] ); | |||
627 | } | |||
628 | else if( pLeast->Y() == pLast->Y() ) | |||
629 | { | |||
630 | while( n < nCount && aNewArr1[ n ].Y() == pLast->Y() ) | |||
631 | pLeast = &( aNewArr1[ n++ ] ); | |||
632 | } | |||
633 | ||||
634 | pLast = pLeast; | |||
635 | aNewArr2[ nNewPos++ ] = *pLast; | |||
636 | } | |||
637 | ||||
638 | aNewArr2.ImplSetRealSize( nNewPos ); | |||
639 | aNewArr2.ImplCreatePoly( maPoly ); | |||
640 | } | |||
641 | ||||
642 | namespace ImplVectorizer { | |||
643 | ||||
644 | bool ImplVectorize( const Bitmap& rColorBmp, GDIMetaFile& rMtf, | |||
645 | sal_uInt8 cReduce, const Link<long,void>* pProgress ) | |||
646 | { | |||
647 | bool bRet = false; | |||
648 | ||||
649 | VECT_PROGRESS( pProgress, 0 ); | |||
650 | ||||
651 | std::unique_ptr<Bitmap> xBmp(new Bitmap( rColorBmp )); | |||
652 | Bitmap::ScopedReadAccess pRAcc(*xBmp); | |||
653 | ||||
654 | if( pRAcc ) | |||
| ||||
655 | { | |||
656 | tools::PolyPolygon aPolyPoly; | |||
657 | double fPercent = 0.0; | |||
658 | double fPercentStep_2 = 0.0; | |||
659 | const long nWidth = pRAcc->Width(); | |||
660 | const long nHeight = pRAcc->Height(); | |||
661 | const sal_uInt16 nColorCount = pRAcc->GetPaletteEntryCount(); | |||
662 | sal_uInt16 n; | |||
663 | std::array<ImplColorSet, 256> aColorSet; | |||
664 | ||||
665 | rMtf.Clear(); | |||
666 | ||||
667 | // get used palette colors and sort them from light to dark colors | |||
668 | for( n = 0; n < nColorCount; n++ ) | |||
669 | { | |||
670 | aColorSet[ n ].mnIndex = n; | |||
671 | aColorSet[ n ].maColor = pRAcc->GetPaletteColor( n ); | |||
672 | } | |||
673 | ||||
674 | for( long nY = 0; nY < nHeight; nY++ ) | |||
675 | { | |||
676 | Scanline pScanlineRead = pRAcc->GetScanline( nY ); | |||
677 | for( long nX = 0; nX < nWidth; nX++ ) | |||
678 | aColorSet[ pRAcc->GetIndexFromData( pScanlineRead, nX ) ].mbSet = true; | |||
679 | } | |||
680 | ||||
681 | std::sort( aColorSet.begin(), aColorSet.end(), ImplColorSetCmpFnc ); | |||
682 | ||||
683 | for( n = 0; n < 256; n++ ) | |||
684 | if( !aColorSet[ n ].mbSet ) | |||
685 | break; | |||
686 | ||||
687 | if( n
| |||
688 | fPercentStep_2 = 45.0 / n; | |||
689 | ||||
690 | fPercent += 10.0; | |||
691 | VECT_PROGRESS( pProgress, FRound( fPercent ) ); | |||
692 | ||||
693 | for( sal_uInt16 i = 0; i < n; i++ ) | |||
694 | { | |||
695 | const BitmapColor aBmpCol( pRAcc->GetPaletteColor( aColorSet[ i ].mnIndex ) ); | |||
696 | const Color aFindColor( aBmpCol.GetRed(), aBmpCol.GetGreen(), aBmpCol.GetBlue() ); | |||
697 | std::unique_ptr<ImplVectMap> xMap(ImplExpand( pRAcc.get(), aFindColor )); | |||
698 | ||||
699 | fPercent += fPercentStep_2; | |||
700 | VECT_PROGRESS( pProgress, FRound( fPercent ) ); | |||
701 | ||||
702 | if( xMap ) | |||
703 | { | |||
704 | aPolyPoly.Clear(); | |||
705 | ImplCalculate( xMap.get(), aPolyPoly, cReduce ); | |||
706 | xMap.reset(); | |||
707 | ||||
708 | if( aPolyPoly.Count() ) | |||
709 | { | |||
710 | ImplLimitPolyPoly( aPolyPoly ); | |||
711 | ||||
712 | aPolyPoly.Optimize( PolyOptimizeFlags::EDGES ); | |||
713 | ||||
714 | if( aPolyPoly.Count() ) | |||
715 | { | |||
716 | rMtf.AddAction( new MetaLineColorAction( aFindColor, true ) ); | |||
717 | rMtf.AddAction( new MetaFillColorAction( aFindColor, true ) ); | |||
718 | rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) ); | |||
719 | } | |||
720 | } | |||
721 | } | |||
722 | ||||
723 | fPercent += fPercentStep_2; | |||
724 | VECT_PROGRESS( pProgress, FRound( fPercent ) ); | |||
725 | } | |||
726 | ||||
727 | if( rMtf.GetActionSize() ) | |||
728 | { | |||
729 | MapMode aMap( MapUnit::Map100thMM ); | |||
730 | ScopedVclPtrInstance< VirtualDevice > aVDev; | |||
731 | const Size aLogSize1( aVDev->PixelToLogic( Size( 1, 1 ), aMap ) ); | |||
732 | ||||
733 | rMtf.SetPrefMapMode( aMap ); | |||
734 | rMtf.SetPrefSize( Size( nWidth + 2, nHeight + 2 ) ); | |||
735 | rMtf.Move( 1, 1 ); | |||
736 | rMtf.Scale( aLogSize1.Width(), aLogSize1.Height() ); | |||
737 | bRet = true; | |||
738 | } | |||
739 | } | |||
740 | ||||
741 | pRAcc.reset(); | |||
742 | xBmp.reset(); | |||
743 | VECT_PROGRESS( pProgress, 100 ); | |||
744 | ||||
745 | return bRet; | |||
746 | } | |||
747 | ||||
748 | void ImplLimitPolyPoly( tools::PolyPolygon& rPolyPoly ) | |||
749 | { | |||
750 | if( rPolyPoly.Count() <= VECT_POLY_MAX8192 ) | |||
751 | return; | |||
752 | ||||
753 | tools::PolyPolygon aNewPolyPoly; | |||
754 | long nReduce = 0; | |||
755 | sal_uInt16 nNewCount; | |||
756 | ||||
757 | do | |||
758 | { | |||
759 | aNewPolyPoly.Clear(); | |||
760 | nReduce++; | |||
761 | ||||
762 | for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ ) | |||
763 | { | |||
764 | const tools::Rectangle aBound( rPolyPoly[ i ].GetBoundRect() ); | |||
765 | ||||
766 | if( aBound.GetWidth() > nReduce && aBound.GetHeight() > nReduce ) | |||
767 | { | |||
768 | if( rPolyPoly[ i ].GetSize() ) | |||
769 | aNewPolyPoly.Insert( rPolyPoly[ i ] ); | |||
770 | } | |||
771 | } | |||
772 | ||||
773 | nNewCount = aNewPolyPoly.Count(); | |||
774 | } | |||
775 | while( nNewCount > VECT_POLY_MAX8192 ); | |||
776 | ||||
777 | rPolyPoly = aNewPolyPoly; | |||
778 | } | |||
779 | ||||
780 | ImplVectMap* ImplExpand( BitmapReadAccess* pRAcc, const Color& rColor ) | |||
781 | { | |||
782 | ImplVectMap* pMap = nullptr; | |||
783 | ||||
784 | if( pRAcc && pRAcc->Width() && pRAcc->Height() ) | |||
785 | { | |||
786 | const long nOldWidth = pRAcc->Width(); | |||
787 | const long nOldHeight = pRAcc->Height(); | |||
788 | const long nNewWidth = ( nOldWidth << 2 ) + 4; | |||
789 | const long nNewHeight = ( nOldHeight << 2 ) + 4; | |||
790 | const BitmapColor aTest( pRAcc->GetBestMatchingColor( rColor ) ); | |||
791 | std::unique_ptr<long[]> pMapIn(new long[ std::max( nOldWidth, nOldHeight ) ]); | |||
792 | std::unique_ptr<long[]> pMapOut(new long[ std::max( nOldWidth, nOldHeight ) ]); | |||
793 | long nX, nY, nTmpX, nTmpY; | |||
794 | ||||
795 | pMap = new ImplVectMap( nNewWidth, nNewHeight ); | |||
796 | ||||
797 | for( nX = 0; nX < nOldWidth; nX++ ) | |||
798 | VECT_MAP( pMapIn, pMapOut, nX ); | |||
799 | ||||
800 | for( nY = 0, nTmpY = 5; nY < nOldHeight; nY++, nTmpY += 4 ) | |||
801 | { | |||
802 | Scanline pScanlineRead = pRAcc->GetScanline( nY ); | |||
803 | for( nX = 0; nX < nOldWidth; ) | |||
804 | { | |||
805 | if( pRAcc->GetPixelFromData( pScanlineRead, nX ) == aTest ) | |||
806 | { | |||
807 | nTmpX = pMapIn[ nX++ ]; | |||
808 | nTmpY -= 3; | |||
809 | ||||
810 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
811 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
812 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
813 | pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX1 ); | |||
814 | ||||
815 | while( nX < nOldWidth && pRAcc->GetPixelFromData( pScanlineRead, nX ) == aTest ) | |||
816 | nX++; | |||
817 | ||||
818 | nTmpX = pMapOut[ nX - 1 ]; | |||
819 | nTmpY -= 3; | |||
820 | ||||
821 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
822 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
823 | pMap->Set( nTmpY++, nTmpX, VECT_CONT_INDEX1 ); | |||
824 | pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX1 ); | |||
825 | } | |||
826 | else | |||
827 | nX++; | |||
828 | } | |||
829 | } | |||
830 | ||||
831 | for( nY = 0; nY < nOldHeight; nY++ ) | |||
832 | VECT_MAP( pMapIn, pMapOut, nY ); | |||
833 | ||||
834 | for( nX = 0, nTmpX = 5; nX < nOldWidth; nX++, nTmpX += 4 ) | |||
835 | { | |||
836 | for( nY = 0; nY < nOldHeight; ) | |||
837 | { | |||
838 | if( pRAcc->GetPixel( nY, nX ) == aTest ) | |||
839 | { | |||
840 | nTmpX -= 3; | |||
841 | nTmpY = pMapIn[ nY++ ]; | |||
842 | ||||
843 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
844 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
845 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
846 | pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX1 ); | |||
847 | ||||
848 | while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest ) | |||
849 | nY++; | |||
850 | ||||
851 | nTmpX -= 3; | |||
852 | nTmpY = pMapOut[ nY - 1 ]; | |||
853 | ||||
854 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
855 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
856 | pMap->Set( nTmpY, nTmpX++, VECT_CONT_INDEX1 ); | |||
857 | pMap->Set( nTmpY, nTmpX, VECT_CONT_INDEX1 ); | |||
858 | } | |||
859 | else | |||
860 | nY++; | |||
861 | } | |||
862 | } | |||
863 | } | |||
864 | ||||
865 | return pMap; | |||
866 | } | |||
867 | ||||
868 | void ImplCalculate( ImplVectMap* pMap, tools::PolyPolygon& rPolyPoly, sal_uInt8 cReduce ) | |||
869 | { | |||
870 | const long nWidth = pMap->Width(), nHeight= pMap->Height(); | |||
871 | ||||
872 | for( long nY = 0; nY < nHeight; nY++ ) | |||
873 | { | |||
874 | long nX = 0; | |||
875 | bool bInner = true; | |||
876 | ||||
877 | while( nX < nWidth ) | |||
878 | { | |||
879 | // skip free | |||
880 | while( ( nX
| |||
881 | nX++; | |||
882 | ||||
883 | if( nX == nWidth ) | |||
884 | break; | |||
885 | ||||
886 | if( pMap->IsCont( nY, nX ) ) | |||
887 | { | |||
888 | // new contour | |||
889 | ImplChain aChain; | |||
890 | const Point aStartPt( nX++, nY ); | |||
891 | ||||
892 | // get chain code | |||
893 | aChain.ImplBeginAdd( aStartPt ); | |||
894 | ImplGetChain( pMap, aStartPt, aChain ); | |||
895 | ||||
896 | aChain.ImplEndAdd( bInner ? VECT_POLY_OUTLINE_INNER4UL : VECT_POLY_OUTLINE_OUTER8UL ); | |||
897 | ||||
898 | const tools::Polygon& rPoly = aChain.ImplGetPoly(); | |||
899 | ||||
900 | if( rPoly.GetSize() > 2 ) | |||
901 | { | |||
902 | if( cReduce ) | |||
903 | { | |||
904 | const tools::Rectangle aBound( rPoly.GetBoundRect() ); | |||
905 | ||||
906 | if( aBound.GetWidth() > cReduce && aBound.GetHeight() > cReduce ) | |||
907 | rPolyPoly.Insert( rPoly ); | |||
908 | } | |||
909 | else | |||
910 | rPolyPoly.Insert( rPoly ); | |||
911 | } | |||
912 | ||||
913 | // skip rest of detected contour | |||
914 | while( pMap->IsCont( nY, nX ) ) | |||
915 | nX++; | |||
916 | } | |||
917 | else | |||
918 | { | |||
919 | // process done segment | |||
920 | const long nStartSegX = nX++; | |||
921 | ||||
922 | while( pMap->IsDone( nY, nX ) ) | |||
923 | nX++; | |||
924 | ||||
925 | if( ( ( nX - nStartSegX ) == 1 ) || ( ImplIsUp( pMap, nY, nStartSegX ) != ImplIsUp( pMap, nY, nX - 1 ) ) ) | |||
926 | bInner = !bInner; | |||
927 | } | |||
928 | } | |||
929 | } | |||
930 | } | |||
931 | ||||
932 | bool ImplGetChain( ImplVectMap* pMap, const Point& rStartPt, ImplChain& rChain ) | |||
933 | { | |||
934 | long nActX = rStartPt.X(); | |||
935 | long nActY = rStartPt.Y(); | |||
936 | sal_uLong nFound; | |||
937 | sal_uLong nLastDir = 0; | |||
938 | sal_uLong nDir; | |||
939 | ||||
940 | do | |||
941 | { | |||
942 | nFound = 0; | |||
943 | ||||
944 | // first try last direction | |||
945 | long nTryX = nActX + aImplMove[ nLastDir ].nDX; | |||
946 | long nTryY = nActY + aImplMove[ nLastDir ].nDY; | |||
947 | ||||
948 | if( pMap->IsCont( nTryY, nTryX ) ) | |||
949 | { | |||
950 | rChain.ImplAdd( static_cast<sal_uInt8>(nLastDir) ); | |||
951 | nActY = nTryY; | |||
952 | nActX = nTryX; | |||
953 | pMap->Set( nActY, nActX, VECT_DONE_INDEX2 ); | |||
954 | nFound = 1; | |||
955 | } | |||
956 | else | |||
957 | { | |||
958 | // try other directions | |||
959 | for( nDir = 0; nDir < 8; nDir++ ) | |||
960 | { | |||
961 | // we already tried nLastDir | |||
962 | if( nDir != nLastDir ) | |||
963 | { | |||
964 | nTryX = nActX + aImplMove[ nDir ].nDX; | |||
965 | nTryY = nActY + aImplMove[ nDir ].nDY; | |||
966 | ||||
967 | if( pMap->IsCont( nTryY, nTryX ) ) | |||
968 | { | |||
969 | rChain.ImplAdd( static_cast<sal_uInt8>(nDir) ); | |||
970 | nActY = nTryY; | |||
971 | nActX = nTryX; | |||
972 | pMap->Set( nActY, nActX, VECT_DONE_INDEX2 ); | |||
973 | nFound = 1; | |||
974 | nLastDir = nDir; | |||
975 | break; | |||
976 | } | |||
977 | } | |||
978 | } | |||
979 | } | |||
980 | } | |||
981 | while( nFound ); | |||
982 | ||||
983 | return true; | |||
984 | } | |||
985 | ||||
986 | bool ImplIsUp( ImplVectMap const * pMap, long nY, long nX ) | |||
987 | { | |||
988 | if( pMap->IsDone( nY - 1, nX ) ) | |||
989 | return true; | |||
990 | else if( pMap->IsDone( nY + 1, nX ) ) | |||
991 | return false; | |||
992 | else if( pMap->IsDone( nY - 1, nX - 1 ) || pMap->IsDone( nY - 1, nX + 1 ) ) | |||
993 | return true; | |||
994 | else | |||
995 | return false; | |||
996 | } | |||
997 | ||||
998 | } | |||
999 | ||||
1000 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |