1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
26 #include <tools/helpers.hxx>
27 #include <tools/fract.hxx>
28 #include <tools/stream.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <basegfx/polygon/b2dpolypolygon.hxx>
31 #include <vcl/lineinfo.hxx>
32 #include <vcl/dibtools.hxx>
33 #include <vcl/metaact.hxx>
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
70 #define WIN_EMR_GDICOMMENT 70
71 #define WIN_EMR_STRETCHDIBITS 81
72 #define WIN_EMR_EXTCREATEFONTINDIRECTW 82
73 #define WIN_EMR_EXTTEXTOUTW 84
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
81 #define HANDLE_INVALID 0xffffffff
82 #define MAXHANDLES 65000
84 #define LINE_SELECT 0x00000001
85 #define FILL_SELECT 0x00000002
86 #define TEXT_SELECT 0x00000004
88 /* Text Alignment Options */
93 #define TA_BASELINE 24
94 #define TA_RTLREADING 256
96 #define MM_ANISOTROPIC 8
98 enum class EmfPlusRecordType
103 FillPolygon
= 0x400C,
104 SetAntiAliasMode
= 0x401E,
105 SetInterpolationMode
= 0x4021,
106 SetPixelOffsetMode
= 0x4022,
107 SetCompositingQuality
= 0x4024
110 void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType
)
112 ImplBeginRecord( WIN_EMR_GDICOMMENT
);
114 m_rStm
.WriteInt32( nCommentType
);
117 void EMFWriter::ImplEndCommentRecord()
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
);
129 void EMFWriter::ImplBeginPlusRecord( EmfPlusRecordType nType
, sal_uInt16 nFlags
)
131 SAL_WARN_IF( mbRecordPlusOpen
, "vcl", "Another EMF+ record is already opened!" );
133 if( !mbRecordPlusOpen
)
135 mbRecordPlusOpen
= true;
136 mnRecordPlusPos
= m_rStm
.Tell();
138 m_rStm
.WriteUInt16( static_cast<sal_uInt16
>(nType
) ).WriteUInt16( nFlags
);
143 void EMFWriter::ImplEndPlusRecord()
145 SAL_WARN_IF( !mbRecordPlusOpen
, "vcl", "EMF+ Record was not opened!" );
147 if( mbRecordPlusOpen
)
149 sal_Int32 nActPos
= m_rStm
.Tell();
150 sal_Int32 nSize
= nActPos
- mnRecordPlusPos
;
151 m_rStm
.Seek( mnRecordPlusPos
+ 4 );
152 m_rStm
.WriteUInt32( nSize
) // Size
153 .WriteUInt32( nSize
- 0xc ); // Data Size
154 m_rStm
.Seek( nActPos
);
155 mbRecordPlusOpen
= false;
159 void EMFWriter::ImplPlusRecord( EmfPlusRecordType nType
, sal_uInt16 nFlags
)
161 ImplBeginPlusRecord( nType
, nFlags
);
165 void EMFWriter::WriteEMFPlusHeader( const Size
&rMtfSizePix
, const Size
&rMtfSizeLog
)
167 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
169 sal_Int32 nDPIX
= rMtfSizePix
.Width()*25;
170 sal_Int32 nDivX
= rMtfSizeLog
.Width()/100;
172 nDPIX
/= nDivX
; // DPI X
174 sal_Int32 nDPIY
= rMtfSizePix
.Height()*25;
175 sal_Int32 nDivY
= rMtfSizeLog
.Height()/100;
177 nDPIY
/= nDivY
; // DPI Y
179 m_rStm
.WriteInt16( sal_Int16(EmfPlusRecordType::Header
) );
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
186 .WriteInt32( nDPIY
);
187 ImplEndCommentRecord();
189 // Write more properties
190 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
191 ImplPlusRecord( EmfPlusRecordType::SetPixelOffsetMode
, 0x0 );
192 ImplPlusRecord( EmfPlusRecordType::SetAntiAliasMode
, 0x09 ); // TODO: Check actual values for AntiAlias
193 ImplPlusRecord( EmfPlusRecordType::SetCompositingQuality
, 0x0100 ); // Default Quality
194 ImplPlusRecord( EmfPlusRecordType::SetInterpolationMode
, 0x00 ); // Default
195 ImplPlusRecord( EmfPlusRecordType::GetDC
, 0x00 );
196 ImplEndCommentRecord();
199 void EMFWriter::ImplWritePlusEOF()
201 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
202 ImplPlusRecord( EmfPlusRecordType::EndOfFile
, 0x0 );
203 ImplEndCommentRecord();
206 void EMFWriter::ImplWritePlusColor( const Color
& rColor
, sal_uInt32 nTrans
)
208 sal_uInt32 nAlpha
= ((100-nTrans
)*0xFF)/100;
209 sal_uInt32 nCol
= rColor
.GetBlue();
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
);
217 void EMFWriter::ImplWritePlusPoint( const Point
& rPoint
)
220 const Point
aPoint(maVDev
->LogicToPixel( rPoint
, maDestMapMode
));
221 m_rStm
.WriteUInt16( aPoint
.X() ).WriteUInt16( aPoint
.Y() );
224 void EMFWriter::ImplWritePlusFillPolygonRecord( const tools::Polygon
& rPoly
, sal_uInt32 nTrans
)
226 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
227 if( rPoly
.GetSize() )
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
] );
236 ImplEndCommentRecord();
239 bool EMFWriter::WriteEMF(const GDIMetaFile
& rMtf
)
241 const sal_uLong nHeaderPos
= m_rStm
.Tell();
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);
248 mnHandleCount
= mnRecordCount
= mnRecordPos
= mnRecordPlusPos
= 0;
249 mbRecordOpen
= mbRecordPlusOpen
= false;
250 mbLineChanged
= mbFillChanged
= mbTextChanged
= false;
251 mnLineHandle
= mnFillHandle
= mnTextHandle
= HANDLE_INVALID
;
254 const Size
aMtfSizePix( maVDev
->LogicToPixel( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode() ) );
255 const Size
aMtfSizeLog( OutputDevice::LogicToLogic(rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode(), MapMode(MapUnit::Map100thMM
)) );
258 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
259 m_rStm
.SeekRel( 108 );
262 WriteEMFPlusHeader( aMtfSizePix
, aMtfSizeLog
);
264 // write initial values
266 // set 100th mm map mode in EMF
267 ImplBeginRecord( WIN_EMR_SETMAPMODE
);
268 m_rStm
.WriteInt32( MM_ANISOTROPIC
);
271 ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX
);
272 m_rStm
.WriteInt32( maVDev
->GetDPIX() ).WriteInt32( maVDev
->GetDPIY() );
275 ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX
);
276 m_rStm
.WriteInt32( 2540 ).WriteInt32( 2540 );
279 ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX
);
280 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
283 ImplBeginRecord( WIN_EMR_SETWINDOWORGEX
);
284 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
287 ImplWriteRasterOp( RasterOp::OverPaint
);
289 ImplBeginRecord( WIN_EMR_SETBKMODE
);
290 m_rStm
.WriteUInt32( 1 ); // TRANSPARENT
298 ImplBeginRecord( WIN_EMR_EOF
);
299 m_rStm
.WriteUInt32( 0 ) // nPalEntries
300 .WriteUInt32( 0x10 ) // offPalEntries
301 .WriteUInt32( 0x14 ); // nSizeLast
305 const sal_uLong nEndPos
= m_rStm
.Tell(); m_rStm
.Seek( nHeaderPos
);
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
)
311 .WriteUInt32( mnRecordCount
).WriteUInt16( mnHandleCount
+ 1 ).WriteUInt16( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
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
317 m_rStm
.Seek( nEndPos
);
318 mHandlesUsed
.clear();
320 return( m_rStm
.GetError() == ERRCODE_NONE
);
323 sal_uLong
EMFWriter::ImplAcquireHandle()
325 sal_uLong nHandle
= HANDLE_INVALID
;
327 for( sal_uLong i
= 0; i
< mHandlesUsed
.size() && ( HANDLE_INVALID
== nHandle
); i
++ )
329 if( !mHandlesUsed
[ i
] )
331 mHandlesUsed
[ i
] = true;
333 if( ( nHandle
= i
) == mnHandleCount
)
338 SAL_WARN_IF( nHandle
== HANDLE_INVALID
, "vcl", "No more handles available" );
339 return( nHandle
!= HANDLE_INVALID
? nHandle
+ 1 : HANDLE_INVALID
);
342 void EMFWriter::ImplReleaseHandle( sal_uLong nHandle
)
344 SAL_WARN_IF( !nHandle
|| ( nHandle
>= mHandlesUsed
.size() ), "vcl", "Handle out of range" );
345 mHandlesUsed
[ nHandle
- 1 ] = false;
348 void EMFWriter::ImplBeginRecord( sal_uInt32 nType
)
350 SAL_WARN_IF( mbRecordOpen
, "vcl", "Another record is already opened!" );
355 mnRecordPos
= m_rStm
.Tell();
357 m_rStm
.WriteUInt32( nType
);
362 void EMFWriter::ImplEndRecord()
364 SAL_WARN_IF( !mbRecordOpen
, "vcl", "Record was not opened!" );
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
375 m_rStm
.WriteUInt32( ( nActPos
- mnRecordPos
) + nFillBytes
);
376 m_rStm
.Seek( nActPos
);
377 while( nFillBytes
-- )
378 m_rStm
.WriteUChar( 0 );
380 mbRecordOpen
= false;
384 bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32
& rHandle
, sal_uLong nSelectType
)
386 if( rHandle
!= HANDLE_INVALID
)
388 sal_uInt32 nStockObject
= 0x80000000;
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;
397 // select stock object first
398 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
399 m_rStm
.WriteUInt32( nStockObject
);
402 // destroy handle of created object
403 ImplBeginRecord( WIN_EMR_DELETEOBJECT
);
404 m_rStm
.WriteUInt32( rHandle
);
407 // mark handle as free
408 ImplReleaseHandle( rHandle
);
411 rHandle
= ImplAcquireHandle();
413 return( HANDLE_INVALID
!= rHandle
);
416 void EMFWriter::ImplCheckLineAttr()
418 if( mbLineChanged
&& ImplPrepareHandleSelect( mnLineHandle
, LINE_SELECT
) )
420 sal_uInt32 nStyle
= maVDev
->IsLineColor() ? 0 : 5;
422 ImplBeginRecord( WIN_EMR_CREATEPEN
);
423 m_rStm
.WriteUInt32( mnLineHandle
).WriteUInt32( nStyle
).WriteUInt32( 0/*nWidth*/ ).WriteUInt32( 0/*nHeight*/ );
424 ImplWriteColor( maVDev
->GetLineColor() );
427 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
428 m_rStm
.WriteUInt32( mnLineHandle
);
433 void EMFWriter::ImplCheckFillAttr()
435 if( mbFillChanged
&& ImplPrepareHandleSelect( mnFillHandle
, FILL_SELECT
) )
437 sal_uInt32 nStyle
= maVDev
->IsFillColor() ? 0 : 1;
439 ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT
);
440 m_rStm
.WriteUInt32( mnFillHandle
).WriteUInt32( nStyle
);
441 ImplWriteColor( maVDev
->GetFillColor() );
442 m_rStm
.WriteUInt32( 0/*nPatternStyle*/ );
445 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
446 m_rStm
.WriteUInt32( mnFillHandle
);
451 void EMFWriter::ImplCheckTextAttr()
453 if( !(mbTextChanged
&& ImplPrepareHandleSelect( mnTextHandle
, TEXT_SELECT
)) )
456 const vcl::Font
& rFont
= maVDev
->GetFont();
457 const OUString
& aFontName( rFont
.GetFamilyName() );
460 sal_uInt8 nPitchAndFamily
;
462 ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW
);
463 m_rStm
.WriteUInt32( mnTextHandle
);
464 ImplWriteExtent( -rFont
.GetFontSize().Height() );
465 ImplWriteExtent( rFont
.GetFontSize().Width() );
466 m_rStm
.WriteInt32( rFont
.GetOrientation() ).WriteInt32( rFont
.GetOrientation() );
468 switch( rFont
.GetWeight() )
470 case WEIGHT_THIN
: nWeight
= 100; break;
471 case WEIGHT_ULTRALIGHT
: nWeight
= 200; break;
472 case WEIGHT_LIGHT
: nWeight
= 300; break;
473 case WEIGHT_SEMILIGHT
: nWeight
= 300; break;
474 case WEIGHT_NORMAL
: nWeight
= 400; break;
475 case WEIGHT_MEDIUM
: nWeight
= 500; break;
476 case WEIGHT_SEMIBOLD
: nWeight
= 600; break;
477 case WEIGHT_BOLD
: nWeight
= 700; break;
478 case WEIGHT_ULTRABOLD
: nWeight
= 800; break;
479 case WEIGHT_BLACK
: nWeight
= 900; break;
480 default: nWeight
= 0; break;
483 m_rStm
.WriteInt32( nWeight
);
484 m_rStm
.WriteUChar( ( ITALIC_NONE
== rFont
.GetItalic() ) ? 0 : 1 );
485 m_rStm
.WriteUChar( ( LINESTYLE_NONE
== rFont
.GetUnderline() ) ? 0 : 1 );
486 m_rStm
.WriteUChar( ( STRIKEOUT_NONE
== rFont
.GetStrikeout() ) ? 0 : 1 );
487 m_rStm
.WriteUChar( ( RTL_TEXTENCODING_SYMBOL
== rFont
.GetCharSet() ) ? 2 : 0 );
488 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
490 switch( rFont
.GetPitch() )
492 case PITCH_FIXED
: nPitchAndFamily
= 0x01; break;
493 case PITCH_VARIABLE
: nPitchAndFamily
= 0x02; break;
494 default: nPitchAndFamily
= 0x00; break;
497 switch( rFont
.GetFamilyType() )
499 case FAMILY_DECORATIVE
: nPitchAndFamily
|= 0x50; break;
500 case FAMILY_MODERN
: nPitchAndFamily
|= 0x30; break;
501 case FAMILY_ROMAN
: nPitchAndFamily
|= 0x10; break;
502 case FAMILY_SCRIPT
: nPitchAndFamily
|= 0x40; break;
503 case FAMILY_SWISS
: nPitchAndFamily
|= 0x20; break;
507 m_rStm
.WriteUChar( nPitchAndFamily
);
509 for( i
= 0; i
< 32; i
++ )
510 m_rStm
.WriteUInt16( ( i
< aFontName
.getLength() ) ? aFontName
[ i
] : 0 );
513 for( i
= 0; i
< 64; i
++ )
514 m_rStm
.WriteUInt16( 0 );
517 for( i
= 0; i
< 32; i
++ )
518 m_rStm
.WriteUInt16( 0 );
520 // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
521 m_rStm
.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ) ;
524 m_rStm
.WriteUInt32( 0 );
527 m_rStm
.WriteUInt32( 0 );
530 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
532 // fill record to get a record size divideable by 4
533 m_rStm
.WriteUInt16( 0 );
538 sal_uInt32 nTextAlign
;
540 switch( rFont
.GetAlignment() )
542 case ALIGN_TOP
: nTextAlign
= TA_TOP
; break;
543 case ALIGN_BOTTOM
: nTextAlign
= TA_BOTTOM
; break;
544 default: nTextAlign
= TA_BASELINE
; break;
546 nTextAlign
|= mnHorTextAlign
;
548 ImplBeginRecord( WIN_EMR_SETTEXTALIGN
);
549 m_rStm
.WriteUInt32( nTextAlign
);
553 ImplBeginRecord( WIN_EMR_SETTEXTCOLOR
);
554 ImplWriteColor( maVDev
->GetTextColor() );
557 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
558 m_rStm
.WriteUInt32( mnTextHandle
);
563 void EMFWriter::ImplWriteColor( const Color
& rColor
)
565 sal_uInt32 nCol
= rColor
.GetRed();
567 nCol
|= static_cast<sal_uInt32
>(rColor
.GetGreen()) << 8;
568 nCol
|= static_cast<sal_uInt32
>(rColor
.GetBlue()) << 16;
570 m_rStm
.WriteUInt32( nCol
);
573 void EMFWriter::ImplWriteRasterOp( RasterOp eRop
)
579 case RasterOp::Invert
: nROP2
= 6; break;
580 case RasterOp::Xor
: nROP2
= 7; break;
581 default: nROP2
= 13;break;
584 ImplBeginRecord( WIN_EMR_SETROP2
);
585 m_rStm
.WriteUInt32( nROP2
);
589 void EMFWriter::ImplWriteExtent( long nExtent
)
591 nExtent
= OutputDevice::LogicToLogic( Size( nExtent
, 0 ), maVDev
->GetMapMode(), maDestMapMode
).Width();
592 m_rStm
.WriteInt32( nExtent
);
595 void EMFWriter::ImplWritePoint( const Point
& rPoint
)
597 const Point
aPoint( OutputDevice::LogicToLogic( rPoint
, maVDev
->GetMapMode(), maDestMapMode
));
598 m_rStm
.WriteInt32( aPoint
.X() ).WriteInt32( aPoint
.Y() );
601 void EMFWriter::ImplWriteSize( const Size
& rSize
)
603 const Size
aSize( OutputDevice::LogicToLogic( rSize
, maVDev
->GetMapMode(), maDestMapMode
));
604 m_rStm
.WriteInt32( aSize
.Width() ).WriteInt32( aSize
.Height() );
607 void EMFWriter::ImplWriteRect( const tools::Rectangle
& rRect
)
609 const tools::Rectangle
aRect( OutputDevice::LogicToLogic ( rRect
, maVDev
->GetMapMode(), maDestMapMode
));
610 auto right
= aRect
.IsWidthEmpty() ? aRect
.Left() : aRect
.Right();
611 auto bottom
= aRect
.IsHeightEmpty() ? aRect
.Top() : aRect
.Bottom();
613 .WriteInt32( aRect
.Left() )
614 .WriteInt32( aRect
.Top() )
616 .WriteInt32( bottom
);
619 void EMFWriter::ImplWritePolygonRecord( const tools::Polygon
& rPoly
, bool bClose
)
621 if( rPoly
.GetSize() )
623 if( rPoly
.HasFlags() )
624 ImplWritePath( rPoly
, bClose
);
632 ImplBeginRecord( bClose
? WIN_EMR_POLYGON
: WIN_EMR_POLYLINE
);
633 ImplWriteRect( rPoly
.GetBoundRect() );
634 m_rStm
.WriteUInt32( rPoly
.GetSize() );
636 for( sal_uInt16 i
= 0; i
< rPoly
.GetSize(); i
++ )
637 ImplWritePoint( rPoly
[ i
] );
644 void EMFWriter::ImplWritePolyPolygonRecord( const tools::PolyPolygon
& rPolyPoly
)
646 sal_uInt16 n
, i
, nPolyCount
= rPolyPoly
.Count();
650 if( 1 == nPolyCount
)
651 ImplWritePolygonRecord( rPolyPoly
[ 0 ], true );
654 bool bHasFlags
= false;
655 sal_uInt32 nTotalPoints
= 0;
657 for( i
= 0; i
< nPolyCount
; i
++ )
659 nTotalPoints
+= rPolyPoly
[ i
].GetSize();
660 if ( rPolyPoly
[ i
].HasFlags() )
666 ImplWritePath( rPolyPoly
, true );
672 ImplBeginRecord( WIN_EMR_POLYPOLYGON
);
673 ImplWriteRect( rPolyPoly
.GetBoundRect() );
674 m_rStm
.WriteUInt32( nPolyCount
).WriteUInt32( nTotalPoints
);
676 for( i
= 0; i
< nPolyCount
; i
++ )
677 m_rStm
.WriteUInt32( rPolyPoly
[ i
].GetSize() );
679 for( i
= 0; i
< nPolyCount
; i
++ )
681 const tools::Polygon
& rPoly
= rPolyPoly
[ i
];
683 for( n
= 0; n
< rPoly
.GetSize(); n
++ )
684 ImplWritePoint( rPoly
[ n
] );
693 void EMFWriter::ImplWritePath( const tools::PolyPolygon
& rPolyPoly
, bool bClosed
)
699 ImplBeginRecord( WIN_EMR_BEGINPATH
);
702 sal_uInt16 i
, n
, o
, nPolyCount
= rPolyPoly
.Count();
703 for ( i
= 0; i
< nPolyCount
; i
++ )
706 const tools::Polygon
& rPoly
= rPolyPoly
[ i
];
707 while ( n
< rPoly
.GetSize() )
711 ImplBeginRecord( WIN_EMR_MOVETOEX
);
712 ImplWritePoint( rPoly
[ 0 ] );
718 sal_uInt16 nBezPoints
= 0;
720 while ( ( ( nBezPoints
+ n
+ 2 ) < rPoly
.GetSize() ) && ( rPoly
.GetFlags( nBezPoints
+ n
) == PolyFlags::Control
) )
725 ImplBeginRecord( WIN_EMR_POLYBEZIERTO
);
726 tools::Polygon
aNewPoly( nBezPoints
+ 1 );
727 aNewPoly
[ 0 ] = rPoly
[ n
- 1 ];
728 for ( o
= 0; o
< nBezPoints
; o
++ )
729 aNewPoly
[ o
+ 1 ] = rPoly
[ n
+ o
];
730 ImplWriteRect( aNewPoly
.GetBoundRect() );
731 m_rStm
.WriteUInt32( nBezPoints
);
732 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
733 ImplWritePoint( aNewPoly
[ o
] );
739 sal_uInt16 nPoints
= 1;
740 while( ( nPoints
+ n
) < rPoly
.GetSize() && ( rPoly
.GetFlags( nPoints
+ n
) != PolyFlags::Control
) )
745 ImplBeginRecord( WIN_EMR_POLYLINETO
);
746 tools::Polygon
aNewPoly( nPoints
+ 1 );
747 aNewPoly
[ 0 ] = rPoly
[ n
- 1];
748 for ( o
= 1; o
<= nPoints
; o
++ )
749 aNewPoly
[ o
] = rPoly
[ n
- 1 + o
];
750 ImplWriteRect( aNewPoly
.GetBoundRect() );
751 m_rStm
.WriteUInt32( nPoints
);
752 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
753 ImplWritePoint( aNewPoly
[ o
] );
758 ImplBeginRecord( WIN_EMR_LINETO
);
759 ImplWritePoint( rPoly
[ n
] );
764 if ( bClosed
&& ( n
== rPoly
.GetSize() ) )
766 ImplBeginRecord( WIN_EMR_CLOSEFIGURE
);
771 ImplBeginRecord( WIN_EMR_ENDPATH
);
773 ImplBeginRecord( bClosed
? WIN_EMR_FILLPATH
: WIN_EMR_STROKEPATH
);
774 ImplWriteRect( rPolyPoly
.GetBoundRect() );
778 void EMFWriter::ImplWriteBmpRecord( const Bitmap
& rBmp
, const Point
& rPt
,
779 const Size
& rSz
, sal_uInt32 nROP
)
784 SvMemoryStream
aMemStm( 65535, 65535 );
785 const Size
aBmpSizePixel( rBmp
.GetSizePixel() );
787 ImplBeginRecord( WIN_EMR_STRETCHDIBITS
);
788 ImplWriteRect( tools::Rectangle( rPt
, rSz
) );
789 ImplWritePoint( rPt
);
790 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel
.Width() ).WriteInt32( aBmpSizePixel
.Height() );
792 // write offset positions and sizes later
793 const sal_uLong nOffPos
= m_rStm
.Tell();
794 m_rStm
.SeekRel( 16 );
796 m_rStm
.WriteUInt32( 0 ).WriteInt32( ( RasterOp::Xor
== maVDev
->GetRasterOp() && WIN_SRCCOPY
== nROP
) ? WIN_SRCINVERT
: nROP
);
797 ImplWriteSize( rSz
);
799 WriteDIB(rBmp
, aMemStm
, true, false);
801 sal_uInt32 nDIBSize
= aMemStm
.Tell(), nHeaderSize
, nCompression
, nColsUsed
, nPalCount
, nImageSize
;
802 sal_uInt16 nBitCount
;
804 // get DIB parameters
806 aMemStm
.ReadUInt32( nHeaderSize
);
807 aMemStm
.SeekRel( 10 );
808 aMemStm
.ReadUInt16( nBitCount
).ReadUInt32( nCompression
).ReadUInt32( nImageSize
);
809 aMemStm
.SeekRel( 8 );
810 aMemStm
.ReadUInt32( nColsUsed
);
815 nPalCount
= nColsUsed
;
817 nPalCount
= 1 << static_cast<sal_uInt32
>(nBitCount
);
821 if (nCompression
== BITFIELDS
)
827 sal_uInt32 nPalSize
= nPalCount
* 4;
829 m_rStm
.WriteBytes( aMemStm
.GetData(), nDIBSize
);
831 const sal_uLong nEndPos
= m_rStm
.Tell();
832 m_rStm
.Seek( nOffPos
);
833 m_rStm
.WriteUInt32( 80 ).WriteUInt32( nHeaderSize
+ nPalSize
);
834 m_rStm
.WriteUInt32( 80 + nHeaderSize
+ nPalSize
).WriteUInt32( nImageSize
);
835 m_rStm
.Seek( nEndPos
);
841 void EMFWriter::ImplWriteTextRecord( const Point
& rPos
, const OUString
& rText
, const long* pDXArray
, sal_uInt32 nWidth
)
843 sal_Int32 nLen
= rText
.getLength(), i
;
848 sal_uInt32 nNormWidth
;
849 std::unique_ptr
<long[]> pOwnArray
;
855 nNormWidth
= maVDev
->GetTextWidth( rText
);
856 pDX
= const_cast<long*>(pDXArray
);
860 pOwnArray
.reset(new long[ nLen
]);
861 nNormWidth
= maVDev
->GetTextArray( rText
, pOwnArray
.get() );
862 pDX
= pOwnArray
.get();
867 nNormWidth
= pDX
[ nLen
- 2 ] + maVDev
->GetTextWidth( OUString(rText
[ nLen
- 1 ]) );
869 if( nWidth
&& nNormWidth
&& ( nWidth
!= nNormWidth
) )
871 const double fFactor
= static_cast<double>(nWidth
) / nNormWidth
;
873 for( i
= 0; i
< ( nLen
- 1 ); i
++ )
874 pDX
[ i
] = FRound( pDX
[ i
] * fFactor
);
879 ImplBeginRecord( WIN_EMR_EXTTEXTOUTW
);
881 ImplWriteRect( tools::Rectangle( rPos
, Size( nNormWidth
, maVDev
->GetTextHeight() ) ) );
882 m_rStm
.WriteUInt32( 1 );
883 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
884 ImplWritePoint( rPos
);
885 m_rStm
.WriteUInt32( nLen
).WriteUInt32( 76 ).WriteUInt32( 2 );
886 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 );
887 m_rStm
.WriteUInt32( 76 + ( nLen
<< 1 ) + ( (nLen
& 1 ) ? 2 : 0 ) );
890 for( i
= 0; i
< nLen
; i
++ )
891 m_rStm
.WriteUInt16( rText
[ i
] );
895 m_rStm
.WriteUInt16( 0 );
898 ImplWriteExtent( pDX
[ 0 ] );
902 for( i
= 1; i
< ( nLen
- 1 ); i
++ )
903 ImplWriteExtent( pDX
[ i
] - pDX
[ i
- 1 ] );
905 ImplWriteExtent( pDX
[ nLen
- 2 ] / ( nLen
- 1 ) );
912 void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo
& rInfo
, const basegfx::B2DPolygon
& rLinePolygon
)
914 if(rLinePolygon
.count())
916 basegfx::B2DPolyPolygon
aLinePolyPolygon(rLinePolygon
);
917 basegfx::B2DPolyPolygon aFillPolyPolygon
;
919 rInfo
.applyToB2DPolyPolygon(aLinePolyPolygon
, aFillPolyPolygon
);
921 if(aLinePolyPolygon
.count())
923 for(auto const& rB2DPolygon
: aLinePolyPolygon
)
925 ImplWritePolygonRecord( tools::Polygon(rB2DPolygon
), false );
929 if(aFillPolyPolygon
.count())
931 const Color
aOldLineColor(maVDev
->GetLineColor());
932 const Color
aOldFillColor(maVDev
->GetFillColor());
934 maVDev
->SetLineColor();
935 maVDev
->SetFillColor(aOldLineColor
);
937 for(auto const& rB2DPolygon
: aFillPolyPolygon
)
939 ImplWritePolyPolygonRecord(tools::PolyPolygon( tools::Polygon(rB2DPolygon
) ));
942 maVDev
->SetLineColor(aOldLineColor
);
943 maVDev
->SetFillColor(aOldFillColor
);
948 void EMFWriter::ImplWrite( const GDIMetaFile
& rMtf
)
950 for( size_t j
= 0, nActionCount
= rMtf
.GetActionSize(); j
< nActionCount
; j
++ )
952 const MetaAction
* pAction
= rMtf
.GetAction( j
);
953 const MetaActionType nType
= pAction
->GetType();
957 case MetaActionType::PIXEL
:
959 const MetaPixelAction
* pA
= static_cast<const MetaPixelAction
*>(pAction
);
962 ImplBeginRecord( WIN_EMR_SETPIXELV
);
963 ImplWritePoint( pA
->GetPoint() );
964 ImplWriteColor( pA
->GetColor() );
969 case MetaActionType::POINT
:
971 if( maVDev
->IsLineColor() )
973 const MetaPointAction
* pA
= static_cast<const MetaPointAction
*>(pAction
);
976 ImplBeginRecord( WIN_EMR_SETPIXELV
);
977 ImplWritePoint( pA
->GetPoint() );
978 ImplWriteColor( maVDev
->GetLineColor() );
984 case MetaActionType::LINE
:
986 if( maVDev
->IsLineColor() )
988 const MetaLineAction
* pA
= static_cast<const MetaLineAction
*>(pAction
);
990 if(pA
->GetLineInfo().IsDefault())
994 ImplBeginRecord( WIN_EMR_MOVETOEX
);
995 ImplWritePoint( pA
->GetStartPoint() );
998 ImplBeginRecord( WIN_EMR_LINETO
);
999 ImplWritePoint( pA
->GetEndPoint() );
1002 ImplBeginRecord( WIN_EMR_SETPIXELV
);
1003 ImplWritePoint( pA
->GetEndPoint() );
1004 ImplWriteColor( maVDev
->GetLineColor() );
1009 // LineInfo used; handle Dash/Dot and fat lines
1010 basegfx::B2DPolygon aPolygon
;
1011 aPolygon
.append(basegfx::B2DPoint(pA
->GetStartPoint().X(), pA
->GetStartPoint().Y()));
1012 aPolygon
.append(basegfx::B2DPoint(pA
->GetEndPoint().X(), pA
->GetEndPoint().Y()));
1013 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), aPolygon
);
1019 case MetaActionType::RECT
:
1021 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1023 const MetaRectAction
* pA
= static_cast<const MetaRectAction
*>(pAction
);
1025 ImplCheckFillAttr();
1026 ImplCheckLineAttr();
1028 ImplBeginRecord( WIN_EMR_RECTANGLE
);
1029 ImplWriteRect( pA
->GetRect() );
1035 case MetaActionType::ROUNDRECT
:
1037 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1039 const MetaRoundRectAction
* pA
= static_cast<const MetaRoundRectAction
*>(pAction
);
1041 ImplCheckFillAttr();
1042 ImplCheckLineAttr();
1044 ImplBeginRecord( WIN_EMR_ROUNDRECT
);
1045 ImplWriteRect( pA
->GetRect() );
1046 ImplWriteSize( Size( pA
->GetHorzRound(), pA
->GetVertRound() ) );
1052 case MetaActionType::ELLIPSE
:
1054 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1056 const MetaEllipseAction
* pA
= static_cast<const MetaEllipseAction
*>(pAction
);
1058 ImplCheckFillAttr();
1059 ImplCheckLineAttr();
1061 ImplBeginRecord( WIN_EMR_ELLIPSE
);
1062 ImplWriteRect( pA
->GetRect() );
1068 case MetaActionType::ARC
:
1069 case MetaActionType::PIE
:
1070 case MetaActionType::CHORD
:
1071 case MetaActionType::POLYGON
:
1073 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1075 tools::Polygon aPoly
;
1079 case MetaActionType::ARC
:
1081 const MetaArcAction
* pA
= static_cast<const MetaArcAction
*>(pAction
);
1082 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), PolyStyle::Arc
);
1086 case MetaActionType::PIE
:
1088 const MetaPieAction
* pA
= static_cast<const MetaPieAction
*>(pAction
);
1089 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), PolyStyle::Pie
);
1093 case MetaActionType::CHORD
:
1095 const MetaChordAction
* pA
= static_cast<const MetaChordAction
*>(pAction
);
1096 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), PolyStyle::Chord
);
1100 case MetaActionType::POLYGON
:
1101 aPoly
= static_cast<const MetaPolygonAction
*>(pAction
)->GetPolygon();
1106 ImplWritePolygonRecord( aPoly
, nType
!= MetaActionType::ARC
);
1111 case MetaActionType::POLYLINE
:
1113 if( maVDev
->IsLineColor() )
1115 const MetaPolyLineAction
* pA
= static_cast<const MetaPolyLineAction
*>(pAction
);
1116 const tools::Polygon
& rPoly
= pA
->GetPolygon();
1118 if( rPoly
.GetSize() )
1120 if(pA
->GetLineInfo().IsDefault())
1122 ImplWritePolygonRecord( rPoly
, false );
1126 // LineInfo used; handle Dash/Dot and fat lines
1127 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), rPoly
.getB2DPolygon());
1134 case MetaActionType::POLYPOLYGON
:
1136 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1137 ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction
*>(pAction
)->GetPolyPolygon() );
1141 case MetaActionType::GRADIENT
:
1143 const MetaGradientAction
* pA
= static_cast<const MetaGradientAction
*>(pAction
);
1144 GDIMetaFile aTmpMtf
;
1146 maVDev
->AddGradientActions( pA
->GetRect(), pA
->GetGradient(), aTmpMtf
);
1147 ImplWrite( aTmpMtf
);
1151 case MetaActionType::HATCH
:
1153 const MetaHatchAction
* pA
= static_cast<const MetaHatchAction
*>(pAction
);
1154 GDIMetaFile aTmpMtf
;
1156 maVDev
->AddHatchActions( pA
->GetPolyPolygon(), pA
->GetHatch(), aTmpMtf
);
1157 ImplWrite( aTmpMtf
);
1161 case MetaActionType::Transparent
:
1163 const tools::PolyPolygon
& rPolyPoly
= static_cast<const MetaTransparentAction
*>(pAction
)->GetPolyPolygon();
1164 if( rPolyPoly
.Count() )
1165 ImplWritePlusFillPolygonRecord( rPolyPoly
[0], static_cast<const MetaTransparentAction
*>(pAction
)->GetTransparence() );
1166 ImplCheckFillAttr();
1167 ImplCheckLineAttr();
1168 ImplWritePolyPolygonRecord( rPolyPoly
);
1170 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
1171 ImplPlusRecord( EmfPlusRecordType::GetDC
, 0x00 );
1172 ImplEndCommentRecord();
1176 case MetaActionType::FLOATTRANSPARENT
:
1178 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pAction
);
1180 GDIMetaFile
aTmpMtf( pA
->GetGDIMetaFile() );
1181 Point
aSrcPt( aTmpMtf
.GetPrefMapMode().GetOrigin() );
1182 const Size
aSrcSize( aTmpMtf
.GetPrefSize() );
1183 const Point
aDestPt( pA
->GetPoint() );
1184 const Size
aDestSize( pA
->GetSize() );
1185 const double fScaleX
= aSrcSize
.Width() ? static_cast<double>(aDestSize
.Width()) / aSrcSize
.Width() : 1.0;
1186 const double fScaleY
= aSrcSize
.Height() ? static_cast<double>(aDestSize
.Height()) / aSrcSize
.Height() : 1.0;
1187 long nMoveX
, nMoveY
;
1189 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
1191 aTmpMtf
.Scale( fScaleX
, fScaleY
);
1192 aSrcPt
.setX( FRound( aSrcPt
.X() * fScaleX
) );
1193 aSrcPt
.setY( FRound( aSrcPt
.Y() * fScaleY
) );
1196 nMoveX
= aDestPt
.X() - aSrcPt
.X();
1197 nMoveY
= aDestPt
.Y() - aSrcPt
.Y();
1199 if( nMoveX
|| nMoveY
)
1200 aTmpMtf
.Move( nMoveX
, nMoveY
);
1202 ImplCheckFillAttr();
1203 ImplCheckLineAttr();
1204 ImplCheckTextAttr();
1205 ImplWrite( aTmpMtf
);
1209 case MetaActionType::EPS
:
1211 const MetaEPSAction
* pA
= static_cast<const MetaEPSAction
*>(pAction
);
1212 const GDIMetaFile
& aSubstitute( pA
->GetSubstitute() );
1214 for( size_t i
= 0, nCount
= aSubstitute
.GetActionSize(); i
< nCount
; i
++ )
1216 const MetaAction
* pSubstAct
= aSubstitute
.GetAction( i
);
1217 if( pSubstAct
->GetType() == MetaActionType::BMPSCALE
)
1220 ImplBeginRecord( WIN_EMR_SAVEDC
);
1223 MapMode
aMapMode( aSubstitute
.GetPrefMapMode() );
1224 Size
aOutSize( OutputDevice::LogicToLogic( pA
->GetSize(), maVDev
->GetMapMode(), aMapMode
) );
1225 aMapMode
.SetScaleX( Fraction( aOutSize
.Width(), aSubstitute
.GetPrefSize().Width() ) );
1226 aMapMode
.SetScaleY( Fraction( aOutSize
.Height(), aSubstitute
.GetPrefSize().Height() ) );
1227 aMapMode
.SetOrigin( OutputDevice::LogicToLogic( pA
->GetPoint(), maVDev
->GetMapMode(), aMapMode
) );
1228 maVDev
->SetMapMode( aMapMode
);
1229 ImplWrite( aSubstitute
);
1232 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1233 m_rStm
.WriteInt32( -1 );
1241 case MetaActionType::BMP
:
1243 const MetaBmpAction
* pA
= static_cast<const MetaBmpAction
*>(pAction
);
1244 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), maVDev
->PixelToLogic( pA
->GetBitmap().GetSizePixel() ), WIN_SRCCOPY
);
1248 case MetaActionType::BMPSCALE
:
1250 const MetaBmpScaleAction
* pA
= static_cast<const MetaBmpScaleAction
*>(pAction
);
1251 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1255 case MetaActionType::BMPSCALEPART
:
1257 const MetaBmpScalePartAction
* pA
= static_cast<const MetaBmpScalePartAction
*>(pAction
);
1258 Bitmap
aTmp( pA
->GetBitmap() );
1260 if( aTmp
.Crop( tools::Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) ) )
1261 ImplWriteBmpRecord( aTmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1265 case MetaActionType::BMPEX
:
1267 const MetaBmpExAction
* pA
= static_cast<const MetaBmpExAction
*>(pAction
);
1268 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1269 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1273 aBmp
.Replace( aMsk
, COL_WHITE
);
1275 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), maVDev
->PixelToLogic( aMsk
.GetSizePixel() ), WIN_SRCPAINT
);
1276 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), maVDev
->PixelToLogic( aBmp
.GetSizePixel() ), WIN_SRCAND
);
1279 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), aBmp
.GetSizePixel(), WIN_SRCCOPY
);
1283 case MetaActionType::BMPEXSCALE
:
1285 const MetaBmpExScaleAction
* pA
= static_cast<const MetaBmpExScaleAction
*>(pAction
);
1286 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1287 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1291 aBmp
.Replace( aMsk
, COL_WHITE
);
1293 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCPAINT
);
1294 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCAND
);
1297 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1301 case MetaActionType::BMPEXSCALEPART
:
1303 const MetaBmpExScalePartAction
* pA
= static_cast<const MetaBmpExScalePartAction
*>(pAction
);
1304 BitmapEx
aBmpEx( pA
->GetBitmapEx() );
1305 aBmpEx
.Crop( tools::Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) );
1306 Bitmap
aBmp( aBmpEx
.GetBitmap() );
1307 Bitmap
aMsk( aBmpEx
.GetMask() );
1311 aBmp
.Replace( aMsk
, COL_WHITE
);
1313 ImplWriteBmpRecord( aMsk
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCPAINT
);
1314 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCAND
);
1317 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1321 case MetaActionType::TEXT
:
1323 const MetaTextAction
* pA
= static_cast<const MetaTextAction
*>(pAction
);
1324 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1326 ImplCheckTextAttr();
1327 ImplWriteTextRecord( pA
->GetPoint(), aText
, nullptr, 0 );
1331 case MetaActionType::TEXTRECT
:
1333 const MetaTextRectAction
* pA
= static_cast<const MetaTextRectAction
*>(pAction
);
1334 const OUString
& aText( pA
->GetText() );
1336 ImplCheckTextAttr();
1337 ImplWriteTextRecord( pA
->GetRect().TopLeft(), aText
, nullptr, 0 );
1341 case MetaActionType::TEXTARRAY
:
1343 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pAction
);
1344 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1346 ImplCheckTextAttr();
1347 ImplWriteTextRecord( pA
->GetPoint(), aText
, pA
->GetDXArray(), 0 );
1351 case MetaActionType::STRETCHTEXT
:
1353 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pAction
);
1354 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1356 ImplCheckTextAttr();
1357 ImplWriteTextRecord( pA
->GetPoint(), aText
, nullptr, pA
->GetWidth() );
1361 case MetaActionType::LINECOLOR
:
1363 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1364 mbLineChanged
= true;
1368 case MetaActionType::FILLCOLOR
:
1370 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1371 mbFillChanged
= true;
1375 case MetaActionType::TEXTCOLOR
:
1376 case MetaActionType::TEXTLINECOLOR
:
1377 case MetaActionType::TEXTFILLCOLOR
:
1378 case MetaActionType::TEXTALIGN
:
1379 case MetaActionType::FONT
:
1381 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1382 mbTextChanged
= true;
1386 case MetaActionType::ISECTRECTCLIPREGION
:
1388 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1390 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT
);
1391 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction
*>(pAction
)->GetRect() );
1396 case MetaActionType::CLIPREGION
:
1397 case MetaActionType::ISECTREGIONCLIPREGION
:
1398 case MetaActionType::MOVECLIPREGION
:
1400 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1404 case MetaActionType::REFPOINT
:
1405 case MetaActionType::MAPMODE
:
1406 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1409 case MetaActionType::PUSH
:
1411 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1413 ImplBeginRecord( WIN_EMR_SAVEDC
);
1418 case MetaActionType::POP
:
1420 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1422 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1423 m_rStm
.WriteInt32( -1 );
1426 ImplWriteRasterOp( maVDev
->GetRasterOp() );
1427 mbLineChanged
= mbFillChanged
= mbTextChanged
= true;
1431 case MetaActionType::RASTEROP
:
1433 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1434 ImplWriteRasterOp( static_cast<const MetaRasterOpAction
*>(pAction
)->GetRasterOp() );
1438 case MetaActionType::LAYOUTMODE
:
1440 ComplexTextLayoutFlags nLayoutMode
= static_cast<const MetaLayoutModeAction
*>(pAction
)->GetLayoutMode();
1442 if ((nLayoutMode
& ComplexTextLayoutFlags::BiDiRtl
) != ComplexTextLayoutFlags::Default
)
1444 mnHorTextAlign
= TA_RIGHT
| TA_RTLREADING
;
1446 if ((nLayoutMode
& ComplexTextLayoutFlags::TextOriginRight
) != ComplexTextLayoutFlags::Default
)
1447 mnHorTextAlign
|= TA_RIGHT
;
1448 else if ((nLayoutMode
& ComplexTextLayoutFlags::TextOriginLeft
) != ComplexTextLayoutFlags::Default
)
1449 mnHorTextAlign
&= ~TA_RIGHT
;
1453 case MetaActionType::COMMENT
:
1455 MetaCommentAction
const*const pCommentAction(
1456 static_cast<MetaCommentAction
const*>(pAction
));
1457 if (pCommentAction
->GetComment() == "EMF_PLUS")
1459 ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS
);
1460 m_rStm
.WriteBytes(pCommentAction
->GetData(),
1461 pCommentAction
->GetDataSize());
1462 ImplEndCommentRecord();
1467 case MetaActionType::MASK
:
1468 case MetaActionType::MASKSCALE
:
1469 case MetaActionType::MASKSCALEPART
:
1470 case MetaActionType::WALLPAPER
:
1471 case MetaActionType::TEXTLINE
:
1472 case MetaActionType::GRADIENTEX
:
1473 // Explicitly ignored cases
1477 // TODO: Implement more cases as necessary. Let's not bother with a warning.
1483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */