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"
25 #include <rtl/strbuf.hxx>
26 #include <tools/helpers.hxx>
27 #include <tools/fract.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <basegfx/polygon/b2dpolypolygon.hxx>
30 #include <vcl/lineinfo.hxx>
31 #include <vcl/dibtools.hxx>
34 #define WIN_EMR_POLYGON 3
35 #define WIN_EMR_POLYLINE 4
36 #define WIN_EMR_POLYBEZIERTO 5
37 #define WIN_EMR_POLYLINETO 6
38 #define WIN_EMR_POLYPOLYGON 8
39 #define WIN_EMR_SETWINDOWEXTEX 9
40 #define WIN_EMR_SETWINDOWORGEX 10
41 #define WIN_EMR_SETVIEWPORTEXTEX 11
42 #define WIN_EMR_SETVIEWPORTORGEX 12
43 #define WIN_EMR_EOF 14
44 #define WIN_EMR_SETPIXELV 15
45 #define WIN_EMR_SETMAPMODE 17
46 #define WIN_EMR_SETBKMODE 18
47 #define WIN_EMR_SETROP2 20
48 #define WIN_EMR_SETTEXTALIGN 22
49 #define WIN_EMR_SETTEXTCOLOR 24
50 #define WIN_EMR_MOVETOEX 27
51 #define WIN_EMR_INTERSECTCLIPRECT 30
52 #define WIN_EMR_SAVEDC 33
53 #define WIN_EMR_RESTOREDC 34
54 #define WIN_EMR_SELECTOBJECT 37
55 #define WIN_EMR_CREATEPEN 38
56 #define WIN_EMR_CREATEBRUSHINDIRECT 39
57 #define WIN_EMR_DELETEOBJECT 40
58 #define WIN_EMR_ELLIPSE 42
59 #define WIN_EMR_RECTANGLE 43
60 #define WIN_EMR_ROUNDRECT 44
61 #define WIN_EMR_LINETO 54
62 #define WIN_EMR_BEGINPATH 59
63 #define WIN_EMR_ENDPATH 60
64 #define WIN_EMR_CLOSEFIGURE 61
65 #define WIN_EMR_FILLPATH 62
66 #define WIN_EMR_STROKEPATH 64
68 #define WIN_EMR_GDICOMMENT 70
69 #define WIN_EMR_STRETCHDIBITS 81
70 #define WIN_EMR_EXTCREATEFONTINDIRECTW 82
71 #define WIN_EMR_EXTTEXTOUTW 84
73 #define WIN_SRCCOPY 0x00CC0020L
74 #define WIN_SRCPAINT 0x00EE0086L
75 #define WIN_SRCAND 0x008800C6L
76 #define WIN_SRCINVERT 0x00660046L
77 #define WIN_EMR_COMMENT_EMFPLUS 0x2B464D45L
79 #define HANDLE_INVALID 0xffffffff
80 #define MAXHANDLES 65000
82 #define LINE_SELECT 0x00000001
83 #define FILL_SELECT 0x00000002
84 #define TEXT_SELECT 0x00000004
86 /* Text Alignment Options */
91 #define TA_BASELINE 24
92 #define TA_RTLREADING 256
94 #define MM_ANISOTROPIC 8
96 enum class EmfPlusRecordType
101 FillPolygon
= 0x400C,
102 SetAntiAliasMode
= 0x401E,
103 SetInterpolationMode
= 0x4021,
104 SetPixelOffsetMode
= 0x4022,
105 SetCompositingQuality
= 0x4024
108 void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType
)
110 ImplBeginRecord( WIN_EMR_GDICOMMENT
);
112 m_rStm
.WriteInt32( nCommentType
);
115 void EMFWriter::ImplEndCommentRecord()
119 sal_Int32 nActPos
= m_rStm
.Tell();
120 m_rStm
.Seek( mnRecordPos
+ 8 );
121 m_rStm
.WriteUInt32( nActPos
- mnRecordPos
- 0xc );
122 m_rStm
.Seek( nActPos
);
127 void EMFWriter::ImplBeginPlusRecord( EmfPlusRecordType nType
, sal_uInt16 nFlags
)
129 SAL_WARN_IF( mbRecordPlusOpen
, "vcl", "Another EMF+ record is already opened!" );
131 if( !mbRecordPlusOpen
)
133 mbRecordPlusOpen
= true;
134 mnRecordPlusPos
= m_rStm
.Tell();
136 m_rStm
.WriteUInt16( (sal_uInt16
)nType
).WriteUInt16( nFlags
);
141 void EMFWriter::ImplEndPlusRecord()
143 SAL_WARN_IF( !mbRecordPlusOpen
, "vcl", "EMF+ Record was not opened!" );
145 if( mbRecordPlusOpen
)
147 sal_Int32 nActPos
= m_rStm
.Tell();
148 sal_Int32 nSize
= nActPos
- mnRecordPlusPos
;
149 m_rStm
.Seek( mnRecordPlusPos
+ 4 );
150 m_rStm
.WriteUInt32( nSize
) // Size
151 .WriteUInt32( nSize
- 0xc ); // Data Size
152 m_rStm
.Seek( nActPos
);
153 mbRecordPlusOpen
= false;
157 void EMFWriter::ImplPlusRecord( EmfPlusRecordType nType
, sal_uInt16 nFlags
)
159 ImplBeginPlusRecord( nType
, nFlags
);
163 void EMFWriter::WriteEMFPlusHeader( const Size
&rMtfSizePix
, const Size
&rMtfSizeLog
)
165 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
167 sal_Int32 nDPIX
= rMtfSizePix
.Width()*25;
168 sal_Int32 nDivX
= rMtfSizeLog
.Width()/100;
170 nDPIX
/= nDivX
; // DPI X
172 sal_Int32 nDPIY
= rMtfSizePix
.Height()*25;
173 sal_Int32 nDivY
= rMtfSizeLog
.Height()/100;
175 nDPIY
/= nDivY
; // DPI Y
177 m_rStm
.WriteInt16( (sal_Int16
)EmfPlusRecordType::Header
);
178 m_rStm
.WriteInt16( 0x01 ) // Flags - Dual Mode // TODO: Check this
179 .WriteInt32( 0x1C ) // Size
180 .WriteInt32( 0x10 ) // Data Size
181 .WriteInt32( 0xdbc01002 ) // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this
182 .WriteInt32( 0x01 ) // Video display
184 .WriteInt32( nDPIY
);
185 ImplEndCommentRecord();
187 // Write more properties
188 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
189 ImplPlusRecord( EmfPlusRecordType::SetPixelOffsetMode
, 0x0 );
190 ImplPlusRecord( EmfPlusRecordType::SetAntiAliasMode
, 0x09 ); // TODO: Check actual values for AntiAlias
191 ImplPlusRecord( EmfPlusRecordType::SetCompositingQuality
, 0x0100 ); // Default Quality
192 ImplPlusRecord( EmfPlusRecordType::SetInterpolationMode
, 0x00 ); // Default
193 ImplPlusRecord( EmfPlusRecordType::GetDC
, 0x00 );
194 ImplEndCommentRecord();
197 void EMFWriter::ImplWritePlusEOF()
199 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
200 ImplPlusRecord( EmfPlusRecordType::EndOfFile
, 0x0 );
201 ImplEndCommentRecord();
204 void EMFWriter::ImplWritePlusColor( const Color
& rColor
, sal_uInt32 nTrans
)
206 sal_uInt32 nAlpha
= ((100-nTrans
)*0xFF)/100;
207 sal_uInt32 nCol
= rColor
.GetBlue();
209 nCol
|= ( (sal_uInt32
) rColor
.GetGreen() ) << 8;
210 nCol
|= ( (sal_uInt32
) rColor
.GetRed() ) << 16;
211 nCol
|= ( nAlpha
<< 24 );
212 m_rStm
.WriteUInt32( nCol
);
215 void EMFWriter::ImplWritePlusPoint( const Point
& rPoint
)
218 const Point
aPoint(maVDev
->LogicToPixel( rPoint
, maDestMapMode
));
219 m_rStm
.WriteUInt16( aPoint
.X() ).WriteUInt16( aPoint
.Y() );
222 void EMFWriter::ImplWritePlusFillPolygonRecord( const tools::Polygon
& rPoly
, sal_uInt32 nTrans
)
224 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
225 if( rPoly
.GetSize() )
227 ImplBeginPlusRecord( EmfPlusRecordType::FillPolygon
, 0xC000 ); // Sets the color as well
228 ImplWritePlusColor( maVDev
->GetFillColor(), nTrans
);
229 m_rStm
.WriteUInt32( rPoly
.GetSize() );
230 for( sal_uInt16 i
= 0; i
< rPoly
.GetSize(); i
++ )
231 ImplWritePlusPoint( rPoly
[ i
] );
234 ImplEndCommentRecord();
237 bool EMFWriter::WriteEMF(const GDIMetaFile
& rMtf
)
239 const sal_uLong nHeaderPos
= m_rStm
.Tell();
241 maVDev
->EnableOutput( false );
242 maVDev
->SetMapMode( rMtf
.GetPrefMapMode() );
243 // don't work with pixel as destination map mode -> higher resolution preferable
244 maDestMapMode
.SetMapUnit( MapUnit::Map100thMM
);
245 mHandlesUsed
= std::vector
<bool>(MAXHANDLES
, false);
246 mnHandleCount
= mnRecordCount
= mnRecordPos
= mnRecordPlusPos
= 0;
247 mbRecordOpen
= mbRecordPlusOpen
= false;
248 mbLineChanged
= mbFillChanged
= mbTextChanged
= false;
249 mnLineHandle
= mnFillHandle
= mnTextHandle
= HANDLE_INVALID
;
252 const Size
aMtfSizePix( maVDev
->LogicToPixel( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode() ) );
253 const Size
aMtfSizeLog( OutputDevice::LogicToLogic( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode(), MapUnit::Map100thMM
) );
256 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
257 m_rStm
.SeekRel( 108 );
260 WriteEMFPlusHeader( aMtfSizePix
, aMtfSizeLog
);
262 // write initial values
264 // set 100th mm map mode in EMF
265 ImplBeginRecord( WIN_EMR_SETMAPMODE
);
266 m_rStm
.WriteInt32( MM_ANISOTROPIC
);
269 ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX
);
270 m_rStm
.WriteInt32( maVDev
->GetDPIX() ).WriteInt32( maVDev
->GetDPIY() );
273 ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX
);
274 m_rStm
.WriteInt32( 2540 ).WriteInt32( 2540 );
277 ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX
);
278 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
281 ImplBeginRecord( WIN_EMR_SETWINDOWORGEX
);
282 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
285 ImplWriteRasterOp( RasterOp::OverPaint
);
287 ImplBeginRecord( WIN_EMR_SETBKMODE
);
288 m_rStm
.WriteUInt32( 1 ); // TRANSPARENT
296 ImplBeginRecord( WIN_EMR_EOF
);
297 m_rStm
.WriteUInt32( 0 ) // nPalEntries
298 .WriteUInt32( 0x10 ) // offPalEntries
299 .WriteUInt32( 0x14 ); // nSizeLast
303 const sal_uLong nEndPos
= m_rStm
.Tell(); m_rStm
.Seek( nHeaderPos
);
305 m_rStm
.WriteUInt32( 0x00000001 ).WriteUInt32( 108 ) //use [MS-EMF 2.2.11] HeaderExtension2 Object
306 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizePix
.Width() - 1 ).WriteInt32( aMtfSizePix
.Height() - 1 )
307 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizeLog
.Width() - 1 ).WriteInt32( aMtfSizeLog
.Height() - 1 )
308 .WriteUInt32( 0x464d4520 ).WriteUInt32( 0x10000 ).WriteUInt32( nEndPos
- nHeaderPos
)
309 .WriteUInt32( mnRecordCount
).WriteUInt16( mnHandleCount
+ 1 ).WriteUInt16( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
310 .WriteInt32( aMtfSizePix
.Width() ).WriteInt32( aMtfSizePix
.Height() )
311 .WriteInt32( aMtfSizeLog
.Width() / 100 ).WriteInt32( aMtfSizeLog
.Height() / 100 )
312 .WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
313 .WriteInt32( aMtfSizeLog
.Width() * 10 ).WriteInt32( aMtfSizeLog
.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
315 m_rStm
.Seek( nEndPos
);
316 mHandlesUsed
.clear();
318 return( m_rStm
.GetError() == ERRCODE_NONE
);
321 sal_uLong
EMFWriter::ImplAcquireHandle()
323 sal_uLong nHandle
= HANDLE_INVALID
;
325 for( sal_uLong i
= 0; i
< mHandlesUsed
.size() && ( HANDLE_INVALID
== nHandle
); i
++ )
327 if( !mHandlesUsed
[ i
] )
329 mHandlesUsed
[ i
] = true;
331 if( ( nHandle
= i
) == mnHandleCount
)
336 SAL_WARN_IF( nHandle
== HANDLE_INVALID
, "vcl", "No more handles available" );
337 return( nHandle
!= HANDLE_INVALID
? nHandle
+ 1 : HANDLE_INVALID
);
340 void EMFWriter::ImplReleaseHandle( sal_uLong nHandle
)
342 SAL_WARN_IF( !nHandle
|| ( nHandle
>= mHandlesUsed
.size() ), "vcl", "Handle out of range" );
343 mHandlesUsed
[ nHandle
- 1 ] = false;
346 void EMFWriter::ImplBeginRecord( sal_uInt32 nType
)
348 SAL_WARN_IF( mbRecordOpen
, "vcl", "Another record is already opened!" );
353 mnRecordPos
= m_rStm
.Tell();
355 m_rStm
.WriteUInt32( nType
);
360 void EMFWriter::ImplEndRecord()
362 SAL_WARN_IF( !mbRecordOpen
, "vcl", "Record was not opened!" );
366 sal_Int32 nFillBytes
, nActPos
= m_rStm
.Tell();
367 m_rStm
.Seek( mnRecordPos
+ 4 );
368 nFillBytes
= nActPos
- mnRecordPos
;
369 nFillBytes
+= 3; // each record has to be dword aligned
372 m_rStm
.WriteUInt32( ( nActPos
- mnRecordPos
) + nFillBytes
);
373 m_rStm
.Seek( nActPos
);
374 while( nFillBytes
-- )
375 m_rStm
.WriteUChar( 0 );
377 mbRecordOpen
= false;
381 bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32
& rHandle
, sal_uLong nSelectType
)
383 if( rHandle
!= HANDLE_INVALID
)
385 sal_uInt32 nStockObject
= 0x80000000;
387 if( LINE_SELECT
== nSelectType
)
388 nStockObject
|= 0x00000007;
389 else if( FILL_SELECT
== nSelectType
)
390 nStockObject
|= 0x00000001;
391 else if( TEXT_SELECT
== nSelectType
)
392 nStockObject
|= 0x0000000a;
394 // select stock object first
395 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
396 m_rStm
.WriteUInt32( nStockObject
);
399 // destroy handle of created object
400 ImplBeginRecord( WIN_EMR_DELETEOBJECT
);
401 m_rStm
.WriteUInt32( rHandle
);
404 // mark handle as free
405 ImplReleaseHandle( rHandle
);
408 rHandle
= ImplAcquireHandle();
410 return( HANDLE_INVALID
!= rHandle
);
413 void EMFWriter::ImplCheckLineAttr()
415 if( mbLineChanged
&& ImplPrepareHandleSelect( mnLineHandle
, LINE_SELECT
) )
417 sal_uInt32 nStyle
= maVDev
->IsLineColor() ? 0 : 5;
418 sal_uInt32 nWidth
= 0, nHeight
= 0;
420 ImplBeginRecord( WIN_EMR_CREATEPEN
);
421 m_rStm
.WriteUInt32( mnLineHandle
).WriteUInt32( nStyle
).WriteUInt32( nWidth
).WriteUInt32( nHeight
);
422 ImplWriteColor( maVDev
->GetLineColor() );
425 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
426 m_rStm
.WriteUInt32( mnLineHandle
);
431 void EMFWriter::ImplCheckFillAttr()
433 if( mbFillChanged
&& ImplPrepareHandleSelect( mnFillHandle
, FILL_SELECT
) )
435 sal_uInt32 nStyle
= maVDev
->IsFillColor() ? 0 : 1;
436 sal_uInt32 nPatternStyle
= 0;
438 ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT
);
439 m_rStm
.WriteUInt32( mnFillHandle
).WriteUInt32( nStyle
);
440 ImplWriteColor( maVDev
->GetFillColor() );
441 m_rStm
.WriteUInt32( nPatternStyle
);
444 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
445 m_rStm
.WriteUInt32( mnFillHandle
);
450 void EMFWriter::ImplCheckTextAttr()
452 if( mbTextChanged
&& ImplPrepareHandleSelect( mnTextHandle
, TEXT_SELECT
) )
454 const vcl::Font
& rFont
= maVDev
->GetFont();
455 const OUString
& aFontName( rFont
.GetFamilyName() );
458 sal_uInt8 nPitchAndFamily
;
460 ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW
);
461 m_rStm
.WriteUInt32( mnTextHandle
);
462 ImplWriteExtent( -rFont
.GetFontSize().Height() );
463 ImplWriteExtent( rFont
.GetFontSize().Width() );
464 m_rStm
.WriteInt32( rFont
.GetOrientation() ).WriteInt32( rFont
.GetOrientation() );
466 switch( rFont
.GetWeight() )
468 case WEIGHT_THIN
: nWeight
= 100; break;
469 case WEIGHT_ULTRALIGHT
: nWeight
= 200; break;
470 case WEIGHT_LIGHT
: nWeight
= 300; break;
471 case WEIGHT_SEMILIGHT
: nWeight
= 300; break;
472 case WEIGHT_NORMAL
: nWeight
= 400; break;
473 case WEIGHT_MEDIUM
: nWeight
= 500; break;
474 case WEIGHT_SEMIBOLD
: nWeight
= 600; break;
475 case WEIGHT_BOLD
: nWeight
= 700; break;
476 case WEIGHT_ULTRABOLD
: nWeight
= 800; break;
477 case WEIGHT_BLACK
: nWeight
= 900; break;
478 default: nWeight
= 0; break;
481 m_rStm
.WriteInt32( nWeight
);
482 m_rStm
.WriteUChar( ( ITALIC_NONE
== rFont
.GetItalic() ) ? 0 : 1 );
483 m_rStm
.WriteUChar( ( LINESTYLE_NONE
== rFont
.GetUnderline() ) ? 0 : 1 );
484 m_rStm
.WriteUChar( ( STRIKEOUT_NONE
== rFont
.GetStrikeout() ) ? 0 : 1 );
485 m_rStm
.WriteUChar( ( RTL_TEXTENCODING_SYMBOL
== rFont
.GetCharSet() ) ? 2 : 0 );
486 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
488 switch( rFont
.GetPitch() )
490 case PITCH_FIXED
: nPitchAndFamily
= 0x01; break;
491 case PITCH_VARIABLE
: nPitchAndFamily
= 0x02; break;
492 default: nPitchAndFamily
= 0x00; break;
495 switch( rFont
.GetFamilyType() )
497 case FAMILY_DECORATIVE
: nPitchAndFamily
|= 0x50; break;
498 case FAMILY_MODERN
: nPitchAndFamily
|= 0x30; break;
499 case FAMILY_ROMAN
: nPitchAndFamily
|= 0x10; break;
500 case FAMILY_SCRIPT
: nPitchAndFamily
|= 0x40; break;
501 case FAMILY_SWISS
: nPitchAndFamily
|= 0x20; break;
505 m_rStm
.WriteUChar( nPitchAndFamily
);
507 for( i
= 0; i
< 32; i
++ )
508 m_rStm
.WriteUInt16( ( i
< aFontName
.getLength() ) ? aFontName
[ i
] : 0 );
511 for( i
= 0; i
< 64; i
++ )
512 m_rStm
.WriteUInt16( 0 );
515 for( i
= 0; i
< 32; i
++ )
516 m_rStm
.WriteUInt16( 0 );
518 // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
519 m_rStm
.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ) ;
522 m_rStm
.WriteUInt32( 0 );
525 m_rStm
.WriteUInt32( 0 );
528 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
530 // fill record to get a record size divideable by 4
531 m_rStm
.WriteUInt16( 0 );
536 sal_uInt32 nTextAlign
;
538 switch( rFont
.GetAlignment() )
540 case ALIGN_TOP
: nTextAlign
= TA_TOP
; break;
541 case ALIGN_BOTTOM
: nTextAlign
= TA_BOTTOM
; break;
542 default: nTextAlign
= TA_BASELINE
; break;
544 nTextAlign
|= mnHorTextAlign
;
546 ImplBeginRecord( WIN_EMR_SETTEXTALIGN
);
547 m_rStm
.WriteUInt32( nTextAlign
);
551 ImplBeginRecord( WIN_EMR_SETTEXTCOLOR
);
552 ImplWriteColor( maVDev
->GetTextColor() );
555 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
556 m_rStm
.WriteUInt32( mnTextHandle
);
561 void EMFWriter::ImplWriteColor( const Color
& rColor
)
563 sal_uInt32 nCol
= rColor
.GetRed();
565 nCol
|= ( (sal_uInt32
) rColor
.GetGreen() ) << 8;
566 nCol
|= ( (sal_uInt32
) rColor
.GetBlue() ) << 16;
568 m_rStm
.WriteUInt32( nCol
);
571 void EMFWriter::ImplWriteRasterOp( RasterOp eRop
)
577 case RasterOp::Invert
: nROP2
= 6; break;
578 case RasterOp::Xor
: nROP2
= 7; break;
579 default: nROP2
= 13;break;
582 ImplBeginRecord( WIN_EMR_SETROP2
);
583 m_rStm
.WriteUInt32( nROP2
);
587 void EMFWriter::ImplWriteExtent( long nExtent
)
589 nExtent
= OutputDevice::LogicToLogic( Size( nExtent
, 0 ), maVDev
->GetMapMode(), maDestMapMode
).Width();
590 m_rStm
.WriteInt32( nExtent
);
593 void EMFWriter::ImplWritePoint( const Point
& rPoint
)
595 const Point
aPoint( OutputDevice::LogicToLogic( rPoint
, maVDev
->GetMapMode(), maDestMapMode
));
596 m_rStm
.WriteInt32( aPoint
.X() ).WriteInt32( aPoint
.Y() );
599 void EMFWriter::ImplWriteSize( const Size
& rSize
)
601 const Size
aSize( OutputDevice::LogicToLogic( rSize
, maVDev
->GetMapMode(), maDestMapMode
));
602 m_rStm
.WriteInt32( aSize
.Width() ).WriteInt32( aSize
.Height() );
605 void EMFWriter::ImplWriteRect( const Rectangle
& rRect
)
607 const Rectangle
aRect( OutputDevice::LogicToLogic ( rRect
, maVDev
->GetMapMode(), maDestMapMode
));
609 .WriteInt32( aRect
.Left() )
610 .WriteInt32( aRect
.Top() )
611 .WriteInt32( aRect
.Right() )
612 .WriteInt32( aRect
.Bottom() );
615 void EMFWriter::ImplWritePolygonRecord( const tools::Polygon
& rPoly
, bool bClose
)
617 if( rPoly
.GetSize() )
619 if( rPoly
.HasFlags() )
620 ImplWritePath( rPoly
, bClose
);
628 ImplBeginRecord( bClose
? WIN_EMR_POLYGON
: WIN_EMR_POLYLINE
);
629 ImplWriteRect( rPoly
.GetBoundRect() );
630 m_rStm
.WriteUInt32( rPoly
.GetSize() );
632 for( sal_uInt16 i
= 0; i
< rPoly
.GetSize(); i
++ )
633 ImplWritePoint( rPoly
[ i
] );
640 void EMFWriter::ImplWritePolyPolygonRecord( const tools::PolyPolygon
& rPolyPoly
)
642 sal_uInt16 n
, i
, nPolyCount
= rPolyPoly
.Count();
646 if( 1 == nPolyCount
)
647 ImplWritePolygonRecord( rPolyPoly
[ 0 ], true );
650 bool bHasFlags
= false;
651 sal_uInt32 nTotalPoints
= 0;
653 for( i
= 0; i
< nPolyCount
; i
++ )
655 nTotalPoints
+= rPolyPoly
[ i
].GetSize();
656 if ( rPolyPoly
[ i
].HasFlags() )
662 ImplWritePath( rPolyPoly
, true );
668 ImplBeginRecord( WIN_EMR_POLYPOLYGON
);
669 ImplWriteRect( rPolyPoly
.GetBoundRect() );
670 m_rStm
.WriteUInt32( nPolyCount
).WriteUInt32( nTotalPoints
);
672 for( i
= 0; i
< nPolyCount
; i
++ )
673 m_rStm
.WriteUInt32( rPolyPoly
[ i
].GetSize() );
675 for( i
= 0; i
< nPolyCount
; i
++ )
677 const tools::Polygon
& rPoly
= rPolyPoly
[ i
];
679 for( n
= 0; n
< rPoly
.GetSize(); n
++ )
680 ImplWritePoint( rPoly
[ n
] );
689 void EMFWriter::ImplWritePath( const tools::PolyPolygon
& rPolyPoly
, bool bClosed
)
695 ImplBeginRecord( WIN_EMR_BEGINPATH
);
698 sal_uInt16 i
, n
, o
, nPolyCount
= rPolyPoly
.Count();
699 for ( i
= 0; i
< nPolyCount
; i
++ )
702 const tools::Polygon
& rPoly
= rPolyPoly
[ i
];
703 while ( n
< rPoly
.GetSize() )
707 ImplBeginRecord( WIN_EMR_MOVETOEX
);
708 ImplWritePoint( rPoly
[ 0 ] );
714 sal_uInt16 nBezPoints
= 0;
716 while ( ( ( nBezPoints
+ n
+ 2 ) < rPoly
.GetSize() ) && ( rPoly
.GetFlags( nBezPoints
+ n
) == PolyFlags::Control
) )
721 ImplBeginRecord( WIN_EMR_POLYBEZIERTO
);
722 tools::Polygon
aNewPoly( nBezPoints
+ 1 );
723 aNewPoly
[ 0 ] = rPoly
[ n
- 1 ];
724 for ( o
= 0; o
< nBezPoints
; o
++ )
725 aNewPoly
[ o
+ 1 ] = rPoly
[ n
+ o
];
726 ImplWriteRect( aNewPoly
.GetBoundRect() );
727 m_rStm
.WriteUInt32( nBezPoints
);
728 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
729 ImplWritePoint( aNewPoly
[ o
] );
735 sal_uInt16 nPoints
= 1;
736 while( ( nPoints
+ n
) < rPoly
.GetSize() && ( rPoly
.GetFlags( nPoints
+ n
) != PolyFlags::Control
) )
741 ImplBeginRecord( WIN_EMR_POLYLINETO
);
742 tools::Polygon
aNewPoly( nPoints
+ 1 );
743 aNewPoly
[ 0 ] = rPoly
[ n
- 1];
744 for ( o
= 1; o
<= nPoints
; o
++ )
745 aNewPoly
[ o
] = rPoly
[ n
- 1 + o
];
746 ImplWriteRect( aNewPoly
.GetBoundRect() );
747 m_rStm
.WriteUInt32( nPoints
);
748 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
749 ImplWritePoint( aNewPoly
[ o
] );
754 ImplBeginRecord( WIN_EMR_LINETO
);
755 ImplWritePoint( rPoly
[ n
] );
760 if ( bClosed
&& ( n
== rPoly
.GetSize() ) )
762 ImplBeginRecord( WIN_EMR_CLOSEFIGURE
);
767 ImplBeginRecord( WIN_EMR_ENDPATH
);
769 ImplBeginRecord( bClosed
? WIN_EMR_FILLPATH
: WIN_EMR_STROKEPATH
);
770 ImplWriteRect( rPolyPoly
.GetBoundRect() );
774 void EMFWriter::ImplWriteBmpRecord( const Bitmap
& rBmp
, const Point
& rPt
,
775 const Size
& rSz
, sal_uInt32 nROP
)
779 SvMemoryStream
aMemStm( 65535, 65535 );
780 const Size
aBmpSizePixel( rBmp
.GetSizePixel() );
782 ImplBeginRecord( WIN_EMR_STRETCHDIBITS
);
783 ImplWriteRect( Rectangle( rPt
, rSz
) );
784 ImplWritePoint( rPt
);
785 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel
.Width() ).WriteInt32( aBmpSizePixel
.Height() );
787 // write offset positions and sizes later
788 const sal_uLong nOffPos
= m_rStm
.Tell();
789 m_rStm
.SeekRel( 16 );
791 m_rStm
.WriteUInt32( 0 ).WriteInt32( ( RasterOp::Xor
== maVDev
->GetRasterOp() && WIN_SRCCOPY
== nROP
) ? WIN_SRCINVERT
: nROP
);
792 ImplWriteSize( rSz
);
794 WriteDIB(rBmp
, aMemStm
, true, false);
796 sal_uInt32 nDIBSize
= aMemStm
.Tell(), nHeaderSize
, nCompression
, nColsUsed
, nPalCount
, nImageSize
;
797 sal_uInt16 nBitCount
;
799 // get DIB parameters
801 aMemStm
.ReadUInt32( nHeaderSize
);
802 aMemStm
.SeekRel( 10 );
803 aMemStm
.ReadUInt16( nBitCount
).ReadUInt32( nCompression
).ReadUInt32( nImageSize
);
804 aMemStm
.SeekRel( 8 );
805 aMemStm
.ReadUInt32( nColsUsed
);
810 nPalCount
= nColsUsed
;
812 nPalCount
= 1 << (sal_uInt32
)nBitCount
;
816 if (nCompression
== BITFIELDS
)
822 sal_uInt32 nPalSize
= nPalCount
* 4;
824 m_rStm
.WriteBytes( aMemStm
.GetData(), nDIBSize
);
826 const sal_uLong nEndPos
= m_rStm
.Tell();
827 m_rStm
.Seek( nOffPos
);
828 m_rStm
.WriteUInt32( 80 ).WriteUInt32( nHeaderSize
+ nPalSize
);
829 m_rStm
.WriteUInt32( 80 + nHeaderSize
+ nPalSize
).WriteUInt32( nImageSize
);
830 m_rStm
.Seek( nEndPos
);
836 void EMFWriter::ImplWriteTextRecord( const Point
& rPos
, const OUString
& rText
, const long* pDXArray
, sal_uInt32 nWidth
)
838 sal_Int32 nLen
= rText
.getLength(), i
;
842 sal_uInt32 nNormWidth
;
843 std::unique_ptr
<long[]> pOwnArray
;
849 nNormWidth
= maVDev
->GetTextWidth( rText
);
850 pDX
= const_cast<long*>(pDXArray
);
854 pOwnArray
.reset(new long[ nLen
]);
855 nNormWidth
= maVDev
->GetTextArray( rText
, pOwnArray
.get() );
856 pDX
= pOwnArray
.get();
861 nNormWidth
= pDX
[ nLen
- 2 ] + maVDev
->GetTextWidth( OUString(rText
[ nLen
- 1 ]) );
863 if( nWidth
&& nNormWidth
&& ( nWidth
!= nNormWidth
) )
865 const double fFactor
= (double) nWidth
/ nNormWidth
;
867 for( i
= 0; i
< ( nLen
- 1 ); i
++ )
868 pDX
[ i
] = FRound( pDX
[ i
] * fFactor
);
873 ImplBeginRecord( WIN_EMR_EXTTEXTOUTW
);
875 ImplWriteRect( Rectangle( rPos
, Size( nNormWidth
, maVDev
->GetTextHeight() ) ) );
876 m_rStm
.WriteUInt32( 1 );
877 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
878 ImplWritePoint( rPos
);
879 m_rStm
.WriteUInt32( nLen
).WriteUInt32( 76 ).WriteUInt32( 2 );
880 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 );
881 m_rStm
.WriteUInt32( 76 + ( nLen
<< 1 ) + ( (nLen
& 1 ) ? 2 : 0 ) );
884 for( i
= 0; i
< nLen
; i
++ )
885 m_rStm
.WriteUInt16( rText
[ i
] );
889 m_rStm
.WriteUInt16( 0 );
892 ImplWriteExtent( pDX
[ 0 ] );
896 for( i
= 1; i
< ( nLen
- 1 ); i
++ )
897 ImplWriteExtent( pDX
[ i
] - pDX
[ i
- 1 ] );
899 ImplWriteExtent( pDX
[ nLen
- 2 ] / ( nLen
- 1 ) );
906 void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo
& rInfo
, const basegfx::B2DPolygon
& rLinePolygon
)
908 if(rLinePolygon
.count())
910 basegfx::B2DPolyPolygon
aLinePolyPolygon(rLinePolygon
);
911 basegfx::B2DPolyPolygon aFillPolyPolygon
;
913 rInfo
.applyToB2DPolyPolygon(aLinePolyPolygon
, aFillPolyPolygon
);
915 if(aLinePolyPolygon
.count())
917 for(sal_uInt32
a(0); a
< aLinePolyPolygon
.count(); a
++)
919 const basegfx::B2DPolygon
aCandidate(aLinePolyPolygon
.getB2DPolygon(a
));
920 ImplWritePolygonRecord( tools::Polygon(aCandidate
), false );
924 if(aFillPolyPolygon
.count())
926 const Color
aOldLineColor(maVDev
->GetLineColor());
927 const Color
aOldFillColor(maVDev
->GetFillColor());
929 maVDev
->SetLineColor();
930 maVDev
->SetFillColor(aOldLineColor
);
932 for(sal_uInt32
a(0); a
< aFillPolyPolygon
.count(); a
++)
934 const tools::Polygon
aPolygon(aFillPolyPolygon
.getB2DPolygon(a
));
935 ImplWritePolyPolygonRecord(tools::PolyPolygon( tools::Polygon(aPolygon
) ));
938 maVDev
->SetLineColor(aOldLineColor
);
939 maVDev
->SetFillColor(aOldFillColor
);
944 void EMFWriter::ImplWrite( const GDIMetaFile
& rMtf
)
946 for( size_t j
= 0, nActionCount
= rMtf
.GetActionSize(); j
< nActionCount
; j
++ )
948 const MetaAction
* pAction
= rMtf
.GetAction( j
);
949 const MetaActionType nType
= pAction
->GetType();
953 case( MetaActionType::PIXEL
):
955 const MetaPixelAction
* pA
= static_cast<const MetaPixelAction
*>(pAction
);
958 ImplBeginRecord( WIN_EMR_SETPIXELV
);
959 ImplWritePoint( pA
->GetPoint() );
960 ImplWriteColor( pA
->GetColor() );
965 case( MetaActionType::POINT
):
967 if( maVDev
->IsLineColor() )
969 const MetaPointAction
* pA
= static_cast<const MetaPointAction
*>(pAction
);
972 ImplBeginRecord( WIN_EMR_SETPIXELV
);
973 ImplWritePoint( pA
->GetPoint() );
974 ImplWriteColor( maVDev
->GetLineColor() );
980 case( MetaActionType::LINE
):
982 if( maVDev
->IsLineColor() )
984 const MetaLineAction
* pA
= static_cast<const MetaLineAction
*>(pAction
);
986 if(pA
->GetLineInfo().IsDefault())
990 ImplBeginRecord( WIN_EMR_MOVETOEX
);
991 ImplWritePoint( pA
->GetStartPoint() );
994 ImplBeginRecord( WIN_EMR_LINETO
);
995 ImplWritePoint( pA
->GetEndPoint() );
998 ImplBeginRecord( WIN_EMR_SETPIXELV
);
999 ImplWritePoint( pA
->GetEndPoint() );
1000 ImplWriteColor( maVDev
->GetLineColor() );
1005 // LineInfo used; handle Dash/Dot and fat lines
1006 basegfx::B2DPolygon aPolygon
;
1007 aPolygon
.append(basegfx::B2DPoint(pA
->GetStartPoint().X(), pA
->GetStartPoint().Y()));
1008 aPolygon
.append(basegfx::B2DPoint(pA
->GetEndPoint().X(), pA
->GetEndPoint().Y()));
1009 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), aPolygon
);
1015 case( MetaActionType::RECT
):
1017 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1019 const MetaRectAction
* pA
= static_cast<const MetaRectAction
*>(pAction
);
1021 ImplCheckFillAttr();
1022 ImplCheckLineAttr();
1024 ImplBeginRecord( WIN_EMR_RECTANGLE
);
1025 ImplWriteRect( pA
->GetRect() );
1031 case( MetaActionType::ROUNDRECT
):
1033 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1035 const MetaRoundRectAction
* pA
= static_cast<const MetaRoundRectAction
*>(pAction
);
1037 ImplCheckFillAttr();
1038 ImplCheckLineAttr();
1040 ImplBeginRecord( WIN_EMR_ROUNDRECT
);
1041 ImplWriteRect( pA
->GetRect() );
1042 ImplWriteSize( Size( pA
->GetHorzRound(), pA
->GetVertRound() ) );
1048 case( MetaActionType::ELLIPSE
):
1050 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1052 const MetaEllipseAction
* pA
= static_cast<const MetaEllipseAction
*>(pAction
);
1054 ImplCheckFillAttr();
1055 ImplCheckLineAttr();
1057 ImplBeginRecord( WIN_EMR_ELLIPSE
);
1058 ImplWriteRect( pA
->GetRect() );
1064 case( MetaActionType::ARC
):
1065 case( MetaActionType::PIE
):
1066 case( MetaActionType::CHORD
):
1067 case( MetaActionType::POLYGON
):
1069 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1071 tools::Polygon aPoly
;
1075 case( MetaActionType::ARC
):
1077 const MetaArcAction
* pA
= static_cast<const MetaArcAction
*>(pAction
);
1078 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_ARC
);
1082 case( MetaActionType::PIE
):
1084 const MetaPieAction
* pA
= static_cast<const MetaPieAction
*>(pAction
);
1085 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_PIE
);
1089 case( MetaActionType::CHORD
):
1091 const MetaChordAction
* pA
= static_cast<const MetaChordAction
*>(pAction
);
1092 aPoly
= tools::Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_CHORD
);
1096 case( MetaActionType::POLYGON
):
1097 aPoly
= static_cast<const MetaPolygonAction
*>(pAction
)->GetPolygon();
1102 ImplWritePolygonRecord( aPoly
, nType
!= MetaActionType::ARC
);
1107 case( MetaActionType::POLYLINE
):
1109 if( maVDev
->IsLineColor() )
1111 const MetaPolyLineAction
* pA
= static_cast<const MetaPolyLineAction
*>(pAction
);
1112 const tools::Polygon
& rPoly
= pA
->GetPolygon();
1114 if( rPoly
.GetSize() )
1116 if(pA
->GetLineInfo().IsDefault())
1118 ImplWritePolygonRecord( rPoly
, false );
1122 // LineInfo used; handle Dash/Dot and fat lines
1123 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), rPoly
.getB2DPolygon());
1130 case( MetaActionType::POLYPOLYGON
):
1132 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1133 ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction
*>(pAction
)->GetPolyPolygon() );
1137 case( MetaActionType::GRADIENT
):
1139 const MetaGradientAction
* pA
= static_cast<const MetaGradientAction
*>(pAction
);
1140 GDIMetaFile aTmpMtf
;
1142 maVDev
->AddGradientActions( pA
->GetRect(), pA
->GetGradient(), aTmpMtf
);
1143 ImplWrite( aTmpMtf
);
1147 case MetaActionType::HATCH
:
1149 const MetaHatchAction
* pA
= static_cast<const MetaHatchAction
*>(pAction
);
1150 GDIMetaFile aTmpMtf
;
1152 maVDev
->AddHatchActions( pA
->GetPolyPolygon(), pA
->GetHatch(), aTmpMtf
);
1153 ImplWrite( aTmpMtf
);
1157 case MetaActionType::Transparent
:
1159 const tools::PolyPolygon
& rPolyPoly
= static_cast<const MetaTransparentAction
*>(pAction
)->GetPolyPolygon();
1160 if( rPolyPoly
.Count() )
1161 ImplWritePlusFillPolygonRecord( rPolyPoly
[0], static_cast<const MetaTransparentAction
*>(pAction
)->GetTransparence() );
1162 ImplCheckFillAttr();
1163 ImplCheckLineAttr();
1164 ImplWritePolyPolygonRecord( rPolyPoly
);
1166 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
1167 ImplPlusRecord( EmfPlusRecordType::GetDC
, 0x00 );
1168 ImplEndCommentRecord();
1172 case MetaActionType::FLOATTRANSPARENT
:
1174 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pAction
);
1176 GDIMetaFile
aTmpMtf( pA
->GetGDIMetaFile() );
1177 Point
aSrcPt( aTmpMtf
.GetPrefMapMode().GetOrigin() );
1178 const Size
aSrcSize( aTmpMtf
.GetPrefSize() );
1179 const Point
aDestPt( pA
->GetPoint() );
1180 const Size
aDestSize( pA
->GetSize() );
1181 const double fScaleX
= aSrcSize
.Width() ? (double) aDestSize
.Width() / aSrcSize
.Width() : 1.0;
1182 const double fScaleY
= aSrcSize
.Height() ? (double) aDestSize
.Height() / aSrcSize
.Height() : 1.0;
1183 long nMoveX
, nMoveY
;
1185 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
1187 aTmpMtf
.Scale( fScaleX
, fScaleY
);
1188 aSrcPt
.X() = FRound( aSrcPt
.X() * fScaleX
);
1189 aSrcPt
.Y() = FRound( aSrcPt
.Y() * fScaleY
);
1192 nMoveX
= aDestPt
.X() - aSrcPt
.X();
1193 nMoveY
= aDestPt
.Y() - aSrcPt
.Y();
1195 if( nMoveX
|| nMoveY
)
1196 aTmpMtf
.Move( nMoveX
, nMoveY
);
1198 ImplCheckFillAttr();
1199 ImplCheckLineAttr();
1200 ImplCheckTextAttr();
1201 ImplWrite( aTmpMtf
);
1205 case( MetaActionType::EPS
):
1207 const MetaEPSAction
* pA
= static_cast<const MetaEPSAction
*>(pAction
);
1208 const GDIMetaFile
aSubstitute( pA
->GetSubstitute() );
1210 for( size_t i
= 0, nCount
= aSubstitute
.GetActionSize(); i
< nCount
; i
++ )
1212 const MetaAction
* pSubstAct
= aSubstitute
.GetAction( i
);
1213 if( pSubstAct
->GetType() == MetaActionType::BMPSCALE
)
1216 ImplBeginRecord( WIN_EMR_SAVEDC
);
1219 MapMode
aMapMode( aSubstitute
.GetPrefMapMode() );
1220 Size
aOutSize( OutputDevice::LogicToLogic( pA
->GetSize(), maVDev
->GetMapMode(), aMapMode
) );
1221 aMapMode
.SetScaleX( Fraction( aOutSize
.Width(), aSubstitute
.GetPrefSize().Width() ) );
1222 aMapMode
.SetScaleY( Fraction( aOutSize
.Height(), aSubstitute
.GetPrefSize().Height() ) );
1223 aMapMode
.SetOrigin( OutputDevice::LogicToLogic( pA
->GetPoint(), maVDev
->GetMapMode(), aMapMode
) );
1224 maVDev
->SetMapMode( aMapMode
);
1225 ImplWrite( aSubstitute
);
1228 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1229 m_rStm
.WriteInt32( -1 );
1237 case MetaActionType::BMP
:
1239 const MetaBmpAction
* pA
= static_cast<const MetaBmpAction
*>(pAction
);
1240 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), maVDev
->PixelToLogic( pA
->GetBitmap().GetSizePixel() ), WIN_SRCCOPY
);
1244 case MetaActionType::BMPSCALE
:
1246 const MetaBmpScaleAction
* pA
= static_cast<const MetaBmpScaleAction
*>(pAction
);
1247 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1251 case MetaActionType::BMPSCALEPART
:
1253 const MetaBmpScalePartAction
* pA
= static_cast<const MetaBmpScalePartAction
*>(pAction
);
1254 Bitmap
aTmp( pA
->GetBitmap() );
1256 if( aTmp
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) ) )
1257 ImplWriteBmpRecord( aTmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1261 case MetaActionType::BMPEX
:
1263 const MetaBmpExAction
* pA
= static_cast<const MetaBmpExAction
*>(pAction
);
1264 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1265 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1269 aBmp
.Replace( aMsk
, COL_WHITE
);
1271 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), maVDev
->PixelToLogic( aMsk
.GetSizePixel() ), WIN_SRCPAINT
);
1272 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), maVDev
->PixelToLogic( aBmp
.GetSizePixel() ), WIN_SRCAND
);
1275 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), aBmp
.GetSizePixel(), WIN_SRCCOPY
);
1279 case MetaActionType::BMPEXSCALE
:
1281 const MetaBmpExScaleAction
* pA
= static_cast<const MetaBmpExScaleAction
*>(pAction
);
1282 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1283 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1287 aBmp
.Replace( aMsk
, COL_WHITE
);
1289 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCPAINT
);
1290 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCAND
);
1293 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1297 case MetaActionType::BMPEXSCALEPART
:
1299 const MetaBmpExScalePartAction
* pA
= static_cast<const MetaBmpExScalePartAction
*>(pAction
);
1300 BitmapEx
aBmpEx( pA
->GetBitmapEx() );
1301 aBmpEx
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) );
1302 Bitmap
aBmp( aBmpEx
.GetBitmap() );
1303 Bitmap
aMsk( aBmpEx
.GetMask() );
1307 aBmp
.Replace( aMsk
, COL_WHITE
);
1309 ImplWriteBmpRecord( aMsk
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCPAINT
);
1310 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCAND
);
1313 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1317 case MetaActionType::TEXT
:
1319 const MetaTextAction
* pA
= static_cast<const MetaTextAction
*>(pAction
);
1320 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1322 ImplCheckTextAttr();
1323 ImplWriteTextRecord( pA
->GetPoint(), aText
, nullptr, 0 );
1327 case MetaActionType::TEXTRECT
:
1329 const MetaTextRectAction
* pA
= static_cast<const MetaTextRectAction
*>(pAction
);
1330 const OUString
aText( pA
->GetText() );
1332 ImplCheckTextAttr();
1333 ImplWriteTextRecord( pA
->GetRect().TopLeft(), aText
, nullptr, 0 );
1337 case MetaActionType::TEXTARRAY
:
1339 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pAction
);
1340 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1342 ImplCheckTextAttr();
1343 ImplWriteTextRecord( pA
->GetPoint(), aText
, pA
->GetDXArray(), 0 );
1347 case MetaActionType::STRETCHTEXT
:
1349 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pAction
);
1350 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1352 ImplCheckTextAttr();
1353 ImplWriteTextRecord( pA
->GetPoint(), aText
, nullptr, pA
->GetWidth() );
1357 case( MetaActionType::LINECOLOR
):
1359 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1360 mbLineChanged
= true;
1364 case( MetaActionType::FILLCOLOR
):
1366 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1367 mbFillChanged
= true;
1371 case( MetaActionType::TEXTCOLOR
):
1372 case( MetaActionType::TEXTLINECOLOR
):
1373 case( MetaActionType::TEXTFILLCOLOR
):
1374 case( MetaActionType::TEXTALIGN
):
1375 case( MetaActionType::FONT
):
1377 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1378 mbTextChanged
= true;
1382 case( MetaActionType::ISECTRECTCLIPREGION
):
1384 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1386 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT
);
1387 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction
*>(pAction
)->GetRect() );
1392 case( MetaActionType::CLIPREGION
):
1393 case( MetaActionType::ISECTREGIONCLIPREGION
):
1394 case( MetaActionType::MOVECLIPREGION
):
1396 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1400 case( MetaActionType::REFPOINT
):
1401 case( MetaActionType::MAPMODE
):
1402 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1405 case( MetaActionType::PUSH
):
1407 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1409 ImplBeginRecord( WIN_EMR_SAVEDC
);
1414 case( MetaActionType::POP
):
1416 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1418 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1419 m_rStm
.WriteInt32( -1 );
1422 ImplWriteRasterOp( maVDev
->GetRasterOp() );
1423 mbLineChanged
= mbFillChanged
= mbTextChanged
= true;
1427 case( MetaActionType::RASTEROP
):
1429 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1430 ImplWriteRasterOp( static_cast<const MetaRasterOpAction
*>(pAction
)->GetRasterOp() );
1434 case( MetaActionType::LAYOUTMODE
):
1436 ComplexTextLayoutFlags nLayoutMode
= static_cast<const MetaLayoutModeAction
*>(pAction
)->GetLayoutMode();
1438 if ((nLayoutMode
& ComplexTextLayoutFlags::BiDiRtl
) != ComplexTextLayoutFlags::Default
)
1440 mnHorTextAlign
= TA_RIGHT
| TA_RTLREADING
;
1442 if ((nLayoutMode
& ComplexTextLayoutFlags::TextOriginRight
) != ComplexTextLayoutFlags::Default
)
1443 mnHorTextAlign
|= TA_RIGHT
;
1444 else if ((nLayoutMode
& ComplexTextLayoutFlags::TextOriginLeft
) != ComplexTextLayoutFlags::Default
)
1445 mnHorTextAlign
&= ~TA_RIGHT
;
1449 case( MetaActionType::COMMENT
):
1451 MetaCommentAction
const*const pCommentAction(
1452 static_cast<MetaCommentAction
const*>(pAction
));
1453 if (pCommentAction
->GetComment() == "EMF_PLUS")
1455 ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS
);
1456 m_rStm
.WriteBytes(pCommentAction
->GetData(),
1457 pCommentAction
->GetDataSize());
1458 ImplEndCommentRecord();
1463 case( MetaActionType::MASK
):
1464 case( MetaActionType::MASKSCALE
):
1465 case( MetaActionType::MASKSCALEPART
):
1466 case( MetaActionType::WALLPAPER
):
1467 case( MetaActionType::TEXTLINE
):
1468 case( MetaActionType::GRADIENTEX
):
1469 // Explicitly ignored cases
1473 // TODO: Implement more cases as necessary. Let's not bother with a warning.
1479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */