LibreOffice Module vcl (master) 1
gdimtf.cxx
Go to the documentation of this file.
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 <cstdlib>
21#include <memory>
22#include <sal/log.hxx>
23#include <osl/diagnose.h>
25#include <tools/helpers.hxx>
26#include <tools/stream.hxx>
27#include <tools/vcompat.hxx>
28#include <tools/fract.hxx>
29#include <vcl/BitmapPalette.hxx>
30#include <vcl/metaact.hxx>
31#include <vcl/outdev.hxx>
32#include <vcl/window.hxx>
33#include <vcl/virdev.hxx>
34#include <vcl/svapp.hxx>
35#include <vcl/gdimtf.hxx>
36#include <vcl/graphictools.hxx>
38#include <vcl/canvastools.hxx>
39#include <vcl/mtfxmldump.hxx>
40
42
43#include <com/sun/star/beans/XFastPropertySet.hpp>
44#include <com/sun/star/rendering/MtfRenderer.hpp>
45#include <com/sun/star/rendering/XBitmapCanvas.hpp>
46#include <com/sun/star/rendering/XCanvas.hpp>
48
49using namespace com::sun::star;
50
51namespace {
52
53struct ImplColAdjustParam
54{
55 std::unique_ptr<sal_uInt8[]> pMapR;
56 std::unique_ptr<sal_uInt8[]> pMapG;
57 std::unique_ptr<sal_uInt8[]> pMapB;
58};
59
60struct ImplBmpAdjustParam
61{
62 short nLuminancePercent;
63 short nContrastPercent;
64 short nChannelRPercent;
65 short nChannelGPercent;
66 short nChannelBPercent;
67 double fGamma;
68 bool bInvert;
69};
70
71struct ImplColConvertParam
72{
73 MtfConversion eConversion;
74};
75
76struct ImplBmpConvertParam
77{
78 BmpConversion eConversion;
79};
80
81struct ImplColMonoParam
82{
83 Color aColor;
84};
85
86struct ImplBmpMonoParam
87{
88 Color aColor;
89};
90
91struct ImplColReplaceParam
92{
93 std::unique_ptr<sal_uLong[]> pMinR;
94 std::unique_ptr<sal_uLong[]> pMaxR;
95 std::unique_ptr<sal_uLong[]> pMinG;
96 std::unique_ptr<sal_uLong[]> pMaxG;
97 std::unique_ptr<sal_uLong[]> pMinB;
98 std::unique_ptr<sal_uLong[]> pMaxB;
99 const Color * pDstCols;
101};
102
103struct ImplBmpReplaceParam
104{
105 const Color* pSrcCols;
106 const Color* pDstCols;
108};
109
110}
111
113 m_nCurrentActionElement( 0 ),
114 m_aPrefSize ( 1, 1 ),
115 m_pPrev ( nullptr ),
116 m_pNext ( nullptr ),
117 m_pOutDev ( nullptr ),
118 m_bPause ( false ),
119 m_bRecord ( false ),
120 m_bUseCanvas ( false )
121{
122}
123
125 m_nCurrentActionElement( rMtf.m_nCurrentActionElement ),
126 m_aPrefMapMode ( rMtf.m_aPrefMapMode ),
127 m_aPrefSize ( rMtf.m_aPrefSize ),
128 m_pPrev ( rMtf.m_pPrev ),
129 m_pNext ( rMtf.m_pNext ),
130 m_pOutDev ( nullptr ),
131 m_bPause ( false ),
132 m_bRecord ( false ),
133 m_bUseCanvas ( rMtf.m_bUseCanvas )
134{
135 for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
136 {
137 m_aList.push_back( rMtf.GetAction( i ) );
138 }
139
140 if( rMtf.m_bRecord )
141 {
142 Record( rMtf.m_pOutDev );
143
144 if ( rMtf.m_bPause )
145 Pause( true );
146 }
147}
148
150{
151 Clear();
152}
153
155{
156 MetaAction* pCurrAct;
157
158 // watch for transparent drawing actions
159 for(pCurrAct = const_cast<GDIMetaFile*>(this)->FirstAction();
160 pCurrAct;
161 pCurrAct = const_cast<GDIMetaFile*>(this)->NextAction())
162 {
163 // #i10613# determine if the action is transparency capable
164
165 // #107169# Also examine metafiles with masked bitmaps in
166 // detail. Further down, this is optimized in such a way
167 // that there's no unnecessary painting of masked bitmaps
168 // (which are _always_ subdivided into rectangular regions
169 // of uniform opacity): if a masked bitmap is printed over
170 // empty background, we convert to a plain bitmap with
171 // white background.
172 if (pCurrAct->IsTransparent())
173 return true;
174 }
175
176 return false;
177}
178
180{
181 return m_aList.size();
182}
183
184MetaAction* GDIMetaFile::GetAction( size_t nAction ) const
185{
186 return (nAction < m_aList.size()) ? m_aList[ nAction ].get() : nullptr;
187}
188
190{
192 return m_aList.empty() ? nullptr : m_aList[ 0 ].get();
193}
194
196{
197 return ( m_nCurrentActionElement + 1 < m_aList.size() ) ? m_aList[ ++m_nCurrentActionElement ].get() : nullptr;
198}
199
201{
202 if ( nAction >= m_aList.size() )
203 {
204 return;
205 }
206 //fdo#39995 This doesn't increment the incoming action ref-count nor does it
207 //decrement the outgoing action ref-count
208 std::swap(pAction, m_aList[nAction]);
209}
210
212{
213 if( this != &rMtf )
214 {
215 Clear();
216
217 // Increment RefCount of MetaActions
218 for( size_t i = 0, n = rMtf.GetActionSize(); i < n; ++i )
219 {
220 m_aList.push_back( rMtf.GetAction( i ) );
221 }
222
225 m_pPrev = rMtf.m_pPrev;
226 m_pNext = rMtf.m_pNext;
227 m_pOutDev = nullptr;
228 m_bPause = false;
229 m_bRecord = false;
231
232 if( rMtf.m_bRecord )
233 {
234 Record( rMtf.m_pOutDev );
235
236 if( rMtf.m_bPause )
237 Pause( true );
238 }
239 }
240
241 return *this;
242}
243
244bool GDIMetaFile::operator==( const GDIMetaFile& rMtf ) const
245{
246 const size_t nObjCount = m_aList.size();
247 bool bRet = false;
248
249 if( this == &rMtf )
250 bRet = true;
251 else if( rMtf.GetActionSize() == nObjCount &&
252 rMtf.GetPrefSize() == m_aPrefSize &&
254 {
255 bRet = true;
256
257 for( size_t n = 0; n < nObjCount; n++ )
258 {
259 if( m_aList[ n ] != rMtf.GetAction( n ) )
260 {
261 bRet = false;
262 break;
263 }
264 }
265 }
266
267 return bRet;
268}
269
271{
272 if( m_bRecord )
273 Stop();
274
275 m_aList.clear();
276}
277
278void GDIMetaFile::Linker( OutputDevice* pOut, bool bLink )
279{
280 if( bLink )
281 {
282 m_pNext = nullptr;
283 m_pPrev = pOut->GetConnectMetaFile();
284 pOut->SetConnectMetaFile( this );
285
286 if( m_pPrev )
287 m_pPrev->m_pNext = this;
288 }
289 else
290 {
291 if( m_pNext )
292 {
294
295 if( m_pPrev )
297 }
298 else
299 {
300 if( m_pPrev )
301 m_pPrev->m_pNext = nullptr;
302
303 pOut->SetConnectMetaFile( m_pPrev );
304 }
305
306 m_pPrev = nullptr;
307 m_pNext = nullptr;
308 }
309}
310
312{
313 if( m_bRecord )
314 Stop();
315
316 m_nCurrentActionElement = m_aList.empty() ? 0 : (m_aList.size() - 1);
317 m_pOutDev = pOut;
318 m_bRecord = true;
319 Linker( pOut, true );
320}
321
323{
324 if (m_bRecord || rMtf.m_bRecord)
325 return;
326
327 MetaAction* pAction = GetCurAction();
328 const size_t nObjCount = m_aList.size();
329
330 rMtf.UseCanvas( rMtf.GetUseCanvas() || m_bUseCanvas );
331
332 for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nObjCount; nCurPos++ )
333 {
334 if( pAction )
335 {
336 rMtf.AddAction( pAction );
337 }
338
339 pAction = NextAction();
340 }
341}
342
343void GDIMetaFile::Play(OutputDevice& rOut, size_t nPos)
344{
345 if( m_bRecord )
346 return;
347
348 MetaAction* pAction = GetCurAction();
349 const size_t nObjCount = m_aList.size();
350 size_t nSyncCount = rOut.GetSyncCount();
351
352 if( nPos > nObjCount )
353 nPos = nObjCount;
354
355 // #i23407# Set backwards-compatible text language and layout mode
356 // This is necessary, since old metafiles don't even know of these
357 // recent add-ons. Newer metafiles must of course explicitly set
358 // those states.
362
363 SAL_INFO( "vcl.gdi", "GDIMetaFile::Play on device of size: " << rOut.GetOutputSizePixel().Width() << " " << rOut.GetOutputSizePixel().Height());
364
365 if (!ImplPlayWithRenderer(rOut, Point(0,0), rOut.GetOutputSize())) {
366 size_t i = 0;
367 for( size_t nCurPos = m_nCurrentActionElement; nCurPos < nPos; nCurPos++ )
368 {
369 if( pAction )
370 {
371 pAction->Execute(&rOut);
372
373 // flush output from time to time
374 if( i++ > nSyncCount )
375 {
376 rOut.Flush();
377 i = 0;
378 }
379 }
380
381 pAction = NextAction();
382 }
383 }
384 rOut.Pop();
385}
386
387bool GDIMetaFile::ImplPlayWithRenderer(OutputDevice& rOut, const Point& rPos, Size rLogicDestSize)
388{
389 if (!m_bUseCanvas)
390 return false;
391
392 Size rDestSize(rOut.LogicToPixel(rLogicDestSize));
393
394 const vcl::Window* win = rOut.GetOwnerWindow();
395
396 if (!win)
398 if (!win)
400
401 if (!win)
402 return false;
403
404 try
405 {
406 uno::Reference<rendering::XCanvas> xCanvas = win->GetOutDev()->GetCanvas ();
407
408 if (!xCanvas.is())
409 return false;
410
411 Size aSize (rDestSize.Width () + 1, rDestSize.Height () + 1);
412 uno::Reference<rendering::XBitmap> xBitmap = xCanvas->getDevice ()->createCompatibleAlphaBitmap (vcl::unotools::integerSize2DFromSize( aSize));
413 if( xBitmap.is () )
414 {
415 uno::Reference< rendering::XBitmapCanvas > xBitmapCanvas( xBitmap, uno::UNO_QUERY );
416 if( xBitmapCanvas.is() )
417 {
418 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
419 uno::Reference< rendering::XMtfRenderer > xMtfRenderer = rendering::MtfRenderer::createWithBitmapCanvas( xContext, xBitmapCanvas );
420
421 xBitmapCanvas->clear();
422 uno::Reference< beans::XFastPropertySet > xMtfFastPropertySet( xMtfRenderer, uno::UNO_QUERY );
423 if( xMtfFastPropertySet.is() )
424 // set this metafile to the renderer to
425 // speedup things (instead of copying data to
426 // sequence of bytes passed to renderer)
427 xMtfFastPropertySet->setFastPropertyValue( 0, uno::Any( reinterpret_cast<sal_Int64>( this ) ) );
428
429 xMtfRenderer->draw( rDestSize.Width(), rDestSize.Height() );
430
431 BitmapEx aBitmapEx;
432 if( aBitmapEx.Create( xBitmapCanvas, aSize ) )
433 {
434 if (rOut.GetMapMode().GetMapUnit() == MapUnit::MapPixel)
435 rOut.DrawBitmapEx( rPos, aBitmapEx );
436 else
437 rOut.DrawBitmapEx( rPos, rLogicDestSize, aBitmapEx );
438 return true;
439 }
440 }
441 }
442 }
443 catch (const uno::RuntimeException& )
444 {
445 throw; // runtime errors are fatal
446 }
447 catch (const uno::Exception&)
448 {
449 // ignore errors, no way of reporting them here
450 TOOLS_WARN_EXCEPTION("vcl.gdi", "GDIMetaFile::ImplPlayWithRenderer");
451 }
452
453 return false;
454}
455
456void GDIMetaFile::Play(OutputDevice& rOut, const Point& rPos,
457 const Size& rSize)
458{
459 MapMode aDrawMap( GetPrefMapMode() );
460 Size aDestSize(rOut.LogicToPixel(rSize));
461
462 if (aDestSize.Width() <= 0 || aDestSize.Height() <= 0)
463 return;
464
465 if (aDestSize.Width() > std::numeric_limits<sal_Int32>::max() ||
466 aDestSize.Height() > std::numeric_limits<sal_Int32>::max())
467 return;
468
469 GDIMetaFile* pMtf = rOut.GetConnectMetaFile();
470
471 if (ImplPlayWithRenderer(rOut, rPos, rSize))
472 return;
473
474 Size aTmpPrefSize(rOut.LogicToPixel(GetPrefSize(), aDrawMap));
475
476 if( !aTmpPrefSize.Width() )
477 aTmpPrefSize.setWidth( aDestSize.Width() );
478
479 if( !aTmpPrefSize.Height() )
480 aTmpPrefSize.setHeight( aDestSize.Height() );
481
482 Fraction aScaleX( aDestSize.Width(), aTmpPrefSize.Width() );
483 Fraction aScaleY( aDestSize.Height(), aTmpPrefSize.Height() );
484
485 aScaleX *= aDrawMap.GetScaleX();
486 aScaleY *= aDrawMap.GetScaleY();
487 // try reducing inaccurary first and abandon if the scaling
488 // still cannot be achieved
489 if (TooLargeScaleForMapMode(aScaleX, rOut.GetDPIX()))
490 aScaleX.ReduceInaccurate(10);
491 if (TooLargeScaleForMapMode(aScaleY, rOut.GetDPIY()))
492 aScaleY.ReduceInaccurate(10);
493 if (TooLargeScaleForMapMode(aScaleX, rOut.GetDPIX()) ||
494 TooLargeScaleForMapMode(aScaleY, rOut.GetDPIY()))
495 {
496 SAL_WARN("vcl", "GDIMetaFile Scaling is too high");
497 return;
498 }
499
500 aDrawMap.SetScaleX(aScaleX);
501 aDrawMap.SetScaleY(aScaleY);
502
503 // #i47260# Convert logical output position to offset within
504 // the metafile's mapmode. Therefore, disable pixel offset on
505 // outdev, it's inverse mnOutOffLogicX/Y is calculated for a
506 // different mapmode (the one currently set on rOut, that is)
507 // - thus, aDrawMap's origin would generally be wrong. And
508 // even _if_ aDrawMap is similar to pOutDev's current mapmode,
509 // it's _still_ undesirable to have pixel offset unequal zero,
510 // because one would still get round-off errors (the
511 // round-trip error for LogicToPixel( PixelToLogic() ) was the
512 // reason for having pixel offset in the first place).
513 const Size& rOldOffset(rOut.GetPixelOffset());
514 const Size aEmptySize;
515 rOut.SetPixelOffset(aEmptySize);
516 aDrawMap.SetOrigin(rOut.PixelToLogic(rOut.LogicToPixel(rPos), aDrawMap));
517 rOut.SetPixelOffset(rOldOffset);
518
519 rOut.Push();
520
521 bool bIsRecord = (pMtf && pMtf->IsRecord());
522 rOut.SetMetafileMapMode(aDrawMap, bIsRecord);
523
524 // #i23407# Set backwards-compatible text language and layout mode
525 // This is necessary, since old metafiles don't even know of these
526 // recent add-ons. Newer metafiles must of course explicitly set
527 // those states.
530
531 Play(rOut);
532
533 rOut.Pop();
534}
535
536void GDIMetaFile::Pause( bool _bPause )
537{
538 if( !m_bRecord )
539 return;
540
541 if( _bPause )
542 {
543 if( !m_bPause )
544 Linker( m_pOutDev, false );
545 }
546 else
547 {
548 if( m_bPause )
549 Linker( m_pOutDev, true );
550 }
551
552 m_bPause = _bPause;
553}
554
556{
557 if( m_bRecord )
558 {
559 m_bRecord = false;
560
561 if( !m_bPause )
562 Linker( m_pOutDev, false );
563 else
564 m_bPause = false;
565 }
566}
567
569{
570 if( !m_bRecord )
572}
573
575{
576 if( !m_bRecord )
577 if ( m_nCurrentActionElement > 0 )
579}
580
582{
583 m_aList.push_back( pAction );
584
585 if( m_pPrev )
586 {
587 m_pPrev->AddAction( pAction );
588 }
589}
590
591void GDIMetaFile::AddAction(const rtl::Reference<MetaAction>& pAction, size_t nPos)
592{
593 if ( nPos < m_aList.size() )
594 {
595 m_aList.insert( m_aList.begin() + nPos, pAction );
596 }
597 else
598 {
599 m_aList.push_back( pAction );
600 }
601
602 if( m_pPrev )
603 {
604 m_pPrev->AddAction( pAction, nPos );
605 }
606}
607
609{
610 m_aList.push_back( pAction );
611}
612
614{
615 const Size aOldPrefSize( GetPrefSize() );
616 tools::Long nMoveX, nMoveY;
617 double fScaleX, fScaleY;
618
619 if( nMirrorFlags & BmpMirrorFlags::Horizontal )
620 {
621 nMoveX = std::abs( aOldPrefSize.Width() ) - 1;
622 fScaleX = -1.0;
623 }
624 else
625 {
626 nMoveX = 0;
627 fScaleX = 1.0;
628 }
629
630 if( nMirrorFlags & BmpMirrorFlags::Vertical )
631 {
632 nMoveY = std::abs( aOldPrefSize.Height() ) - 1;
633 fScaleY = -1.0;
634 }
635 else
636 {
637 nMoveY = 0;
638 fScaleY = 1.0;
639 }
640
641 if( ( fScaleX != 1.0 ) || ( fScaleY != 1.0 ) )
642 {
643 Scale( fScaleX, fScaleY );
644 Move( nMoveX, nMoveY );
645 SetPrefSize( aOldPrefSize );
646 }
647}
648
650{
651 const Size aBaseOffset( nX, nY );
652 Size aOffset( aBaseOffset );
654
655 aMapVDev->EnableOutput( false );
656 aMapVDev->SetMapMode( GetPrefMapMode() );
657
658 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
659 {
660 const MetaActionType nType = pAct->GetType();
661 MetaAction* pModAct;
662
663 if( pAct->GetRefCount() > 1 )
664 {
665 m_aList[ m_nCurrentActionElement ] = pAct->Clone();
666 pModAct = m_aList[ m_nCurrentActionElement ].get();
667 }
668 else
669 pModAct = pAct;
670
671 if( ( MetaActionType::MAPMODE == nType ) ||
674 {
675 pModAct->Execute( aMapVDev.get() );
676 aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
677 }
678
679 pModAct->Move( aOffset.Width(), aOffset.Height() );
680 }
681}
682
684{
685 const Size aBaseOffset( nX, nY );
686 Size aOffset( aBaseOffset );
688
689 aMapVDev->EnableOutput( false );
690 aMapVDev->SetReferenceDevice( nDPIX, nDPIY );
691 aMapVDev->SetMapMode( GetPrefMapMode() );
692
693 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
694 {
695 const MetaActionType nType = pAct->GetType();
696 MetaAction* pModAct;
697
698 if( pAct->GetRefCount() > 1 )
699 {
700 m_aList[ m_nCurrentActionElement ] = pAct->Clone();
701 pModAct = m_aList[ m_nCurrentActionElement ].get();
702 }
703 else
704 pModAct = pAct;
705
706 if( ( MetaActionType::MAPMODE == nType ) ||
709 {
710 pModAct->Execute( aMapVDev.get() );
711 if( aMapVDev->GetMapMode().GetMapUnit() == MapUnit::MapPixel )
712 {
713 aOffset = aMapVDev->LogicToPixel( aBaseOffset, GetPrefMapMode() );
714 MapMode aMap( aMapVDev->GetMapMode() );
715 aOffset.setWidth( static_cast<tools::Long>(aOffset.Width() * static_cast<double>(aMap.GetScaleX())) );
716 aOffset.setHeight( static_cast<tools::Long>(aOffset.Height() * static_cast<double>(aMap.GetScaleY())) );
717 }
718 else
719 aOffset = OutputDevice::LogicToLogic( aBaseOffset, GetPrefMapMode(), aMapVDev->GetMapMode() );
720 }
721
722 pModAct->Move( aOffset.Width(), aOffset.Height() );
723 }
724}
725
726void GDIMetaFile::Scale( double fScaleX, double fScaleY )
727{
728 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
729 {
730 MetaAction* pModAct;
731
732 if( pAct->GetRefCount() > 1 )
733 {
734 m_aList[ m_nCurrentActionElement ] = pAct->Clone();
735 pModAct = m_aList[ m_nCurrentActionElement ].get();
736 }
737 else
738 pModAct = pAct;
739
740 pModAct->Scale( fScaleX, fScaleY );
741 }
742
743 m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) );
745}
746
747void GDIMetaFile::Scale( const Fraction& rScaleX, const Fraction& rScaleY )
748{
749 Scale( static_cast<double>(rScaleX), static_cast<double>(rScaleY) );
750}
751
752void GDIMetaFile::Clip( const tools::Rectangle& i_rClipRect )
753{
754 tools::Rectangle aCurRect( i_rClipRect );
756
757 aMapVDev->EnableOutput( false );
758 aMapVDev->SetMapMode( GetPrefMapMode() );
759
760 for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
761 {
762 const MetaActionType nType = pAct->GetType();
763
764 if( ( MetaActionType::MAPMODE == nType ) ||
767 {
768 pAct->Execute( aMapVDev.get() );
769 aCurRect = OutputDevice::LogicToLogic( i_rClipRect, GetPrefMapMode(), aMapVDev->GetMapMode() );
770 }
772 {
773 MetaClipRegionAction* pOldAct = static_cast<MetaClipRegionAction*>(pAct);
774 vcl::Region aNewReg( aCurRect );
775 if( pOldAct->IsClipping() )
776 aNewReg.Intersect( pOldAct->GetRegion() );
777 MetaClipRegionAction* pNewAct = new MetaClipRegionAction( std::move(aNewReg), true );
778 m_aList[ m_nCurrentActionElement ] = pNewAct;
779 }
780 }
781}
782
783Point GDIMetaFile::ImplGetRotatedPoint( const Point& rPt, const Point& rRotatePt,
784 const Size& rOffset, double fSin, double fCos )
785{
786 const tools::Long nX = rPt.X() - rRotatePt.X();
787 const tools::Long nY = rPt.Y() - rRotatePt.Y();
788
789 return Point( FRound( fCos * nX + fSin * nY ) + rRotatePt.X() + rOffset.Width(),
790 -FRound( fSin * nX - fCos * nY ) + rRotatePt.Y() + rOffset.Height() );
791}
792
794 const Size& rOffset, double fSin, double fCos )
795{
796 tools::Polygon aRet( rPoly );
797
798 aRet.Rotate( rRotatePt, fSin, fCos );
799 aRet.Move( rOffset.Width(), rOffset.Height() );
800
801 return aRet;
802}
803
805 const Size& rOffset, double fSin, double fCos )
806{
807 tools::PolyPolygon aRet( rPolyPoly );
808
809 aRet.Rotate( rRotatePt, fSin, fCos );
810 aRet.Move( rOffset.Width(), rOffset.Height() );
811
812 return aRet;
813}
814
816 const OutputDevice& rMapDev,
817 const tools::PolyPolygon& rPolyPoly,
818 const Gradient& rGrad )
819{
820 // Generate comment, GradientEx and Gradient actions (within DrawGradient)
822 aVDev->EnableOutput( false );
823 GDIMetaFile aGradMtf;
824
825 aGradMtf.Record( aVDev.get() );
826 aVDev->DrawGradient( rPolyPoly, rGrad );
827 aGradMtf.Stop();
828
829 size_t i, nAct( aGradMtf.GetActionSize() );
830 for( i=0; i < nAct; ++i )
831 {
832 MetaAction* pMetaAct = aGradMtf.GetAction( i );
833 rMtf.AddAction( pMetaAct );
834 }
835}
836
838{
839 nAngle10 %= 3600_deg10;
840 nAngle10 = ( nAngle10 < 0_deg10 ) ? ( Degree10(3599) + nAngle10 ) : nAngle10;
841
842 if( !nAngle10 )
843 return;
844
845 GDIMetaFile aMtf;
847 const double fAngle = toRadians(nAngle10);
848 const double fSin = sin( fAngle );
849 const double fCos = cos( fAngle );
850 tools::Rectangle aRect( Point(), GetPrefSize() );
851 tools::Polygon aPoly( aRect );
852
853 aPoly.Rotate( Point(), fSin, fCos );
854
855 aMapVDev->EnableOutput( false );
856 aMapVDev->SetMapMode( GetPrefMapMode() );
857
858 const tools::Rectangle aNewBound( aPoly.GetBoundRect() );
859
860 const Point aOrigin( GetPrefMapMode().GetOrigin().X(), GetPrefMapMode().GetOrigin().Y() );
861 const Size aOffset( -aNewBound.Left(), -aNewBound.Top() );
862
863 Point aRotAnchor( aOrigin );
864 Size aRotOffset( aOffset );
865
866 for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
867 {
868 const MetaActionType nActionType = pAction->GetType();
869
870 switch( nActionType )
871 {
873 {
874 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
875 aMtf.AddAction( new MetaPixelAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
876 pAct->GetColor() ) );
877 }
878 break;
879
881 {
882 MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
883 aMtf.AddAction( new MetaPointAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
884 }
885 break;
886
888 {
889 MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
890 aMtf.AddAction( new MetaLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
891 ImplGetRotatedPoint( pAct->GetEndPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
892 pAct->GetLineInfo() ) );
893 }
894 break;
895
897 {
898 MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
899 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
900 }
901 break;
902
904 {
905 MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
906 const tools::Polygon aRoundRectPoly( pAct->GetRect(), pAct->GetHorzRound(), pAct->GetVertRound() );
907
908 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aRoundRectPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
909 }
910 break;
911
913 {
914 MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
915 const tools::Polygon aEllipsePoly( pAct->GetRect().Center(), pAct->GetRect().GetWidth() >> 1, pAct->GetRect().GetHeight() >> 1 );
916
917 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aEllipsePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
918 }
919 break;
920
922 {
923 MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
924 const tools::Polygon aArcPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Arc );
925
926 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aArcPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
927 }
928 break;
929
931 {
932 MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
933 const tools::Polygon aPiePoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Pie );
934
935 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aPiePoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
936 }
937 break;
938
940 {
941 MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
942 const tools::Polygon aChordPoly( pAct->GetRect(), pAct->GetStartPoint(), pAct->GetEndPoint(), PolyStyle::Chord );
943
944 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( aChordPoly, aRotAnchor, aRotOffset, fSin, fCos ) ) );
945 }
946 break;
947
949 {
950 MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
951 aMtf.AddAction( new MetaPolyLineAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->GetLineInfo() ) );
952 }
953 break;
954
956 {
957 MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
958 aMtf.AddAction( new MetaPolygonAction( ImplGetRotatedPolygon( pAct->GetPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
959 }
960 break;
961
963 {
964 MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
965 aMtf.AddAction( new MetaPolyPolygonAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) );
966 }
967 break;
968
970 {
971 MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
972 aMtf.AddAction( new MetaTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
973 pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
974 }
975 break;
976
978 {
979 MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
980 aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
981 pAct->GetText(), pAct->GetDXArray(), pAct->GetKashidaArray(), pAct->GetIndex(), pAct->GetLen() ) );
982 }
983 break;
984
986 {
987 MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
988 aMtf.AddAction( new MetaStretchTextAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
989 pAct->GetWidth(), pAct->GetText(), pAct->GetIndex(), pAct->GetLen() ) );
990 }
991 break;
992
994 {
995 MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
996 aMtf.AddAction( new MetaTextLineAction( ImplGetRotatedPoint( pAct->GetStartPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
997 pAct->GetWidth(), pAct->GetStrikeout(), pAct->GetUnderline(), pAct->GetOverline() ) );
998 }
999 break;
1000
1002 {
1003 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1004 tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1005 tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1006 BitmapEx aBmpEx( pAct->GetBitmap() );
1007
1008 aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1009 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(),
1010 aBmpEx ) );
1011 }
1012 break;
1013
1015 {
1016 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1017 tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1018 tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1019 BitmapEx aBmpEx( pAct->GetBitmap() );
1020
1021 aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1022 aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1023
1024 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1025 }
1026 break;
1027
1029 {
1030 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1031 tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1032 tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1033 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1034
1035 aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1036
1037 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1038 }
1039 break;
1040
1042 {
1043 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1044 tools::Polygon aBmpPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetDestPoint(), pAct->GetDestSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1045 tools::Rectangle aBmpRect( aBmpPoly.GetBoundRect() );
1046 BitmapEx aBmpEx( pAct->GetBitmapEx() );
1047
1048 aBmpEx.Crop( tools::Rectangle( pAct->GetSrcPoint(), pAct->GetSrcSize() ) );
1049 aBmpEx.Rotate( nAngle10, COL_TRANSPARENT );
1050
1051 aMtf.AddAction( new MetaBmpExScaleAction( aBmpRect.TopLeft(), aBmpRect.GetSize(), aBmpEx ) );
1052 }
1053 break;
1054
1056 {
1057 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1058
1059 ImplAddGradientEx( aMtf, *aMapVDev,
1060 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor, aRotOffset, fSin, fCos ),
1061 pAct->GetGradient() );
1062 }
1063 break;
1064
1066 {
1067 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1068 aMtf.AddAction( new MetaGradientExAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1069 pAct->GetGradient() ) );
1070 }
1071 break;
1072
1073 // Handle gradientex comment block correctly
1075 {
1076 MetaCommentAction* pCommentAct = static_cast<MetaCommentAction*>(pAction);
1077 if( pCommentAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1078 {
1079 int nBeginComments( 1 );
1080 pAction = NextAction();
1081
1082 // skip everything, except gradientex action
1083 while( pAction )
1084 {
1085 const MetaActionType nType = pAction->GetType();
1086
1088 {
1089 // Add rotated gradientex
1090 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1091 ImplAddGradientEx( aMtf, *aMapVDev,
1092 ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1093 pAct->GetGradient() );
1094 }
1095 else if( MetaActionType::COMMENT == nType)
1096 {
1097 MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pAction);
1098 if( pAct->GetComment() == "XGRAD_SEQ_END" )
1099 {
1100 // handle nested blocks
1101 --nBeginComments;
1102
1103 // gradientex comment block: end reached, done.
1104 if( !nBeginComments )
1105 break;
1106 }
1107 else if( pAct->GetComment() == "XGRAD_SEQ_BEGIN" )
1108 {
1109 // handle nested blocks
1110 ++nBeginComments;
1111 }
1112
1113 }
1114
1115 pAction =NextAction();
1116 }
1117 }
1118 else
1119 {
1120 bool bPathStroke = (pCommentAct->GetComment() == "XPATHSTROKE_SEQ_BEGIN");
1121 if ( bPathStroke || pCommentAct->GetComment() == "XPATHFILL_SEQ_BEGIN" )
1122 {
1123 if ( pCommentAct->GetDataSize() )
1124 {
1125 SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pCommentAct->GetData()), pCommentAct->GetDataSize(), StreamMode::READ );
1126 SvMemoryStream aDest;
1127 if ( bPathStroke )
1128 {
1129 SvtGraphicStroke aStroke;
1130 ReadSvtGraphicStroke( aMemStm, aStroke );
1131 tools::Polygon aPath;
1132 aStroke.getPath( aPath );
1133 aStroke.setPath( ImplGetRotatedPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1134 WriteSvtGraphicStroke( aDest, aStroke );
1135 aMtf.AddAction( new MetaCommentAction( "XPATHSTROKE_SEQ_BEGIN", 0,
1136 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1137 }
1138 else
1139 {
1140 SvtGraphicFill aFill;
1141 ReadSvtGraphicFill( aMemStm, aFill );
1142 tools::PolyPolygon aPath;
1143 aFill.getPath( aPath );
1144 aFill.setPath( ImplGetRotatedPolyPolygon( aPath, aRotAnchor, aRotOffset, fSin, fCos ) );
1145 WriteSvtGraphicFill( aDest, aFill );
1146 aMtf.AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
1147 static_cast<const sal_uInt8*>( aDest.GetData()), aDest.Tell() ) );
1148 }
1149 }
1150 }
1151 else if ( pCommentAct->GetComment() == "XPATHSTROKE_SEQ_END"
1152 || pCommentAct->GetComment() == "XPATHFILL_SEQ_END" )
1153 {
1154 pAction->Execute( aMapVDev.get() );
1155 aMtf.AddAction( pAction );
1156 }
1157 }
1158 }
1159 break;
1160
1162 {
1163 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1164 Hatch aHatch( pAct->GetHatch() );
1165
1166 aHatch.SetAngle( aHatch.GetAngle() + nAngle10 );
1167 aMtf.AddAction( new MetaHatchAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1168 aHatch ) );
1169 }
1170 break;
1171
1173 {
1174 MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1175 aMtf.AddAction( new MetaTransparentAction( ImplGetRotatedPolyPolygon( pAct->GetPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ),
1176 pAct->GetTransparence() ) );
1177 }
1178 break;
1179
1181 {
1182 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1183 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
1184 tools::Polygon aMtfPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1185 tools::Rectangle aMtfRect( aMtfPoly.GetBoundRect() );
1186
1187 aTransMtf.Rotate( nAngle10 );
1188 aMtf.AddAction( new MetaFloatTransparentAction( aTransMtf, aMtfRect.TopLeft(), aMtfRect.GetSize(),
1189 pAct->GetGradient() ) );
1190 }
1191 break;
1192
1194 {
1195 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1196 GDIMetaFile aEPSMtf( pAct->GetSubstitute() );
1197 tools::Polygon aEPSPoly( ImplGetRotatedPolygon( tools::Rectangle( pAct->GetPoint(), pAct->GetSize() ), aRotAnchor, aRotOffset, fSin, fCos ) );
1198 tools::Rectangle aEPSRect( aEPSPoly.GetBoundRect() );
1199
1200 aEPSMtf.Rotate( nAngle10 );
1201 aMtf.AddAction( new MetaEPSAction( aEPSRect.TopLeft(), aEPSRect.GetSize(),
1202 pAct->GetLink(), aEPSMtf ) );
1203 }
1204 break;
1205
1207 {
1208 MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1209
1210 if( pAct->IsClipping() && pAct->GetRegion().HasPolyPolygonOrB2DPolyPolygon() )
1211 aMtf.AddAction( new MetaClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( pAct->GetRegion().GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ), true ) );
1212 else
1213 {
1214 aMtf.AddAction( pAction );
1215 }
1216 }
1217 break;
1218
1220 {
1221 MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1223 ImplGetRotatedPolygon( pAct->GetRect(), aRotAnchor,
1224 aRotOffset, fSin, fCos )) ) );
1225 }
1226 break;
1227
1229 {
1231 const vcl::Region& rRegion = pAct->GetRegion();
1232
1233 if( rRegion.HasPolyPolygonOrB2DPolyPolygon() )
1234 aMtf.AddAction( new MetaISectRegionClipRegionAction( vcl::Region( ImplGetRotatedPolyPolygon( rRegion.GetAsPolyPolygon(), aRotAnchor, aRotOffset, fSin, fCos ) ) ) );
1235 else
1236 {
1237 aMtf.AddAction( pAction );
1238 }
1239 }
1240 break;
1241
1243 {
1244 MetaRefPointAction* pAct = static_cast<MetaRefPointAction*>(pAction);
1245 aMtf.AddAction( new MetaRefPointAction( ImplGetRotatedPoint( pAct->GetRefPoint(), aRotAnchor, aRotOffset, fSin, fCos ), pAct->IsSetting() ) );
1246 }
1247 break;
1248
1250 {
1251 MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1252 vcl::Font aFont( pAct->GetFont() );
1253
1254 aFont.SetOrientation( aFont.GetOrientation() + nAngle10 );
1255 aMtf.AddAction( new MetaFontAction( std::move(aFont) ) );
1256 }
1257 break;
1258
1267 {
1268 OSL_FAIL( "GDIMetaFile::Rotate(): unsupported action" );
1269 }
1270 break;
1271
1272 default:
1273 {
1274 pAction->Execute( aMapVDev.get() );
1275 aMtf.AddAction( pAction );
1276
1277 // update rotation point and offset, if necessary
1278 if( ( MetaActionType::MAPMODE == nActionType ) ||
1279 ( MetaActionType::PUSH == nActionType ) ||
1280 ( MetaActionType::POP == nActionType ) )
1281 {
1282 aRotAnchor = OutputDevice::LogicToLogic( aOrigin, m_aPrefMapMode, aMapVDev->GetMapMode() );
1283 aRotOffset = OutputDevice::LogicToLogic( aOffset, m_aPrefMapMode, aMapVDev->GetMapMode() );
1284 }
1285 }
1286 break;
1287 }
1288 }
1289
1291 aMtf.m_aPrefSize = aNewBound.GetSize();
1292
1293 *this = aMtf;
1294
1295}
1296
1297static void ImplActionBounds( tools::Rectangle& o_rOutBounds,
1298 const tools::Rectangle& i_rInBounds,
1299 const std::vector<tools::Rectangle>& i_rClipStack )
1300{
1301 tools::Rectangle aBounds( i_rInBounds );
1302 if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
1303 aBounds.Intersection( i_rClipStack.back() );
1304 if( aBounds.IsEmpty() )
1305 return;
1306
1307 if( ! o_rOutBounds.IsEmpty() )
1308 o_rOutBounds.Union( aBounds );
1309 else
1310 o_rOutBounds = aBounds;
1311}
1312
1314{
1315 ScopedVclPtrInstance< VirtualDevice > aMapVDev( i_rReference );
1316
1317 aMapVDev->EnableOutput( false );
1318 aMapVDev->SetMapMode( GetPrefMapMode() );
1319
1320 std::vector<tools::Rectangle> aClipStack( 1, tools::Rectangle() );
1321 std::vector<vcl::PushFlags> aPushFlagStack;
1322
1323 tools::Rectangle aBound;
1325
1326 for(sal_uLong a(0); a < nCount; a++)
1327 {
1328 MetaAction* pAction = GetAction(a);
1329 const MetaActionType nActionType = pAction->GetType();
1330
1331 switch( nActionType )
1332 {
1334 {
1335 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1336 ImplActionBounds( aBound,
1337 tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1338 aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1339 aClipStack );
1340 }
1341 break;
1342
1344 {
1345 MetaPointAction* pAct = static_cast<MetaPointAction*>(pAction);
1346 ImplActionBounds( aBound,
1347 tools::Rectangle( OutputDevice::LogicToLogic( pAct->GetPoint(), aMapVDev->GetMapMode(), GetPrefMapMode() ),
1348 aMapVDev->PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
1349 aClipStack );
1350 }
1351 break;
1352
1354 {
1355 MetaLineAction* pAct = static_cast<MetaLineAction*>(pAction);
1356 Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
1357 tools::Rectangle aRect( aP1, aP2 );
1358 aRect.Normalize();
1359
1360 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1361 }
1362 break;
1363
1365 {
1366 MetaRectAction* pAct = static_cast<MetaRectAction*>(pAction);
1367 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1368 }
1369 break;
1370
1372 {
1373 MetaRoundRectAction* pAct = static_cast<MetaRoundRectAction*>(pAction);
1374 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1375 }
1376 break;
1377
1379 {
1380 MetaEllipseAction* pAct = static_cast<MetaEllipseAction*>(pAction);
1381 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1382 }
1383 break;
1384
1386 {
1387 MetaArcAction* pAct = static_cast<MetaArcAction*>(pAction);
1388 // FIXME: this is imprecise
1389 // e.g. for small arcs the whole rectangle is WAY too large
1390 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1391 }
1392 break;
1393
1395 {
1396 MetaPieAction* pAct = static_cast<MetaPieAction*>(pAction);
1397 // FIXME: this is imprecise
1398 // e.g. for small arcs the whole rectangle is WAY too large
1399 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1400 }
1401 break;
1402
1404 {
1405 MetaChordAction* pAct = static_cast<MetaChordAction*>(pAction);
1406 // FIXME: this is imprecise
1407 // e.g. for small arcs the whole rectangle is WAY too large
1408 ImplActionBounds( aBound, OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1409 }
1410 break;
1411
1413 {
1414 MetaPolyLineAction* pAct = static_cast<MetaPolyLineAction*>(pAction);
1415 tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1416
1417 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1418 }
1419 break;
1420
1422 {
1423 MetaPolygonAction* pAct = static_cast<MetaPolygonAction*>(pAction);
1424 tools::Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
1425 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1426 }
1427 break;
1428
1430 {
1431 MetaPolyPolygonAction* pAct = static_cast<MetaPolyPolygonAction*>(pAction);
1432 tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1433 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1434 }
1435 break;
1436
1438 {
1439 MetaTextAction* pAct = static_cast<MetaTextAction*>(pAction);
1440 tools::Rectangle aRect;
1441 // hdu said base = index
1442 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
1443 Point aPt( pAct->GetPoint() );
1444 aRect.Move( aPt.X(), aPt.Y() );
1445 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1446 }
1447 break;
1448
1450 {
1451 MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
1452 tools::Rectangle aRect;
1453 // hdu said base = index
1454 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1455 0, pAct->GetDXArray(), pAct->GetKashidaArray() );
1456 Point aPt( pAct->GetPoint() );
1457 aRect.Move( aPt.X(), aPt.Y() );
1458 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1459 }
1460 break;
1461
1463 {
1464 MetaStretchTextAction* pAct = static_cast<MetaStretchTextAction*>(pAction);
1465 tools::Rectangle aRect;
1466 // hdu said base = index
1467 aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
1468 pAct->GetWidth() );
1469 Point aPt( pAct->GetPoint() );
1470 aRect.Move( aPt.X(), aPt.Y() );
1471 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1472 }
1473 break;
1474
1476 {
1477 MetaTextLineAction* pAct = static_cast<MetaTextLineAction*>(pAction);
1478 // measure a test string to get ascend and descent right
1479 static constexpr OUStringLiteral pStr = u"\u00c4g";
1480 OUString aStr( pStr );
1481
1482 tools::Rectangle aRect;
1483 aMapVDev->GetTextBoundRect( aRect, aStr, 0, 0, aStr.getLength() );
1484 Point aPt( pAct->GetStartPoint() );
1485 aRect.Move( aPt.X(), aPt.Y() );
1486 aRect.SetRight( aRect.Left() + pAct->GetWidth() );
1487 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1488 }
1489 break;
1490
1492 {
1493 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1494 tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1495 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1496 }
1497 break;
1498
1500 {
1501 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1502 tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1503 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1504 }
1505 break;
1506
1508 {
1509 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1510 tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1511 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1512 }
1513 break;
1514
1516 {
1517 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1518 tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1519 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1520 }
1521 break;
1522
1524 {
1525 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1526 tools::Rectangle aRect( pAct->GetRect() );
1527 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1528 }
1529 break;
1530
1532 {
1533 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
1534 tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1535 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1536 }
1537 break;
1538
1540 {
1541 // nothing to do
1542 };
1543 break;
1544
1546 {
1547 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
1548 tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1549 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1550 }
1551 break;
1552
1554 {
1555 MetaTransparentAction* pAct = static_cast<MetaTransparentAction*>(pAction);
1556 tools::Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
1557 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1558 }
1559 break;
1560
1562 {
1563 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
1564 // MetaFloatTransparentAction is defined limiting its content Metafile
1565 // to its geometry definition(Point, Size), so use these directly
1566 const tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1567 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1568 }
1569 break;
1570
1572 {
1573 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
1574 tools::Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
1575 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1576 }
1577 break;
1578
1580 {
1581 MetaClipRegionAction* pAct = static_cast<MetaClipRegionAction*>(pAction);
1582 if( pAct->IsClipping() )
1583 aClipStack.back() = OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() );
1584 else
1585 aClipStack.back() = tools::Rectangle();
1586 }
1587 break;
1588
1590 {
1591 MetaISectRectClipRegionAction* pAct = static_cast<MetaISectRectClipRegionAction*>(pAction);
1592 tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1593 if( aClipStack.back().IsEmpty() )
1594 aClipStack.back() = aRect;
1595 else
1596 aClipStack.back().Intersection( aRect );
1597 }
1598 break;
1599
1601 {
1603 tools::Rectangle aRect( OutputDevice::LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev->GetMapMode(), GetPrefMapMode() ) );
1604 if( aClipStack.back().IsEmpty() )
1605 aClipStack.back() = aRect;
1606 else
1607 aClipStack.back().Intersection( aRect );
1608 }
1609 break;
1610
1612 {
1613 MetaBmpAction* pAct = static_cast<MetaBmpAction*>(pAction);
1614 tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1615 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1616 }
1617 break;
1618
1620 {
1621 MetaBmpExAction* pAct = static_cast<MetaBmpExAction*>(pAction);
1622 tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
1623 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1624 }
1625 break;
1626
1628 {
1629 MetaMaskAction* pAct = static_cast<MetaMaskAction*>(pAction);
1630 tools::Rectangle aRect( pAct->GetPoint(), aMapVDev->PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
1631 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1632 }
1633 break;
1634
1636 {
1637 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1638 tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1639 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1640 }
1641 break;
1642
1644 {
1645 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1646 tools::Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
1647 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1648 }
1649 break;
1650
1652 {
1653 MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1654 tools::Rectangle aRect( pAct->GetRect() );
1655 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1656 }
1657 break;
1658
1660 {
1661 MetaTextRectAction* pAct = static_cast<MetaTextRectAction*>(pAction);
1662 tools::Rectangle aRect( pAct->GetRect() );
1663 ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
1664 }
1665 break;
1666
1668 {
1669 MetaMoveClipRegionAction* pAct = static_cast<MetaMoveClipRegionAction*>(pAction);
1670 if( ! aClipStack.back().IsEmpty() )
1671 {
1672 Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
1673 aDelta = OutputDevice::LogicToLogic( aDelta, aMapVDev->GetMapMode(), GetPrefMapMode() );
1674 aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
1675 }
1676 }
1677 break;
1678
1679 default:
1680 {
1681 pAction->Execute( aMapVDev.get() );
1682
1683 if( nActionType == MetaActionType::PUSH )
1684 {
1685 MetaPushAction* pAct = static_cast<MetaPushAction*>(pAction);
1686 aPushFlagStack.push_back( pAct->GetFlags() );
1687 if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1688 {
1689 tools::Rectangle aRect( aClipStack.back() );
1690 aClipStack.push_back( aRect );
1691 }
1692 }
1693 else if( nActionType == MetaActionType::POP )
1694 {
1695 // sanity check
1696 if( ! aPushFlagStack.empty() )
1697 {
1698 if( aPushFlagStack.back() & vcl::PushFlags::CLIPREGION )
1699 {
1700 if( aClipStack.size() > 1 )
1701 aClipStack.pop_back();
1702 }
1703 aPushFlagStack.pop_back();
1704 }
1705 }
1706 }
1707 break;
1708 }
1709 }
1710 return aBound;
1711}
1712
1713Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
1714{
1715 return Color( ColorAlpha, rColor.GetAlpha(),
1716 static_cast<const ImplColAdjustParam*>(pColParam)->pMapR[ rColor.GetRed() ],
1717 static_cast<const ImplColAdjustParam*>(pColParam)->pMapG[ rColor.GetGreen() ],
1718 static_cast<const ImplColAdjustParam*>(pColParam)->pMapB[ rColor.GetBlue() ] );
1719
1720}
1721
1722BitmapEx GDIMetaFile::ImplBmpAdjustFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1723{
1724 const ImplBmpAdjustParam* p = static_cast<const ImplBmpAdjustParam*>(pBmpParam);
1725 BitmapEx aRet( rBmpEx );
1726
1727 aRet.Adjust( p->nLuminancePercent, p->nContrastPercent,
1728 p->nChannelRPercent, p->nChannelGPercent, p->nChannelBPercent,
1729 p->fGamma, p->bInvert );
1730
1731 return aRet;
1732}
1733
1734Color GDIMetaFile::ImplColConvertFnc( const Color& rColor, const void* pColParam )
1735{
1736 sal_uInt8 cLum = rColor.GetLuminance();
1737
1738 if( MtfConversion::N1BitThreshold == static_cast<const ImplColConvertParam*>(pColParam)->eConversion )
1739 cLum = ( cLum < 128 ) ? 0 : 255;
1740
1741 return Color( ColorTransparency, 255 - rColor.GetAlpha(), cLum, cLum, cLum );
1742}
1743
1744BitmapEx GDIMetaFile::ImplBmpConvertFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1745{
1746 BitmapEx aRet( rBmpEx );
1747
1748 aRet.Convert( static_cast<const ImplBmpConvertParam*>(pBmpParam)->eConversion );
1749
1750 return aRet;
1751}
1752
1753Color GDIMetaFile::ImplColMonoFnc( const Color&, const void* pColParam )
1754{
1755 return static_cast<const ImplColMonoParam*>(pColParam)->aColor;
1756}
1757
1758BitmapEx GDIMetaFile::ImplBmpMonoFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1759{
1760 BitmapPalette aPal( 3 );
1761 aPal[ 0 ] = COL_BLACK;
1762 aPal[ 1 ] = COL_WHITE;
1763 aPal[ 2 ] = static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor;
1764
1765 Bitmap aBmp(rBmpEx.GetSizePixel(), vcl::PixelFormat::N8_BPP, &aPal);
1766 aBmp.Erase( static_cast<const ImplBmpMonoParam*>(pBmpParam)->aColor );
1767
1768 if( rBmpEx.IsAlpha() )
1769 return BitmapEx( aBmp, rBmpEx.GetAlpha() );
1770 else
1771 return BitmapEx( aBmp );
1772}
1773
1774Color GDIMetaFile::ImplColReplaceFnc( const Color& rColor, const void* pColParam )
1775{
1776 const sal_uLong nR = rColor.GetRed(), nG = rColor.GetGreen(), nB = rColor.GetBlue();
1777
1778 for( sal_uLong i = 0; i < static_cast<const ImplColReplaceParam*>(pColParam)->nCount; i++ )
1779 {
1780 if( ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinR[ i ] <= nR ) &&
1781 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxR[ i ] >= nR ) &&
1782 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinG[ i ] <= nG ) &&
1783 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxG[ i ] >= nG ) &&
1784 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMinB[ i ] <= nB ) &&
1785 ( static_cast<const ImplColReplaceParam*>(pColParam)->pMaxB[ i ] >= nB ) )
1786 {
1787 return static_cast<const ImplColReplaceParam*>(pColParam)->pDstCols[ i ];
1788 }
1789 }
1790
1791 return rColor;
1792}
1793
1794BitmapEx GDIMetaFile::ImplBmpReplaceFnc( const BitmapEx& rBmpEx, const void* pBmpParam )
1795{
1796 const ImplBmpReplaceParam* p = static_cast<const ImplBmpReplaceParam*>(pBmpParam);
1797 BitmapEx aRet( rBmpEx );
1798
1799 aRet.Replace( p->pSrcCols, p->pDstCols, p->nCount );
1800
1801 return aRet;
1802}
1803
1804void GDIMetaFile::ImplExchangeColors( ColorExchangeFnc pFncCol, const void* pColParam,
1805 BmpExchangeFnc pFncBmp, const void* pBmpParam )
1806{
1807 GDIMetaFile aMtf;
1808
1809 aMtf.m_aPrefSize = m_aPrefSize;
1812
1813 for( MetaAction* pAction = FirstAction(); pAction; pAction = NextAction() )
1814 {
1815 const MetaActionType nType = pAction->GetType();
1816
1817 switch( nType )
1818 {
1820 {
1821 MetaPixelAction* pAct = static_cast<MetaPixelAction*>(pAction);
1822 aMtf.push_back( new MetaPixelAction( pAct->GetPoint(), pFncCol( pAct->GetColor(), pColParam ) ) );
1823 }
1824 break;
1825
1827 {
1828 MetaLineColorAction* pAct = static_cast<MetaLineColorAction*>(pAction);
1829
1830 if( pAct->IsSetting() )
1831 pAct = new MetaLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1832
1833 aMtf.push_back( pAct );
1834 }
1835 break;
1836
1838 {
1839 MetaFillColorAction* pAct = static_cast<MetaFillColorAction*>(pAction);
1840
1841 if( pAct->IsSetting() )
1842 pAct = new MetaFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1843
1844 aMtf.push_back( pAct );
1845 }
1846 break;
1847
1849 {
1850 MetaTextColorAction* pAct = static_cast<MetaTextColorAction*>(pAction);
1851 aMtf.push_back( new MetaTextColorAction( pFncCol( pAct->GetColor(), pColParam ) ) );
1852 }
1853 break;
1854
1856 {
1857 MetaTextFillColorAction* pAct = static_cast<MetaTextFillColorAction*>(pAction);
1858
1859 if( pAct->IsSetting() )
1860 pAct = new MetaTextFillColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1861
1862 aMtf.push_back( pAct );
1863 }
1864 break;
1865
1867 {
1868 MetaTextLineColorAction* pAct = static_cast<MetaTextLineColorAction*>(pAction);
1869
1870 if( pAct->IsSetting() )
1871 pAct = new MetaTextLineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1872
1873 aMtf.push_back( pAct );
1874 }
1875 break;
1876
1878 {
1879 MetaOverlineColorAction* pAct = static_cast<MetaOverlineColorAction*>(pAction);
1880
1881 if( pAct->IsSetting() )
1882 pAct = new MetaOverlineColorAction( pFncCol( pAct->GetColor(), pColParam ), true );
1883
1884 aMtf.push_back( pAct );
1885 }
1886 break;
1887
1889 {
1890 MetaFontAction* pAct = static_cast<MetaFontAction*>(pAction);
1891 vcl::Font aFont( pAct->GetFont() );
1892
1893 aFont.SetColor( pFncCol( aFont.GetColor(), pColParam ) );
1894 aFont.SetFillColor( pFncCol( aFont.GetFillColor(), pColParam ) );
1895 aMtf.push_back( new MetaFontAction( std::move(aFont) ) );
1896 }
1897 break;
1898
1900 {
1901 MetaWallpaperAction* pAct = static_cast<MetaWallpaperAction*>(pAction);
1902 Wallpaper aWall( pAct->GetWallpaper() );
1903 const tools::Rectangle& rRect = pAct->GetRect();
1904
1905 aWall.SetColor( pFncCol( aWall.GetColor(), pColParam ) );
1906
1907 if( aWall.IsBitmap() )
1908 aWall.SetBitmap( pFncBmp( aWall.GetBitmap(), pBmpParam ) );
1909
1910 if( aWall.IsGradient() )
1911 {
1912 Gradient aGradient( aWall.GetGradient() );
1913
1914 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1915 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1916 aWall.SetGradient( aGradient );
1917 }
1918
1919 aMtf.push_back( new MetaWallpaperAction( rRect, std::move(aWall) ) );
1920 }
1921 break;
1922
1926 {
1927 OSL_FAIL( "Don't use bitmap actions of this type in metafiles!" );
1928 }
1929 break;
1930
1932 {
1933 MetaBmpScaleAction* pAct = static_cast<MetaBmpScaleAction*>(pAction);
1934 aMtf.push_back( new MetaBmpScaleAction( pAct->GetPoint(), pAct->GetSize(),
1935 pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() ) );
1936 }
1937 break;
1938
1940 {
1941 MetaBmpScalePartAction* pAct = static_cast<MetaBmpScalePartAction*>(pAction);
1942 aMtf.push_back( new MetaBmpScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1943 pAct->GetSrcPoint(), pAct->GetSrcSize(),
1944 pFncBmp( BitmapEx(pAct->GetBitmap()), pBmpParam ).GetBitmap() )
1945 );
1946 }
1947 break;
1948
1950 {
1951 MetaBmpExScaleAction* pAct = static_cast<MetaBmpExScaleAction*>(pAction);
1952 aMtf.push_back( new MetaBmpExScaleAction( pAct->GetPoint(), pAct->GetSize(),
1953 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1954 );
1955 }
1956 break;
1957
1959 {
1960 MetaBmpExScalePartAction* pAct = static_cast<MetaBmpExScalePartAction*>(pAction);
1961 aMtf.push_back( new MetaBmpExScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1962 pAct->GetSrcPoint(), pAct->GetSrcSize(),
1963 pFncBmp( pAct->GetBitmapEx(), pBmpParam ) )
1964 );
1965 }
1966 break;
1967
1969 {
1970 MetaMaskScaleAction* pAct = static_cast<MetaMaskScaleAction*>(pAction);
1971 aMtf.push_back( new MetaMaskScaleAction( pAct->GetPoint(), pAct->GetSize(),
1972 pAct->GetBitmap(),
1973 pFncCol( pAct->GetColor(), pColParam ) )
1974 );
1975 }
1976 break;
1977
1979 {
1980 MetaMaskScalePartAction* pAct = static_cast<MetaMaskScalePartAction*>(pAction);
1981 aMtf.push_back( new MetaMaskScalePartAction( pAct->GetDestPoint(), pAct->GetDestSize(),
1982 pAct->GetSrcPoint(), pAct->GetSrcSize(),
1983 pAct->GetBitmap(),
1984 pFncCol( pAct->GetColor(), pColParam ) )
1985 );
1986 }
1987 break;
1988
1990 {
1991 MetaGradientAction* pAct = static_cast<MetaGradientAction*>(pAction);
1992 Gradient aGradient( pAct->GetGradient() );
1993
1994 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
1995 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
1996 aMtf.push_back( new MetaGradientAction( pAct->GetRect(), std::move(aGradient) ) );
1997 }
1998 break;
1999
2001 {
2002 MetaGradientExAction* pAct = static_cast<MetaGradientExAction*>(pAction);
2003 Gradient aGradient( pAct->GetGradient() );
2004
2005 aGradient.SetStartColor( pFncCol( aGradient.GetStartColor(), pColParam ) );
2006 aGradient.SetEndColor( pFncCol( aGradient.GetEndColor(), pColParam ) );
2007 aMtf.push_back( new MetaGradientExAction( pAct->GetPolyPolygon(), std::move(aGradient) ) );
2008 }
2009 break;
2010
2012 {
2013 MetaHatchAction* pAct = static_cast<MetaHatchAction*>(pAction);
2014 Hatch aHatch( pAct->GetHatch() );
2015
2016 aHatch.SetColor( pFncCol( aHatch.GetColor(), pColParam ) );
2017 aMtf.push_back( new MetaHatchAction( pAct->GetPolyPolygon(), aHatch ) );
2018 }
2019 break;
2020
2022 {
2023 MetaFloatTransparentAction* pAct = static_cast<MetaFloatTransparentAction*>(pAction);
2024 GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
2025
2026 aTransMtf.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2027 aMtf.push_back( new MetaFloatTransparentAction( aTransMtf,
2028 pAct->GetPoint(), pAct->GetSize(),
2029 pAct->GetGradient() )
2030 );
2031 }
2032 break;
2033
2035 {
2036 MetaEPSAction* pAct = static_cast<MetaEPSAction*>(pAction);
2037 GDIMetaFile aSubst( pAct->GetSubstitute() );
2038
2039 aSubst.ImplExchangeColors( pFncCol, pColParam, pFncBmp, pBmpParam );
2040 aMtf.push_back( new MetaEPSAction( pAct->GetPoint(), pAct->GetSize(),
2041 pAct->GetLink(), aSubst )
2042 );
2043 }
2044 break;
2045
2046 default:
2047 {
2048 aMtf.push_back( pAction );
2049 }
2050 break;
2051 }
2052 }
2053
2054 *this = aMtf;
2055}
2056
2057void GDIMetaFile::Adjust( short nLuminancePercent, short nContrastPercent,
2058 short nChannelRPercent, short nChannelGPercent,
2059 short nChannelBPercent, double fGamma, bool bInvert, bool msoBrightness )
2060{
2061 // nothing to do? => return quickly
2062 if( !(nLuminancePercent || nContrastPercent ||
2063 nChannelRPercent || nChannelGPercent || nChannelBPercent ||
2064 ( fGamma != 1.0 ) || bInvert) )
2065 return;
2066
2067 double fM, fROff, fGOff, fBOff, fOff;
2068 ImplColAdjustParam aColParam;
2069 ImplBmpAdjustParam aBmpParam;
2070
2071 aColParam.pMapR.reset(new sal_uInt8[ 256 ]);
2072 aColParam.pMapG.reset(new sal_uInt8[ 256 ]);
2073 aColParam.pMapB.reset(new sal_uInt8[ 256 ]);
2074
2075 // calculate slope
2076 if( nContrastPercent >= 0 )
2077 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
2078 else
2079 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
2080
2081 if(!msoBrightness)
2082 // total offset = luminance offset + contrast offset
2083 fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
2084 else
2085 fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
2086
2087 // channel offset = channel offset + total offset
2088 fROff = nChannelRPercent * 2.55 + fOff;
2089 fGOff = nChannelGPercent * 2.55 + fOff;
2090 fBOff = nChannelBPercent * 2.55 + fOff;
2091
2092 // calculate gamma value
2093 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
2094 const bool bGamma = ( fGamma != 1.0 );
2095
2096 // create mapping table
2097 for( tools::Long nX = 0; nX < 256; nX++ )
2098 {
2099 if(!msoBrightness)
2100 {
2101 aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
2102 aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
2103 aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
2104 }
2105 else
2106 {
2107 aColParam.pMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
2108 aColParam.pMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
2109 aColParam.pMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
2110 }
2111 if( bGamma )
2112 {
2113 aColParam.pMapR[ nX ] = GAMMA( aColParam.pMapR[ nX ], fGamma );
2114 aColParam.pMapG[ nX ] = GAMMA( aColParam.pMapG[ nX ], fGamma );
2115 aColParam.pMapB[ nX ] = GAMMA( aColParam.pMapB[ nX ], fGamma );
2116 }
2117
2118 if( bInvert )
2119 {
2120 aColParam.pMapR[ nX ] = ~aColParam.pMapR[ nX ];
2121 aColParam.pMapG[ nX ] = ~aColParam.pMapG[ nX ];
2122 aColParam.pMapB[ nX ] = ~aColParam.pMapB[ nX ];
2123 }
2124 }
2125
2126 aBmpParam.nLuminancePercent = nLuminancePercent;
2127 aBmpParam.nContrastPercent = nContrastPercent;
2128 aBmpParam.nChannelRPercent = nChannelRPercent;
2129 aBmpParam.nChannelGPercent = nChannelGPercent;
2130 aBmpParam.nChannelBPercent = nChannelBPercent;
2131 aBmpParam.fGamma = fGamma;
2132 aBmpParam.bInvert = bInvert;
2133
2134 // do color adjustment
2135 ImplExchangeColors( ImplColAdjustFnc, &aColParam, ImplBmpAdjustFnc, &aBmpParam );
2136}
2137
2139{
2140 ImplColConvertParam aColParam;
2141 ImplBmpConvertParam aBmpParam;
2142
2143 aColParam.eConversion = eConversion;
2144 aBmpParam.eConversion = ( MtfConversion::N1BitThreshold == eConversion ) ? BmpConversion::N1BitThreshold : BmpConversion::N8BitGreys;
2145
2146 ImplExchangeColors( ImplColConvertFnc, &aColParam, ImplBmpConvertFnc, &aBmpParam );
2147}
2148
2149void GDIMetaFile::ReplaceColors( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount )
2150{
2151 ImplColReplaceParam aColParam;
2152 ImplBmpReplaceParam aBmpParam;
2153
2154 aColParam.pMinR.reset(new sal_uLong[ nColorCount ]);
2155 aColParam.pMaxR.reset(new sal_uLong[ nColorCount ]);
2156 aColParam.pMinG.reset(new sal_uLong[ nColorCount ]);
2157 aColParam.pMaxG.reset(new sal_uLong[ nColorCount ]);
2158 aColParam.pMinB.reset(new sal_uLong[ nColorCount ]);
2159 aColParam.pMaxB.reset(new sal_uLong[ nColorCount ]);
2160
2161 for( sal_uLong i = 0; i < nColorCount; i++ )
2162 {
2163 tools::Long nVal;
2164
2165 nVal = pSearchColors[ i ].GetRed();
2166 aColParam.pMinR[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2167 aColParam.pMaxR[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2168
2169 nVal = pSearchColors[ i ].GetGreen();
2170 aColParam.pMinG[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2171 aColParam.pMaxG[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2172
2173 nVal = pSearchColors[ i ].GetBlue();
2174 aColParam.pMinB[ i ] = static_cast<sal_uLong>(std::max( nVal, tools::Long(0) ));
2175 aColParam.pMaxB[ i ] = static_cast<sal_uLong>(std::min( nVal, tools::Long(255) ));
2176 }
2177
2178 aColParam.pDstCols = pReplaceColors;
2179 aColParam.nCount = nColorCount;
2180
2181 aBmpParam.pSrcCols = pSearchColors;
2182 aBmpParam.pDstCols = pReplaceColors;
2183 aBmpParam.nCount = nColorCount;
2184
2185 ImplExchangeColors( ImplColReplaceFnc, &aColParam, ImplBmpReplaceFnc, &aBmpParam );
2186};
2187
2189{
2190 GDIMetaFile aRet( *this );
2191
2192 ImplColMonoParam aColParam;
2193 ImplBmpMonoParam aBmpParam;
2194
2195 aColParam.aColor = rColor;
2196 aBmpParam.aColor = rColor;
2197
2198 aRet.ImplExchangeColors( ImplColMonoFnc, &aColParam, ImplBmpMonoFnc, &aBmpParam );
2199
2200 return aRet;
2201}
2202
2204{
2205 sal_uLong nSizeBytes = 0;
2206
2207 for( size_t i = 0, nObjCount = GetActionSize(); i < nObjCount; ++i )
2208 {
2209 MetaAction* pAction = GetAction( i );
2210
2211 // default action size is set to 32 (=> not the exact value)
2212 nSizeBytes += 32;
2213
2214 // add sizes for large action content
2215 switch( pAction->GetType() )
2216 {
2217 case MetaActionType::BMP: nSizeBytes += static_cast<MetaBmpAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2218 case MetaActionType::BMPSCALE: nSizeBytes += static_cast<MetaBmpScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2219 case MetaActionType::BMPSCALEPART: nSizeBytes += static_cast<MetaBmpScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2220
2221 case MetaActionType::BMPEX: nSizeBytes += static_cast<MetaBmpExAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2222 case MetaActionType::BMPEXSCALE: nSizeBytes += static_cast<MetaBmpExScaleAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2223 case MetaActionType::BMPEXSCALEPART: nSizeBytes += static_cast<MetaBmpExScalePartAction*>( pAction )->GetBitmapEx().GetSizeBytes(); break;
2224
2225 case MetaActionType::MASK: nSizeBytes += static_cast<MetaMaskAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2226 case MetaActionType::MASKSCALE: nSizeBytes += static_cast<MetaMaskScaleAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2227 case MetaActionType::MASKSCALEPART: nSizeBytes += static_cast<MetaMaskScalePartAction*>( pAction )->GetBitmap().GetSizeBytes(); break;
2228
2229 case MetaActionType::POLYLINE: nSizeBytes += static_cast<MetaPolyLineAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2230 case MetaActionType::POLYGON: nSizeBytes += static_cast<MetaPolygonAction*>( pAction )->GetPolygon().GetSize() * sizeof( Point ); break;
2232 {
2233 const tools::PolyPolygon& rPolyPoly = static_cast<MetaPolyPolygonAction*>( pAction )->GetPolyPolygon();
2234
2235 for( sal_uInt16 n = 0; n < rPolyPoly.Count(); ++n )
2236 nSizeBytes += ( rPolyPoly[ n ].GetSize() * sizeof( Point ) );
2237 }
2238 break;
2239
2240 case MetaActionType::TEXT: nSizeBytes += static_cast<MetaTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2241 case MetaActionType::STRETCHTEXT: nSizeBytes += static_cast<MetaStretchTextAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2242 case MetaActionType::TEXTRECT: nSizeBytes += static_cast<MetaTextRectAction*>( pAction )->GetText().getLength() * sizeof( sal_Unicode ); break;
2244 {
2245 MetaTextArrayAction* pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction);
2246
2247 nSizeBytes += ( pTextArrayAction->GetText().getLength() * sizeof( sal_Unicode ) );
2248
2249 if( !pTextArrayAction->GetDXArray().empty() )
2250 nSizeBytes += ( pTextArrayAction->GetLen() << 2 );
2251 }
2252 break;
2253 default: break;
2254 }
2255 }
2256
2257 return nSizeBytes;
2258}
2259
2260bool GDIMetaFile::CreateThumbnail(BitmapEx& rBitmapEx, BmpConversion eColorConversion, BmpScaleFlag nScaleFlag) const
2261{
2262 // initialization seems to be complicated but is used to avoid rounding errors
2264 // set Enable to tease the rendering down the code paths which use B2DPolygon and
2265 // avoid integer overflows on scaling tools::Polygon, e.g. moz1545040-1.svg
2266 // note: this is similar to DocumentToGraphicRenderer::renderToGraphic
2267 aVDev->SetAntialiasing(AntialiasingFlags::Enable | aVDev->GetAntialiasing());
2268 const Point aNullPt;
2269 const Point aTLPix( aVDev->LogicToPixel( aNullPt, GetPrefMapMode() ) );
2270 const Point aBRPix( aVDev->LogicToPixel( Point( GetPrefSize().Width() - 1, GetPrefSize().Height() - 1 ), GetPrefMapMode() ) );
2271 Size aDrawSize( aVDev->LogicToPixel( GetPrefSize(), GetPrefMapMode() ) );
2272 Size aSizePix( std::abs( aBRPix.X() - aTLPix.X() ) + 1, std::abs( aBRPix.Y() - aTLPix.Y() ) + 1 );
2273 sal_uInt32 nMaximumExtent = 512;
2274
2275 if (!rBitmapEx.IsEmpty())
2276 rBitmapEx.SetEmpty();
2277
2278 // determine size that has the same aspect ratio as image size and
2279 // fits into the rectangle determined by nMaximumExtent
2280 if ( aSizePix.Width() && aSizePix.Height()
2281 && ( sal::static_int_cast< tools::ULong >(aSizePix.Width()) >
2282 nMaximumExtent ||
2283 sal::static_int_cast< tools::ULong >(aSizePix.Height()) >
2284 nMaximumExtent ) )
2285 {
2286 const Size aOldSizePix( aSizePix );
2287 double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
2288
2289 if ( fWH <= 1.0 )
2290 {
2291 aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
2292 aSizePix.setHeight( nMaximumExtent );
2293 }
2294 else
2295 {
2296 aSizePix.setWidth( nMaximumExtent );
2297 aSizePix.setHeight( FRound( nMaximumExtent / fWH ) );
2298 }
2299
2300 aDrawSize.setWidth( FRound( ( static_cast< double >( aDrawSize.Width() ) * aSizePix.Width() ) / aOldSizePix.Width() ) );
2301 aDrawSize.setHeight( FRound( ( static_cast< double >( aDrawSize.Height() ) * aSizePix.Height() ) / aOldSizePix.Height() ) );
2302 }
2303
2304 // draw image(s) into VDev and get resulting image
2305 // do it 4x larger to be able to scale it down & get beautiful antialias
2306 Size aAntialiasSize(aSizePix.Width() * 4, aSizePix.Height() * 4);
2307 if (aVDev->SetOutputSizePixel(aAntialiasSize))
2308 {
2309 // antialias: provide 4x larger size, and then scale down the result
2310 Size aAntialias(aDrawSize.Width() * 4, aDrawSize.Height() * 4);
2311
2312 // draw metafile into VDev
2313 const_cast<GDIMetaFile *>(this)->WindStart();
2314 const_cast<GDIMetaFile *>(this)->Play(*aVDev, Point(), aAntialias);
2315
2316 // get paint bitmap
2317 BitmapEx aBitmap( aVDev->GetBitmapEx( aNullPt, aVDev->GetOutputSizePixel() ) );
2318
2319 // scale down the image to the desired size - use the input scaler for the scaling operation
2320 aBitmap.Scale(aDrawSize, nScaleFlag);
2321
2322 // convert to desired bitmap color format
2323 Size aSize(aBitmap.GetSizePixel());
2324 if (aSize.Width() && aSize.Height())
2325 aBitmap.Convert(eColorConversion);
2326
2327 rBitmapEx = aBitmap;
2328 }
2329
2330 return !rBitmapEx.IsEmpty();
2331}
2332
2333void GDIMetaFile::UseCanvas( bool _bUseCanvas )
2334{
2335 m_bUseCanvas = _bUseCanvas;
2336}
2337
2338void GDIMetaFile::dumpAsXml(const char* pFileName) const
2339{
2340 SvFileStream aStream(pFileName ? OUString::fromUtf8(pFileName) : OUString("file:///tmp/metafile.xml"),
2341 StreamMode::STD_READWRITE | StreamMode::TRUNC);
2342 assert(aStream.good());
2343 MetafileXmlDump aDumper;
2344 aDumper.dump(*this, aStream);
2345}
2346
2347/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool TooLargeScaleForMapMode(const Fraction &rScale, int nDPI)
static vcl::Window * GetActiveTopWindow()
Get the "active" top window.
Definition: svapp.cxx:1215
static vcl::Window * GetFirstTopLevelWindow()
Get the first top-level window of the application.
Definition: svapp.cxx:1171
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
sal_Int64 GetSizeBytes() const
Definition: BitmapEx.cxx:220
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:296
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: BitmapEx.cxx:374
bool IsAlpha() const
Definition: BitmapEx.cxx:193
bool Rotate(Degree10 nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: BitmapEx.cxx:316
bool IsEmpty() const
Definition: BitmapEx.cxx:177
void Replace(const Color &rSearchColor, const Color &rReplaceColor)
Replace all pixel having the search color with the specified color.
Definition: BitmapEx.cxx:479
bool Create(const css::uno::Reference< css::rendering::XBitmapCanvas > &xBitmapCanvas, const Size &rSize)
populate from a canvas implementation
Definition: BitmapEx.cxx:619
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:354
bool Adjust(short nLuminancePercent, short nContrastPercent, short nChannelRPercent, short nChannelGPercent, short nChannelBPercent, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Change various global color characteristics.
Definition: BitmapEx.cxx:491
const Size & GetSizePixel() const
Definition: bitmapex.hxx:72
void SetEmpty()
Definition: BitmapEx.cxx:182
Size GetSizePixel() const
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
sal_uInt8 GetLuminance() const
sal_uInt8 GetBlue() const
sal_uInt8 GetAlpha() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
void ReduceInaccurate(unsigned nSignificantBits)
bool m_bPause
Definition: gdimtf.hxx:66
bool HasTransparentActions() const
Definition: gdimtf.cxx:154
GDIMetaFile & operator=(const GDIMetaFile &rMtf)
Definition: gdimtf.cxx:211
size_t GetActionSize() const
Definition: gdimtf.cxx:179
static SAL_DLLPRIVATE tools::Polygon ImplGetRotatedPolygon(const tools::Polygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:793
static SAL_DLLPRIVATE BitmapEx ImplBmpConvertFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1744
void Move(tools::Long nX, tools::Long nY)
Definition: gdimtf.cxx:649
void WindStart()
Definition: gdimtf.cxx:568
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:726
static SAL_DLLPRIVATE Color ImplColConvertFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1734
SAL_DLLPRIVATE void ImplExchangeColors(ColorExchangeFnc pFncCol, const void *pColParam, BmpExchangeFnc pFncBmp, const void *pBmpParam)
Definition: gdimtf.cxx:1804
bool m_bUseCanvas
Definition: gdimtf.hxx:68
size_t m_nCurrentActionElement
Definition: gdimtf.hxx:59
void push_back(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:608
void Stop()
Definition: gdimtf.cxx:555
void Clip(const tools::Rectangle &)
Definition: gdimtf.cxx:752
static SAL_DLLPRIVATE BitmapEx ImplBmpAdjustFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1722
~GDIMetaFile()
Definition: gdimtf.cxx:149
void Pause(bool bPause)
Definition: gdimtf.cxx:536
const Size & GetPrefSize() const
Definition: gdimtf.hxx:172
tools::Rectangle GetBoundRect(OutputDevice &i_rReference) const
Definition: gdimtf.cxx:1313
void Rotate(Degree10 nAngle10)
Definition: gdimtf.cxx:837
void Mirror(BmpMirrorFlags nMirrorFlags)
Definition: gdimtf.cxx:613
bool IsRecord() const
Definition: gdimtf.hxx:142
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:184
MetaAction * GetCurAction() const
Definition: gdimtf.hxx:170
static SAL_DLLPRIVATE BitmapEx ImplBmpReplaceFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1794
GDIMetaFile * m_pNext
Definition: gdimtf.hxx:64
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:581
static SAL_DLLPRIVATE Point ImplGetRotatedPoint(const Point &rPt, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:783
GDIMetaFile * m_pPrev
Definition: gdimtf.hxx:63
void UseCanvas(bool _bUseCanvas)
Definition: gdimtf.cxx:2333
::std::vector< rtl::Reference< MetaAction > > m_aList
Definition: gdimtf.hxx:58
sal_uLong GetSizeBytes() const
Definition: gdimtf.cxx:2203
static SAL_DLLPRIVATE tools::PolyPolygon ImplGetRotatedPolyPolygon(const tools::PolyPolygon &rPoly, const Point &rRotatePt, const Size &rOffset, double fSin, double fCos)
Definition: gdimtf.cxx:804
MetaAction * NextAction()
Definition: gdimtf.cxx:195
VclPtr< OutputDevice > m_pOutDev
Definition: gdimtf.hxx:65
bool operator==(const GDIMetaFile &rMtf) const
Definition: gdimtf.cxx:244
void Clear()
Definition: gdimtf.cxx:270
void Adjust(short nLuminancePercent, short nContrastPercent, short nChannelRPercent=0, short nChannelGPercent=0, short nChannelBPercent=0, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Definition: gdimtf.cxx:2057
void Convert(MtfConversion eConversion)
Definition: gdimtf.cxx:2138
MetaAction * FirstAction()
Definition: gdimtf.cxx:189
static SAL_DLLPRIVATE void ImplAddGradientEx(GDIMetaFile &rMtf, const OutputDevice &rMapDev, const tools::PolyPolygon &rPolyPoly, const Gradient &rGrad)
Definition: gdimtf.cxx:815
static SAL_DLLPRIVATE Color ImplColReplaceFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1774
GDIMetaFile GetMonochromeMtf(const Color &rCol) const
Definition: gdimtf.cxx:2188
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:322
bool GetUseCanvas() const
Definition: gdimtf.hxx:187
void ReplaceColors(const Color *pSearchColors, const Color *rReplaceColors, sal_uLong nColorCount)
Definition: gdimtf.cxx:2149
void dumpAsXml(const char *pFileName=nullptr) const
Dumps the meta actions as XML in metafile.xml.
Definition: gdimtf.cxx:2338
void Record(OutputDevice *pOutDev)
Definition: gdimtf.cxx:311
static SAL_DLLPRIVATE Color ImplColMonoFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1753
bool CreateThumbnail(BitmapEx &rBitmapEx, BmpConversion nColorConversion=BmpConversion::N24Bit, BmpScaleFlag nScaleFlag=BmpScaleFlag::BestQuality) const
Creates an antialiased thumbnail.
Definition: gdimtf.cxx:2260
MapMode m_aPrefMapMode
Definition: gdimtf.hxx:61
void ReplaceAction(rtl::Reference< MetaAction > pAction, size_t nAction)
Definition: gdimtf.cxx:200
void WindPrev()
Definition: gdimtf.cxx:574
Size m_aPrefSize
Definition: gdimtf.hxx:62
bool m_bRecord
Definition: gdimtf.hxx:67
void Linker(OutputDevice *pOut, bool bLink)
Definition: gdimtf.cxx:278
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:175
static SAL_DLLPRIVATE BitmapEx ImplBmpMonoFnc(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.cxx:1758
void SetPrefSize(const Size &rSize)
Definition: gdimtf.hxx:173
SAL_DLLPRIVATE bool ImplPlayWithRenderer(OutputDevice &rOut, const Point &rPos, Size rLogicDestSize)
Definition: gdimtf.cxx:387
static SAL_DLLPRIVATE Color ImplColAdjustFnc(const Color &rColor, const void *pColParam)
Definition: gdimtf.cxx:1713
const Color & GetEndColor() const
const Color & GetStartColor() const
void SetStartColor(const Color &rColor)
void SetEndColor(const Color &rColor)
Definition: hatch.hxx:47
void SetAngle(Degree10 nAngle10)
Definition: gdi/hatch.cxx:74
Degree10 GetAngle() const
Definition: hatch.hxx:68
void SetColor(const Color &rColor)
Definition: gdi/hatch.cxx:64
const Color & GetColor() const
Definition: hatch.hxx:62
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:105
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:118
const Fraction & GetScaleX() const
Definition: mapmod.cxx:154
MapUnit GetMapUnit() const
Definition: mapmod.cxx:150
const Fraction & GetScaleY() const
Definition: mapmod.cxx:156
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:111
virtual bool IsTransparent() const
#i10613# Extracted from Printer::GetPreparedMetaFile.
Definition: metaact.hxx:98
MetaActionType GetType() const
Definition: metaact.hxx:94
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:99
virtual void Scale(double fScaleX, double fScaleY)
Definition: metaact.cxx:112
virtual void Move(tools::Long nHorzMove, tools::Long nVertMove)
Definition: metaact.cxx:108
const Point & GetStartPoint() const
Definition: metaact.hxx:306
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:305
const Point & GetEndPoint() const
Definition: metaact.hxx:307
const Bitmap & GetBitmap() const
Definition: metaact.hxx:691
const Point & GetPoint() const
Definition: metaact.hxx:692
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:796
const Point & GetPoint() const
Definition: metaact.hxx:797
const Size & GetSize() const
Definition: metaact.hxx:831
const Point & GetPoint() const
Definition: metaact.hxx:830
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:829
const Point & GetPoint() const
Definition: metaact.hxx:724
const Size & GetSize() const
Definition: metaact.hxx:725
const Bitmap & GetBitmap() const
Definition: metaact.hxx:723
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:373
const Point & GetStartPoint() const
Definition: metaact.hxx:374
const Point & GetEndPoint() const
Definition: metaact.hxx:375
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1140
bool IsClipping() const
Definition: metaact.hxx:1141
const sal_uInt8 * GetData() const
Definition: metaact.hxx:1702
const OString & GetComment() const
Definition: metaact.hxx:1699
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1701
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1637
const Point & GetPoint() const
Definition: metaact.hxx:1638
const Size & GetSize() const
Definition: metaact.hxx:1639
const GfxLink & GetLink() const
Definition: metaact.hxx:1636
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:275
const Color & GetColor() const
Definition: metaact.hxx:1277
bool IsSetting() const
Definition: metaact.hxx:1278
const Gradient & GetGradient() const
Definition: metaact.hxx:1601
const Size & GetSize() const
Definition: metaact.hxx:1600
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1598
const Point & GetPoint() const
Definition: metaact.hxx:1599
const vcl::Font & GetFont() const
Definition: metaact.hxx:1470
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1020
const Gradient & GetGradient() const
Definition: metaact.hxx:1021
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1050
const Gradient & GetGradient() const
Definition: metaact.hxx:1051
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1080
const Hatch & GetHatch() const
Definition: metaact.hxx:1081
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1169
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1196
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:185
const Point & GetEndPoint() const
Definition: metaact.hxx:184
const Point & GetStartPoint() const
Definition: metaact.hxx:183
bool IsSetting() const
Definition: metaact.hxx:1251
const Color & GetColor() const
Definition: metaact.hxx:1250
const Point & GetPoint() const
Definition: metaact.hxx:909
const Bitmap & GetBitmap() const
Definition: metaact.hxx:907
const Bitmap & GetBitmap() const
Definition: metaact.hxx:942
const Point & GetPoint() const
Definition: metaact.hxx:944
const Color & GetColor() const
Definition: metaact.hxx:943
const Size & GetSize() const
Definition: metaact.hxx:945
const Bitmap & GetBitmap() const
Definition: metaact.hxx:982
const Point & GetSrcPoint() const
Definition: metaact.hxx:986
const Color & GetColor() const
Definition: metaact.hxx:983
const Size & GetSrcSize() const
Definition: metaact.hxx:987
const Point & GetDestPoint() const
Definition: metaact.hxx:984
const Size & GetDestSize() const
Definition: metaact.hxx:985
tools::Long GetVertMove() const
Definition: metaact.hxx:1224
tools::Long GetHorzMove() const
Definition: metaact.hxx:1223
const Color & GetColor() const
Definition: metaact.hxx:1384
bool IsSetting() const
Definition: metaact.hxx:1387
const Point & GetEndPoint() const
Definition: metaact.hxx:341
const Point & GetStartPoint() const
Definition: metaact.hxx:340
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:339
const Point & GetPoint() const
Definition: metaact.hxx:124
const Color & GetColor() const
Definition: metaact.hxx:125
const Point & GetPoint() const
Definition: metaact.hxx:152
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:407
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:406
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:462
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:435
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1495
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:214
bool IsSetting() const
Definition: metaact.hxx:1670
const Point & GetRefPoint() const
Definition: metaact.hxx:1667
sal_uInt32 GetHorzRound() const
Definition: metaact.hxx:245
sal_uInt32 GetVertRound() const
Definition: metaact.hxx:246
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:244
sal_uInt32 GetWidth() const
Definition: metaact.hxx:582
sal_Int32 GetLen() const
Definition: metaact.hxx:584
sal_Int32 GetIndex() const
Definition: metaact.hxx:583
const OUString & GetText() const
Definition: metaact.hxx:581
const Point & GetPoint() const
Definition: metaact.hxx:580
const Point & GetPoint() const
Definition: metaact.hxx:493
sal_Int32 GetLen() const
Definition: metaact.hxx:496
const OUString & GetText() const
Definition: metaact.hxx:494
sal_Int32 GetIndex() const
Definition: metaact.hxx:495
const Color & GetColor() const
Definition: metaact.hxx:1304
bool IsSetting() const
Definition: metaact.hxx:1332
const Color & GetColor() const
Definition: metaact.hxx:1329
const Point & GetStartPoint() const
Definition: metaact.hxx:655
tools::Long GetWidth() const
Definition: metaact.hxx:656
FontLineStyle GetUnderline() const
Definition: metaact.hxx:658
FontLineStyle GetOverline() const
Definition: metaact.hxx:659
FontStrikeout GetStrikeout() const
Definition: metaact.hxx:657
bool IsSetting() const
Definition: metaact.hxx:1360
const Color & GetColor() const
Definition: metaact.hxx:1357
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:618
sal_uInt16 GetTransparence() const
Definition: metaact.hxx:1564
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1563
Class that is used for testing of the decomposition into shapes.
Definition: mtfxmldump.hxx:45
void dump(const GDIMetaFile &rMetaFile, SvStream &rStream)
The actual result that will be used for testing.
Definition: mtfxmldump.cxx:583
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:171
Size GetOutputSize() const
Definition: outdev.hxx:328
SAL_DLLPRIVATE sal_Int32 GetDPIX() const
Get the output device's DPI x-axis value.
Definition: outdev.hxx:386
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:286
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
Definition: bitmapex.cxx:33
SAL_WARN_UNUSED_RESULT Size GetPixelOffset() const
Get the offset in pixel.
Definition: outdev.hxx:1602
virtual void SetMetafileMapMode(const MapMode &rNewMapMode, bool bIsRecord)
Definition: map.cxx:770
SAL_DLLPRIVATE sal_Int32 GetDPIY() const
Get the output device's DPI y-axis value.
Definition: outdev.hxx:392
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1169
Size GetOutputSizePixel() const
Definition: outdev.hxx:315
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1639
void SetPixelOffset(const Size &rOffset)
Set an offset in pixel.
Definition: map.cxx:1881
void SetDigitLanguage(LanguageType)
Definition: text.cxx:71
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:938
virtual size_t GetSyncCount() const
Definition: outdev.hxx:336
const MapMode & GetMapMode() const
Definition: outdev.hxx:1558
virtual void Flush()
Definition: outdev.hxx:430
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
void Pop()
Definition: stack.cxx:92
css::uno::Reference< css::rendering::XCanvas > GetCanvas() const
request XCanvas render interface
Definition: outdev.cxx:747
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
Definition: text.cxx:60
virtual vcl::Window * GetOwnerWindow() const
Get the vcl::Window that this OutputDevice belongs to, if any.
Definition: outdev.hxx:1900
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
const void * GetData()
sal_uInt64 Tell() const
bool good() const
Encapsulates geometry and associated attributes of a filled area.
void getPath(tools::PolyPolygon &) const
Query path to fill.
void setPath(const tools::PolyPolygon &rPath)
Set path to fill.
Encapsulates geometry and associated attributes of a graphical 'pen stroke'.
void getPath(tools::Polygon &) const
Query path to stroke.
void setPath(const tools::Polygon &)
Set path to stroke.
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
const BitmapEx & GetBitmap() const
Definition: wall.cxx:184
const Color & GetColor() const
Definition: wall.hxx:71
void SetGradient(const Gradient &rGradient)
Definition: wall.cxx:194
bool IsBitmap() const
Definition: wall.cxx:189
void SetBitmap(const BitmapEx &rBitmap)
Definition: wall.cxx:175
bool IsGradient() const
Definition: wall.cxx:213
Gradient GetGradient() const
Definition: wall.cxx:203
void SetColor(const Color &rColor)
Definition: wall.cxx:156
sal_uInt16 Count() const
void Move(tools::Long nHorzMove, tools::Long nVertMove)
void Rotate(const Point &rCenter, double fSin, double fCos)
tools::Rectangle GetBoundRect() const
void Move(tools::Long nHorzMove, tools::Long nVertMove)
tools::Rectangle GetBoundRect() const
void Rotate(const Point &rCenter, double fSin, double fCos)
constexpr Point Center() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr void SetRight(tools::Long v)
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long GetHeight() const
tools::Rectangle & Union(const tools::Rectangle &rRect)
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
constexpr bool IsEmpty() const
void SetOrientation(Degree10 nLineOrientation)
Definition: font/font.cxx:227
void SetFillColor(const Color &)
Definition: font/font.cxx:115
void SetColor(const Color &)
Definition: font/font.cxx:107
const Color & GetColor() const
Definition: font/font.cxx:922
Degree10 GetOrientation() const
Definition: font/font.cxx:944
const Color & GetFillColor() const
Definition: font/font.cxx:923
tools::PolyPolygon GetAsPolyPolygon() const
Definition: region.cxx:1266
void Intersect(const tools::Rectangle &rRegion)
Definition: region.cxx:583
bool HasPolyPolygonOrB2DPolyPolygon() const
Definition: region.hxx:107
tools::Rectangle GetBoundRect() const
Definition: region.cxx:1219
::OutputDevice const * GetOutDev() const
Definition: window.cxx:567
ColorAlpha
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
ColorTransparency
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
int nCount
double toRadians(D x)
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
static void ImplActionBounds(tools::Rectangle &o_rOutBounds, const tools::Rectangle &i_rInBounds, const std::vector< tools::Rectangle > &i_rClipStack)
Definition: gdimtf.cxx:1297
Color(* ColorExchangeFnc)(const Color &rColor, const void *pColParam)
Definition: gdimtf.hxx:52
BitmapEx(* BmpExchangeFnc)(const BitmapEx &rBmpEx, const void *pBmpParam)
Definition: gdimtf.hxx:53
MtfConversion
Definition: gdimtf.hxx:46
SvStream & WriteSvtGraphicFill(SvStream &rOStm, const SvtGraphicFill &rClass)
SvStream & ReadSvtGraphicStroke(SvStream &rIStm, SvtGraphicStroke &rClass)
SvStream & ReadSvtGraphicFill(SvStream &rIStm, SvtGraphicFill &rClass)
SvStream & WriteSvtGraphicStroke(SvStream &rOStm, const SvtGraphicStroke &rClass)
tools::Long FRound(double fVal)
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
BmpMirrorFlags
#define GAMMA(_def_cVal, _def_InvGamma)
void * p
sal_Int64 n
uno_Any a
#define LANGUAGE_SYSTEM
sal_uInt16 nPos
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
MetaActionType
aStr
Reference< XComponentContext > getProcessComponentContext()
int i
long Long
BitmapEx GetBitmapEx(BitmapEx const &rBitmapEx, DrawModeFlags nDrawMode)
Definition: drawmode.cxx:224
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
HashMap_OWString_Interface aMap
#define Y
QPRO_FUNC_TYPE nType
sal_uIntPtr sal_uLong
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
oslFileHandle & pOut