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 <rtl/crc.h>
21 : #include <tools/stream.hxx>
22 : #include <tools/vcompat.hxx>
23 : #include <tools/fract.hxx>
24 : #include <vcl/metaact.hxx>
25 : #include <vcl/salbtype.hxx>
26 : #include <vcl/outdev.hxx>
27 : #include <vcl/window.hxx>
28 : #include <vcl/virdev.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <vcl/gdimtf.hxx>
31 : #include <vcl/graphictools.hxx>
32 : #include <basegfx/polygon/b2dpolygon.hxx>
33 : #include <vcl/canvastools.hxx>
34 :
35 : #include <cvtsvm.hxx>
36 : #include <salbmp.hxx>
37 : #include <salinst.hxx>
38 : #include <svdata.hxx>
39 :
40 : #include <com/sun/star/beans/XFastPropertySet.hpp>
41 : #include <com/sun/star/rendering/MtfRenderer.hpp>
42 : #include <com/sun/star/rendering/XBitmapCanvas.hpp>
43 : #include <com/sun/star/rendering/XCanvas.hpp>
44 : #include <comphelper/processfactory.hxx>
45 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 : #include <com/sun/star/lang/XInitialization.hpp>
47 : #include <com/sun/star/awt/XGraphics.hpp>
48 : #include <com/sun/star/graphic/XGraphic.hpp>
49 : #include <com/sun/star/graphic/XGraphicRenderer.hpp>
50 :
51 : using namespace com::sun::star;
52 :
53 : #define GAMMA( _def_cVal, _def_InvGamma ) ((sal_uInt8)MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0L,255L))
54 :
55 : struct ImplColAdjustParam
56 : {
57 : sal_uInt8* pMapR;
58 : sal_uInt8* pMapG;
59 : sal_uInt8* pMapB;
60 : };
61 :
62 : struct ImplBmpAdjustParam
63 : {
64 : short nLuminancePercent;
65 : short nContrastPercent;
66 : short nChannelRPercent;
67 : short nChannelGPercent;
68 : short nChannelBPercent;
69 : double fGamma;
70 : bool bInvert;
71 : };
72 :
73 : struct ImplColConvertParam
74 : {
75 : MtfConversion eConversion;
76 : };
77 :
78 : struct ImplBmpConvertParam
79 : {
80 : BmpConversion eConversion;
81 : };
82 :
83 41 : struct ImplColMonoParam
84 : {
85 : Color aColor;
86 : };
87 :
88 41 : struct ImplBmpMonoParam
89 : {
90 : Color aColor;
91 : };
92 :
93 : struct ImplColReplaceParam
94 : {
95 : sal_uLong* pMinR;
96 : sal_uLong* pMaxR;
97 : sal_uLong* pMinG;
98 : sal_uLong* pMaxG;
99 : sal_uLong* pMinB;
100 : sal_uLong* pMaxB;
101 : const Color* pDstCols;
102 : sal_uLong nCount;
103 : };
104 :
105 : struct ImplBmpReplaceParam
106 : {
107 : const Color* pSrcCols;
108 : const Color* pDstCols;
109 : sal_uLong nCount;
110 : const sal_uLong* pTols;
111 : };
112 :
113 346240 : GDIMetaFile::GDIMetaFile() :
114 : nCurrentActionElement( 0 ),
115 : aPrefSize ( 1, 1 ),
116 : pPrev ( NULL ),
117 : pNext ( NULL ),
118 : pOutDev ( NULL ),
119 : bPause ( false ),
120 : bRecord ( false ),
121 346240 : bUseCanvas ( false )
122 : {
123 346240 : }
124 :
125 21589 : GDIMetaFile::GDIMetaFile( const GDIMetaFile& rMtf ) :
126 : nCurrentActionElement( rMtf.nCurrentActionElement ),
127 : aPrefMapMode ( rMtf.aPrefMapMode ),
128 : aPrefSize ( rMtf.aPrefSize ),
129 : aHookHdlLink ( rMtf.aHookHdlLink ),
130 : pPrev ( rMtf.pPrev ),
131 : pNext ( rMtf.pNext ),
132 : pOutDev ( NULL ),
133 : bPause ( false ),
134 : bRecord ( false ),
135 21589 : bUseCanvas ( rMtf.bUseCanvas )
136 : {
137 : // Increment RefCount of MetaActions
138 620420 : for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
139 : {
140 598831 : rMtf.GetAction( i )->Duplicate();
141 598831 : aList.push_back( rMtf.GetAction( i ) );
142 : }
143 :
144 21589 : if( rMtf.bRecord )
145 : {
146 0 : Record( rMtf.pOutDev );
147 :
148 0 : if ( rMtf.bPause )
149 0 : Pause( true );
150 : }
151 21589 : }
152 :
153 740664 : GDIMetaFile::~GDIMetaFile()
154 : {
155 367653 : Clear();
156 373011 : }
157 :
158 39121 : size_t GDIMetaFile::GetActionSize() const
159 : {
160 39121 : return aList.size();
161 : }
162 :
163 2119477 : MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
164 : {
165 2119477 : return (nAction < aList.size()) ? aList[ nAction ] : NULL;
166 : }
167 :
168 5622 : MetaAction* GDIMetaFile::FirstAction()
169 : {
170 5622 : nCurrentActionElement = 0;
171 5622 : return aList.empty() ? NULL : aList[ 0 ];
172 : }
173 :
174 820447 : MetaAction* GDIMetaFile::NextAction()
175 : {
176 820447 : return ( nCurrentActionElement + 1 < aList.size() ) ? aList[ ++nCurrentActionElement ] : NULL;
177 : }
178 :
179 0 : MetaAction* GDIMetaFile::ReplaceAction( MetaAction* pAction, size_t nAction )
180 : {
181 0 : if ( nAction >= aList.size() )
182 : {
183 : // this method takes ownership of pAction and is
184 : // therefore responsible for deleting it
185 0 : pAction->Delete();
186 0 : return NULL;
187 : }
188 : //fdo#39995 This does't increment the incoming action ref-count nor does it
189 : //decrement the outgoing action ref-count
190 0 : std::swap(pAction, aList[nAction]);
191 0 : return pAction;
192 : }
193 :
194 5211 : GDIMetaFile& GDIMetaFile::operator=( const GDIMetaFile& rMtf )
195 : {
196 5211 : if( this != &rMtf )
197 : {
198 5211 : Clear();
199 :
200 : // Increment RefCount of MetaActions
201 333410 : for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
202 : {
203 328199 : rMtf.GetAction( i )->Duplicate();
204 328199 : aList.push_back( rMtf.GetAction( i ) );
205 : }
206 :
207 5211 : aPrefMapMode = rMtf.aPrefMapMode;
208 5211 : aPrefSize = rMtf.aPrefSize;
209 5211 : aHookHdlLink = rMtf.aHookHdlLink;
210 5211 : pPrev = rMtf.pPrev;
211 5211 : pNext = rMtf.pNext;
212 5211 : pOutDev = NULL;
213 5211 : bPause = false;
214 5211 : bRecord = false;
215 5211 : bUseCanvas = rMtf.bUseCanvas;
216 :
217 5211 : if( rMtf.bRecord )
218 : {
219 0 : Record( rMtf.pOutDev );
220 :
221 0 : if( rMtf.bPause )
222 0 : Pause( true );
223 : }
224 : }
225 :
226 5211 : return *this;
227 : }
228 :
229 112 : bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
230 : {
231 112 : const size_t nObjCount = aList.size();
232 112 : bool bRet = false;
233 :
234 112 : if( this == &rMtf )
235 0 : bRet = true;
236 336 : else if( rMtf.GetActionSize() == nObjCount &&
237 224 : rMtf.GetPrefSize() == aPrefSize &&
238 112 : rMtf.GetPrefMapMode() == aPrefMapMode )
239 : {
240 112 : bRet = true;
241 :
242 6717 : for( size_t n = 0; n < nObjCount; n++ )
243 : {
244 6605 : if( aList[ n ] != rMtf.GetAction( n ) )
245 : {
246 0 : bRet = false;
247 0 : break;
248 : }
249 : }
250 : }
251 :
252 112 : return bRet;
253 : }
254 :
255 725403 : void GDIMetaFile::Clear()
256 : {
257 725403 : if( bRecord )
258 0 : Stop();
259 :
260 2780966 : for( size_t i = 0, n = aList.size(); i < n; ++i )
261 2055563 : aList[ i ]->Delete();
262 725403 : aList.clear();
263 725403 : }
264 :
265 20844 : void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
266 : {
267 20844 : if( bLink )
268 : {
269 10422 : pNext = NULL;
270 10422 : pPrev = pOut->GetConnectMetaFile();
271 10422 : pOut->SetConnectMetaFile( this );
272 :
273 10422 : if( pPrev )
274 0 : pPrev->pNext = this;
275 : }
276 : else
277 : {
278 10422 : if( pNext )
279 : {
280 0 : pNext->pPrev = pPrev;
281 :
282 0 : if( pPrev )
283 0 : pPrev->pNext = pNext;
284 : }
285 : else
286 : {
287 10422 : if( pPrev )
288 0 : pPrev->pNext = NULL;
289 :
290 10422 : pOut->SetConnectMetaFile( pPrev );
291 : }
292 :
293 10422 : pPrev = NULL;
294 10422 : pNext = NULL;
295 : }
296 20844 : }
297 :
298 442049 : long GDIMetaFile::Hook()
299 : {
300 442049 : return aHookHdlLink.Call( this );
301 : }
302 :
303 10422 : void GDIMetaFile::Record( OutputDevice* pOut )
304 : {
305 10422 : if( bRecord )
306 0 : Stop();
307 :
308 10422 : nCurrentActionElement = aList.empty() ? 0 : (aList.size() - 1);
309 10422 : pOutDev = pOut;
310 10422 : bRecord = true;
311 10422 : Linker( pOut, true );
312 10422 : }
313 :
314 8 : void GDIMetaFile::Play( GDIMetaFile& rMtf, size_t nPos )
315 : {
316 8 : if ( !bRecord && !rMtf.bRecord )
317 : {
318 8 : MetaAction* pAction = GetCurAction();
319 8 : const size_t nObjCount = aList.size();
320 :
321 8 : rMtf.UseCanvas( rMtf.GetUseCanvas() || bUseCanvas );
322 :
323 8 : if( nPos > nObjCount )
324 8 : nPos = nObjCount;
325 :
326 199 : for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
327 : {
328 191 : if( !Hook() && pAction )
329 : {
330 191 : pAction->Duplicate();
331 191 : rMtf.AddAction( pAction );
332 : }
333 :
334 191 : pAction = NextAction();
335 : }
336 : }
337 8 : }
338 :
339 13021 : void GDIMetaFile::Play( OutputDevice* pOut, size_t nPos )
340 : {
341 13021 : if( !bRecord )
342 : {
343 13021 : MetaAction* pAction = GetCurAction();
344 13021 : const size_t nObjCount = aList.size();
345 13021 : size_t nSyncCount = ( pOut->GetOutDevType() == OUTDEV_WINDOW ) ? 0x000000ff : 0xffffffff;
346 :
347 13021 : if( nPos > nObjCount )
348 13021 : nPos = nObjCount;
349 :
350 : // #i23407# Set backwards-compatible text language and layout mode
351 : // This is necessary, since old metafiles don't even know of these
352 : // recent add-ons. Newer metafiles must of course explicitly set
353 : // those states.
354 13021 : pOut->Push( PushFlags::TEXTLAYOUTMODE|PushFlags::TEXTLANGUAGE );
355 13021 : pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
356 13021 : pOut->SetDigitLanguage( 0 );
357 :
358 : OSL_TRACE("GDIMetaFile::Play on device of size: %ld x %ld", pOut->GetOutputSizePixel().Width(), pOut->GetOutputSizePixel().Height());
359 :
360 13021 : if( !ImplPlayWithRenderer( pOut, Point(0,0), pOut->GetOutputSize() ) ) {
361 13021 : size_t i = 0;
362 454879 : for( size_t nCurPos = nCurrentActionElement; nCurPos < nPos; nCurPos++ )
363 : {
364 441858 : if( !Hook() && pAction )
365 : {
366 444340 : if( pAction->GetType() == MetaActionType::COMMENT &&
367 2482 : static_cast<MetaCommentAction*>(pAction)->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" )
368 : {
369 0 : ImplDelegate2PluggableRenderer(static_cast<MetaCommentAction*>(pAction), pOut);
370 : }
371 : else
372 : {
373 441858 : pAction->Execute( pOut );
374 : }
375 :
376 : // flush output from time to time
377 441858 : if( i++ > nSyncCount )
378 : {
379 0 : static_cast<vcl::Window*>( pOut )->Flush();
380 0 : i = 0;
381 : }
382 : }
383 :
384 441858 : pAction = NextAction();
385 : }
386 : }
387 13021 : pOut->Pop();
388 : }
389 13021 : }
390 :
391 13261 : bool GDIMetaFile::ImplPlayWithRenderer( OutputDevice* pOut, const Point& rPos, Size rLogicDestSize )
392 : {
393 13261 : if (!bUseCanvas)
394 13175 : return false;
395 :
396 86 : Size rDestSize( pOut->LogicToPixel( rLogicDestSize ) );
397 :
398 86 : const vcl::Window* win = dynamic_cast <vcl::Window*> ( pOut );
399 :
400 86 : if (!win)
401 86 : win = Application::GetActiveTopWindow();
402 86 : if (!win)
403 82 : win = Application::GetFirstTopLevelWindow();
404 :
405 86 : if (!win)
406 0 : return false;
407 :
408 : try
409 : {
410 86 : uno::Reference<rendering::XCanvas> xCanvas = win->GetCanvas ();
411 :
412 86 : if (!xCanvas.is())
413 84 : return false;
414 :
415 2 : Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
416 2 : uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
417 2 : if( xBitmap.is () )
418 : {
419 2 : uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
420 2 : if( xBitmapCanvas.is() )
421 : {
422 2 : uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
423 2 : uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
424 :
425 2 : xBitmapCanvas->clear();
426 2 : uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
427 2 : if( xMtfFastPropertySet.is() )
428 : // set this metafile to the renderer to
429 : // speedup things (instead of copying data to
430 : // sequence of bytes passed to renderer)
431 2 : xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
432 :
433 2 : xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
434 :
435 2 : BitmapEx aBitmapEx;
436 2 : if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
437 : {
438 2 : if ( pOut->GetMapMode() == MAP_PIXEL )
439 0 : pOut->DrawBitmapEx( rPos, aBitmapEx );
440 : else
441 2 : pOut->DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
442 2 : return true;
443 0 : }
444 0 : }
445 0 : }
446 : }
447 0 : catch (const uno::RuntimeException& )
448 : {
449 0 : throw; // runtime errors are fatal
450 : }
451 0 : catch (const uno::Exception& e)
452 : {
453 : // ignore errors, no way of reporting them here
454 : SAL_WARN("vcl",
455 : "GDIMetaFile::ImplPlayWithRenderer: exception: " << e.Message);
456 : }
457 :
458 0 : return false;
459 : }
460 :
461 0 : void GDIMetaFile::ImplDelegate2PluggableRenderer( const MetaCommentAction* pAct, OutputDevice* pOut )
462 : {
463 : OSL_ASSERT( pAct->GetComment() == "DELEGATE_PLUGGABLE_RENDERER" );
464 :
465 : // read payload - string of service name, followed by raw render input
466 0 : const sal_uInt8* pData = pAct->GetData();
467 0 : const sal_uInt8* const pEndData = pData + pAct->GetDataSize();
468 0 : if( !pData )
469 0 : return;
470 :
471 0 : OUStringBuffer aBuffer;
472 0 : while( pData<pEndData && *pData )
473 0 : aBuffer.append(static_cast<sal_Unicode>(*pData++));
474 0 : const OUString aRendererServiceName=aBuffer.makeStringAndClear();
475 0 : ++pData;
476 :
477 0 : while( pData<pEndData && *pData )
478 0 : aBuffer.append(static_cast<sal_Unicode>(*pData++));
479 0 : const OUString aGraphicServiceName=aBuffer.makeStringAndClear();
480 0 : ++pData;
481 :
482 0 : uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
483 0 : if( pData<pEndData )
484 : {
485 : try
486 : {
487 : // instantiate render service
488 0 : uno::Sequence<uno::Any> aRendererArgs(1);
489 0 : aRendererArgs[0] = makeAny(uno::Reference<awt::XGraphics>(pOut->CreateUnoGraphics()));
490 : uno::Reference<graphic::XGraphicRenderer> xRenderer(
491 0 : xFactory->createInstanceWithArguments(
492 : aRendererServiceName,
493 0 : aRendererArgs),
494 0 : uno::UNO_QUERY );
495 :
496 : // instantiate graphic service
497 : uno::Reference<graphic::XGraphic> xGraphic(
498 0 : xFactory->createInstance(
499 0 : aGraphicServiceName),
500 0 : uno::UNO_QUERY );
501 :
502 : uno::Reference<lang::XInitialization> xInit(
503 0 : xGraphic, uno::UNO_QUERY);
504 :
505 0 : if(xGraphic.is() && xRenderer.is() && xInit.is())
506 : {
507 : // delay intialization of XGraphic, to only expose
508 : // XGraphic-generating services to arbitrary binary data
509 : uno::Sequence< sal_Int8 > aSeq(
510 0 : reinterpret_cast<sal_Int8 const *>(pData), pEndData-pData );
511 0 : uno::Sequence<uno::Any> aGraphicsArgs(1);
512 0 : aGraphicsArgs[0] = makeAny(aSeq);
513 0 : xInit->initialize(aGraphicsArgs);
514 :
515 0 : xRenderer->render(xGraphic);
516 0 : }
517 : }
518 0 : catch (const uno::RuntimeException&)
519 : {
520 : // runtime errors are fatal
521 0 : throw;
522 : }
523 0 : catch (const uno::Exception& e)
524 : {
525 : // ignore errors, no way of reporting them here
526 : SAL_WARN("vcl", "GDIMetaFile::ImplDelegate2PluggableRenderer:"
527 : " exception: " << e.Message);
528 : }
529 0 : }
530 : }
531 :
532 280 : void GDIMetaFile::Play( OutputDevice* pOut, const Point& rPos,
533 : const Size& rSize, size_t nPos )
534 : {
535 280 : vcl::Region aDrawClipRegion;
536 558 : MapMode aDrawMap( GetPrefMapMode() );
537 280 : Size aDestSize( pOut->LogicToPixel( rSize ) );
538 :
539 280 : if( aDestSize.Width() && aDestSize.Height() )
540 : {
541 240 : GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
542 :
543 240 : if( ImplPlayWithRenderer( pOut, rPos, rSize ) )
544 282 : return;
545 :
546 238 : Size aTmpPrefSize( pOut->LogicToPixel( GetPrefSize(), aDrawMap ) );
547 :
548 238 : if( !aTmpPrefSize.Width() )
549 0 : aTmpPrefSize.Width() = aDestSize.Width();
550 :
551 238 : if( !aTmpPrefSize.Height() )
552 0 : aTmpPrefSize.Height() = aDestSize.Height();
553 :
554 238 : Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
555 476 : Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
556 :
557 238 : aScaleX *= aDrawMap.GetScaleX(); aDrawMap.SetScaleX( aScaleX );
558 238 : aScaleY *= aDrawMap.GetScaleY(); aDrawMap.SetScaleY( aScaleY );
559 :
560 : // #i47260# Convert logical output position to offset within
561 : // the metafile's mapmode. Therefore, disable pixel offset on
562 : // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
563 : // different mapmode (the one currently set on pOut, that is)
564 : // - thus, aDrawMap's origin would generally be wrong. And
565 : // even _if_ aDrawMap is similar to pOutDev's current mapmode,
566 : // it's _still_ undesirable to have pixel offset unequal zero,
567 : // because one would still get round-off errors (the
568 : // round-trip error for LogicToPixel( PixelToLogic() ) was the
569 : // reason for having pixel offset in the first place).
570 238 : const Size& rOldOffset( pOut->GetPixelOffset() );
571 238 : const Size aEmptySize;
572 238 : pOut->SetPixelOffset( aEmptySize );
573 238 : aDrawMap.SetOrigin( pOut->PixelToLogic( pOut->LogicToPixel( rPos ), aDrawMap ) );
574 238 : pOut->SetPixelOffset( rOldOffset );
575 :
576 238 : pOut->Push();
577 :
578 238 : if ( pMtf && pMtf->IsRecord() && ( pOut->GetOutDevType() != OUTDEV_PRINTER ) )
579 48 : pOut->SetRelativeMapMode( aDrawMap );
580 : else
581 190 : pOut->SetMapMode( aDrawMap );
582 :
583 : // #i23407# Set backwards-compatible text language and layout mode
584 : // This is necessary, since old metafiles don't even know of these
585 : // recent add-ons. Newer metafiles must of course explicitly set
586 : // those states.
587 238 : pOut->SetLayoutMode( TEXT_LAYOUT_DEFAULT );
588 238 : pOut->SetDigitLanguage( 0 );
589 :
590 238 : Play( pOut, nPos );
591 :
592 476 : pOut->Pop();
593 278 : }
594 : }
595 :
596 0 : void GDIMetaFile::Pause( bool _bPause )
597 : {
598 0 : if( bRecord )
599 : {
600 0 : if( _bPause )
601 : {
602 0 : if( !bPause )
603 0 : Linker( pOutDev, false );
604 : }
605 : else
606 : {
607 0 : if( bPause )
608 0 : Linker( pOutDev, true );
609 : }
610 :
611 0 : bPause = _bPause;
612 : }
613 0 : }
614 :
615 10426 : void GDIMetaFile::Stop()
616 : {
617 10426 : if( bRecord )
618 : {
619 10422 : bRecord = false;
620 :
621 10422 : if( !bPause )
622 10422 : Linker( pOutDev, false );
623 : else
624 0 : bPause = false;
625 : }
626 10426 : }
627 :
628 13555 : void GDIMetaFile::WindStart()
629 : {
630 13555 : if( !bRecord )
631 13555 : nCurrentActionElement = 0;
632 13555 : }
633 :
634 0 : void GDIMetaFile::WindPrev()
635 : {
636 0 : if( !bRecord )
637 0 : if ( nCurrentActionElement > 0 )
638 0 : --nCurrentActionElement;
639 0 : }
640 :
641 1128445 : void GDIMetaFile::AddAction( MetaAction* pAction )
642 : {
643 1128445 : aList.push_back( pAction );
644 :
645 1128445 : if( pPrev )
646 : {
647 0 : pAction->Duplicate();
648 0 : pPrev->AddAction( pAction );
649 : }
650 1128445 : }
651 :
652 0 : void GDIMetaFile::AddAction( MetaAction* pAction, size_t nPos )
653 : {
654 0 : if ( nPos < aList.size() )
655 : {
656 0 : ::std::vector< MetaAction* >::iterator it = aList.begin();
657 0 : ::std::advance( it, nPos );
658 0 : aList.insert( it, pAction );
659 : }
660 : else
661 : {
662 0 : aList.push_back( pAction );
663 : }
664 :
665 0 : if( pPrev )
666 : {
667 0 : pAction->Duplicate();
668 0 : pPrev->AddAction( pAction, nPos );
669 : }
670 0 : }
671 :
672 88 : void GDIMetaFile::push_back( MetaAction* pAction )
673 : {
674 88 : aList.push_back( pAction );
675 88 : }
676 :
677 0 : void GDIMetaFile::RemoveAction( size_t nPos )
678 : {
679 0 : if ( nPos < aList.size() )
680 : {
681 0 : ::std::vector< MetaAction* >::iterator it = aList.begin();
682 0 : ::std::advance( it, nPos );
683 0 : (*it)->Delete();
684 0 : aList.erase( it );
685 :
686 : }
687 :
688 0 : if( pPrev )
689 0 : pPrev->RemoveAction( nPos );
690 0 : }
691 :
692 0 : bool GDIMetaFile::Mirror( BmpMirrorFlags nMirrorFlags )
693 : {
694 0 : const Size aOldPrefSize( GetPrefSize() );
695 : long nMoveX, nMoveY;
696 : double fScaleX, fScaleY;
697 : bool bRet;
698 :
699 0 : if( nMirrorFlags & BmpMirrorFlags::Horizontal )
700 0 : nMoveX = SAL_ABS( aOldPrefSize.Width() ) - 1, fScaleX = -1.0;
701 : else
702 0 : nMoveX = 0, fScaleX = 1.0;
703 :
704 0 : if( nMirrorFlags & BmpMirrorFlags::Vertical )
705 0 : nMoveY = SAL_ABS( aOldPrefSize.Height() ) - 1, fScaleY = -1.0;
706 : else
707 0 : nMoveY = 0, fScaleY = 1.0;
708 :
709 0 : if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
710 : {
711 0 : Scale( fScaleX, fScaleY );
712 0 : Move( nMoveX, nMoveY );
713 0 : SetPrefSize( aOldPrefSize );
714 0 : bRet = true;
715 : }
716 : else
717 0 : bRet = false;
718 :
719 0 : return bRet;
720 : }
721 :
722 265 : void GDIMetaFile::Move( long nX, long nY )
723 : {
724 265 : const Size aBaseOffset( nX, nY );
725 265 : Size aOffset( aBaseOffset );
726 265 : ScopedVclPtrInstance< VirtualDevice > aMapVDev;
727 :
728 265 : aMapVDev->EnableOutput( false );
729 265 : aMapVDev->SetMapMode( GetPrefMapMode() );
730 :
731 17439 : for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
732 : {
733 17174 : const MetaActionType nType = pAct->GetType();
734 : MetaAction* pModAct;
735 :
736 17174 : if( pAct->GetRefCount() > 1 )
737 : {
738 283 : aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
739 283 : pAct->Delete();
740 : }
741 : else
742 16891 : pModAct = pAct;
743 :
744 17174 : if( ( MetaActionType::MAPMODE == nType ) ||
745 16833 : ( MetaActionType::PUSH == nType ) ||
746 : ( MetaActionType::POP == nType ) )
747 : {
748 642 : pModAct->Execute( aMapVDev.get() );
749 642 : aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
750 : }
751 :
752 17174 : pModAct->Move( aOffset.Width(), aOffset.Height() );
753 265 : }
754 265 : }
755 :
756 0 : void GDIMetaFile::Move( long nX, long nY, long nDPIX, long nDPIY )
757 : {
758 0 : const Size aBaseOffset( nX, nY );
759 0 : Size aOffset( aBaseOffset );
760 0 : ScopedVclPtrInstance< VirtualDevice > aMapVDev;
761 :
762 0 : aMapVDev->EnableOutput( false );
763 0 : aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
764 0 : aMapVDev->SetMapMode( GetPrefMapMode() );
765 :
766 0 : for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
767 : {
768 0 : const MetaActionType nType = pAct->GetType();
769 : MetaAction* pModAct;
770 :
771 0 : if( pAct->GetRefCount() > 1 )
772 : {
773 0 : aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
774 0 : pAct->Delete();
775 : }
776 : else
777 0 : pModAct = pAct;
778 :
779 0 : if( ( MetaActionType::MAPMODE == nType ) ||
780 0 : ( MetaActionType::PUSH == nType ) ||
781 : ( MetaActionType::POP == nType ) )
782 : {
783 0 : pModAct->Execute( aMapVDev.get() );
784 0 : if( aMapVDev->GetMapMode().GetMapUnit() == MAP_PIXEL )
785 : {
786 0 : aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
787 0 : MapMode aMap( aMapVDev->GetMapMode() );
788 0 : aOffset.Width() = static_cast<long>(aOffset.Width() * (double)aMap.GetScaleX());
789 0 : aOffset.Height() = static_cast<long>(aOffset.Height() * (double)aMap.GetScaleY());
790 : }
791 : else
792 0 : aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
793 : }
794 :
795 0 : pModAct->Move( aOffset.Width(), aOffset.Height() );
796 0 : }
797 0 : }
798 :
799 27 : void GDIMetaFile::Scale( double fScaleX, double fScaleY )
800 : {
801 7340 : for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
802 : {
803 : MetaAction* pModAct;
804 :
805 7313 : if( pAct->GetRefCount() > 1 )
806 : {
807 7313 : aList[ nCurrentActionElement ] = pModAct = pAct->Clone();
808 7313 : pAct->Delete();
809 : }
810 : else
811 0 : pModAct = pAct;
812 :
813 7313 : pModAct->Scale( fScaleX, fScaleY );
814 : }
815 :
816 27 : aPrefSize.Width() = FRound( aPrefSize.Width() * fScaleX );
817 27 : aPrefSize.Height() = FRound( aPrefSize.Height() * fScaleY );
818 27 : }
819 :
820 27 : void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
821 : {
822 27 : Scale( (double) rScaleX, (double) rScaleY );
823 27 : }
824 :
825 0 : void GDIMetaFile::Clip( const Rectangle& i_rClipRect )
826 : {
827 0 : Rectangle aCurRect( i_rClipRect );
828 0 : ScopedVclPtrInstance< VirtualDevice > aMapVDev;
829 :
830 0 : aMapVDev->EnableOutput( false );
831 0 : aMapVDev->SetMapMode( GetPrefMapMode() );
832 :
833 0 : for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
834 : {
835 0 : const MetaActionType nType = pAct->GetType();
836 :
837 0 : if( ( MetaActionType::MAPMODE == nType ) ||
838 0 : ( MetaActionType::PUSH == nType ) ||
839 : ( MetaActionType::POP == nType ) )
840 : {
841 0 : pAct->Execute( aMapVDev.get() );
842 0 : aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
843 : }
844 0 : else if( nType == MetaActionType::CLIPREGION )
845 : {
846 0 : MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
847 0 : vcl::Region aNewReg( aCurRect );
848 0 : if( pOldAct->IsClipping() )
849 0 : aNewReg.Intersect( pOldAct->GetRegion() );
850 0 : MetaClipRegionAction* pNewAct = new MetaClipRegionAction( aNewReg, true );
851 0 : aList[ nCurrentActionElement ] = pNewAct;
852 0 : pOldAct->Delete();
853 : }
854 0 : }
855 0 : }
856 :
857 0 : Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
858 : const Size& rOffset, double fSin, double fCos )
859 : {
860 0 : const long nX = rPt.X() - rRotatePt.X();
861 0 : const long nY = rPt.Y() - rRotatePt.Y();
862 :
863 0 : return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
864 0 : -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
865 : }
866 :
867 0 : Polygon GDIMetaFile::ImplGetRotatedPolygon( const Polygon& rPoly, const Point& rRotatePt,
868 : const Size& rOffset, double fSin, double fCos )
869 : {
870 0 : Polygon aRet( rPoly );
871 :
872 0 : aRet.Rotate( rRotatePt, fSin, fCos );
873 0 : aRet.Move( rOffset.Width(), rOffset.Height() );
874 :
875 0 : return aRet;
876 : }
877 :
878 0 : tools::PolyPolygon GDIMetaFile::ImplGetRotatedPolyPolygon( const tools::PolyPolygon& rPolyPoly, const Point& rRotatePt,
879 : const Size& rOffset, double fSin, double fCos )
880 : {
881 0 : tools::PolyPolygon aRet( rPolyPoly );
882 :
883 0 : aRet.Rotate( rRotatePt, fSin, fCos );
884 0 : aRet.Move( rOffset.Width(), rOffset.Height() );
885 :
886 0 : return aRet;
887 : }
888 :
889 0 : void GDIMetaFile::ImplAddGradientEx( GDIMetaFile& rMtf,
890 : const OutputDevice& rMapDev,
891 : const tools::PolyPolygon& rPolyPoly,
892 : const Gradient& rGrad )
893 : {
894 : // Generate comment, GradientEx and Gradient actions (within DrawGradient)
895 0 : ScopedVclPtrInstance< VirtualDevice > aVDev( rMapDev, 0 );
896 0 : aVDev->EnableOutput( false );
897 0 : GDIMetaFile aGradMtf;
898 :
899 0 : aGradMtf.Record( aVDev.get() );
900 0 : aVDev->DrawGradient( rPolyPoly, rGrad );
901 0 : aGradMtf.Stop();
902 :
903 0 : size_t i, nAct( aGradMtf.GetActionSize() );
904 0 : for( i=0; i < nAct; ++i )
905 : {
906 0 : MetaAction* pMetaAct = aGradMtf.GetAction( i );
907 0 : pMetaAct->Duplicate();
908 0 : rMtf.AddAction( pMetaAct );
909 0 : }
910 0 : }
911 :
912 0 : void GDIMetaFile::Rotate( long nAngle10 )
913 : {
914 0 : nAngle10 %= 3600L;
915 0 : nAngle10 = ( nAngle10 < 0L ) ? ( 3599L + nAngle10 ) : nAngle10;
916 :
917 0 : if( nAngle10 )
918 : {
919 0 : GDIMetaFile aMtf;
920 0 : ScopedVclPtrInstance< VirtualDevice > aMapVDev;
921 0 : const double fAngle = F_PI1800 * nAngle10;
922 0 : const double fSin = sin( fAngle );
923 0 : const double fCos = cos( fAngle );
924 0 : Rectangle aRect=Rectangle( Point(), GetPrefSize() );
925 0 : Polygon aPoly( aRect );
926 :
927 0 : aPoly.Rotate( Point(), fSin, fCos );
928 :
929 0 : aMapVDev->EnableOutput( false );
930 0 : aMapVDev->SetMapMode( GetPrefMapMode() );
931 :
932 0 : const Rectangle aNewBound( aPoly.GetBoundRect() );
933 :
934 0 : const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
935 0 : const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
936 :
937 0 : Point aRotAnchor( aOrigin );
938 0 : Size aRotOffset( aOffset );
939 :
940 0 : for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
941 : {
942 0 : const MetaActionType nActionType = pAction->GetType();
943 :
944 0 : switch( nActionType )
945 : {
946 : case( MetaActionType::PIXEL ):
947 : {
948 0 : MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
949 0 : aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
950 0 : pAct->GetColor() ) );
951 : }
952 0 : break;
953 :
954 : case( MetaActionType::POINT ):
955 : {
956 0 : MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
957 0 : aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
958 : }
959 0 : break;
960 :
961 : case( MetaActionType::LINE ):
962 : {
963 0 : MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
964 0 : aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
965 0 : ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
966 0 : pAct->GetLineInfo() ) );
967 : }
968 0 : break;
969 :
970 : case( MetaActionType::RECT ):
971 : {
972 0 : MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
973 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
974 : }
975 0 : break;
976 :
977 : case( MetaActionType::ROUNDRECT ):
978 : {
979 0 : MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
980 0 : const Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
981 :
982 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
983 : }
984 0 : break;
985 :
986 : case( MetaActionType::ELLIPSE ):
987 : {
988 0 : MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
989 0 : const Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
990 :
991 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
992 : }
993 0 : break;
994 :
995 : case( MetaActionType::ARC ):
996 : {
997 0 : MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
998 0 : const Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_ARC );
999 :
1000 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1001 : }
1002 0 : break;
1003 :
1004 : case( MetaActionType::PIE ):
1005 : {
1006 0 : MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1007 0 : const Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_PIE );
1008 :
1009 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1010 : }
1011 0 : break;
1012 :
1013 : case( MetaActionType::CHORD ):
1014 : {
1015 0 : MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1016 0 : const Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), POLY_CHORD );
1017 :
1018 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
1019 : }
1020 0 : break;
1021 :
1022 : case( MetaActionType::POLYLINE ):
1023 : {
1024 0 : MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1025 0 : aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
1026 : }
1027 0 : break;
1028 :
1029 : case( MetaActionType::POLYGON ):
1030 : {
1031 0 : MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1032 0 : aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1033 : }
1034 0 : break;
1035 :
1036 : case( MetaActionType::POLYPOLYGON ):
1037 : {
1038 0 : MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1039 0 : aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
1040 : }
1041 0 : break;
1042 :
1043 : case( MetaActionType::TEXT ):
1044 : {
1045 0 : MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1046 0 : aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1047 0 : pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1048 : }
1049 0 : break;
1050 :
1051 : case( MetaActionType::TEXTARRAY ):
1052 : {
1053 0 : MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1054 0 : aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1055 0 : pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
1056 : }
1057 0 : break;
1058 :
1059 : case( MetaActionType::STRETCHTEXT ):
1060 : {
1061 0 : MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1062 0 : aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1063 0 : pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
1064 : }
1065 0 : break;
1066 :
1067 : case( MetaActionType::TEXTLINE ):
1068 : {
1069 0 : MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1070 0 : aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
1071 0 : pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
1072 : }
1073 0 : break;
1074 :
1075 : case( MetaActionType::BMPSCALE ):
1076 : {
1077 0 : MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1078 0 : Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1079 0 : Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1080 0 : BitmapEx aBmpEx( pAct->GetBitmap() );
1081 :
1082 0 : aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1083 : aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1084 0 : aBmpEx ) );
1085 : }
1086 0 : break;
1087 :
1088 : case( MetaActionType::BMPSCALEPART ):
1089 : {
1090 0 : MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1091 0 : Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1092 0 : Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1093 0 : BitmapEx aBmpEx( pAct->GetBitmap() );
1094 :
1095 0 : aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1096 0 : aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1097 :
1098 0 : aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1099 : }
1100 0 : break;
1101 :
1102 : case( MetaActionType::BMPEXSCALE ):
1103 : {
1104 0 : MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1105 0 : Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1106 0 : Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1107 0 : BitmapEx aBmpEx( pAct->GetBitmapEx() );
1108 :
1109 0 : aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1110 :
1111 0 : aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1112 : }
1113 0 : break;
1114 :
1115 : case( MetaActionType::BMPEXSCALEPART ):
1116 : {
1117 0 : MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1118 0 : Polygon aBmpPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1119 0 : Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1120 0 : BitmapEx aBmpEx( pAct->GetBitmapEx() );
1121 :
1122 0 : aBmpEx.Crop( Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1123 0 : aBmpEx.Rotate( nAngle10, Color( COL_TRANSPARENT ) );
1124 :
1125 0 : aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1126 : }
1127 0 : break;
1128 :
1129 : case( MetaActionType::GRADIENT ):
1130 : {
1131 0 : MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1132 :
1133 0 : ImplAddGradientEx( aMtf, *aMapVDev.get(),
1134 0 : ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1135 0 : pAct->GetGradient() );
1136 : }
1137 0 : break;
1138 :
1139 : case( MetaActionType::GRADIENTEX ):
1140 : {
1141 0 : MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1142 0 : aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1143 0 : pAct->GetGradient() ) );
1144 : }
1145 0 : break;
1146 :
1147 : // Handle gradientex comment block correctly
1148 : case( MetaActionType::COMMENT ):
1149 : {
1150 0 : MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1151 0 : if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1152 : {
1153 0 : int nBeginComments( 1 );
1154 0 : pAction = NextAction();
1155 :
1156 : // skip everything, except gradientex action
1157 0 : while( pAction )
1158 : {
1159 0 : const MetaActionType nType = pAction->GetType();
1160 :
1161 0 : if( MetaActionType::GRADIENTEX == nType )
1162 : {
1163 : // Add rotated gradientex
1164 0 : MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1165 0 : ImplAddGradientEx( aMtf, *aMapVDev.get(),
1166 0 : ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1167 0 : pAct->GetGradient() );
1168 : }
1169 0 : else if( MetaActionType::COMMENT == nType)
1170 : {
1171 0 : MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1172 0 : if( pAct->GetComment() == "XGRAD_SEQ_END" )
1173 : {
1174 : // handle nested blocks
1175 0 : --nBeginComments;
1176 :
1177 : // gradientex comment block: end reached, done.
1178 0 : if( !nBeginComments )
1179 0 : break;
1180 : }
1181 0 : else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1182 : {
1183 : // handle nested blocks
1184 0 : ++nBeginComments;
1185 : }
1186 :
1187 : }
1188 :
1189 0 : pAction =NextAction();
1190 : }
1191 : }
1192 : else
1193 : {
1194 0 : bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1195 0 : if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1196 : {
1197 0 : if ( pCommentAct->GetDataSize() )
1198 : {
1199 0 : SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
1200 0 : SvMemoryStream aDest;
1201 0 : if ( bPathStroke )
1202 : {
1203 0 : SvtGraphicStroke aStroke;
1204 0 : ReadSvtGraphicStroke( aMemStm, aStroke );
1205 0 : Polygon aPath;
1206 0 : aStroke.getPath( aPath );
1207 0 : aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1208 0 : WriteSvtGraphicStroke( aDest, aStroke );
1209 : aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1210 0 : static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1211 : }
1212 : else
1213 : {
1214 0 : SvtGraphicFill aFill;
1215 0 : ReadSvtGraphicFill( aMemStm, aFill );
1216 0 : tools::PolyPolygon aPath;
1217 0 : aFill.getPath( aPath );
1218 0 : aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1219 0 : WriteSvtGraphicFill( aDest, aFill );
1220 : aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1221 0 : static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1222 0 : }
1223 : }
1224 : }
1225 0 : else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1226 0 : || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1227 : {
1228 0 : pAction->Execute( aMapVDev.get() );
1229 0 : pAction->Duplicate();
1230 0 : aMtf.AddAction( pAction );
1231 : }
1232 : }
1233 : }
1234 0 : break;
1235 :
1236 : case( MetaActionType::HATCH ):
1237 : {
1238 0 : MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1239 0 : Hatch aHatch( pAct->GetHatch() );
1240 :
1241 0 : aHatch.SetAngle( aHatch.GetAngle() + (sal_uInt16) nAngle10 );
1242 0 : aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1243 0 : aHatch ) );
1244 : }
1245 0 : break;
1246 :
1247 : case( MetaActionType::Transparent ):
1248 : {
1249 0 : MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1250 0 : aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1251 0 : pAct->GetTransparence() ) );
1252 : }
1253 0 : break;
1254 :
1255 : case( MetaActionType::FLOATTRANSPARENT ):
1256 : {
1257 0 : MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1258 0 : GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1259 0 : Polygon aMtfPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1260 0 : Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1261 :
1262 0 : aTransMtf.Rotate( nAngle10 );
1263 : aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1264 0 : pAct->GetGradient() ) );
1265 : }
1266 0 : break;
1267 :
1268 : case( MetaActionType::EPS ):
1269 : {
1270 0 : MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1271 0 : GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1272 0 : Polygon aEPSPoly( ImplGetRotatedPolygon( Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1273 0 : Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1274 :
1275 0 : aEPSMtf.Rotate( nAngle10 );
1276 : aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1277 0 : pAct->GetLink(), aEPSMtf ) );
1278 : }
1279 0 : break;
1280 :
1281 : case( MetaActionType::CLIPREGION ):
1282 : {
1283 0 : MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1284 :
1285 0 : if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1286 0 : aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1287 : else
1288 : {
1289 0 : pAction->Duplicate();
1290 0 : aMtf.AddAction( pAction );
1291 : }
1292 : }
1293 0 : break;
1294 :
1295 : case( MetaActionType::ISECTRECTCLIPREGION ):
1296 : {
1297 0 : MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1298 : aMtf.AddAction( new MetaISectRegionClipRegionAction(vcl::Region(
1299 0 : ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1300 0 : aRotOffset, fSin, fCos )) ) );
1301 : }
1302 0 : break;
1303 :
1304 : case( MetaActionType::ISECTREGIONCLIPREGION ):
1305 : {
1306 0 : MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1307 0 : const vcl::Region& rRegion = pAct->GetRegion();
1308 :
1309 0 : if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1310 0 : aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1311 : else
1312 : {
1313 0 : pAction->Duplicate();
1314 0 : aMtf.AddAction( pAction );
1315 : }
1316 : }
1317 0 : break;
1318 :
1319 : case( MetaActionType::REFPOINT ):
1320 : {
1321 0 : MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1322 0 : aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1323 : }
1324 0 : break;
1325 :
1326 : case( MetaActionType::FONT ):
1327 : {
1328 0 : MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1329 0 : vcl::Font aFont( pAct->GetFont() );
1330 :
1331 0 : aFont.SetOrientation( aFont.GetOrientation() + (sal_uInt16) nAngle10 );
1332 0 : aMtf.AddAction( new MetaFontAction( aFont ) );
1333 : }
1334 0 : break;
1335 :
1336 : case( MetaActionType::BMP ):
1337 : case( MetaActionType::BMPEX ):
1338 : case( MetaActionType::MASK ):
1339 : case( MetaActionType::MASKSCALE ):
1340 : case( MetaActionType::MASKSCALEPART ):
1341 : case( MetaActionType::WALLPAPER ):
1342 : case( MetaActionType::TEXTRECT ):
1343 : case( MetaActionType::MOVECLIPREGION ):
1344 : {
1345 : OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1346 : }
1347 0 : break;
1348 :
1349 : default:
1350 : {
1351 0 : pAction->Execute( aMapVDev.get() );
1352 0 : pAction->Duplicate();
1353 0 : aMtf.AddAction( pAction );
1354 :
1355 : // update rotation point and offset, if necessary
1356 0 : if( ( MetaActionType::MAPMODE == nActionType ) ||
1357 0 : ( MetaActionType::PUSH == nActionType ) ||
1358 : ( MetaActionType::POP == nActionType ) )
1359 : {
1360 0 : aRotAnchor = OutputDevice::LogicToLogic( aOrigin, aPrefMapMode, aMapVDev->GetMapMode() );
1361 0 : aRotOffset = OutputDevice::LogicToLogic( aOffset, aPrefMapMode, aMapVDev->GetMapMode() );
1362 : }
1363 : }
1364 0 : break;
1365 : }
1366 : }
1367 :
1368 0 : aMtf.aPrefMapMode = aPrefMapMode;
1369 0 : aMtf.aPrefSize = aNewBound.GetSize();
1370 :
1371 0 : *this = aMtf;
1372 : }
1373 0 : }
1374 :
1375 2388 : static void ImplActionBounds( Rectangle& o_rOutBounds,
1376 : const Rectangle& i_rInBounds,
1377 : const std::vector<Rectangle>& i_rClipStack,
1378 : Rectangle* o_pHairline )
1379 : {
1380 2388 : Rectangle aBounds( i_rInBounds );
1381 2388 : if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1382 1590 : aBounds.Intersection( i_rClipStack.back() );
1383 2388 : if( ! aBounds.IsEmpty() )
1384 : {
1385 2148 : if( ! o_rOutBounds.IsEmpty() )
1386 1978 : o_rOutBounds.Union( aBounds );
1387 : else
1388 170 : o_rOutBounds = aBounds;
1389 :
1390 2148 : if(o_pHairline)
1391 : {
1392 0 : if( ! o_pHairline->IsEmpty() )
1393 0 : o_pHairline->Union( aBounds );
1394 : else
1395 0 : *o_pHairline = aBounds;
1396 : }
1397 : }
1398 2388 : }
1399 :
1400 211 : Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference, Rectangle* pHairline ) const
1401 : {
1402 211 : GDIMetaFile aMtf;
1403 422 : ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1404 :
1405 211 : aMapVDev->EnableOutput( false );
1406 211 : aMapVDev->SetMapMode( GetPrefMapMode() );
1407 :
1408 422 : std::vector<Rectangle> aClipStack( 1, Rectangle() );
1409 422 : std::vector<PushFlags> aPushFlagStack;
1410 :
1411 211 : Rectangle aBound;
1412 :
1413 211 : if(pHairline)
1414 82 : *pHairline = Rectangle();
1415 :
1416 211 : const sal_uLong nCount(GetActionSize());
1417 :
1418 9001 : for(sal_uLong a(0); a < nCount; a++)
1419 : {
1420 8790 : MetaAction* pAction = GetAction(a);
1421 8790 : const MetaActionType nActionType = pAction->GetType();
1422 8790 : Rectangle* pUseHairline = (pHairline && aMapVDev->IsLineColor()) ? pHairline : 0;
1423 :
1424 8790 : switch( nActionType )
1425 : {
1426 : case( MetaActionType::PIXEL ):
1427 : {
1428 104 : MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1429 : ImplActionBounds( aBound,
1430 104 : Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1431 208 : aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1432 208 : aClipStack, pUseHairline );
1433 : }
1434 104 : break;
1435 :
1436 : case( MetaActionType::POINT ):
1437 : {
1438 0 : MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1439 : ImplActionBounds( aBound,
1440 0 : Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1441 0 : aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1442 0 : aClipStack, pUseHairline );
1443 : }
1444 0 : break;
1445 :
1446 : case( MetaActionType::LINE ):
1447 : {
1448 315 : MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1449 315 : Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1450 315 : Rectangle aRect( aP1, aP2 );
1451 315 : aRect.Justify();
1452 :
1453 315 : if(pUseHairline)
1454 : {
1455 0 : const LineInfo& rLineInfo = pAct->GetLineInfo();
1456 :
1457 0 : if(0 != rLineInfo.GetWidth())
1458 0 : pUseHairline = 0;
1459 : }
1460 :
1461 315 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1462 : }
1463 315 : break;
1464 :
1465 : case( MetaActionType::RECT ):
1466 : {
1467 371 : MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1468 371 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1469 : }
1470 371 : break;
1471 :
1472 : case( MetaActionType::ROUNDRECT ):
1473 : {
1474 0 : MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1475 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1476 : }
1477 0 : break;
1478 :
1479 : case( MetaActionType::ELLIPSE ):
1480 : {
1481 0 : MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1482 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1483 : }
1484 0 : break;
1485 :
1486 : case( MetaActionType::ARC ):
1487 : {
1488 0 : MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1489 : // FIXME: this is imprecise
1490 : // e.g. for small arcs the whole rectangle is WAY too large
1491 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1492 : }
1493 0 : break;
1494 :
1495 : case( MetaActionType::PIE ):
1496 : {
1497 0 : MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1498 : // FIXME: this is imprecise
1499 : // e.g. for small arcs the whole rectangle is WAY too large
1500 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1501 : }
1502 0 : break;
1503 :
1504 : case( MetaActionType::CHORD ):
1505 : {
1506 0 : MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1507 : // FIXME: this is imprecise
1508 : // e.g. for small arcs the whole rectangle is WAY too large
1509 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1510 : }
1511 0 : break;
1512 :
1513 : case( MetaActionType::POLYLINE ):
1514 : {
1515 31 : MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1516 31 : Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1517 :
1518 31 : if(pUseHairline)
1519 : {
1520 0 : const LineInfo& rLineInfo = pAct->GetLineInfo();
1521 :
1522 0 : if(0 != rLineInfo.GetWidth())
1523 0 : pUseHairline = 0;
1524 : }
1525 :
1526 31 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1527 : }
1528 31 : break;
1529 :
1530 : case( MetaActionType::POLYGON ):
1531 : {
1532 334 : MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1533 334 : Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1534 334 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1535 : }
1536 334 : break;
1537 :
1538 : case( MetaActionType::POLYPOLYGON ):
1539 : {
1540 323 : MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1541 323 : Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1542 323 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, pUseHairline );
1543 : }
1544 323 : break;
1545 :
1546 : case( MetaActionType::TEXT ):
1547 : {
1548 557 : MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1549 557 : Rectangle aRect;
1550 : // hdu said base = index
1551 557 : aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1552 557 : Point aPt( pAct->GetPoint() );
1553 557 : aRect.Move( aPt.X(), aPt.Y() );
1554 557 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1555 : }
1556 557 : break;
1557 :
1558 : case( MetaActionType::TEXTARRAY ):
1559 : {
1560 255 : MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1561 255 : Rectangle aRect;
1562 : // hdu said base = index
1563 255 : aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1564 510 : 0, pAct->GetDXArray() );
1565 255 : Point aPt( pAct->GetPoint() );
1566 255 : aRect.Move( aPt.X(), aPt.Y() );
1567 255 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1568 : }
1569 255 : break;
1570 :
1571 : case( MetaActionType::STRETCHTEXT ):
1572 : {
1573 0 : MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1574 0 : Rectangle aRect;
1575 : // hdu said base = index
1576 0 : aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1577 0 : pAct->GetWidth(), NULL );
1578 0 : Point aPt( pAct->GetPoint() );
1579 0 : aRect.Move( aPt.X(), aPt.Y() );
1580 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1581 : }
1582 0 : break;
1583 :
1584 : case( MetaActionType::TEXTLINE ):
1585 : {
1586 0 : MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1587 : // measure a test string to get ascend and descent right
1588 : static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
1589 0 : OUString aStr( pStr );
1590 :
1591 0 : Rectangle aRect;
1592 0 : aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength(), 0, NULL );
1593 0 : Point aPt( pAct->GetStartPoint() );
1594 0 : aRect.Move( aPt.X(), aPt.Y() );
1595 0 : aRect.Right() = aRect.Left() + pAct->GetWidth();
1596 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1597 : }
1598 0 : break;
1599 :
1600 : case( MetaActionType::BMPSCALE ):
1601 : {
1602 49 : MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1603 49 : Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1604 49 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1605 : }
1606 49 : break;
1607 :
1608 : case( MetaActionType::BMPSCALEPART ):
1609 : {
1610 0 : MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1611 0 : Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1612 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1613 : }
1614 0 : break;
1615 :
1616 : case( MetaActionType::BMPEXSCALE ):
1617 : {
1618 49 : MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1619 49 : Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1620 49 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1621 : }
1622 49 : break;
1623 :
1624 : case( MetaActionType::BMPEXSCALEPART ):
1625 : {
1626 0 : MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1627 0 : Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1628 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1629 : }
1630 0 : break;
1631 :
1632 : case( MetaActionType::GRADIENT ):
1633 : {
1634 0 : MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1635 0 : Rectangle aRect( pAct->GetRect() );
1636 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1637 : }
1638 0 : break;
1639 :
1640 : case( MetaActionType::GRADIENTEX ):
1641 : {
1642 0 : MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1643 0 : Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1644 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1645 : }
1646 0 : break;
1647 :
1648 : case( MetaActionType::COMMENT ):
1649 : {
1650 : // nothing to do
1651 : };
1652 445 : break;
1653 :
1654 : case( MetaActionType::HATCH ):
1655 : {
1656 0 : MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1657 0 : Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1658 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1659 : }
1660 0 : break;
1661 :
1662 : case( MetaActionType::Transparent ):
1663 : {
1664 0 : MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1665 0 : Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1666 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1667 : }
1668 0 : break;
1669 :
1670 : case( MetaActionType::FLOATTRANSPARENT ):
1671 : {
1672 0 : MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1673 : // MetaFloatTransparentAction is defined limiting it's content Metafile
1674 : // to it's geometry definition(Point, Size), so use these directly
1675 0 : const Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1676 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1677 : }
1678 0 : break;
1679 :
1680 : case( MetaActionType::EPS ):
1681 : {
1682 0 : MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1683 0 : Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1684 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1685 : }
1686 0 : break;
1687 :
1688 : case( MetaActionType::CLIPREGION ):
1689 : {
1690 142 : MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1691 142 : if( pAct->IsClipping() )
1692 107 : aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1693 : else
1694 35 : aClipStack.back() = Rectangle();
1695 : }
1696 142 : break;
1697 :
1698 : case( MetaActionType::ISECTRECTCLIPREGION ):
1699 : {
1700 38 : MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1701 38 : Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1702 38 : if( aClipStack.back().IsEmpty() )
1703 38 : aClipStack.back() = aRect;
1704 : else
1705 0 : aClipStack.back().Intersection( aRect );
1706 : }
1707 38 : break;
1708 :
1709 : case( MetaActionType::ISECTREGIONCLIPREGION ):
1710 : {
1711 6 : MetaISectRegionClipRegionAction* pAct = static_cast<MetaISectRegionClipRegionAction*>(pAction);
1712 6 : Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1713 6 : if( aClipStack.back().IsEmpty() )
1714 6 : aClipStack.back() = aRect;
1715 : else
1716 0 : aClipStack.back().Intersection( aRect );
1717 : }
1718 6 : break;
1719 :
1720 : case( MetaActionType::BMP ):
1721 : {
1722 0 : MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1723 0 : Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1724 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1725 : }
1726 0 : break;
1727 :
1728 : case( MetaActionType::BMPEX ):
1729 : {
1730 0 : MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1731 0 : Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1732 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1733 : }
1734 0 : break;
1735 :
1736 : case( MetaActionType::MASK ):
1737 : {
1738 0 : MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1739 0 : Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1740 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1741 : }
1742 0 : break;
1743 :
1744 : case( MetaActionType::MASKSCALE ):
1745 : {
1746 0 : MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1747 0 : Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1748 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1749 : }
1750 0 : break;
1751 :
1752 : case( MetaActionType::MASKSCALEPART ):
1753 : {
1754 0 : MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1755 0 : Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1756 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1757 : }
1758 0 : break;
1759 :
1760 : case( MetaActionType::WALLPAPER ):
1761 : {
1762 0 : MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1763 0 : Rectangle aRect( pAct->GetRect() );
1764 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1765 : }
1766 0 : break;
1767 :
1768 : case( MetaActionType::TEXTRECT ):
1769 : {
1770 0 : MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1771 0 : Rectangle aRect( pAct->GetRect() );
1772 0 : ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack, 0 );
1773 : }
1774 0 : break;
1775 :
1776 : case( MetaActionType::MOVECLIPREGION ):
1777 : {
1778 0 : MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1779 0 : if( ! aClipStack.back().IsEmpty() )
1780 : {
1781 0 : Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1782 0 : aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1783 0 : aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1784 : }
1785 : }
1786 0 : break;
1787 :
1788 : default:
1789 : {
1790 5771 : pAction->Execute( aMapVDev.get() );
1791 :
1792 5771 : if( nActionType == MetaActionType::PUSH )
1793 : {
1794 361 : MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1795 361 : aPushFlagStack.push_back( pAct->GetFlags() );
1796 361 : if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1797 : {
1798 342 : Rectangle aRect( aClipStack.back() );
1799 342 : aClipStack.push_back( aRect );
1800 : }
1801 : }
1802 5410 : else if( nActionType == MetaActionType::POP )
1803 : {
1804 : // sanity check
1805 361 : if( ! aPushFlagStack.empty() )
1806 : {
1807 361 : if( aPushFlagStack.back() & PushFlags::CLIPREGION )
1808 : {
1809 342 : if( aClipStack.size() > 1 )
1810 342 : aClipStack.pop_back();
1811 : }
1812 361 : aPushFlagStack.pop_back();
1813 : }
1814 : }
1815 : }
1816 5771 : break;
1817 : }
1818 : }
1819 422 : return aBound;
1820 : }
1821 :
1822 0 : Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1823 : {
1824 0 : return Color( rColor.GetTransparency(),
1825 0 : static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1826 0 : static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1827 0 : static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1828 :
1829 : }
1830 :
1831 0 : BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1832 : {
1833 0 : const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1834 0 : BitmapEx aRet( rBmpEx );
1835 :
1836 : aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1837 : p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1838 0 : p->fGamma, p->bInvert );
1839 :
1840 0 : return aRet;
1841 : }
1842 :
1843 0 : Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1844 : {
1845 0 : sal_uInt8 cLum = rColor.GetLuminance();
1846 :
1847 0 : if( MTF_CONVERSION_1BIT_THRESHOLD == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1848 0 : cLum = ( cLum < 128 ) ? 0 : 255;
1849 :
1850 0 : return Color( rColor.GetTransparency(), cLum, cLum, cLum );
1851 : }
1852 :
1853 0 : BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1854 : {
1855 0 : BitmapEx aRet( rBmpEx );
1856 :
1857 0 : aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1858 :
1859 0 : return aRet;
1860 : }
1861 :
1862 7 : Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1863 : {
1864 7 : return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1865 : }
1866 :
1867 19 : BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1868 : {
1869 19 : BitmapPalette aPal( 3 );
1870 :
1871 19 : aPal[ 0 ] = Color( COL_BLACK );
1872 19 : aPal[ 1 ] = Color( COL_WHITE );
1873 19 : aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1874 :
1875 38 : Bitmap aBmp( rBmpEx.GetSizePixel(), 4, &aPal );
1876 19 : aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1877 :
1878 19 : if( rBmpEx.IsAlpha() )
1879 3 : return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1880 16 : else if( rBmpEx.IsTransparent() )
1881 16 : return BitmapEx( aBmp, rBmpEx.GetMask() );
1882 : else
1883 19 : return aBmp;
1884 : }
1885 :
1886 0 : Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1887 : {
1888 0 : const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1889 :
1890 0 : for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1891 : {
1892 0 : if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1893 0 : ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1894 0 : ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1895 0 : ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1896 0 : ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1897 0 : ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1898 : {
1899 0 : return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1900 : }
1901 : }
1902 :
1903 0 : return rColor;
1904 : }
1905 :
1906 0 : BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1907 : {
1908 0 : const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1909 0 : BitmapEx aRet( rBmpEx );
1910 :
1911 0 : aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount, p->pTols );
1912 :
1913 0 : return aRet;
1914 : }
1915 :
1916 41 : void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1917 : BmpExchangeFnc pFncBmp, const void* pBmpParam )
1918 : {
1919 41 : GDIMetaFile aMtf;
1920 :
1921 41 : aMtf.aPrefSize = aPrefSize;
1922 41 : aMtf.aPrefMapMode = aPrefMapMode;
1923 41 : aMtf.bUseCanvas = bUseCanvas;
1924 :
1925 129 : for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1926 : {
1927 88 : const MetaActionType nType = pAction->GetType();
1928 :
1929 88 : switch( nType )
1930 : {
1931 : case( MetaActionType::PIXEL ):
1932 : {
1933 0 : MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1934 0 : aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1935 : }
1936 0 : break;
1937 :
1938 : case( MetaActionType::LINECOLOR ):
1939 : {
1940 4 : MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1941 :
1942 4 : if( !pAct->IsSetting() )
1943 4 : pAct->Duplicate();
1944 : else
1945 0 : pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1946 :
1947 4 : aMtf.push_back( pAct );
1948 : }
1949 4 : break;
1950 :
1951 : case( MetaActionType::FILLCOLOR ):
1952 : {
1953 8 : MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1954 :
1955 8 : if( !pAct->IsSetting() )
1956 1 : pAct->Duplicate();
1957 : else
1958 7 : pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1959 :
1960 8 : aMtf.push_back( pAct );
1961 : }
1962 8 : break;
1963 :
1964 : case( MetaActionType::TEXTCOLOR ):
1965 : {
1966 0 : MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1967 0 : aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1968 : }
1969 0 : break;
1970 :
1971 : case( MetaActionType::TEXTFILLCOLOR ):
1972 : {
1973 0 : MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1974 :
1975 0 : if( !pAct->IsSetting() )
1976 0 : pAct->Duplicate();
1977 : else
1978 0 : pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1979 :
1980 0 : aMtf.push_back( pAct );
1981 : }
1982 0 : break;
1983 :
1984 : case( MetaActionType::TEXTLINECOLOR ):
1985 : {
1986 0 : MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1987 :
1988 0 : if( !pAct->IsSetting() )
1989 0 : pAct->Duplicate();
1990 : else
1991 0 : pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1992 :
1993 0 : aMtf.push_back( pAct );
1994 : }
1995 0 : break;
1996 :
1997 : case( MetaActionType::OVERLINECOLOR ):
1998 : {
1999 0 : MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
2000 :
2001 0 : if( !pAct->IsSetting() )
2002 0 : pAct->Duplicate();
2003 : else
2004 0 : pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
2005 :
2006 0 : aMtf.push_back( pAct );
2007 : }
2008 0 : break;
2009 :
2010 : case( MetaActionType::FONT ):
2011 : {
2012 0 : MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
2013 0 : vcl::Font aFont( pAct->GetFont() );
2014 :
2015 0 : aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
2016 0 : aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
2017 0 : aMtf.push_back( new MetaFontAction( aFont ) );
2018 : }
2019 0 : break;
2020 :
2021 : case( MetaActionType::WALLPAPER ):
2022 : {
2023 0 : MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
2024 0 : Wallpaper aWall( pAct->GetWallpaper() );
2025 0 : const Rectangle& rRect = pAct->GetRect();
2026 :
2027 0 : aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
2028 :
2029 0 : if( aWall.IsBitmap() )
2030 0 : aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
2031 :
2032 0 : if( aWall.IsGradient() )
2033 : {
2034 0 : Gradient aGradient( aWall.GetGradient() );
2035 :
2036 0 : aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2037 0 : aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2038 0 : aWall.SetGradient( aGradient );
2039 : }
2040 :
2041 0 : aMtf.push_back( new MetaWallpaperAction( rRect, aWall ) );
2042 : }
2043 0 : break;
2044 :
2045 : case( MetaActionType::BMP ):
2046 : case( MetaActionType::BMPEX ):
2047 : case( MetaActionType::MASK ):
2048 : {
2049 : OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
2050 : }
2051 0 : break;
2052 :
2053 : case( MetaActionType::BMPSCALE ):
2054 : {
2055 0 : MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
2056 : aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
2057 0 : pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() ) );
2058 : }
2059 0 : break;
2060 :
2061 : case( MetaActionType::BMPSCALEPART ):
2062 : {
2063 0 : MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
2064 : aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2065 : pAct->GetSrcPoint(), pAct->GetSrcSize(),
2066 0 : pFncBmp( pAct->GetBitmap(), pBmpParam ).GetBitmap() )
2067 0 : );
2068 : }
2069 0 : break;
2070 :
2071 : case( MetaActionType::BMPEXSCALE ):
2072 : {
2073 19 : MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
2074 : aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
2075 38 : pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
2076 57 : );
2077 : }
2078 19 : break;
2079 :
2080 : case( MetaActionType::BMPEXSCALEPART ):
2081 : {
2082 0 : MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
2083 : aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2084 : pAct->GetSrcPoint(), pAct->GetSrcSize(),
2085 0 : pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
2086 0 : );
2087 : }
2088 0 : break;
2089 :
2090 : case( MetaActionType::MASKSCALE ):
2091 : {
2092 0 : MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
2093 : aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
2094 : pAct->GetBitmap(),
2095 0 : pFncCol( pAct->GetColor(), pColParam ) )
2096 0 : );
2097 : }
2098 0 : break;
2099 :
2100 : case( MetaActionType::MASKSCALEPART ):
2101 : {
2102 0 : MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
2103 : aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
2104 : pAct->GetSrcPoint(), pAct->GetSrcSize(),
2105 : pAct->GetBitmap(),
2106 0 : pFncCol( pAct->GetColor(), pColParam ) )
2107 0 : );
2108 : }
2109 0 : break;
2110 :
2111 : case( MetaActionType::GRADIENT ):
2112 : {
2113 0 : MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
2114 0 : Gradient aGradient( pAct->GetGradient() );
2115 :
2116 0 : aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2117 0 : aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2118 0 : aMtf.push_back( new MetaGradientAction( pAct->GetRect(), aGradient ) );
2119 : }
2120 0 : break;
2121 :
2122 : case( MetaActionType::GRADIENTEX ):
2123 : {
2124 0 : MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
2125 0 : Gradient aGradient( pAct->GetGradient() );
2126 :
2127 0 : aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2128 0 : aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2129 0 : aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), aGradient ) );
2130 : }
2131 0 : break;
2132 :
2133 : case( MetaActionType::HATCH ):
2134 : {
2135 0 : MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2136 0 : Hatch aHatch( pAct->GetHatch() );
2137 :
2138 0 : aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2139 0 : aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2140 : }
2141 0 : break;
2142 :
2143 : case( MetaActionType::FLOATTRANSPARENT ):
2144 : {
2145 0 : MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2146 0 : GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2147 :
2148 0 : aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2149 : aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2150 : pAct->GetPoint(), pAct->GetSize(),
2151 0 : pAct->GetGradient() )
2152 0 : );
2153 : }
2154 0 : break;
2155 :
2156 : case( MetaActionType::EPS ):
2157 : {
2158 0 : MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2159 0 : GDIMetaFile aSubst( pAct->GetSubstitute() );
2160 :
2161 0 : aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2162 : aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2163 0 : pAct->GetLink(), aSubst )
2164 0 : );
2165 : }
2166 0 : break;
2167 :
2168 : default:
2169 : {
2170 57 : pAction->Duplicate();
2171 57 : aMtf.push_back( pAction );
2172 : }
2173 57 : break;
2174 : }
2175 : }
2176 :
2177 41 : *this = aMtf;
2178 41 : }
2179 :
2180 0 : void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2181 : short nChannelRPercent, short nChannelGPercent,
2182 : short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2183 : {
2184 : // nothing to do? => return quickly
2185 0 : if( nLuminancePercent || nContrastPercent ||
2186 0 : nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2187 0 : ( fGamma != 1.0 ) || bInvert )
2188 : {
2189 : double fM, fROff, fGOff, fBOff, fOff;
2190 : ImplColAdjustParam aColParam;
2191 : ImplBmpAdjustParam aBmpParam;
2192 :
2193 0 : aColParam.pMapR = new sal_uInt8[ 256 ];
2194 0 : aColParam.pMapG = new sal_uInt8[ 256 ];
2195 0 : aColParam.pMapB = new sal_uInt8[ 256 ];
2196 :
2197 : // calculate slope
2198 0 : if( nContrastPercent >= 0 )
2199 0 : fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0L, 100L ) );
2200 : else
2201 0 : fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100L, 0L ) ) / 128.0;
2202 :
2203 0 : if(!msoBrightness)
2204 : // total offset = luminance offset + contrast offset
2205 0 : fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55 + 128.0 - fM * 128.0;
2206 : else
2207 0 : fOff = MinMax( nLuminancePercent, -100L, 100L ) * 2.55;
2208 :
2209 : // channel offset = channel offset + total offset
2210 0 : fROff = nChannelRPercent * 2.55 + fOff;
2211 0 : fGOff = nChannelGPercent * 2.55 + fOff;
2212 0 : fBOff = nChannelBPercent * 2.55 + fOff;
2213 :
2214 : // calculate gamma value
2215 0 : fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2216 0 : const bool bGamma = ( fGamma != 1.0 );
2217 :
2218 : // create mapping table
2219 0 : for( long nX = 0L; nX < 256L; nX++ )
2220 : {
2221 0 : if(!msoBrightness)
2222 : {
2223 0 : aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fROff ), 0L, 255L );
2224 0 : aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fGOff ), 0L, 255L );
2225 0 : aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( nX * fM + fBOff ), 0L, 255L );
2226 : }
2227 : else
2228 : {
2229 0 : aColParam.pMapR[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0L, 255L );
2230 0 : aColParam.pMapG[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0L, 255L );
2231 0 : aColParam.pMapB[ nX ] = (sal_uInt8) MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0L, 255L );
2232 : }
2233 0 : if( bGamma )
2234 : {
2235 0 : aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2236 0 : aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2237 0 : aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2238 : }
2239 :
2240 0 : if( bInvert )
2241 : {
2242 0 : aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2243 0 : aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2244 0 : aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2245 : }
2246 : }
2247 :
2248 0 : aBmpParam.nLuminancePercent = nLuminancePercent;
2249 0 : aBmpParam.nContrastPercent = nContrastPercent;
2250 0 : aBmpParam.nChannelRPercent = nChannelRPercent;
2251 0 : aBmpParam.nChannelGPercent = nChannelGPercent;
2252 0 : aBmpParam.nChannelBPercent = nChannelBPercent;
2253 0 : aBmpParam.fGamma = fGamma;
2254 0 : aBmpParam.bInvert = bInvert;
2255 :
2256 : // do color adjustment
2257 0 : ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2258 :
2259 0 : delete[] aColParam.pMapR;
2260 0 : delete[] aColParam.pMapG;
2261 0 : delete[] aColParam.pMapB;
2262 : }
2263 0 : }
2264 :
2265 0 : void GDIMetaFile::Convert( MtfConversion eConversion )
2266 : {
2267 : // nothing to do? => return quickly
2268 0 : if( eConversion != MTF_CONVERSION_NONE )
2269 : {
2270 : ImplColConvertParam aColParam;
2271 : ImplBmpConvertParam aBmpParam;
2272 :
2273 0 : aColParam.eConversion = eConversion;
2274 0 : aBmpParam.eConversion = ( MTF_CONVERSION_1BIT_THRESHOLD == eConversion ) ? BMP_CONVERSION_1BIT_THRESHOLD : BMP_CONVERSION_8BIT_GREYS;
2275 :
2276 0 : ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2277 : }
2278 0 : }
2279 :
2280 0 : void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, sal_uLong* pTols )
2281 : {
2282 : ImplColReplaceParam aColParam;
2283 : ImplBmpReplaceParam aBmpParam;
2284 :
2285 0 : aColParam.pMinR = new sal_uLong[ nColorCount ];
2286 0 : aColParam.pMaxR = new sal_uLong[ nColorCount ];
2287 0 : aColParam.pMinG = new sal_uLong[ nColorCount ];
2288 0 : aColParam.pMaxG = new sal_uLong[ nColorCount ];
2289 0 : aColParam.pMinB = new sal_uLong[ nColorCount ];
2290 0 : aColParam.pMaxB = new sal_uLong[ nColorCount ];
2291 :
2292 0 : for( sal_uLong i = 0; i < nColorCount; i++ )
2293 : {
2294 0 : const long nTol = pTols ? ( pTols[ i ] * 255 ) / 100 : 0;
2295 : long nVal;
2296 :
2297 0 : nVal = pSearchColors[ i ].GetRed();
2298 0 : aColParam.pMinR[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2299 0 : aColParam.pMaxR[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2300 :
2301 0 : nVal = pSearchColors[ i ].GetGreen();
2302 0 : aColParam.pMinG[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2303 0 : aColParam.pMaxG[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2304 :
2305 0 : nVal = pSearchColors[ i ].GetBlue();
2306 0 : aColParam.pMinB[ i ] = (sal_uLong) std::max( nVal - nTol, 0L );
2307 0 : aColParam.pMaxB[ i ] = (sal_uLong) std::min( nVal + nTol, 255L );
2308 : }
2309 :
2310 0 : aColParam.pDstCols = pReplaceColors;
2311 0 : aColParam.nCount = nColorCount;
2312 :
2313 0 : aBmpParam.pSrcCols = pSearchColors;
2314 0 : aBmpParam.pDstCols = pReplaceColors;
2315 0 : aBmpParam.nCount = nColorCount;
2316 0 : aBmpParam.pTols = pTols;
2317 :
2318 0 : ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2319 :
2320 0 : delete[] aColParam.pMinR;
2321 0 : delete[] aColParam.pMaxR;
2322 0 : delete[] aColParam.pMinG;
2323 0 : delete[] aColParam.pMaxG;
2324 0 : delete[] aColParam.pMinB;
2325 0 : delete[] aColParam.pMaxB;
2326 0 : };
2327 :
2328 41 : GDIMetaFile GDIMetaFile::GetMonochromeMtf( const Color& rColor ) const
2329 : {
2330 41 : GDIMetaFile aRet( *this );
2331 :
2332 41 : ImplColMonoParam aColParam;
2333 41 : ImplBmpMonoParam aBmpParam;
2334 :
2335 41 : aColParam.aColor = rColor;
2336 41 : aBmpParam.aColor = rColor;
2337 :
2338 41 : aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2339 :
2340 41 : return aRet;
2341 : }
2342 :
2343 834 : sal_uLong GDIMetaFile::GetChecksum() const
2344 : {
2345 834 : GDIMetaFile aMtf;
2346 1668 : SvMemoryStream aMemStm( 65535, 65535 );
2347 834 : ImplMetaWriteData aWriteData;
2348 : SVBT16 aBT16;
2349 : SVBT32 aBT32;
2350 834 : sal_uLong nCrc = 0;
2351 :
2352 834 : aWriteData.meActualCharSet = aMemStm.GetStreamCharSet();
2353 72991 : for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; i++ )
2354 : {
2355 72157 : MetaAction* pAction = GetAction( i );
2356 :
2357 72157 : switch( pAction->GetType() )
2358 : {
2359 : case( MetaActionType::BMP ):
2360 : {
2361 0 : MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
2362 :
2363 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2364 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2365 :
2366 0 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2367 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2368 :
2369 0 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2370 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2371 :
2372 0 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2373 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2374 : }
2375 0 : break;
2376 :
2377 : case( MetaActionType::BMPSCALE ):
2378 : {
2379 389 : MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
2380 :
2381 389 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2382 389 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2383 :
2384 389 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2385 389 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2386 :
2387 389 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2388 389 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2389 :
2390 389 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2391 389 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2392 :
2393 389 : UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2394 389 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2395 :
2396 389 : UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2397 389 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2398 : }
2399 389 : break;
2400 :
2401 : case( MetaActionType::BMPSCALEPART ):
2402 : {
2403 0 : MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
2404 :
2405 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2406 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2407 :
2408 0 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2409 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2410 :
2411 0 : UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2412 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2413 :
2414 0 : UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2415 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2416 :
2417 0 : UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2418 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2419 :
2420 0 : UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2421 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2422 :
2423 0 : UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2424 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2425 :
2426 0 : UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2427 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2428 :
2429 0 : UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2430 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2431 :
2432 0 : UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2433 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2434 : }
2435 0 : break;
2436 :
2437 : case( MetaActionType::BMPEX ):
2438 : {
2439 4 : MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
2440 :
2441 4 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2442 4 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2443 :
2444 4 : UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2445 4 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2446 :
2447 4 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2448 4 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2449 :
2450 4 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2451 4 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2452 : }
2453 4 : break;
2454 :
2455 : case( MetaActionType::BMPEXSCALE ):
2456 : {
2457 51 : MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
2458 :
2459 51 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2460 51 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2461 :
2462 51 : UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2463 51 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2464 :
2465 51 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2466 51 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2467 :
2468 51 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2469 51 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2470 :
2471 51 : UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2472 51 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2473 :
2474 51 : UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2475 51 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2476 : }
2477 51 : break;
2478 :
2479 : case( MetaActionType::BMPEXSCALEPART ):
2480 : {
2481 0 : MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
2482 :
2483 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2484 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2485 :
2486 0 : UInt32ToSVBT32( pAct->GetBitmapEx().GetChecksum(), aBT32 );
2487 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2488 :
2489 0 : UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2490 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2491 :
2492 0 : UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2493 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2494 :
2495 0 : UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2496 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2497 :
2498 0 : UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2499 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2500 :
2501 0 : UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2502 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2503 :
2504 0 : UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2505 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2506 :
2507 0 : UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2508 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2509 :
2510 0 : UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2511 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2512 : }
2513 0 : break;
2514 :
2515 : case( MetaActionType::MASK ):
2516 : {
2517 0 : MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
2518 :
2519 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2520 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2521 :
2522 0 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2523 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2524 :
2525 0 : UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2526 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2527 :
2528 0 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2529 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2530 :
2531 0 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2532 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2533 : }
2534 0 : break;
2535 :
2536 : case( MetaActionType::MASKSCALE ):
2537 : {
2538 0 : MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
2539 :
2540 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2541 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2542 :
2543 0 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2544 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2545 :
2546 0 : UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2547 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2548 :
2549 0 : UInt32ToSVBT32( pAct->GetPoint().X(), aBT32 );
2550 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2551 :
2552 0 : UInt32ToSVBT32( pAct->GetPoint().Y(), aBT32 );
2553 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2554 :
2555 0 : UInt32ToSVBT32( pAct->GetSize().Width(), aBT32 );
2556 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2557 :
2558 0 : UInt32ToSVBT32( pAct->GetSize().Height(), aBT32 );
2559 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2560 : }
2561 0 : break;
2562 :
2563 : case( MetaActionType::MASKSCALEPART ):
2564 : {
2565 0 : MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
2566 :
2567 0 : ShortToSVBT16( static_cast<sal_uInt16>(pAct->GetType()), aBT16 );
2568 0 : nCrc = rtl_crc32( nCrc, aBT16, 2 );
2569 :
2570 0 : UInt32ToSVBT32( pAct->GetBitmap().GetChecksum(), aBT32 );
2571 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2572 :
2573 0 : UInt32ToSVBT32( pAct->GetColor().GetColor(), aBT32 );
2574 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2575 :
2576 0 : UInt32ToSVBT32( pAct->GetDestPoint().X(), aBT32 );
2577 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2578 :
2579 0 : UInt32ToSVBT32( pAct->GetDestPoint().Y(), aBT32 );
2580 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2581 :
2582 0 : UInt32ToSVBT32( pAct->GetDestSize().Width(), aBT32 );
2583 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2584 :
2585 0 : UInt32ToSVBT32( pAct->GetDestSize().Height(), aBT32 );
2586 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2587 :
2588 0 : UInt32ToSVBT32( pAct->GetSrcPoint().X(), aBT32 );
2589 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2590 :
2591 0 : UInt32ToSVBT32( pAct->GetSrcPoint().Y(), aBT32 );
2592 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2593 :
2594 0 : UInt32ToSVBT32( pAct->GetSrcSize().Width(), aBT32 );
2595 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2596 :
2597 0 : UInt32ToSVBT32( pAct->GetSrcSize().Height(), aBT32 );
2598 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
2599 : }
2600 0 : break;
2601 :
2602 : case MetaActionType::EPS :
2603 : {
2604 0 : MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2605 0 : nCrc = rtl_crc32( nCrc, pAct->GetLink().GetData(), pAct->GetLink().GetDataSize() );
2606 : }
2607 0 : break;
2608 :
2609 : case MetaActionType::CLIPREGION :
2610 : {
2611 632 : MetaClipRegionAction& rAct = static_cast<MetaClipRegionAction&>(*pAction);
2612 632 : const vcl::Region& rRegion = rAct.GetRegion();
2613 :
2614 632 : if(rRegion.HasPolyPolygonOrB2DPolyPolygon())
2615 : {
2616 : // It has shown that this is a possible bottleneck for checksum calculation.
2617 : // In worst case a very expensive RegionHandle representation gets created.
2618 : // In this case it's cheaper to use the PolyPolygon
2619 84 : const basegfx::B2DPolyPolygon aPolyPolygon(rRegion.GetAsB2DPolyPolygon());
2620 84 : const sal_uInt32 nPolyCount(aPolyPolygon.count());
2621 : SVBT64 aSVBT64;
2622 :
2623 336 : for(sal_uInt32 a(0); a < nPolyCount; a++)
2624 : {
2625 252 : const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a));
2626 252 : const sal_uInt32 nPointCount(aPolygon.count());
2627 252 : const bool bControl(aPolygon.areControlPointsUsed());
2628 :
2629 11046 : for(sal_uInt32 b(0); b < nPointCount; b++)
2630 : {
2631 10794 : const basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(b));
2632 :
2633 10794 : DoubleToSVBT64(aPoint.getX(), aSVBT64);
2634 10794 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2635 10794 : DoubleToSVBT64(aPoint.getY(), aSVBT64);
2636 10794 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2637 :
2638 10794 : if(bControl)
2639 : {
2640 0 : if(aPolygon.isPrevControlPointUsed(b))
2641 : {
2642 0 : const basegfx::B2DPoint aCtrl(aPolygon.getPrevControlPoint(b));
2643 :
2644 0 : DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2645 0 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2646 0 : DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2647 0 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2648 : }
2649 :
2650 0 : if(aPolygon.isNextControlPointUsed(b))
2651 : {
2652 0 : const basegfx::B2DPoint aCtrl(aPolygon.getNextControlPoint(b));
2653 :
2654 0 : DoubleToSVBT64(aCtrl.getX(), aSVBT64);
2655 0 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2656 0 : DoubleToSVBT64(aCtrl.getY(), aSVBT64);
2657 0 : nCrc = rtl_crc32(nCrc, aSVBT64, 8);
2658 : }
2659 : }
2660 10794 : }
2661 252 : }
2662 :
2663 84 : sal_uInt8 tmp = (sal_uInt8)rAct.IsClipping();
2664 84 : nCrc = rtl_crc32(nCrc, &tmp, 1);
2665 : }
2666 : else
2667 : {
2668 548 : pAction->Write( aMemStm, &aWriteData );
2669 548 : nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2670 548 : aMemStm.Seek( 0 );
2671 : }
2672 : }
2673 632 : break;
2674 :
2675 : default:
2676 : {
2677 71081 : pAction->Write( aMemStm, &aWriteData );
2678 71081 : nCrc = rtl_crc32( nCrc, aMemStm.GetData(), aMemStm.Tell() );
2679 71081 : aMemStm.Seek( 0 );
2680 : }
2681 71081 : break;
2682 : }
2683 : }
2684 :
2685 1668 : return nCrc;
2686 : }
2687 :
2688 1623 : sal_uLong GDIMetaFile::GetSizeBytes() const
2689 : {
2690 1623 : sal_uLong nSizeBytes = 0;
2691 :
2692 142254 : for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2693 : {
2694 140631 : MetaAction* pAction = GetAction( i );
2695 :
2696 : // default action size is set to 32 (=> not the exact value)
2697 140631 : nSizeBytes += 32;
2698 :
2699 : // add sizes for large action content
2700 140631 : switch( pAction->GetType() )
2701 : {
2702 0 : case( MetaActionType::BMP ): nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2703 837 : case( MetaActionType::BMPSCALE ): nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2704 0 : case( MetaActionType::BMPSCALEPART ): nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2705 :
2706 4 : case( MetaActionType::BMPEX ): nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2707 102 : case( MetaActionType::BMPEXSCALE ): nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2708 0 : case( MetaActionType::BMPEXSCALEPART ): nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2709 :
2710 0 : case( MetaActionType::MASK ): nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2711 0 : case( MetaActionType::MASKSCALE ): nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2712 0 : case( MetaActionType::MASKSCALEPART ): nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2713 :
2714 1409 : case( MetaActionType::POLYLINE ): nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2715 2610 : case( MetaActionType::POLYGON ): nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2716 : case( MetaActionType::POLYPOLYGON ):
2717 : {
2718 3619 : const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2719 :
2720 9570 : for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2721 5951 : nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2722 : }
2723 3619 : break;
2724 :
2725 6155 : case( MetaActionType::TEXT ): nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2726 0 : case( MetaActionType::STRETCHTEXT ): nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2727 0 : case( MetaActionType::TEXTRECT ): nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2728 : case( MetaActionType::TEXTARRAY ):
2729 : {
2730 8700 : MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2731 :
2732 8700 : nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2733 :
2734 8700 : if( pTextArrayAction->GetDXArray() )
2735 8700 : nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2736 : }
2737 8700 : break;
2738 117195 : default: break;
2739 : }
2740 : }
2741 :
2742 1623 : return nSizeBytes;
2743 : }
2744 :
2745 4966 : SvStream& ReadGDIMetaFile( SvStream& rIStm, GDIMetaFile& rGDIMetaFile )
2746 : {
2747 4966 : if( !rIStm.GetError() )
2748 : {
2749 : char aId[ 7 ];
2750 4966 : sal_uLong nStmPos = rIStm.Tell();
2751 4966 : SvStreamEndian nOldFormat = rIStm.GetEndian();
2752 :
2753 4966 : rIStm.SetEndian( SvStreamEndian::LITTLE );
2754 :
2755 4966 : aId[ 0 ] = 0;
2756 4966 : aId[ 6 ] = 0;
2757 4966 : rIStm.Read( aId, 6 );
2758 :
2759 4966 : if ( !strcmp( aId, "VCLMTF" ) )
2760 : {
2761 : // new format
2762 : VersionCompat* pCompat;
2763 : MetaAction* pAction;
2764 4957 : sal_uInt32 nStmCompressMode = 0;
2765 4957 : sal_uInt32 nCount = 0;
2766 :
2767 4957 : pCompat = new VersionCompat( rIStm, StreamMode::READ );
2768 :
2769 4957 : rIStm.ReadUInt32( nStmCompressMode );
2770 4957 : ReadMapMode( rIStm, rGDIMetaFile.aPrefMapMode );
2771 4957 : ReadPair( rIStm, rGDIMetaFile.aPrefSize );
2772 4957 : rIStm.ReadUInt32( nCount );
2773 :
2774 4957 : delete pCompat;
2775 :
2776 4957 : ImplMetaReadData aReadData;
2777 4957 : aReadData.meActualCharSet = rIStm.GetStreamCharSet();
2778 :
2779 329502 : for( sal_uInt32 nAction = 0UL; ( nAction < nCount ) && !rIStm.IsEof(); nAction++ )
2780 : {
2781 324545 : pAction = MetaAction::ReadMetaAction( rIStm, &aReadData );
2782 :
2783 324545 : if( pAction )
2784 : {
2785 324545 : if (pAction->GetType() == MetaActionType::COMMENT)
2786 : {
2787 4786 : MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
2788 4786 : if ( pCommentAct->GetComment() == "EMF_PLUS" )
2789 0 : rGDIMetaFile.UseCanvas( true );
2790 : }
2791 324545 : rGDIMetaFile.AddAction( pAction );
2792 : }
2793 : }
2794 : }
2795 : else
2796 : {
2797 : // to avoid possible compiler optimizations => new/delete
2798 9 : rIStm.Seek( nStmPos );
2799 9 : delete( new SVMConverter( rIStm, rGDIMetaFile, CONVERT_FROM_SVM1 ) );
2800 : }
2801 :
2802 : // check for errors
2803 4966 : if( rIStm.GetError() )
2804 : {
2805 9 : rGDIMetaFile.Clear();
2806 9 : rIStm.Seek( nStmPos );
2807 : }
2808 :
2809 4966 : rIStm.SetEndian( nOldFormat );
2810 : }
2811 : else
2812 : {
2813 : SAL_WARN("vcl.gdi", "Stream error: " << rIStm.GetError());
2814 : }
2815 :
2816 4966 : return rIStm;
2817 : }
2818 :
2819 349 : SvStream& WriteGDIMetaFile( SvStream& rOStm, const GDIMetaFile& rGDIMetaFile )
2820 : {
2821 349 : if( !rOStm.GetError() )
2822 : {
2823 349 : static const char* pEnableSVM1 = getenv( "SAL_ENABLE_SVM1" );
2824 349 : static const bool bNoSVM1 = (NULL == pEnableSVM1 ) || ( '0' == *pEnableSVM1 );
2825 :
2826 349 : if( bNoSVM1 || rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 )
2827 : {
2828 349 : const_cast< GDIMetaFile& >( rGDIMetaFile ).Write( rOStm );
2829 : }
2830 : else
2831 : {
2832 0 : delete( new SVMConverter( rOStm, const_cast< GDIMetaFile& >( rGDIMetaFile ), CONVERT_TO_SVM1 ) );
2833 : }
2834 :
2835 : #ifdef DEBUG
2836 : if( !bNoSVM1 && rOStm.GetVersion() < SOFFICE_FILEFORMAT_50 )
2837 : {
2838 : OSL_TRACE( \
2839 : "GDIMetaFile would normally be written in old SVM1 format by this call. \
2840 : The current implementation always writes in VCLMTF format. \
2841 : Please set environment variable SAL_ENABLE_SVM1 to '1' to reenable old behavior" );
2842 : }
2843 : #endif // DEBUG
2844 : }
2845 :
2846 349 : return rOStm;
2847 : }
2848 :
2849 0 : SvStream& GDIMetaFile::Read( SvStream& rIStm )
2850 : {
2851 0 : Clear();
2852 0 : ReadGDIMetaFile( rIStm, *this );
2853 :
2854 0 : return rIStm;
2855 : }
2856 :
2857 5287 : SvStream& GDIMetaFile::Write( SvStream& rOStm )
2858 : {
2859 : VersionCompat* pCompat;
2860 5287 : const SvStreamCompressFlags nStmCompressMode = rOStm.GetCompressMode();
2861 5287 : SvStreamEndian nOldFormat = rOStm.GetEndian();
2862 :
2863 5287 : rOStm.SetEndian( SvStreamEndian::LITTLE );
2864 5287 : rOStm.Write( "VCLMTF", 6 );
2865 :
2866 5287 : pCompat = new VersionCompat( rOStm, StreamMode::WRITE, 1 );
2867 :
2868 5287 : rOStm.WriteUInt32( static_cast<sal_uInt32>(nStmCompressMode) );
2869 5287 : WriteMapMode( rOStm, aPrefMapMode );
2870 5287 : WritePair( rOStm, aPrefSize );
2871 5287 : rOStm.WriteUInt32( GetActionSize() );
2872 :
2873 5287 : delete pCompat;
2874 :
2875 5287 : ImplMetaWriteData aWriteData;
2876 :
2877 5287 : aWriteData.meActualCharSet = rOStm.GetStreamCharSet();
2878 :
2879 5287 : MetaAction* pAct = FirstAction();
2880 364347 : while ( pAct )
2881 : {
2882 353773 : pAct->Write( rOStm, &aWriteData );
2883 353773 : pAct = NextAction();
2884 : }
2885 :
2886 5287 : rOStm.SetEndian( nOldFormat );
2887 :
2888 5287 : return rOStm;
2889 : }
2890 :
2891 78 : bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, sal_uInt32 nMaximumExtent, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2892 : {
2893 : // initialization seems to be complicated but is used to avoid rounding errors
2894 78 : ScopedVclPtrInstance< VirtualDevice > aVDev;
2895 78 : const Point aNullPt;
2896 78 : const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2897 78 : const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2898 78 : Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2899 78 : Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2900 :
2901 78 : if (!rBitmapEx.IsEmpty())
2902 0 : rBitmapEx.SetEmpty();
2903 :
2904 : // determine size that has the same aspect ratio as image size and
2905 : // fits into the rectangle determined by nMaximumExtent
2906 234 : if ( aSizePix.Width() && aSizePix.Height()
2907 234 : && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
2908 0 : nMaximumExtent ||
2909 0 : sal::static_int_cast< unsigned long >(aSizePix.Height()) >
2910 : nMaximumExtent ) )
2911 : {
2912 78 : const Size aOldSizePix( aSizePix );
2913 78 : double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2914 :
2915 78 : if ( fWH <= 1.0 )
2916 : {
2917 73 : aSizePix.Width() = FRound( nMaximumExtent * fWH );
2918 73 : aSizePix.Height() = nMaximumExtent;
2919 : }
2920 : else
2921 : {
2922 5 : aSizePix.Width() = nMaximumExtent;
2923 5 : aSizePix.Height() = FRound( nMaximumExtent / fWH );
2924 : }
2925 :
2926 78 : aDrawSize.Width() = FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() );
2927 78 : aDrawSize.Height() = FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() );
2928 : }
2929 :
2930 : // draw image(s) into VDev and get resulting image
2931 : // do it 4x larger to be able to scale it down & get beautiful antialias
2932 78 : Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2933 78 : if (aVDev->SetOutputSizePixel(aAntialiasSize))
2934 : {
2935 : // antialias: provide 4x larger size, and then scale down the result
2936 78 : Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2937 :
2938 : // draw metafile into VDev
2939 78 : Point aBackPosPix;
2940 78 : const_cast<GDIMetaFile *>(this)->WindStart();
2941 78 : const_cast<GDIMetaFile *>(this)->Play(aVDev.get(), aBackPosPix, aAntialias);
2942 :
2943 : // get paint bitmap
2944 78 : Bitmap aBitmap( aVDev->GetBitmap( aNullPt, aVDev->GetOutputSizePixel() ) );
2945 :
2946 : // scale down the image to the desired size - use the input scaler for the scaling operation
2947 78 : aBitmap.Scale(aDrawSize, nScaleFlag);
2948 :
2949 : // convert to desired bitmap color format
2950 78 : aBitmap.Convert(eColorConversion);
2951 :
2952 78 : rBitmapEx = BitmapEx(aBitmap);
2953 : }
2954 :
2955 78 : return !rBitmapEx.IsEmpty();
2956 : }
2957 :
2958 88 : void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2959 : {
2960 88 : bUseCanvas = _bUseCanvas;
2961 88 : }
2962 :
2963 0 : MetaCommentAction* makePluggableRendererAction( const OUString& rRendererServiceName,
2964 : const OUString& rGraphicServiceName,
2965 : const void* _pData,
2966 : sal_uInt32 nDataSize )
2967 : {
2968 0 : const sal_uInt8* pData=static_cast<sal_uInt8 const *>(_pData);
2969 :
2970 : // FIXME: Data gets copied twice, unfortunately
2971 : OString aRendererServiceName(
2972 : rRendererServiceName.getStr(),
2973 : rRendererServiceName.getLength(),
2974 0 : RTL_TEXTENCODING_ASCII_US);
2975 : OString aGraphicServiceName(
2976 : rGraphicServiceName.getStr(),
2977 : rGraphicServiceName.getLength(),
2978 0 : RTL_TEXTENCODING_ASCII_US);
2979 :
2980 : std::vector<sal_uInt8> aMem(
2981 0 : aRendererServiceName.getLength()+
2982 0 : aGraphicServiceName.getLength()+2+nDataSize);
2983 0 : sal_uInt8* pMem=&aMem[0];
2984 :
2985 : std::copy(aRendererServiceName.getStr(),
2986 0 : aRendererServiceName.getStr()+aRendererServiceName.getLength()+1,
2987 0 : pMem);
2988 0 : pMem+=aRendererServiceName.getLength()+1;
2989 : std::copy(aGraphicServiceName.getStr(),
2990 0 : aGraphicServiceName.getStr()+aGraphicServiceName.getLength()+1,
2991 0 : pMem);
2992 0 : pMem+=aGraphicServiceName.getLength()+1;
2993 :
2994 : std::copy(pData,pData+nDataSize,
2995 0 : pMem);
2996 :
2997 : return new MetaCommentAction(
2998 : "DELEGATE_PLUGGABLE_RENDERER",
2999 : 0,
3000 : &aMem[0],
3001 0 : aMem.size());
3002 : }
3003 :
3004 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|