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