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 : #include <sot/factory.hxx>
21 : #include <tools/poly.hxx>
22 : #include <vcl/bmpacc.hxx>
23 : #include <vcl/virdev.hxx>
24 : #include <vcl/wrkwin.hxx>
25 : #include <svl/solar.hrc>
26 : #include <sfx2/docfile.hxx>
27 : #include <sfx2/app.hxx>
28 : #include "svx/xoutbmp.hxx"
29 : #include <vcl/dibtools.hxx>
30 : #include <vcl/FilterConfigItem.hxx>
31 : #include <vcl/graphicfilter.hxx>
32 : #include <vcl/cvtgrf.hxx>
33 : #include <sax/tools/converter.hxx>
34 :
35 : #define FORMAT_BMP OUString("bmp")
36 : #define FORMAT_GIF OUString("gif")
37 : #define FORMAT_JPG OUString("jpg")
38 : #define FORMAT_PNG OUString("png")
39 :
40 : GraphicFilter* XOutBitmap::pGrfFilter = NULL;
41 :
42 0 : Animation XOutBitmap::MirrorAnimation( const Animation& rAnimation, bool bHMirr, bool bVMirr )
43 : {
44 0 : Animation aNewAnim( rAnimation );
45 :
46 0 : if( bHMirr || bVMirr )
47 : {
48 0 : const Size& rGlobalSize = aNewAnim.GetDisplaySizePixel();
49 0 : sal_uIntPtr nMirrorFlags = 0L;
50 :
51 0 : if( bHMirr )
52 0 : nMirrorFlags |= BMP_MIRROR_HORZ;
53 :
54 0 : if( bVMirr )
55 0 : nMirrorFlags |= BMP_MIRROR_VERT;
56 :
57 0 : for( sal_uInt16 i = 0, nCount = aNewAnim.Count(); i < nCount; i++ )
58 : {
59 0 : AnimationBitmap aAnimBmp( aNewAnim.Get( i ) );
60 :
61 : // mirror the BitmapEx
62 0 : aAnimBmp.aBmpEx.Mirror( nMirrorFlags );
63 :
64 : // Adjust the positions inside the whole bitmap
65 0 : if( bHMirr )
66 0 : aAnimBmp.aPosPix.X() = rGlobalSize.Width() - aAnimBmp.aPosPix.X() -
67 0 : aAnimBmp.aSizePix.Width();
68 :
69 0 : if( bVMirr )
70 0 : aAnimBmp.aPosPix.Y() = rGlobalSize.Height() - aAnimBmp.aPosPix.Y() -
71 0 : aAnimBmp.aSizePix.Height();
72 :
73 0 : aNewAnim.Replace( aAnimBmp, i );
74 0 : }
75 : }
76 :
77 0 : return aNewAnim;
78 : }
79 :
80 0 : Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const sal_uIntPtr nMirrorFlags )
81 : {
82 0 : Graphic aRetGraphic;
83 :
84 0 : if( nMirrorFlags )
85 : {
86 0 : if( rGraphic.IsAnimated() )
87 : {
88 0 : aRetGraphic = MirrorAnimation( rGraphic.GetAnimation(),
89 0 : ( nMirrorFlags & BMP_MIRROR_HORZ ) == BMP_MIRROR_HORZ,
90 0 : ( nMirrorFlags & BMP_MIRROR_VERT ) == BMP_MIRROR_VERT );
91 : }
92 : else
93 : {
94 0 : if( rGraphic.IsTransparent() )
95 : {
96 0 : BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
97 :
98 0 : aBmpEx.Mirror( nMirrorFlags );
99 0 : aRetGraphic = aBmpEx;
100 : }
101 : else
102 : {
103 0 : Bitmap aBmp( rGraphic.GetBitmap() );
104 :
105 0 : aBmp.Mirror( nMirrorFlags );
106 0 : aRetGraphic = aBmp;
107 : }
108 : }
109 : }
110 : else
111 0 : aRetGraphic = rGraphic;
112 :
113 0 : return aRetGraphic;
114 : }
115 :
116 0 : sal_uInt16 XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
117 : const OUString& rFilterName, const sal_uIntPtr nFlags,
118 : const Size* pMtfSize_100TH_MM )
119 : {
120 0 : if( rGraphic.GetType() != GRAPHIC_NONE )
121 : {
122 0 : INetURLObject aURL( rFileName );
123 0 : Graphic aGraphic;
124 0 : OUString aExt;
125 0 : GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
126 0 : sal_uInt16 nErr = GRFILTER_FILTERERROR, nFilter = GRFILTER_FORMAT_NOTFOUND;
127 0 : sal_Bool bTransparent = rGraphic.IsTransparent(), bAnimated = rGraphic.IsAnimated();
128 :
129 : DBG_ASSERT( aURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::WriteGraphic(...): invalid URL" );
130 :
131 : // calculate correct file name
132 0 : if( !( nFlags & XOUTBMP_DONT_EXPAND_FILENAME ) )
133 : {
134 0 : OUString aName( aURL.getBase() );
135 0 : aName += "_";
136 0 : aName += aURL.getExtension();
137 0 : aName += "_";
138 0 : OUString aStr( OUString::number( rGraphic.GetChecksum(), 16 ) );
139 0 : if ( aStr[0] == '-' )
140 0 : aStr = "m" + aStr.copy(1);
141 0 : aName += aStr;
142 0 : aURL.setBase( aName );
143 : }
144 :
145 : // #i121128# use shortcut to write SVG data in original form (if possible)
146 0 : const SvgDataPtr aSvgDataPtr(rGraphic.getSvgData());
147 :
148 0 : if(aSvgDataPtr.get()
149 0 : && aSvgDataPtr->getSvgDataArrayLength()
150 0 : && rFilterName.equalsIgnoreAsciiCase("svg"))
151 : {
152 0 : if(!(nFlags & XOUTBMP_DONT_ADD_EXTENSION))
153 : {
154 0 : aURL.setExtension(rFilterName);
155 : }
156 :
157 0 : rFileName = aURL.GetMainURL(INetURLObject::NO_DECODE);
158 0 : SfxMedium aMedium(aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_WRITE|STREAM_SHARE_DENYNONE|STREAM_TRUNC);
159 0 : SvStream* pOStm = aMedium.GetOutStream();
160 :
161 0 : if(pOStm)
162 : {
163 0 : pOStm->Write(aSvgDataPtr->getSvgDataArray().get(), aSvgDataPtr->getSvgDataArrayLength());
164 0 : aMedium.Commit();
165 :
166 0 : if(!aMedium.GetError())
167 : {
168 0 : nErr = GRFILTER_OK;
169 : }
170 0 : }
171 : }
172 :
173 0 : if( GRFILTER_OK != nErr )
174 : {
175 0 : if( ( nFlags & XOUTBMP_USE_NATIVE_IF_POSSIBLE ) &&
176 0 : !( nFlags & XOUTBMP_MIRROR_HORZ ) &&
177 0 : !( nFlags & XOUTBMP_MIRROR_VERT ) &&
178 0 : ( rGraphic.GetType() != GRAPHIC_GDIMETAFILE ) && rGraphic.IsLink() )
179 : {
180 : // try to write native link
181 0 : const GfxLink aGfxLink( ( (Graphic&) rGraphic ).GetLink() );
182 :
183 0 : switch( aGfxLink.GetType() )
184 : {
185 0 : case( GFX_LINK_TYPE_NATIVE_GIF ): aExt = FORMAT_GIF; break;
186 :
187 : // #i15508# added BMP type for better exports (no call/trigger found, prob used in HTML export)
188 0 : case( GFX_LINK_TYPE_NATIVE_BMP ): aExt = FORMAT_BMP; break;
189 :
190 0 : case( GFX_LINK_TYPE_NATIVE_JPG ): aExt = FORMAT_JPG; break;
191 0 : case( GFX_LINK_TYPE_NATIVE_PNG ): aExt = FORMAT_PNG; break;
192 :
193 : default:
194 0 : break;
195 : }
196 :
197 0 : if( !aExt.isEmpty() )
198 : {
199 0 : if( 0 == (nFlags & XOUTBMP_DONT_ADD_EXTENSION))
200 0 : aURL.setExtension( aExt );
201 0 : rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE );
202 :
203 0 : SfxMedium aMedium(aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC);
204 0 : SvStream* pOStm = aMedium.GetOutStream();
205 :
206 0 : if( pOStm && aGfxLink.GetDataSize() && aGfxLink.GetData() )
207 : {
208 0 : pOStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
209 0 : aMedium.Commit();
210 :
211 0 : if( !aMedium.GetError() )
212 0 : nErr = GRFILTER_OK;
213 0 : }
214 0 : }
215 : }
216 : }
217 :
218 0 : if( GRFILTER_OK != nErr )
219 : {
220 0 : OUString aFilter( rFilterName );
221 0 : bool bWriteTransGrf = ( aFilter.equalsIgnoreAsciiCase( "transgrf" ) ) ||
222 0 : ( aFilter.equalsIgnoreAsciiCase( "gif" ) ) ||
223 0 : ( nFlags & XOUTBMP_USE_GIF_IF_POSSIBLE ) ||
224 0 : ( ( nFlags & XOUTBMP_USE_GIF_IF_SENSIBLE ) && ( bAnimated || bTransparent ) );
225 :
226 : // get filter and extension
227 0 : if( bWriteTransGrf )
228 0 : aFilter = FORMAT_GIF;
229 :
230 0 : nFilter = rFilter.GetExportFormatNumberForShortName( aFilter );
231 :
232 0 : if( GRFILTER_FORMAT_NOTFOUND == nFilter )
233 : {
234 0 : nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_PNG );
235 :
236 0 : if( GRFILTER_FORMAT_NOTFOUND == nFilter )
237 0 : nFilter = rFilter.GetExportFormatNumberForShortName( FORMAT_BMP );
238 : }
239 :
240 0 : if( GRFILTER_FORMAT_NOTFOUND != nFilter )
241 : {
242 0 : aExt = rFilter.GetExportFormatShortName( nFilter ).toAsciiLowerCase();
243 :
244 0 : if( bWriteTransGrf )
245 : {
246 0 : if( bAnimated )
247 0 : aGraphic = rGraphic;
248 : else
249 : {
250 0 : if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) )
251 : {
252 0 : VirtualDevice aVDev;
253 0 : const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) );
254 :
255 0 : if( aVDev.SetOutputSizePixel( aSize ) )
256 : {
257 0 : const Wallpaper aWallpaper( aVDev.GetBackground() );
258 0 : const Point aPt;
259 :
260 0 : aVDev.SetBackground( Wallpaper( Color( COL_BLACK ) ) );
261 0 : aVDev.Erase();
262 0 : rGraphic.Draw( &aVDev, aPt, aSize );
263 :
264 0 : const Bitmap aBitmap( aVDev.GetBitmap( aPt, aSize ) );
265 :
266 0 : aVDev.SetBackground( aWallpaper );
267 0 : aVDev.Erase();
268 0 : rGraphic.Draw( &aVDev, aPt, aSize );
269 :
270 0 : aVDev.SetRasterOp( ROP_XOR );
271 0 : aVDev.DrawBitmap( aPt, aSize, aBitmap );
272 0 : aGraphic = BitmapEx( aBitmap, aVDev.GetBitmap( aPt, aSize ) );
273 : }
274 : else
275 0 : aGraphic = rGraphic.GetBitmapEx();
276 : }
277 : else
278 0 : aGraphic = rGraphic.GetBitmapEx();
279 : }
280 : }
281 : else
282 : {
283 0 : if( pMtfSize_100TH_MM && ( rGraphic.GetType() != GRAPHIC_BITMAP ) )
284 : {
285 0 : VirtualDevice aVDev;
286 0 : const Size aSize( aVDev.LogicToPixel( *pMtfSize_100TH_MM, MAP_100TH_MM ) );
287 :
288 0 : if( aVDev.SetOutputSizePixel( aSize ) )
289 : {
290 0 : rGraphic.Draw( &aVDev, Point(), aSize );
291 0 : aGraphic = aVDev.GetBitmap( Point(), aSize );
292 : }
293 : else
294 0 : aGraphic = rGraphic.GetBitmap();
295 : }
296 : else
297 0 : aGraphic = rGraphic.GetBitmap();
298 : }
299 :
300 : // mirror?
301 0 : if( ( nFlags & XOUTBMP_MIRROR_HORZ ) || ( nFlags & XOUTBMP_MIRROR_VERT ) )
302 0 : aGraphic = MirrorGraphic( aGraphic, nFlags );
303 :
304 0 : if( ( GRFILTER_FORMAT_NOTFOUND != nFilter ) && ( aGraphic.GetType() != GRAPHIC_NONE ) )
305 : {
306 0 : if( 0 == (nFlags & XOUTBMP_DONT_ADD_EXTENSION))
307 0 : aURL.setExtension( aExt );
308 0 : rFileName = aURL.GetMainURL( INetURLObject::NO_DECODE );
309 0 : nErr = ExportGraphic( aGraphic, aURL, rFilter, nFilter, NULL );
310 : }
311 0 : }
312 : }
313 :
314 0 : return nErr;
315 : }
316 : else
317 : {
318 0 : return GRFILTER_OK;
319 : }
320 : }
321 :
322 0 : sal_uLong XOutBitmap::GraphicToBase64(const Graphic& rGraphic, OUString& rOUString)
323 : {
324 0 : SvMemoryStream aOStm;
325 0 : OUString aMimeType;
326 0 : GfxLink aLink = rGraphic.GetLink();
327 : sal_uLong aCvtType;
328 0 : switch( aLink.GetType() )
329 : {
330 : case( GFX_LINK_TYPE_NATIVE_JPG ):
331 0 : aCvtType = CVT_JPG;
332 0 : aMimeType = "image/jpeg";
333 0 : break;
334 : case( GFX_LINK_TYPE_NATIVE_PNG ):
335 0 : aCvtType = CVT_PNG;
336 0 : aMimeType = "image/png";
337 0 : break;
338 : case( GFX_LINK_TYPE_NATIVE_SVG ):
339 0 : aCvtType = CVT_SVG;
340 0 : aMimeType = "image/svg+xml";
341 0 : break;
342 : default:
343 : // save everything else (including gif) into png
344 0 : aCvtType = CVT_PNG;
345 0 : aMimeType = "image/png";
346 0 : break;
347 : }
348 0 : sal_uLong nErr = GraphicConverter::Export(aOStm,rGraphic,aCvtType);
349 0 : if ( nErr )
350 : {
351 : SAL_WARN("svx", "XOutBitmap::GraphicToBase64() invalid Graphic? error: " << nErr );
352 0 : return nErr;
353 : }
354 0 : aOStm.Seek(STREAM_SEEK_TO_END);
355 0 : css::uno::Sequence<sal_Int8> aOStmSeq( (sal_Int8*) aOStm.GetData(),aOStm.Tell() );
356 0 : OUStringBuffer aStrBuffer;
357 0 : ::sax::Converter::encodeBase64(aStrBuffer,aOStmSeq);
358 0 : rOUString = aMimeType + ";base64," + aStrBuffer.makeStringAndClear();
359 0 : return 0;
360 : }
361 :
362 0 : sal_uInt16 XOutBitmap::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rURL,
363 : GraphicFilter& rFilter, const sal_uInt16 nFormat,
364 : const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData )
365 : {
366 : DBG_ASSERT( rURL.GetProtocol() != INET_PROT_NOT_VALID, "XOutBitmap::ExportGraphic(...): invalid URL" );
367 :
368 0 : SfxMedium aMedium( rURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_SHARE_DENYNONE | STREAM_TRUNC );
369 0 : SvStream* pOStm = aMedium.GetOutStream();
370 0 : sal_uInt16 nRet = GRFILTER_IOERROR;
371 :
372 0 : if( pOStm )
373 : {
374 0 : pGrfFilter = &rFilter;
375 :
376 0 : nRet = rFilter.ExportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::NO_DECODE ), *pOStm, nFormat, pFilterData );
377 :
378 0 : pGrfFilter = NULL;
379 0 : aMedium.Commit();
380 :
381 0 : if( aMedium.GetError() && ( GRFILTER_OK == nRet ) )
382 0 : nRet = GRFILTER_IOERROR;
383 : }
384 :
385 0 : return nRet;
386 : }
387 :
388 0 : Bitmap XOutBitmap::DetectEdges( const Bitmap& rBmp, const sal_uInt8 cThreshold )
389 : {
390 0 : const Size aSize( rBmp.GetSizePixel() );
391 0 : Bitmap aRetBmp;
392 0 : bool bRet = false;
393 :
394 0 : if( ( aSize.Width() > 2L ) && ( aSize.Height() > 2L ) )
395 : {
396 0 : Bitmap aWorkBmp( rBmp );
397 :
398 0 : if( aWorkBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
399 : {
400 0 : Bitmap aDstBmp( aSize, 1 );
401 0 : BitmapReadAccess* pReadAcc = aWorkBmp.AcquireReadAccess();
402 0 : BitmapWriteAccess* pWriteAcc = aDstBmp.AcquireWriteAccess();
403 :
404 0 : if( pReadAcc && pWriteAcc )
405 : {
406 0 : const long nWidth = aSize.Width();
407 0 : const long nWidth2 = nWidth - 2L;
408 0 : const long nHeight = aSize.Height();
409 0 : const long nHeight2 = nHeight - 2L;
410 0 : const long lThres2 = (long) cThreshold * cThreshold;
411 0 : const sal_uInt8 nWhitePalIdx(static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(Color(COL_WHITE))));
412 0 : const sal_uInt8 nBlackPalIdx(static_cast< sal_uInt8 >(pWriteAcc->GetBestPaletteIndex(Color(COL_BLACK))));
413 : long nSum1;
414 : long nSum2;
415 : long lGray;
416 :
417 : // initialize border with white pixels
418 0 : pWriteAcc->SetLineColor( Color( COL_WHITE) );
419 0 : pWriteAcc->DrawLine( Point(), Point( nWidth - 1L, 0L ) );
420 0 : pWriteAcc->DrawLine( Point( nWidth - 1L, 0L ), Point( nWidth - 1L, nHeight - 1L ) );
421 0 : pWriteAcc->DrawLine( Point( nWidth - 1L, nHeight - 1L ), Point( 0L, nHeight - 1L ) );
422 0 : pWriteAcc->DrawLine( Point( 0, nHeight - 1L ), Point() );
423 :
424 0 : for( long nY = 0L, nY1 = 1L, nY2 = 2; nY < nHeight2; nY++, nY1++, nY2++ )
425 : {
426 0 : for( long nX = 0L, nXDst = 1L, nXTmp; nX < nWidth2; nX++, nXDst++ )
427 : {
428 0 : nXTmp = nX;
429 :
430 0 : nSum1 = -( nSum2 = lGray = pReadAcc->GetPixelIndex( nY, nXTmp++ ) );
431 0 : nSum2 += ( (long) pReadAcc->GetPixelIndex( nY, nXTmp++ ) ) << 1;
432 0 : nSum1 += ( lGray = pReadAcc->GetPixelIndex( nY, nXTmp ) );
433 0 : nSum2 += lGray;
434 :
435 0 : nSum1 += ( (long) pReadAcc->GetPixelIndex( nY1, nXTmp ) ) << 1;
436 0 : nSum1 -= ( (long) pReadAcc->GetPixelIndex( nY1, nXTmp -= 2 ) ) << 1;
437 :
438 0 : nSum1 += ( lGray = -(long) pReadAcc->GetPixelIndex( nY2, nXTmp++ ) );
439 0 : nSum2 += lGray;
440 0 : nSum2 -= ( (long) pReadAcc->GetPixelIndex( nY2, nXTmp++ ) ) << 1;
441 0 : nSum1 += ( lGray = (long) pReadAcc->GetPixelIndex( nY2, nXTmp ) );
442 0 : nSum2 -= lGray;
443 :
444 0 : if( ( nSum1 * nSum1 + nSum2 * nSum2 ) < lThres2 )
445 0 : pWriteAcc->SetPixelIndex( nY1, nXDst, nWhitePalIdx );
446 : else
447 0 : pWriteAcc->SetPixelIndex( nY1, nXDst, nBlackPalIdx );
448 : }
449 : }
450 :
451 0 : bRet = true;
452 : }
453 :
454 0 : aWorkBmp.ReleaseAccess( pReadAcc );
455 0 : aDstBmp.ReleaseAccess( pWriteAcc );
456 :
457 0 : if( bRet )
458 0 : aRetBmp = aDstBmp;
459 0 : }
460 : }
461 :
462 0 : if( !aRetBmp )
463 0 : aRetBmp = rBmp;
464 : else
465 : {
466 0 : aRetBmp.SetPrefMapMode( rBmp.GetPrefMapMode() );
467 0 : aRetBmp.SetPrefSize( rBmp.GetPrefSize() );
468 : }
469 :
470 0 : return aRetBmp;
471 : };
472 :
473 0 : Polygon XOutBitmap::GetCountour( const Bitmap& rBmp, const sal_uIntPtr nFlags,
474 : const sal_uInt8 cEdgeDetectThreshold, const Rectangle* pWorkRectPixel )
475 : {
476 0 : Bitmap aWorkBmp;
477 0 : Polygon aRetPoly;
478 0 : Point aTmpPoint;
479 0 : Rectangle aWorkRect( aTmpPoint, rBmp.GetSizePixel() );
480 :
481 0 : if( pWorkRectPixel )
482 0 : aWorkRect.Intersection( *pWorkRectPixel );
483 :
484 0 : aWorkRect.Justify();
485 :
486 0 : if( ( aWorkRect.GetWidth() > 4 ) && ( aWorkRect.GetHeight() > 4 ) )
487 : {
488 : // if the flag is set, we need to detect edges
489 0 : if( nFlags & XOUTBMP_CONTOUR_EDGEDETECT )
490 0 : aWorkBmp = DetectEdges( rBmp, cEdgeDetectThreshold );
491 : else
492 0 : aWorkBmp = rBmp;
493 :
494 0 : BitmapReadAccess* pAcc = aWorkBmp.AcquireReadAccess();
495 :
496 0 : if( pAcc )
497 : {
498 0 : const Size& rPrefSize = aWorkBmp.GetPrefSize();
499 0 : const long nWidth = pAcc->Width();
500 0 : const long nHeight = pAcc->Height();
501 0 : const double fFactorX = (double) rPrefSize.Width() / nWidth;
502 0 : const double fFactorY = (double) rPrefSize.Height() / nHeight;
503 0 : const long nStartX1 = aWorkRect.Left() + 1L;
504 0 : const long nEndX1 = aWorkRect.Right();
505 0 : const long nStartX2 = nEndX1 - 1L;
506 0 : const long nStartY1 = aWorkRect.Top() + 1L;
507 0 : const long nEndY1 = aWorkRect.Bottom();
508 0 : const long nStartY2 = nEndY1 - 1L;
509 0 : Point* pPoints1 = NULL;
510 0 : Point* pPoints2 = NULL;
511 : long nX, nY;
512 0 : sal_uInt16 nPolyPos = 0;
513 0 : const BitmapColor aBlack = pAcc->GetBestMatchingColor( Color( COL_BLACK ) );
514 :
515 0 : if( nFlags & XOUTBMP_CONTOUR_VERT )
516 : {
517 0 : pPoints1 = new Point[ nWidth ];
518 0 : pPoints2 = new Point[ nWidth ];
519 :
520 0 : for( nX = nStartX1; nX < nEndX1; nX++ )
521 : {
522 0 : nY = nStartY1;
523 :
524 : // scan row from left to right
525 0 : while( nY < nEndY1 )
526 : {
527 0 : if( aBlack == pAcc->GetPixel( nY, nX ) )
528 : {
529 0 : pPoints1[ nPolyPos ] = Point( nX, nY );
530 0 : nY = nStartY2;
531 :
532 : // this loop always breaks eventually as there is at least one pixel
533 : while( true )
534 : {
535 0 : if( aBlack == pAcc->GetPixel( nY, nX ) )
536 : {
537 0 : pPoints2[ nPolyPos ] = Point( nX, nY );
538 0 : break;
539 : }
540 :
541 0 : nY--;
542 : }
543 :
544 0 : nPolyPos++;
545 0 : break;
546 : }
547 :
548 0 : nY++;
549 : }
550 : }
551 : }
552 : else
553 : {
554 0 : pPoints1 = new Point[ nHeight ];
555 0 : pPoints2 = new Point[ nHeight ];
556 :
557 0 : for ( nY = nStartY1; nY < nEndY1; nY++ )
558 : {
559 0 : nX = nStartX1;
560 :
561 : // scan row from left to right
562 0 : while( nX < nEndX1 )
563 : {
564 0 : if( aBlack == pAcc->GetPixel( nY, nX ) )
565 : {
566 0 : pPoints1[ nPolyPos ] = Point( nX, nY );
567 0 : nX = nStartX2;
568 :
569 : // this loop always breaks eventually as there is at least one pixel
570 : while( true )
571 : {
572 0 : if( aBlack == pAcc->GetPixel( nY, nX ) )
573 : {
574 0 : pPoints2[ nPolyPos ] = Point( nX, nY );
575 0 : break;
576 : }
577 :
578 0 : nX--;
579 : }
580 :
581 0 : nPolyPos++;
582 0 : break;
583 : }
584 :
585 0 : nX++;
586 : }
587 : }
588 : }
589 :
590 0 : const sal_uInt16 nNewSize1 = nPolyPos << 1;
591 :
592 0 : aRetPoly = Polygon( nPolyPos, pPoints1 );
593 0 : aRetPoly.SetSize( nNewSize1 + 1 );
594 0 : aRetPoly[ nNewSize1 ] = aRetPoly[ 0 ];
595 :
596 0 : for( sal_uInt16 j = nPolyPos; nPolyPos < nNewSize1; )
597 0 : aRetPoly[ nPolyPos++ ] = pPoints2[ --j ];
598 :
599 0 : if( ( fFactorX != 0. ) && ( fFactorY != 0. ) )
600 0 : aRetPoly.Scale( fFactorX, fFactorY );
601 :
602 0 : delete[] pPoints1;
603 0 : delete[] pPoints2;
604 : }
605 : }
606 :
607 0 : return aRetPoly;
608 : };
609 :
610 0 : bool DitherBitmap( Bitmap& rBitmap )
611 : {
612 0 : bool bRet = false;
613 :
614 0 : if( ( rBitmap.GetBitCount() >= 8 ) && ( Application::GetDefaultDevice()->GetColorCount() < 257 ) )
615 0 : bRet = rBitmap.Dither( BMP_DITHER_FLOYD );
616 : else
617 0 : bRet = false;
618 :
619 0 : return bRet;
620 : }
621 :
622 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|