LibreOffice Module vcl (master) 1
emfwr.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 <sal/config.h>
21#include <sal/log.hxx>
22
23#include <algorithm>
24
25#include "emfwr.hxx"
26#include <tools/helpers.hxx>
27#include <tools/fract.hxx>
28#include <tools/stream.hxx>
31#include <vcl/lineinfo.hxx>
32#include <vcl/dibtools.hxx>
33#include <vcl/metaact.hxx>
34#include <memory>
35
36#define WIN_EMR_POLYGON 3
37#define WIN_EMR_POLYLINE 4
38#define WIN_EMR_POLYBEZIERTO 5
39#define WIN_EMR_POLYLINETO 6
40#define WIN_EMR_POLYPOLYGON 8
41#define WIN_EMR_SETWINDOWEXTEX 9
42#define WIN_EMR_SETWINDOWORGEX 10
43#define WIN_EMR_SETVIEWPORTEXTEX 11
44#define WIN_EMR_SETVIEWPORTORGEX 12
45#define WIN_EMR_EOF 14
46#define WIN_EMR_SETPIXELV 15
47#define WIN_EMR_SETMAPMODE 17
48#define WIN_EMR_SETBKMODE 18
49#define WIN_EMR_SETROP2 20
50#define WIN_EMR_SETTEXTALIGN 22
51#define WIN_EMR_SETTEXTCOLOR 24
52#define WIN_EMR_MOVETOEX 27
53#define WIN_EMR_INTERSECTCLIPRECT 30
54#define WIN_EMR_SAVEDC 33
55#define WIN_EMR_RESTOREDC 34
56#define WIN_EMR_SELECTOBJECT 37
57#define WIN_EMR_CREATEPEN 38
58#define WIN_EMR_CREATEBRUSHINDIRECT 39
59#define WIN_EMR_DELETEOBJECT 40
60#define WIN_EMR_ELLIPSE 42
61#define WIN_EMR_RECTANGLE 43
62#define WIN_EMR_ROUNDRECT 44
63#define WIN_EMR_LINETO 54
64#define WIN_EMR_BEGINPATH 59
65#define WIN_EMR_ENDPATH 60
66#define WIN_EMR_CLOSEFIGURE 61
67#define WIN_EMR_FILLPATH 62
68#define WIN_EMR_STROKEPATH 64
69
70#define WIN_EMR_GDICOMMENT 70
71#define WIN_EMR_STRETCHDIBITS 81
72#define WIN_EMR_EXTCREATEFONTINDIRECTW 82
73#define WIN_EMR_EXTTEXTOUTW 84
74
75#define WIN_SRCCOPY 0x00CC0020L
76#define WIN_SRCPAINT 0x00EE0086L
77#define WIN_SRCAND 0x008800C6L
78#define WIN_SRCINVERT 0x00660046L
79#define WIN_EMR_COMMENT_EMFPLUS 0x2B464D45L
80
81#define HANDLE_INVALID 0xffffffff
82#define MAXHANDLES 65000
83
84#define LINE_SELECT 0x00000001
85#define FILL_SELECT 0x00000002
86#define TEXT_SELECT 0x00000004
87
88/* Text Alignment Options */
89#define TA_RIGHT 2
90
91#define TA_TOP 0
92#define TA_BOTTOM 8
93#define TA_BASELINE 24
94#define TA_RTLREADING 256
95
96#define MM_ANISOTROPIC 8
97
99{
100 Header = 0x4001,
101 EndOfFile = 0x4002,
102 GetDC = 0x4004,
103 FillPolygon = 0x400C,
104 SetAntiAliasMode = 0x401E,
105 SetInterpolationMode = 0x4021,
106 SetPixelOffsetMode = 0x4022,
107 SetCompositingQuality = 0x4024
108};
109
110void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType )
111{
113 m_rStm.SeekRel( 4 );
114 m_rStm.WriteInt32( nCommentType );
115}
116
118{
119 if( mbRecordOpen )
120 {
121 sal_Int32 nActPos = m_rStm.Tell();
122 m_rStm.Seek( mnRecordPos + 8 );
123 m_rStm.WriteUInt32( nActPos - mnRecordPos - 0xc );
124 m_rStm.Seek( nActPos );
125 }
127}
128
129void EMFWriter::ImplBeginPlusRecord( EmfPlusRecordType nType, sal_uInt16 nFlags )
130{
131 SAL_WARN_IF( mbRecordPlusOpen, "vcl", "Another EMF+ record is already opened!" );
132
133 if( !mbRecordPlusOpen )
134 {
135 mbRecordPlusOpen = true;
137
138 m_rStm.WriteUInt16( static_cast<sal_uInt16>(nType) ).WriteUInt16( nFlags );
139 m_rStm.SeekRel( 8 );
140 }
141}
142
144{
145 SAL_WARN_IF( !mbRecordPlusOpen, "vcl", "EMF+ Record was not opened!" );
146
147 if( mbRecordPlusOpen )
148 {
149 sal_Int32 nActPos = m_rStm.Tell();
150 sal_Int32 nSize = nActPos - mnRecordPlusPos;
152 m_rStm.WriteUInt32( nSize ) // Size
153 .WriteUInt32( nSize - 0xc ); // Data Size
154 m_rStm.Seek( nActPos );
155 mbRecordPlusOpen = false;
156 }
157}
158
159void EMFWriter::ImplPlusRecord( EmfPlusRecordType nType, sal_uInt16 nFlags )
160{
161 ImplBeginPlusRecord( nType, nFlags );
163}
164
165void EMFWriter::WriteEMFPlusHeader( const Size &rMtfSizePix, const Size &rMtfSizeLog )
166{
168
169 sal_Int32 nDPIX = rMtfSizePix.Width()*25;
170 sal_Int32 nDivX = rMtfSizeLog.Width()/100;
171 if (nDivX)
172 nDPIX /= nDivX; // DPI X
173
174 sal_Int32 nDPIY = rMtfSizePix.Height()*25;
175 sal_Int32 nDivY = rMtfSizeLog.Height()/100;
176 if (nDivY)
177 nDPIY /= nDivY; // DPI Y
178
180 m_rStm.WriteInt16( 0x01 ) // Flags - Dual Mode // TODO: Check this
181 .WriteInt32( 0x1C ) // Size
182 .WriteInt32( 0x10 ) // Data Size
183 .WriteInt32( 0xdbc01002 ) // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this
184 .WriteInt32( 0x01 ) // Video display
185 .WriteInt32( nDPIX )
186 .WriteInt32( nDPIY );
188
189 // Write more properties
192 ImplPlusRecord( EmfPlusRecordType::SetAntiAliasMode, 0x09 ); // TODO: Check actual values for AntiAlias
193 ImplPlusRecord( EmfPlusRecordType::SetCompositingQuality, 0x0100 ); // Default Quality
197}
198
200{
204}
205
206void EMFWriter::ImplWritePlusColor( const Color& rColor, sal_uInt32 nTrans )
207{
208 sal_uInt32 nAlpha = ((100-nTrans)*0xFF)/100;
209 sal_uInt32 nCol = rColor.GetBlue();
210
211 nCol |= static_cast<sal_uInt32>(rColor.GetGreen()) << 8;
212 nCol |= static_cast<sal_uInt32>(rColor.GetRed()) << 16;
213 nCol |= ( nAlpha << 24 );
214 m_rStm.WriteUInt32( nCol );
215}
216
217void EMFWriter::ImplWritePlusPoint( const Point& rPoint )
218{
219 // Convert to pixels
220 const Point aPoint(maVDev->LogicToPixel( rPoint, maDestMapMode ));
221 m_rStm.WriteUInt16( aPoint.X() ).WriteUInt16( aPoint.Y() );
222}
223
224void EMFWriter::ImplWritePlusFillPolygonRecord( const tools::Polygon& rPoly, sal_uInt32 nTrans )
225{
227 if( rPoly.GetSize() )
228 {
229 ImplBeginPlusRecord( EmfPlusRecordType::FillPolygon, 0xC000 ); // Sets the color as well
230 ImplWritePlusColor( maVDev->GetFillColor(), nTrans );
231 m_rStm.WriteUInt32( rPoly.GetSize() );
232 for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
233 ImplWritePlusPoint( rPoly[ i ] );
235 }
237}
238
240{
241 const sal_uInt64 nHeaderPos = m_rStm.Tell();
242
243 maVDev->EnableOutput( false );
244 maVDev->SetMapMode( rMtf.GetPrefMapMode() );
245 // don't work with pixel as destination map mode -> higher resolution preferable
246 maDestMapMode.SetMapUnit( MapUnit::Map100thMM );
247 mHandlesUsed = std::vector<bool>(MAXHANDLES, false);
252 mnHorTextAlign = 0;
253
254 const Size aMtfSizePix( maVDev->LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
255 const Size aMtfSizeLog( OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
256
257 // seek over header
258 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
259 m_rStm.SeekRel( 108 );
260
261 // Write EMF+ Header
262 WriteEMFPlusHeader( aMtfSizePix, aMtfSizeLog );
263
264 // write initial values
265
266 // set 100th mm map mode in EMF
270
272 m_rStm.WriteInt32( maVDev->GetDPIX() ).WriteInt32( maVDev->GetDPIY() );
274
276 m_rStm.WriteInt32( 2540 ).WriteInt32( 2540 );
278
280 m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
282
284 m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
286
288
290 m_rStm.WriteUInt32( 1 ); // TRANSPARENT
292
293 // write emf data
294 ImplWrite( rMtf );
295
297
299 m_rStm.WriteUInt32( 0 ) // nPalEntries
300 .WriteUInt32( 0x10 ) // offPalEntries
301 .WriteUInt32( 0x14 ); // nSizeLast
303
304 // write header
305 const sal_uInt64 nEndPos = m_rStm.Tell(); m_rStm.Seek( nHeaderPos );
306
307 m_rStm.WriteUInt32( 0x00000001 ).WriteUInt32( 108 ) //use [MS-EMF 2.2.11] HeaderExtension2 Object
308 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizePix.Width() - 1 ).WriteInt32( aMtfSizePix.Height() - 1 )
309 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizeLog.Width() - 1 ).WriteInt32( aMtfSizeLog.Height() - 1 )
310 .WriteUInt32( 0x464d4520 ).WriteUInt32( 0x10000 ).WriteUInt32( nEndPos - nHeaderPos )
312 .WriteInt32( aMtfSizePix.Width() ).WriteInt32( aMtfSizePix.Height() )
313 .WriteInt32( aMtfSizeLog.Width() / 100 ).WriteInt32( aMtfSizeLog.Height() / 100 )
314 .WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
315 .WriteInt32( aMtfSizeLog.Width() * 10 ).WriteInt32( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
316
317 m_rStm.Seek( nEndPos );
318 mHandlesUsed.clear();
319
320 return( m_rStm.GetError() == ERRCODE_NONE );
321}
322
324{
326
327 for( sal_uLong i = 0; i < mHandlesUsed.size() && ( HANDLE_INVALID == nHandle ); i++ )
328 {
329 if( !mHandlesUsed[ i ] )
330 {
331 mHandlesUsed[ i ] = true;
332
333 if( ( nHandle = i ) == mnHandleCount )
335 }
336 }
337
338 SAL_WARN_IF( nHandle == HANDLE_INVALID, "vcl", "No more handles available" );
339 return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID );
340}
341
343{
344 SAL_WARN_IF( !nHandle || ( nHandle >= mHandlesUsed.size() ), "vcl", "Handle out of range" );
345 mHandlesUsed[ nHandle - 1 ] = false;
346}
347
348void EMFWriter::ImplBeginRecord( sal_uInt32 nType )
349{
350 SAL_WARN_IF( mbRecordOpen, "vcl", "Another record is already opened!" );
351
352 if( !mbRecordOpen )
353 {
354 mbRecordOpen = true;
356
358 m_rStm.SeekRel( 4 );
359 }
360}
361
363{
364 SAL_WARN_IF( !mbRecordOpen, "vcl", "Record was not opened!" );
365
366 if( !mbRecordOpen )
367 return;
368
369 sal_Int32 nFillBytes, nActPos = m_rStm.Tell();
370 m_rStm.Seek( mnRecordPos + 4 );
371 nFillBytes = nActPos - mnRecordPos;
372 nFillBytes += 3; // each record has to be dword aligned
373 nFillBytes ^= 3;
374 nFillBytes &= 3;
375 m_rStm.WriteUInt32( ( nActPos - mnRecordPos ) + nFillBytes );
376 m_rStm.Seek( nActPos );
377 while( nFillBytes-- )
378 m_rStm.WriteUChar( 0 );
380 mbRecordOpen = false;
381
382}
383
384bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType )
385{
386 if( rHandle != HANDLE_INVALID )
387 {
388 sal_uInt32 nStockObject = 0x80000000;
389
390 if( LINE_SELECT == nSelectType )
391 nStockObject |= 0x00000007;
392 else if( FILL_SELECT == nSelectType )
393 nStockObject |= 0x00000001;
394 else if( TEXT_SELECT == nSelectType )
395 nStockObject |= 0x0000000a;
396
397 // select stock object first
399 m_rStm.WriteUInt32( nStockObject );
401
402 // destroy handle of created object
404 m_rStm.WriteUInt32( rHandle );
406
407 // mark handle as free
408 ImplReleaseHandle( rHandle );
409 }
410
411 rHandle = ImplAcquireHandle();
412
413 return( HANDLE_INVALID != rHandle );
414}
415
417{
419 return;
420
421 sal_uInt32 nStyle = maVDev->IsLineColor() ? 0 : 5;
422
424 m_rStm.WriteUInt32( mnLineHandle ).WriteUInt32( nStyle ).WriteUInt32( 0/*nWidth*/ ).WriteUInt32( 0/*nHeight*/ );
425 ImplWriteColor( maVDev->GetLineColor() );
427
431}
432
434{
436 return;
437
438 sal_uInt32 nStyle = maVDev->IsFillColor() ? 0 : 1;
439
442 ImplWriteColor( maVDev->GetFillColor() );
443 m_rStm.WriteUInt32( 0/*nPatternStyle*/ );
445
449}
450
452{
454 return;
455
456 const vcl::Font& rFont = maVDev->GetFont();
457 const OUString& aFontName( rFont.GetFamilyName() );
458 sal_Int32 nWeight;
459 sal_uInt16 i;
460 sal_uInt8 nPitchAndFamily;
461
462 // tdf#127471 adapt nFontWidth from NormedFontScaling to
463 // Windows-like notation if used for text scaling
464 const tools::Long nFontHeight(rFont.GetFontSize().Height());
465 tools::Long nFontWidth(rFont.GetFontSize().Width());
466
467#ifndef _WIN32
468 const bool bFontScaledHorizontally(nFontWidth != 0 && nFontWidth != nFontHeight);
469
470 if(bFontScaledHorizontally)
471 {
472 // tdf#127471 nFontWidth is the non-Windows NormedFontScaling, need to convert to
473 // Windows-like notation with pre-multiplied AvgFontWidth since EMF/WMF are Windows
474 // specific formats.
475 const tools::Long nAverageFontWidth(rFont.GetOrCalculateAverageFontWidth());
476
477 if(nFontHeight > 0)
478 {
479 const double fScaleFactor(static_cast<double>(nAverageFontWidth) / static_cast<double>(nFontHeight));
480 nFontWidth = static_cast<tools::Long>(static_cast<double>(nFontWidth) * fScaleFactor);
481 }
482 }
483#endif
484
487 ImplWriteExtent( -nFontHeight );
488 ImplWriteExtent( nFontWidth );
490
491 switch( rFont.GetWeight() )
492 {
493 case WEIGHT_THIN: nWeight = 100; break;
494 case WEIGHT_ULTRALIGHT: nWeight = 200; break;
495 case WEIGHT_LIGHT: nWeight = 300; break;
496 case WEIGHT_SEMILIGHT: nWeight = 300; break;
497 case WEIGHT_NORMAL: nWeight = 400; break;
498 case WEIGHT_MEDIUM: nWeight = 500; break;
499 case WEIGHT_SEMIBOLD: nWeight = 600; break;
500 case WEIGHT_BOLD: nWeight = 700; break;
501 case WEIGHT_ULTRABOLD: nWeight = 800; break;
502 case WEIGHT_BLACK: nWeight = 900; break;
503 default: nWeight = 0; break;
504 }
505
506 m_rStm.WriteInt32( nWeight );
507 m_rStm.WriteUChar( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
508 m_rStm.WriteUChar( ( LINESTYLE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
509 m_rStm.WriteUChar( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
510 m_rStm.WriteUChar( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
511 m_rStm.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
512
513 switch( rFont.GetPitch() )
514 {
515 case PITCH_FIXED: nPitchAndFamily = 0x01; break;
516 case PITCH_VARIABLE: nPitchAndFamily = 0x02; break;
517 default: nPitchAndFamily = 0x00; break;
518 }
519
520 switch( rFont.GetFamilyType() )
521 {
522 case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break;
523 case FAMILY_MODERN: nPitchAndFamily |= 0x30; break;
524 case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break;
525 case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break;
526 case FAMILY_SWISS: nPitchAndFamily |= 0x20; break;
527 default: break;
528 }
529
530 m_rStm.WriteUChar( nPitchAndFamily );
531
532 for( i = 0; i < 32; i++ )
533 m_rStm.WriteUInt16( ( i < aFontName.getLength() ) ? aFontName[ i ] : 0 );
534
535 // dummy elfFullName
536 for( i = 0; i < 64; i++ )
537 m_rStm.WriteUInt16( 0 );
538
539 // dummy elfStyle
540 for( i = 0; i < 32; i++ )
541 m_rStm.WriteUInt16( 0 );
542
543 // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
545
546 // dummy elfVendorId
547 m_rStm.WriteUInt32( 0 );
548
549 // dummy elfCulture
550 m_rStm.WriteUInt32( 0 );
551
552 // dummy elfPanose
554
555 // fill record to get a record size divideable by 4
556 m_rStm.WriteUInt16( 0 );
557
559
560 // TextAlign
561 sal_uInt32 nTextAlign;
562
563 switch( rFont.GetAlignment() )
564 {
565 case ALIGN_TOP: nTextAlign = TA_TOP; break;
566 case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break;
567 default: nTextAlign = TA_BASELINE; break;
568 }
569 nTextAlign |= mnHorTextAlign;
570
572 m_rStm.WriteUInt32( nTextAlign );
574
575 // Text color
577 ImplWriteColor( maVDev->GetTextColor() );
579
583
584}
585
586void EMFWriter::ImplWriteColor( const Color& rColor )
587{
588 sal_uInt32 nCol = rColor.GetRed();
589
590 nCol |= static_cast<sal_uInt32>(rColor.GetGreen()) << 8;
591 nCol |= static_cast<sal_uInt32>(rColor.GetBlue()) << 16;
592
593 m_rStm.WriteUInt32( nCol );
594}
595
597{
598 sal_uInt32 nROP2;
599
600 switch( eRop )
601 {
602 case RasterOp::Invert: nROP2 = 6; break;
603 case RasterOp::Xor: nROP2 = 7; break;
604 default: nROP2 = 13;break;
605 }
606
608 m_rStm.WriteUInt32( nROP2 );
610}
611
613{
614 nExtent = OutputDevice::LogicToLogic( Size( nExtent, 0 ), maVDev->GetMapMode(), maDestMapMode ).Width();
615 m_rStm.WriteInt32( nExtent );
616}
617
618void EMFWriter::ImplWritePoint( const Point& rPoint )
619{
620 const Point aPoint( OutputDevice::LogicToLogic( rPoint, maVDev->GetMapMode(), maDestMapMode ));
621 m_rStm.WriteInt32( aPoint.X() ).WriteInt32( aPoint.Y() );
622}
623
625{
626 const Size aSize( OutputDevice::LogicToLogic( rSize, maVDev->GetMapMode(), maDestMapMode ));
627 m_rStm.WriteInt32( aSize.Width() ).WriteInt32( aSize.Height() );
628}
629
631{
632 const tools::Rectangle aRect( OutputDevice::LogicToLogic ( rRect, maVDev->GetMapMode(), maDestMapMode ));
633 auto right = aRect.IsWidthEmpty() ? aRect.Left() : aRect.Right();
634 auto bottom = aRect.IsHeightEmpty() ? aRect.Top() : aRect.Bottom();
635 m_rStm
636 .WriteInt32( aRect.Left() )
637 .WriteInt32( aRect.Top() )
638 .WriteInt32( right )
639 .WriteInt32( bottom );
640}
641
642void EMFWriter::ImplWritePolygonRecord( const tools::Polygon& rPoly, bool bClose )
643{
644 if( !rPoly.GetSize() )
645 return;
646
647 if( rPoly.HasFlags() )
648 ImplWritePath( rPoly, bClose );
649 else
650 {
651 if( bClose )
653
655
657 ImplWriteRect( rPoly.GetBoundRect() );
658 m_rStm.WriteUInt32( rPoly.GetSize() );
659
660 for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
661 ImplWritePoint( rPoly[ i ] );
662
664 }
665}
666
668{
669 sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
670
671 if( !nPolyCount )
672 return;
673
674 if( 1 == nPolyCount )
675 ImplWritePolygonRecord( rPolyPoly[ 0 ], true );
676 else
677 {
678 bool bHasFlags = false;
679 sal_uInt32 nTotalPoints = 0;
680
681 for( i = 0; i < nPolyCount; i++ )
682 {
683 nTotalPoints += rPolyPoly[ i ].GetSize();
684 if ( rPolyPoly[ i ].HasFlags() )
685 bHasFlags = true;
686 }
687 if( nTotalPoints )
688 {
689 if ( bHasFlags )
690 ImplWritePath( rPolyPoly, true );
691 else
692 {
695
697 ImplWriteRect( rPolyPoly.GetBoundRect() );
698 m_rStm.WriteUInt32( nPolyCount ).WriteUInt32( nTotalPoints );
699
700 for( i = 0; i < nPolyCount; i++ )
701 m_rStm.WriteUInt32( rPolyPoly[ i ].GetSize() );
702
703 for( i = 0; i < nPolyCount; i++ )
704 {
705 const tools::Polygon& rPoly = rPolyPoly[ i ];
706
707 for( n = 0; n < rPoly.GetSize(); n++ )
708 ImplWritePoint( rPoly[ n ] );
709 }
711 }
712 }
713 }
714}
715
716void EMFWriter::ImplWritePath( const tools::PolyPolygon& rPolyPoly, bool bClosed )
717{
718 if ( bClosed )
721
724
725 sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
726 for ( i = 0; i < nPolyCount; i++ )
727 {
728 n = 0;
729 const tools::Polygon& rPoly = rPolyPoly[ i ];
730 while ( n < rPoly.GetSize() )
731 {
732 if( n == 0 )
733 {
735 ImplWritePoint( rPoly[ 0 ] );
737 n++;
738 continue;
739 }
740
741 sal_uInt16 nBezPoints = 0;
742
743 while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == PolyFlags::Control ) )
744 nBezPoints += 3;
745
746 if ( nBezPoints )
747 {
749 tools::Polygon aNewPoly( nBezPoints + 1 );
750 aNewPoly[ 0 ] = rPoly[ n - 1 ];
751 for ( o = 0; o < nBezPoints; o++ )
752 aNewPoly[ o + 1 ] = rPoly[ n + o ];
753 ImplWriteRect( aNewPoly.GetBoundRect() );
754 m_rStm.WriteUInt32( nBezPoints );
755 for( o = 1; o < aNewPoly.GetSize(); o++ )
756 ImplWritePoint( aNewPoly[ o ] );
758 n = n + nBezPoints;
759 }
760 else
761 {
762 sal_uInt16 nPoints = 1;
763 while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != PolyFlags::Control ) )
764 nPoints++;
765
766 if ( nPoints > 1 )
767 {
769 tools::Polygon aNewPoly( nPoints + 1 );
770 aNewPoly[ 0 ] = rPoly[ n - 1];
771 for ( o = 1; o <= nPoints; o++ )
772 aNewPoly[ o ] = rPoly[ n - 1 + o ];
773 ImplWriteRect( aNewPoly.GetBoundRect() );
774 m_rStm.WriteUInt32( nPoints );
775 for( o = 1; o < aNewPoly.GetSize(); o++ )
776 ImplWritePoint( aNewPoly[ o ] );
778 }
779 else
780 {
782 ImplWritePoint( rPoly[ n ] );
784 }
785 n = n + nPoints;
786 }
787 if ( bClosed && ( n == rPoly.GetSize() ) )
788 {
791 }
792 }
793 }
797 ImplWriteRect( rPolyPoly.GetBoundRect() );
799}
800
801void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
802 const Size& rSz, sal_uInt32 nROP )
803{
804 if( rBmp.IsEmpty() )
805 return;
806
807 SvMemoryStream aMemStm( 65535, 65535 );
808 const Size aBmpSizePixel( rBmp.GetSizePixel() );
809
811 ImplWriteRect( tools::Rectangle( rPt, rSz ) );
812 ImplWritePoint( rPt );
813 m_rStm.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel.Width() ).WriteInt32( aBmpSizePixel.Height() );
814
815 // write offset positions and sizes later
816 const sal_uInt64 nOffPos = m_rStm.Tell();
817 m_rStm.SeekRel( 16 );
818
819 m_rStm.WriteUInt32( 0 ).WriteInt32( ( RasterOp::Xor == maVDev->GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
820 ImplWriteSize( rSz );
821
822 WriteDIB(rBmp, aMemStm, true, false);
823
824 sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize;
825 sal_uInt16 nBitCount;
826
827 // get DIB parameters
828 aMemStm.Seek( 0 );
829 aMemStm.ReadUInt32( nHeaderSize );
830 aMemStm.SeekRel( 10 );
831 aMemStm.ReadUInt16( nBitCount ).ReadUInt32( nCompression ).ReadUInt32( nImageSize );
832 aMemStm.SeekRel( 8 );
833 aMemStm.ReadUInt32( nColsUsed );
834
835 if (nBitCount <= 8)
836 {
837 if (nColsUsed)
838 nPalCount = nColsUsed;
839 else
840 nPalCount = 1 << static_cast<sal_uInt32>(nBitCount);
841 }
842 else
843 {
844 if (nCompression == BITFIELDS)
845 nPalCount = 3;
846 else
847 nPalCount = 0;
848 }
849
850 sal_uInt32 nPalSize = nPalCount * 4;
851
852 m_rStm.WriteBytes( aMemStm.GetData(), nDIBSize );
853
854 const sal_uInt64 nEndPos = m_rStm.Tell();
855 m_rStm.Seek( nOffPos );
856 m_rStm.WriteUInt32( 80 ).WriteUInt32( nHeaderSize + nPalSize );
857 m_rStm.WriteUInt32( 80 + nHeaderSize + nPalSize ).WriteUInt32( nImageSize );
858 m_rStm.Seek( nEndPos );
859
861
862}
863
864void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_uInt32 nWidth )
865{
866 sal_Int32 nLen = rText.getLength(), i;
867
868 if( !nLen )
869 return;
870
871 sal_uInt32 nNormWidth;
872 std::vector<sal_Int32> aOwnArray;
874
875 // get text sizes
876 if( !pDXArray.empty() )
877 {
878 nNormWidth = maVDev->GetTextWidth( rText );
879 pDX = pDXArray;
880 }
881 else
882 {
883 nNormWidth = maVDev->GetTextArray( rText, &aOwnArray );
884 pDX = aOwnArray;
885 }
886
887 if( nLen > 1 )
888 {
889 nNormWidth = pDX[ nLen - 2 ] + maVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
890
891 if( nWidth && nNormWidth && ( nWidth != nNormWidth ) )
892 {
893 if (!pDXArray.empty())
894 {
895 aOwnArray.insert(aOwnArray.begin(), pDXArray.begin(), pDXArray.end());
896 pDX = aOwnArray;
897 }
898 const double fFactor = static_cast<double>(nWidth) / nNormWidth;
899
900 for( i = 0; i < ( nLen - 1 ); i++ )
901 aOwnArray[ i ] = FRound( aOwnArray[ i ] * fFactor );
902 }
903 }
904
905 // write text record
907
908 ImplWriteRect( tools::Rectangle( rPos, Size( nNormWidth, maVDev->GetTextHeight() ) ) );
909 m_rStm.WriteUInt32( 1 );
910 m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
911 ImplWritePoint( rPos );
912 m_rStm.WriteUInt32( nLen ).WriteUInt32( 76 ).WriteUInt32( 2 );
914 m_rStm.WriteUInt32( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
915
916 // write text
917 for( i = 0; i < nLen; i++ )
918 m_rStm.WriteUInt16( rText[ i ] );
919
920 // padding word
921 if( nLen & 1 )
922 m_rStm.WriteUInt16( 0 );
923
924 // write DX array
925 ImplWriteExtent( pDX[ 0 ] );
926
927 if( nLen > 1 )
928 {
929 for( i = 1; i < ( nLen - 1 ); i++ )
930 ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
931
932 ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
933 }
934
936
937}
938
940{
941 if(!rLinePolygon.count())
942 return;
943
944 basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
945 basegfx::B2DPolyPolygon aFillPolyPolygon;
946
947 rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
948
949 if(aLinePolyPolygon.count())
950 {
951 for(auto const& rB2DPolygon : std::as_const(aLinePolyPolygon))
952 {
953 ImplWritePolygonRecord( tools::Polygon(rB2DPolygon), false );
954 }
955 }
956
957 if(!aFillPolyPolygon.count())
958 return;
959
960 const Color aOldLineColor(maVDev->GetLineColor());
961 const Color aOldFillColor(maVDev->GetFillColor());
962
963 maVDev->SetLineColor();
964 maVDev->SetFillColor(aOldLineColor);
965
966 for(auto const& rB2DPolygon : std::as_const(aFillPolyPolygon))
967 {
969 }
970
971 maVDev->SetLineColor(aOldLineColor);
972 maVDev->SetFillColor(aOldFillColor);
973}
974
976{
977 for( size_t j = 0, nActionCount = rMtf.GetActionSize(); j < nActionCount; j++ )
978 {
979 const MetaAction* pAction = rMtf.GetAction( j );
980 const MetaActionType nType = pAction->GetType();
981
982 switch( nType )
983 {
985 {
986 const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
987
990 ImplWritePoint( pA->GetPoint() );
991 ImplWriteColor( pA->GetColor() );
993 }
994 break;
995
997 {
998 if( maVDev->IsLineColor() )
999 {
1000 const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
1001
1004 ImplWritePoint( pA->GetPoint() );
1005 ImplWriteColor( maVDev->GetLineColor() );
1006 ImplEndRecord();
1007 }
1008 }
1009 break;
1010
1012 {
1013 if( maVDev->IsLineColor() )
1014 {
1015 const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
1016
1017 if(pA->GetLineInfo().IsDefault())
1018 {
1020
1023 ImplEndRecord();
1024
1026 ImplWritePoint( pA->GetEndPoint() );
1027 ImplEndRecord();
1028
1030 ImplWritePoint( pA->GetEndPoint() );
1031 ImplWriteColor( maVDev->GetLineColor() );
1032 ImplEndRecord();
1033 }
1034 else
1035 {
1036 // LineInfo used; handle Dash/Dot and fat lines
1037 basegfx::B2DPolygon aPolygon;
1038 aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1039 aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1041 }
1042 }
1043 }
1044 break;
1045
1047 {
1048 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1049 {
1050 const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
1051
1054
1056 ImplWriteRect( pA->GetRect() );
1057 ImplEndRecord();
1058 }
1059 }
1060 break;
1061
1063 {
1064 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1065 {
1066 const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
1067
1070
1072 ImplWriteRect( pA->GetRect() );
1073 ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
1074 ImplEndRecord();
1075 }
1076 }
1077 break;
1078
1080 {
1081 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1082 {
1083 const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
1084
1087
1089 ImplWriteRect( pA->GetRect() );
1090 ImplEndRecord();
1091 }
1092 }
1093 break;
1094
1099 {
1100 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1101 {
1102 tools::Polygon aPoly;
1103
1104 switch( nType )
1105 {
1107 {
1108 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
1109 aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Arc );
1110 }
1111 break;
1112
1114 {
1115 const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
1116 aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Pie );
1117 }
1118 break;
1119
1121 {
1122 const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
1123 aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Chord );
1124 }
1125 break;
1126
1128 aPoly = static_cast<const MetaPolygonAction*>(pAction)->GetPolygon();
1129 break;
1130 default: break;
1131 }
1132
1134 }
1135 }
1136 break;
1137
1139 {
1140 if( maVDev->IsLineColor() )
1141 {
1142 const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
1143 const tools::Polygon& rPoly = pA->GetPolygon();
1144
1145 if( rPoly.GetSize() )
1146 {
1147 if(pA->GetLineInfo().IsDefault())
1148 {
1149 ImplWritePolygonRecord( rPoly, false );
1150 }
1151 else
1152 {
1153 // LineInfo used; handle Dash/Dot and fat lines
1155 }
1156 }
1157 }
1158 }
1159 break;
1160
1162 {
1163 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1164 ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction*>(pAction)->GetPolyPolygon() );
1165 }
1166 break;
1167
1169 {
1170 const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
1171 GDIMetaFile aTmpMtf;
1172
1173 Gradient aGradient = pA->GetGradient();
1174 aGradient.AddGradientActions( pA->GetRect(), aTmpMtf );
1175 ImplWrite( aTmpMtf );
1176 }
1177 break;
1178
1180 {
1181 const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
1182 GDIMetaFile aTmpMtf;
1183
1184 maVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1185 ImplWrite( aTmpMtf );
1186 }
1187 break;
1188
1190 {
1191 const tools::PolyPolygon& rPolyPoly = static_cast<const MetaTransparentAction*>(pAction)->GetPolyPolygon();
1192 if( rPolyPoly.Count() )
1193 ImplWritePlusFillPolygonRecord( rPolyPoly[0], static_cast<const MetaTransparentAction*>(pAction)->GetTransparence() );
1196 ImplWritePolyPolygonRecord( rPolyPoly );
1197
1201 }
1202 break;
1203
1205 {
1206 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
1207
1208 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1209 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1210 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1211 const Point aDestPt( pA->GetPoint() );
1212 const Size aDestSize( pA->GetSize() );
1213 const double fScaleX = aSrcSize.Width() ? static_cast<double>(aDestSize.Width()) / aSrcSize.Width() : 1.0;
1214 const double fScaleY = aSrcSize.Height() ? static_cast<double>(aDestSize.Height()) / aSrcSize.Height() : 1.0;
1215 tools::Long nMoveX, nMoveY;
1216
1217 if( fScaleX != 1.0 || fScaleY != 1.0 )
1218 {
1219 aTmpMtf.Scale( fScaleX, fScaleY );
1220 aSrcPt.setX( FRound( aSrcPt.X() * fScaleX ) );
1221 aSrcPt.setY( FRound( aSrcPt.Y() * fScaleY ) );
1222 }
1223
1224 nMoveX = aDestPt.X() - aSrcPt.X();
1225 nMoveY = aDestPt.Y() - aSrcPt.Y();
1226
1227 if( nMoveX || nMoveY )
1228 aTmpMtf.Move( nMoveX, nMoveY );
1229
1233 ImplWrite( aTmpMtf );
1234 }
1235 break;
1236
1238 {
1239 const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pAction);
1240 const GDIMetaFile& aSubstitute( pA->GetSubstitute() );
1241
1242 for( size_t i = 0, nCount = aSubstitute.GetActionSize(); i < nCount; i++ )
1243 {
1244 const MetaAction* pSubstAct = aSubstitute.GetAction( i );
1245 if( pSubstAct->GetType() == MetaActionType::BMPSCALE )
1246 {
1247 maVDev->Push();
1249 ImplEndRecord();
1250
1251 MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1252 Size aOutSize( OutputDevice::LogicToLogic( pA->GetSize(), maVDev->GetMapMode(), aMapMode ) );
1253 aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
1254 aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
1255 aMapMode.SetOrigin( OutputDevice::LogicToLogic( pA->GetPoint(), maVDev->GetMapMode(), aMapMode ) );
1256 maVDev->SetMapMode( aMapMode );
1257 ImplWrite( aSubstitute );
1258
1259 maVDev->Pop();
1261 m_rStm.WriteInt32( -1 );
1262 ImplEndRecord();
1263 break;
1264 }
1265 }
1266 }
1267 break;
1268
1270 {
1271 const MetaBmpAction* pA = static_cast<const MetaBmpAction *>(pAction);
1272 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY );
1273 }
1274 break;
1275
1277 {
1278 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
1280 }
1281 break;
1282
1284 {
1285 const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pAction);
1286 Bitmap aTmp( pA->GetBitmap() );
1287
1288 if( aTmp.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1289 ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1290 }
1291 break;
1292
1294 {
1295 const MetaBmpExAction* pA = static_cast<const MetaBmpExAction *>(pAction);
1296 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1297 Bitmap aMsk( pA->GetBitmapEx().GetAlpha() );
1298
1299 if( !aMsk.IsEmpty() )
1300 {
1301 aBmp.Replace( aMsk, COL_WHITE );
1302 aMsk.Invert();
1303 ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev->PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
1304 ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev->PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
1305 }
1306 else
1307 ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
1308 }
1309 break;
1310
1312 {
1313 const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
1314 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1315 Bitmap aMsk( pA->GetBitmapEx().GetAlpha() );
1316
1317 if( !aMsk.IsEmpty() )
1318 {
1319 aBmp.Replace( aMsk, COL_WHITE );
1320 aMsk.Invert();
1321 ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
1322 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
1323 }
1324 else
1325 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1326 }
1327 break;
1328
1330 {
1331 const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
1332 BitmapEx aBmpEx( pA->GetBitmapEx() );
1333 aBmpEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1334 Bitmap aBmp( aBmpEx.GetBitmap() );
1335 Bitmap aMsk( aBmpEx.GetAlpha() );
1336
1337 if( !aMsk.IsEmpty() )
1338 {
1339 aBmp.Replace( aMsk, COL_WHITE );
1340 aMsk.Invert();
1341 ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT );
1342 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
1343 }
1344 else
1345 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1346 }
1347 break;
1348
1350 {
1351 const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
1352 const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1353
1355 ImplWriteTextRecord( pA->GetPoint(), aText, {}, 0 );
1356 }
1357 break;
1358
1360 {
1361 const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
1362 const OUString& aText( pA->GetText() );
1363
1365 ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, {}, 0 );
1366 }
1367 break;
1368
1370 {
1371 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
1372 const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1373
1375 ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
1376 }
1377 break;
1378
1380 {
1381 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
1382 const OUString aText = pA->GetText().copy( pA->GetIndex(), std::min(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) );
1383
1385 ImplWriteTextRecord( pA->GetPoint(), aText, {}, pA->GetWidth() );
1386 }
1387 break;
1388
1390 {
1391 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1392 mbLineChanged = true;
1393 }
1394 break;
1395
1397 {
1398 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1399 mbFillChanged = true;
1400 }
1401 break;
1402
1408 {
1409 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1410 mbTextChanged = true;
1411 }
1412 break;
1413
1415 {
1416 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1417
1419 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction*>(pAction)->GetRect() );
1420 ImplEndRecord();
1421 }
1422 break;
1423
1427 {
1428 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1429 }
1430 break;
1431
1434 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1435 break;
1436
1438 {
1439 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1440
1442 ImplEndRecord();
1443 }
1444 break;
1445
1447 {
1448 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1449
1451 m_rStm.WriteInt32( -1 );
1452 ImplEndRecord();
1453
1454 ImplWriteRasterOp( maVDev->GetRasterOp() );
1456 }
1457 break;
1458
1460 {
1461 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1462 ImplWriteRasterOp( static_cast<const MetaRasterOpAction*>(pAction)->GetRasterOp() );
1463 }
1464 break;
1465
1467 {
1468 vcl::text::ComplexTextLayoutFlags nLayoutMode = static_cast<const MetaLayoutModeAction*>(pAction)->GetLayoutMode();
1469 mnHorTextAlign = 0;
1471 {
1473 }
1478 break;
1479 }
1480
1482 {
1483 MetaCommentAction const*const pCommentAction(
1484 static_cast<MetaCommentAction const*>(pAction));
1485 if (pCommentAction->GetComment() == "EMF_PLUS")
1486 {
1488 m_rStm.WriteBytes(pCommentAction->GetData(),
1489 pCommentAction->GetDataSize());
1491 }
1492 }
1493 break;
1494
1501 // Explicitly ignored cases
1502 break;
1503
1504 default:
1505 // TODO: Implement more cases as necessary. Let's not bother with a warning.
1506 break;
1507 }
1508 }
1509}
1510
1511/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
RasterOp
Definition: RasterOp.hxx:23
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:354
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Size GetSizePixel() const
bool IsEmpty() const
bool Invert()
Perform the Invert operation on every pixel.
Definition: bitmappaint.cxx:61
bool Replace(const Bitmap &rMask, const Color &rReplaceColor)
Replace all pixel where the given mask is on with the specified color.
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
sal_uLong mnRecordCount
Definition: emfwr.hxx:38
void ImplWritePlusColor(const Color &rColor, sal_uInt32 nTrans)
Definition: emfwr.cxx:206
void ImplWritePath(const tools::PolyPolygon &rPolyPoly, bool bClose)
Definition: emfwr.cxx:716
bool mbFillChanged
Definition: emfwr.hxx:45
void ImplWriteExtent(tools::Long nExtent)
Definition: emfwr.cxx:612
sal_uLong mnRecordPos
Definition: emfwr.hxx:39
void ImplPlusRecord(EmfPlusRecordType nType, sal_uInt16 nFlags)
Definition: emfwr.cxx:159
sal_uInt32 mnFillHandle
Definition: emfwr.hxx:46
bool mbLineChanged
Definition: emfwr.hxx:43
void ImplWrite(const GDIMetaFile &rMtf)
Definition: emfwr.cxx:975
void ImplWritePoint(const Point &rPoint)
Definition: emfwr.cxx:618
sal_uLong mnRecordPlusPos
Definition: emfwr.hxx:40
void ImplWritePolygonRecord(const tools::Polygon &rPoly, bool bClose)
Definition: emfwr.cxx:642
sal_uInt32 mnLineHandle
Definition: emfwr.hxx:44
void ImplEndRecord()
Definition: emfwr.cxx:362
void ImplBeginPlusRecord(EmfPlusRecordType nType, sal_uInt16 nFlags)
Definition: emfwr.cxx:129
bool ImplPrepareHandleSelect(sal_uInt32 &rHandle, sal_uLong nSelectType)
Definition: emfwr.cxx:384
void ImplBeginCommentRecord(sal_Int32 nCommentType)
Definition: emfwr.cxx:110
void ImplWritePlusFillPolygonRecord(const tools::Polygon &rPoly, sal_uInt32 nTrans)
Definition: emfwr.cxx:224
void ImplWritePlusEOF()
Definition: emfwr.cxx:199
void ImplWriteRect(const tools::Rectangle &rRect)
Definition: emfwr.cxx:630
void ImplCheckFillAttr()
Definition: emfwr.cxx:433
void ImplBeginRecord(sal_uInt32 nType)
Definition: emfwr.cxx:348
void ImplCheckTextAttr()
Definition: emfwr.cxx:451
void ImplWriteRasterOp(RasterOp eRop)
Definition: emfwr.cxx:596
void ImplWritePlusPoint(const Point &rPoint)
Definition: emfwr.cxx:217
void ImplWritePolyPolygonRecord(const tools::PolyPolygon &rPolyPoly)
Definition: emfwr.cxx:667
MapMode maDestMapMode
Definition: emfwr.hxx:34
void ImplReleaseHandle(sal_uLong nHandle)
Definition: emfwr.cxx:342
bool mbRecordPlusOpen
Definition: emfwr.hxx:42
sal_uInt32 mnHorTextAlign
Definition: emfwr.hxx:49
void ImplCheckLineAttr()
Definition: emfwr.cxx:416
void Impl_handleLineInfoPolyPolygons(const LineInfo &rInfo, const basegfx::B2DPolygon &rLinePolygon)
Definition: emfwr.cxx:939
void ImplWriteSize(const Size &rSize)
Definition: emfwr.cxx:624
void WriteEMFPlusHeader(const Size &rMtfSizePix, const Size &rMtfSizeLog)
Definition: emfwr.cxx:165
bool mbRecordOpen
Definition: emfwr.hxx:41
sal_uLong mnHandleCount
Definition: emfwr.hxx:37
void ImplEndPlusRecord()
Definition: emfwr.cxx:143
std::vector< bool > mHandlesUsed
Definition: emfwr.hxx:36
sal_uLong ImplAcquireHandle()
Definition: emfwr.cxx:323
bool mbTextChanged
Definition: emfwr.hxx:47
void ImplEndCommentRecord()
Definition: emfwr.cxx:117
sal_uInt32 mnTextHandle
Definition: emfwr.hxx:48
void ImplWriteBmpRecord(const Bitmap &rBmp, const Point &rPt, const Size &rSz, sal_uInt32 nROP)
Definition: emfwr.cxx:801
SvStream & m_rStm
Definition: emfwr.hxx:35
bool WriteEMF(const GDIMetaFile &rMtf)
Definition: emfwr.cxx:239
void ImplWriteTextRecord(const Point &rPos, const OUString &rText, o3tl::span< const sal_Int32 > pDXArray, sal_uInt32 nWidth)
Definition: emfwr.cxx:864
void ImplWriteColor(const Color &rColor)
Definition: emfwr.cxx:586
ScopedVclPtr< VirtualDevice > maVDev
Definition: emfwr.hxx:33
size_t GetActionSize() const
Definition: gdimtf.cxx:179
void Move(tools::Long nX, tools::Long nY)
Definition: gdimtf.cxx:649
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:726
const Size & GetPrefSize() const
Definition: gdimtf.hxx:172
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:184
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:175
void AddGradientActions(tools::Rectangle const &rRect, GDIMetaFile &rMetaFile)
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:103
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:115
void SetMapUnit(MapUnit eUnit)
Definition: mapmod.cxx:98
const Point & GetOrigin() const
Definition: mapmod.cxx:148
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:109
MetaActionType GetType() const
Definition: metaact.hxx:94
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 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 tools::Rectangle & GetRect() const
Definition: metaact.hxx:275
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 tools::Rectangle & GetRect() const
Definition: metaact.hxx:1020
const Gradient & GetGradient() const
Definition: metaact.hxx:1021
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1080
const Hatch & GetHatch() const
Definition: metaact.hxx:1081
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:185
const Point & GetEndPoint() const
Definition: metaact.hxx:184
const Point & GetStartPoint() const
Definition: metaact.hxx:183
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::Rectangle & GetRect() const
Definition: metaact.hxx:214
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 tools::Rectangle & GetRect() const
Definition: metaact.hxx:618
const OUString & GetText() const
Definition: metaact.hxx:619
sal_uInt16 GetTransparence() const
Definition: metaact.hxx:1564
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1605
constexpr tools::Long Height() const
constexpr tools::Long Width() const
const void * GetData()
SvStream & WriteInt32(sal_Int32 nInt32)
sal_uInt64 Tell() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
SvStream & WriteInt16(sal_Int16 nInt16)
SvStream & WriteUChar(unsigned char nChar)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
SvStream & WriteUInt32(sal_uInt32 nUInt32)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
sal_uInt64 Seek(sal_uInt64 nPos)
sal_uInt64 SeekRel(sal_Int64 nPos)
ErrCode GetError() const
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
sal_uInt32 count() const
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
sal_uInt32 count() const
constexpr iterator begin() const noexcept
constexpr iterator end() const noexcept
constexpr bool empty() const noexcept
sal_uInt16 Count() const
tools::Rectangle GetBoundRect() const
::basegfx::B2DPolygon getB2DPolygon() const
PolyFlags GetFlags(sal_uInt16 nPos) const
bool HasFlags() const
sal_uInt16 GetSize() const
tools::Rectangle GetBoundRect() const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr tools::Long Right() const
constexpr bool IsWidthEmpty() const
constexpr bool IsHeightEmpty() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
FontFamily GetFamilyType()
Definition: font/font.cxx:927
FontStrikeout GetStrikeout() const
Definition: font/font.cxx:945
FontItalic GetItalic()
Definition: font/font.cxx:926
tools::Long GetOrCalculateAverageFontWidth() const
Definition: font/font.cxx:421
const OUString & GetFamilyName() const
Definition: font/font.cxx:903
TextAlign GetAlignment() const
Definition: font/font.cxx:901
const Size & GetFontSize() const
Definition: font/font.cxx:906
FontPitch GetPitch()
Definition: font/font.cxx:923
FontWeight GetWeight()
Definition: font/font.cxx:924
FontLineStyle GetUnderline() const
Definition: font/font.cxx:943
rtl_TextEncoding GetCharSet() const
Definition: font/font.cxx:912
Degree10 GetOrientation() const
Definition: font/font.cxx:919
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
int nCount
bool WriteDIB(const Bitmap &rSource, SvStream &rOStm, bool bCompressed, bool bFileHeader)
Definition: dibtools.cxx:1832
#define BITFIELDS
Definition: dibtools.hxx:37
OString right
OString bottom
#define WIN_EMR_SETPIXELV
Definition: emfwr.cxx:46
#define WIN_EMR_POLYLINE
Definition: emfwr.cxx:37
#define WIN_SRCPAINT
Definition: emfwr.cxx:76
#define WIN_EMR_SAVEDC
Definition: emfwr.cxx:54
#define WIN_EMR_SETBKMODE
Definition: emfwr.cxx:48
#define WIN_EMR_SETWINDOWORGEX
Definition: emfwr.cxx:42
#define LINE_SELECT
Definition: emfwr.cxx:84
#define WIN_EMR_STROKEPATH
Definition: emfwr.cxx:68
#define WIN_EMR_DELETEOBJECT
Definition: emfwr.cxx:59
#define TEXT_SELECT
Definition: emfwr.cxx:86
#define WIN_EMR_SETMAPMODE
Definition: emfwr.cxx:47
#define WIN_EMR_CREATEBRUSHINDIRECT
Definition: emfwr.cxx:58
#define WIN_EMR_ELLIPSE
Definition: emfwr.cxx:60
#define WIN_SRCINVERT
Definition: emfwr.cxx:78
#define WIN_EMR_LINETO
Definition: emfwr.cxx:63
#define WIN_EMR_CLOSEFIGURE
Definition: emfwr.cxx:66
EmfPlusRecordType
Definition: emfwr.cxx:99
#define WIN_SRCCOPY
Definition: emfwr.cxx:75
#define TA_RIGHT
Definition: emfwr.cxx:89
#define WIN_EMR_POLYPOLYGON
Definition: emfwr.cxx:40
#define WIN_EMR_EOF
Definition: emfwr.cxx:45
#define WIN_EMR_BEGINPATH
Definition: emfwr.cxx:64
#define MM_ANISOTROPIC
Definition: emfwr.cxx:96
#define WIN_EMR_SELECTOBJECT
Definition: emfwr.cxx:56
#define WIN_EMR_POLYGON
Definition: emfwr.cxx:36
#define HANDLE_INVALID
Definition: emfwr.cxx:81
#define WIN_EMR_ENDPATH
Definition: emfwr.cxx:65
#define TA_RTLREADING
Definition: emfwr.cxx:94
#define WIN_EMR_POLYBEZIERTO
Definition: emfwr.cxx:38
#define WIN_EMR_COMMENT_EMFPLUS
Definition: emfwr.cxx:79
#define WIN_SRCAND
Definition: emfwr.cxx:77
#define WIN_EMR_STRETCHDIBITS
Definition: emfwr.cxx:71
#define WIN_EMR_ROUNDRECT
Definition: emfwr.cxx:62
#define WIN_EMR_INTERSECTCLIPRECT
Definition: emfwr.cxx:53
#define WIN_EMR_CREATEPEN
Definition: emfwr.cxx:57
#define TA_TOP
Definition: emfwr.cxx:91
#define TA_BOTTOM
Definition: emfwr.cxx:92
#define TA_BASELINE
Definition: emfwr.cxx:93
#define FILL_SELECT
Definition: emfwr.cxx:85
#define WIN_EMR_RECTANGLE
Definition: emfwr.cxx:61
#define WIN_EMR_SETVIEWPORTORGEX
Definition: emfwr.cxx:44
#define WIN_EMR_EXTCREATEFONTINDIRECTW
Definition: emfwr.cxx:72
#define WIN_EMR_POLYLINETO
Definition: emfwr.cxx:39
#define WIN_EMR_SETROP2
Definition: emfwr.cxx:49
#define WIN_EMR_SETWINDOWEXTEX
Definition: emfwr.cxx:41
#define WIN_EMR_SETVIEWPORTEXTEX
Definition: emfwr.cxx:43
#define WIN_EMR_GDICOMMENT
Definition: emfwr.cxx:70
#define WIN_EMR_FILLPATH
Definition: emfwr.cxx:67
#define MAXHANDLES
Definition: emfwr.cxx:82
#define WIN_EMR_MOVETOEX
Definition: emfwr.cxx:52
#define WIN_EMR_SETTEXTCOLOR
Definition: emfwr.cxx:51
#define WIN_EMR_EXTTEXTOUTW
Definition: emfwr.cxx:73
#define WIN_EMR_RESTOREDC
Definition: emfwr.cxx:55
#define WIN_EMR_SETTEXTALIGN
Definition: emfwr.cxx:50
#define ERRCODE_NONE
LINESTYLE_NONE
STRIKEOUT_NONE
PITCH_VARIABLE
PITCH_FIXED
ITALIC_NONE
ALIGN_BOTTOM
ALIGN_TOP
FAMILY_DECORATIVE
FAMILY_SCRIPT
FAMILY_SWISS
FAMILY_MODERN
FAMILY_ROMAN
WEIGHT_ULTRALIGHT
WEIGHT_ULTRABOLD
WEIGHT_THIN
WEIGHT_BOLD
WEIGHT_NORMAL
WEIGHT_LIGHT
WEIGHT_SEMIBOLD
WEIGHT_SEMILIGHT
WEIGHT_MEDIUM
WEIGHT_BLACK
tools::Long FRound(double fVal)
short nBitCount
Definition: ipict.cxx:80
sal_Int64 n
#define SAL_WARN_IF(condition, area, stream)
MetaActionType
int i
Header
const ::avmedia::MediaItem * Execute(const SdrMarkView *pSdrView, SfxRequest const &rReq)
long Long
ComplexTextLayoutFlags
Definition: State.hxx:76
QPRO_FUNC_TYPE nType
sal_Int32 nHandle
sal_uIntPtr sal_uLong
UNDERLYING_TYPE get() const
unsigned char sal_uInt8