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