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