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>
32 #include <boost/scoped_array.hpp>
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
98 EmfPlusHeader
= 0x4001,
99 EmfPlusEndOfFile
= 0x4002,
100 EmfPlusComment
= 0x4003,
101 EmfPlusGetDC
= 0x4004,
102 EmfPlusMultiFormatStart
= 0x4005,
103 EmfPlusMultiFormatSection
= 0x4006,
104 EmfPlusMultiFormatEnd
= 0x4007,
105 EmfPlusObject
= 0x4008,
106 EmfPlusClear
= 0x4009,
107 EmfPlusFillRects
= 0x400A,
108 EmfPlusDrawRects
= 0x400B,
109 EmfPlusFillPolygon
= 0x400C,
110 EmfPlusDrawLines
= 0x400D,
111 EmfPlusFillEllipse
= 0x400E,
112 EmfPlusDrawEllipse
= 0x400F,
113 EmfPlusFillPie
= 0x4010,
114 EmfPlusDrawPie
= 0x4011,
115 EmfPlusDrawArc
= 0x4012,
116 EmfPlusFillRegion
= 0x4013,
117 EmfPlusFillPath
= 0x4014,
118 EmfPlusDrawPath
= 0x4015,
119 EmfPlusFillClosedCurve
= 0x4016,
120 EmfPlusDrawClosedCurve
= 0x4017,
121 EmfPlusDrawCurve
= 0x4018,
122 EmfPlusDrawBeziers
= 0x4019,
123 EmfPlusDrawImage
= 0x401A,
124 EmfPlusDrawImagePoints
= 0x401B,
125 EmfPlusDrawstring
= 0x401C,
126 EmfPlusSetRenderingOrigin
= 0x401D,
127 EmfPlusSetAntiAliasMode
= 0x401E,
128 EmfPlusSetTextRenderingHint
= 0x401F,
129 EmfPlusSetTextContrast
= 0x4020,
130 EmfPlusSetInterpolationMode
= 0x4021,
131 EmfPlusSetPixelOffsetMode
= 0x4022,
132 EmfPlusSetCompositingMode
= 0x4023,
133 EmfPlusSetCompositingQuality
= 0x4024,
134 EmfPlusSave
= 0x4025,
135 EmfPlusRestore
= 0x4026,
136 EmfPlusBeginContainer
= 0x4027,
137 EmfPlusBeginContainerNoParams
= 0x4028,
138 EmfPlusEndContainer
= 0x4029,
139 EmfPlusSetWorldTransform
= 0x402A,
140 EmfPlusResetWorldTransform
= 0x402B,
141 EmfPlusMultiplyWorldTransform
= 0x402C,
142 EmfPlusTranslateWorldTransform
= 0x402D,
143 EmfPlusScaleWorldTransform
= 0x402E,
144 EmfPlusRotateWorldTransform
= 0x402F,
145 EmfPlusSetPageTransform
= 0x4030,
146 EmfPlusResetClip
= 0x4031,
147 EmfPlusSetClipRect
= 0x4032,
148 EmfPlusSetClipPath
= 0x4033,
149 EmfPlusSetClipRegion
= 0x4034,
150 EmfPlusOffsetClip
= 0x4035,
151 EmfPlusDrawDriverstring
= 0x4036,
152 EmfPlusStrokeFillPath
= 0x4037,
153 EmfPlusSerializableObject
= 0x4038,
154 EmfPlusSetTSGraphics
= 0x4039,
155 EmfPlusSetTSClip
= 0x403A
158 void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType
)
160 ImplBeginRecord( WIN_EMR_GDICOMMENT
);
162 m_rStm
.WriteInt32( nCommentType
);
165 void EMFWriter::ImplEndCommentRecord()
169 sal_Int32 nActPos
= m_rStm
.Tell();
170 m_rStm
.Seek( mnRecordPos
+ 8 );
171 m_rStm
.WriteUInt32( nActPos
- mnRecordPos
- 0xc );
172 m_rStm
.Seek( nActPos
);
177 void EMFWriter::ImplBeginPlusRecord( sal_uInt16 nType
, sal_uInt16 nFlags
)
179 DBG_ASSERT( !mbRecordPlusOpen
, "Another EMF+ record is already opened!" );
181 if( !mbRecordPlusOpen
)
183 mbRecordPlusOpen
= true;
184 mnRecordPlusPos
= m_rStm
.Tell();
186 m_rStm
.WriteUInt16( nType
).WriteUInt16( nFlags
);
191 void EMFWriter::ImplEndPlusRecord()
193 DBG_ASSERT( mbRecordPlusOpen
, "EMF+ Record was not opened!" );
195 if( mbRecordPlusOpen
)
197 sal_Int32 nActPos
= m_rStm
.Tell();
198 sal_Int32 nSize
= nActPos
- mnRecordPlusPos
;
199 m_rStm
.Seek( mnRecordPlusPos
+ 4 );
200 m_rStm
.WriteUInt32( nSize
) // Size
201 .WriteUInt32( nSize
- 0xc ); // Data Size
202 m_rStm
.Seek( nActPos
);
203 mbRecordPlusOpen
= false;
207 void EMFWriter::ImplPlusRecord( sal_uInt16 nType
, sal_uInt16 nFlags
)
209 ImplBeginPlusRecord( nType
, nFlags
);
213 void EMFWriter::WriteEMFPlusHeader( const Size
&rMtfSizePix
, const Size
&rMtfSizeLog
)
215 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
217 sal_Int32 nDPIX
= rMtfSizePix
.Width()*25;
218 sal_Int32 nDivX
= rMtfSizeLog
.Width()/100;
220 nDPIX
/= nDivX
; // DPI X
222 sal_Int32 nDPIY
= rMtfSizePix
.Height()*25;
223 sal_Int32 nDivY
= rMtfSizeLog
.Height()/100;
225 nDPIY
/= nDivY
; // DPI Y
227 m_rStm
.WriteInt16( EmfPlusHeader
);
228 m_rStm
.WriteInt16( 0x01 ) // Flags - Dual Mode // TODO: Check this
229 .WriteInt32( 0x1C ) // Size
230 .WriteInt32( 0x10 ) // Data Size
231 .WriteInt32( 0xdbc01002 ) // (lower 12bits) 1-> v1 2-> v1.1 // TODO: Check this
232 .WriteInt32( 0x01 ) // Video display
234 .WriteInt32( nDPIY
);
235 ImplEndCommentRecord();
237 // Write more properties
238 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
239 ImplPlusRecord( EmfPlusSetPixelOffsetMode
, 0x0 );
240 ImplPlusRecord( EmfPlusSetAntiAliasMode
, 0x09 ); // TODO: Check actual values for AntiAlias
241 ImplPlusRecord( EmfPlusSetCompositingQuality
, 0x0100 ); // Default Quality
242 ImplPlusRecord( EmfPlusSetPageTransform
, 1 );
243 ImplPlusRecord( EmfPlusSetInterpolationMode
, 0x00 ); // Default
244 ImplPlusRecord( EmfPlusGetDC
, 0x00 );
245 ImplEndCommentRecord();
248 void EMFWriter::ImplWritePlusEOF()
250 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
251 ImplPlusRecord( EmfPlusEndOfFile
, 0x0 );
252 ImplEndCommentRecord();
255 void EMFWriter::ImplWritePlusColor( const Color
& rColor
, const sal_uInt32
& nTrans
)
257 sal_uInt32 nAlpha
= ((100-nTrans
)*0xFF)/100;
258 sal_uInt32 nCol
= rColor
.GetBlue();
260 nCol
|= ( (sal_uInt32
) rColor
.GetGreen() ) << 8;
261 nCol
|= ( (sal_uInt32
) rColor
.GetRed() ) << 16;
262 nCol
|= ( nAlpha
<< 24 );
263 m_rStm
.WriteUInt32( nCol
);
266 void EMFWriter::ImplWritePlusPoint( const Point
& rPoint
)
269 const Point
aPoint(maVDev
->LogicToPixel( rPoint
, maDestMapMode
));
270 m_rStm
.WriteUInt16( aPoint
.X() ).WriteUInt16( aPoint
.Y() );
273 void EMFWriter::ImplWritePlusFillPolygonRecord( const Polygon
& rPoly
, const sal_uInt32
& nTrans
)
275 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
276 if( rPoly
.GetSize() )
278 ImplBeginPlusRecord( EmfPlusFillPolygon
, 0xC000 ); // Sets the color as well
279 ImplWritePlusColor( maVDev
->GetFillColor(), nTrans
);
280 m_rStm
.WriteUInt32( rPoly
.GetSize() );
281 for( sal_uInt16 i
= 0; i
< rPoly
.GetSize(); i
++ )
282 ImplWritePlusPoint( rPoly
[ i
] );
285 ImplEndCommentRecord();
288 bool EMFWriter::WriteEMF(const GDIMetaFile
& rMtf
)
290 const sal_uLong nHeaderPos
= m_rStm
.Tell();
292 maVDev
->EnableOutput( false );
293 maVDev
->SetMapMode( rMtf
.GetPrefMapMode() );
294 // don't work with pixel as destination map mode -> higher resolution preferrable
295 maDestMapMode
.SetMapUnit( MAP_100TH_MM
);
296 mpHandlesUsed
= new bool[ MAXHANDLES
];
297 memset( mpHandlesUsed
, 0, MAXHANDLES
* sizeof( bool ) );
298 mnHandleCount
= mnRecordCount
= mnRecordPos
= mnRecordPlusPos
= 0;
299 mbRecordOpen
= mbRecordPlusOpen
= false;
300 mbLineChanged
= mbFillChanged
= mbTextChanged
= false;
301 mnLineHandle
= mnFillHandle
= mnTextHandle
= HANDLE_INVALID
;
304 const Size
aMtfSizePix( maVDev
->LogicToPixel( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode() ) );
305 const Size
aMtfSizeLog( OutputDevice::LogicToLogic( rMtf
.GetPrefSize(), rMtf
.GetPrefMapMode(), MAP_100TH_MM
) );
308 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
309 m_rStm
.SeekRel( 108 );
312 WriteEMFPlusHeader( aMtfSizePix
, aMtfSizeLog
);
314 // write initial values
316 // set 100th mm map mode in EMF
317 ImplBeginRecord( WIN_EMR_SETMAPMODE
);
318 m_rStm
.WriteInt32( MM_ANISOTROPIC
);
321 ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX
);
322 m_rStm
.WriteInt32( maVDev
->GetDPIX() ).WriteInt32( maVDev
->GetDPIY() );
325 ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX
);
326 m_rStm
.WriteInt32( 2540 ).WriteInt32( 2540 );
329 ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX
);
330 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
333 ImplBeginRecord( WIN_EMR_SETWINDOWORGEX
);
334 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
337 ImplWriteRasterOp( ROP_OVERPAINT
);
339 ImplBeginRecord( WIN_EMR_SETBKMODE
);
340 m_rStm
.WriteUInt32( 1 ); // TRANSPARENT
348 ImplBeginRecord( WIN_EMR_EOF
);
349 m_rStm
.WriteUInt32( 0 ) // nPalEntries
350 .WriteUInt32( 0x10 ) // offPalEntries
351 .WriteUInt32( 0x14 ); // nSizeLast
355 const sal_uLong nEndPos
= m_rStm
.Tell(); m_rStm
.Seek( nHeaderPos
);
357 m_rStm
.WriteUInt32( 0x00000001 ).WriteUInt32( 108 ) //use [MS-EMF 2.2.11] HeaderExtension2 Object
358 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizePix
.Width() - 1 ).WriteInt32( aMtfSizePix
.Height() - 1 )
359 .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aMtfSizeLog
.Width() - 1 ).WriteInt32( aMtfSizeLog
.Height() - 1 )
360 .WriteUInt32( 0x464d4520 ).WriteUInt32( 0x10000 ).WriteUInt32( nEndPos
- nHeaderPos
)
361 .WriteUInt32( mnRecordCount
).WriteUInt16( mnHandleCount
+ 1 ).WriteUInt16( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
362 .WriteInt32( aMtfSizePix
.Width() ).WriteInt32( aMtfSizePix
.Height() )
363 .WriteInt32( aMtfSizeLog
.Width() / 100 ).WriteInt32( aMtfSizeLog
.Height() / 100 )
364 .WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
365 .WriteInt32( aMtfSizeLog
.Width() * 10 ).WriteInt32( aMtfSizeLog
.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
367 m_rStm
.Seek( nEndPos
);
368 delete[] mpHandlesUsed
;
370 return( m_rStm
.GetError() == ERRCODE_NONE
);
373 sal_uLong
EMFWriter::ImplAcquireHandle()
375 sal_uLong nHandle
= HANDLE_INVALID
;
377 for( sal_uLong i
= 0; i
< MAXHANDLES
&& ( HANDLE_INVALID
== nHandle
); i
++ )
379 if( !mpHandlesUsed
[ i
] )
381 mpHandlesUsed
[ i
] = true;
383 if( ( nHandle
= i
) == mnHandleCount
)
388 DBG_ASSERT( nHandle
!= HANDLE_INVALID
, "No more handles available" );
389 return( nHandle
!= HANDLE_INVALID
? nHandle
+ 1 : HANDLE_INVALID
);
392 void EMFWriter::ImplReleaseHandle( sal_uLong nHandle
)
394 DBG_ASSERT( nHandle
&& ( nHandle
< MAXHANDLES
), "Handle out of range" );
395 mpHandlesUsed
[ nHandle
- 1 ] = false;
398 void EMFWriter::ImplBeginRecord( sal_uInt32 nType
)
400 DBG_ASSERT( !mbRecordOpen
, "Another record is already opened!" );
405 mnRecordPos
= m_rStm
.Tell();
407 m_rStm
.WriteUInt32( nType
);
412 void EMFWriter::ImplEndRecord()
414 DBG_ASSERT( mbRecordOpen
, "Record was not opened!" );
418 sal_Int32 nFillBytes
, nActPos
= m_rStm
.Tell();
419 m_rStm
.Seek( mnRecordPos
+ 4 );
420 nFillBytes
= nActPos
- mnRecordPos
;
421 nFillBytes
+= 3; // each record has to be dword aligned
424 m_rStm
.WriteUInt32( ( nActPos
- mnRecordPos
) + nFillBytes
);
425 m_rStm
.Seek( nActPos
);
426 while( nFillBytes
-- )
427 m_rStm
.WriteUChar( 0 );
429 mbRecordOpen
= false;
433 bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32
& rHandle
, sal_uLong nSelectType
)
435 if( rHandle
!= HANDLE_INVALID
)
437 sal_uInt32 nStockObject
= 0x80000000;
439 if( LINE_SELECT
== nSelectType
)
440 nStockObject
|= 0x00000007;
441 else if( FILL_SELECT
== nSelectType
)
442 nStockObject
|= 0x00000001;
443 else if( TEXT_SELECT
== nSelectType
)
444 nStockObject
|= 0x0000000a;
446 // select stock object first
447 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
448 m_rStm
.WriteUInt32( nStockObject
);
451 // destroy handle of created object
452 ImplBeginRecord( WIN_EMR_DELETEOBJECT
);
453 m_rStm
.WriteUInt32( rHandle
);
456 // mark handle as free
457 ImplReleaseHandle( rHandle
);
460 rHandle
= ImplAcquireHandle();
462 return( HANDLE_INVALID
!= rHandle
);
465 void EMFWriter::ImplCheckLineAttr()
467 if( mbLineChanged
&& ImplPrepareHandleSelect( mnLineHandle
, LINE_SELECT
) )
469 sal_uInt32 nStyle
= maVDev
->IsLineColor() ? 0 : 5;
470 sal_uInt32 nWidth
= 0, nHeight
= 0;
472 ImplBeginRecord( WIN_EMR_CREATEPEN
);
473 m_rStm
.WriteUInt32( mnLineHandle
).WriteUInt32( nStyle
).WriteUInt32( nWidth
).WriteUInt32( nHeight
);
474 ImplWriteColor( maVDev
->GetLineColor() );
477 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
478 m_rStm
.WriteUInt32( mnLineHandle
);
483 void EMFWriter::ImplCheckFillAttr()
485 if( mbFillChanged
&& ImplPrepareHandleSelect( mnFillHandle
, FILL_SELECT
) )
487 sal_uInt32 nStyle
= maVDev
->IsFillColor() ? 0 : 1;
488 sal_uInt32 nPatternStyle
= 0;
490 ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT
);
491 m_rStm
.WriteUInt32( mnFillHandle
).WriteUInt32( nStyle
);
492 ImplWriteColor( maVDev
->GetFillColor() );
493 m_rStm
.WriteUInt32( nPatternStyle
);
496 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
497 m_rStm
.WriteUInt32( mnFillHandle
);
502 void EMFWriter::ImplCheckTextAttr()
504 if( mbTextChanged
&& ImplPrepareHandleSelect( mnTextHandle
, TEXT_SELECT
) )
506 const vcl::Font
& rFont
= maVDev
->GetFont();
507 OUString
aFontName( rFont
.GetName() );
510 sal_uInt8 nPitchAndFamily
;
512 ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW
);
513 m_rStm
.WriteUInt32( mnTextHandle
);
514 ImplWriteExtent( -rFont
.GetSize().Height() );
515 ImplWriteExtent( rFont
.GetSize().Width() );
516 m_rStm
.WriteInt32( rFont
.GetOrientation() ).WriteInt32( rFont
.GetOrientation() );
518 switch( rFont
.GetWeight() )
520 case WEIGHT_THIN
: nWeight
= 100; break;
521 case WEIGHT_ULTRALIGHT
: nWeight
= 200; break;
522 case WEIGHT_LIGHT
: nWeight
= 300; break;
523 case WEIGHT_SEMILIGHT
: nWeight
= 300; break;
524 case WEIGHT_NORMAL
: nWeight
= 400; break;
525 case WEIGHT_MEDIUM
: nWeight
= 500; break;
526 case WEIGHT_SEMIBOLD
: nWeight
= 600; break;
527 case WEIGHT_BOLD
: nWeight
= 700; break;
528 case WEIGHT_ULTRABOLD
: nWeight
= 800; break;
529 case WEIGHT_BLACK
: nWeight
= 900; break;
530 default: nWeight
= 0; break;
533 m_rStm
.WriteInt32( nWeight
);
534 m_rStm
.WriteUChar( ( ITALIC_NONE
== rFont
.GetItalic() ) ? 0 : 1 );
535 m_rStm
.WriteUChar( ( UNDERLINE_NONE
== rFont
.GetUnderline() ) ? 0 : 1 );
536 m_rStm
.WriteUChar( ( STRIKEOUT_NONE
== rFont
.GetStrikeout() ) ? 0 : 1 );
537 m_rStm
.WriteUChar( ( RTL_TEXTENCODING_SYMBOL
== rFont
.GetCharSet() ) ? 2 : 0 );
538 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
540 switch( rFont
.GetPitch() )
542 case PITCH_FIXED
: nPitchAndFamily
= 0x01; break;
543 case PITCH_VARIABLE
: nPitchAndFamily
= 0x02; break;
544 default: nPitchAndFamily
= 0x00; break;
547 switch( rFont
.GetFamily() )
549 case FAMILY_DECORATIVE
: nPitchAndFamily
|= 0x50; break;
550 case FAMILY_MODERN
: nPitchAndFamily
|= 0x30; break;
551 case FAMILY_ROMAN
: nPitchAndFamily
|= 0x10; break;
552 case FAMILY_SCRIPT
: nPitchAndFamily
|= 0x40; break;
553 case FAMILY_SWISS
: nPitchAndFamily
|= 0x20; break;
557 m_rStm
.WriteUChar( nPitchAndFamily
);
559 for( i
= 0; i
< 32; i
++ )
560 m_rStm
.WriteUInt16( ( i
< aFontName
.getLength() ) ? aFontName
[ i
] : 0 );
563 for( i
= 0; i
< 64; i
++ )
564 m_rStm
.WriteUInt16( 0 );
567 for( i
= 0; i
< 32; i
++ )
568 m_rStm
.WriteUInt16( 0 );
570 // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
571 m_rStm
.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ) ;
574 m_rStm
.WriteUInt32( 0 );
577 m_rStm
.WriteUInt32( 0 );
580 m_rStm
.WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
582 // fill record to get a record size divideable by 4
583 m_rStm
.WriteUInt16( 0 );
588 sal_uInt32 nTextAlign
;
590 switch( rFont
.GetAlign() )
592 case ALIGN_TOP
: nTextAlign
= TA_TOP
; break;
593 case ALIGN_BOTTOM
: nTextAlign
= TA_BOTTOM
; break;
594 default: nTextAlign
= TA_BASELINE
; break;
596 nTextAlign
|= mnHorTextAlign
;
598 ImplBeginRecord( WIN_EMR_SETTEXTALIGN
);
599 m_rStm
.WriteUInt32( nTextAlign
);
603 ImplBeginRecord( WIN_EMR_SETTEXTCOLOR
);
604 ImplWriteColor( maVDev
->GetTextColor() );
607 ImplBeginRecord( WIN_EMR_SELECTOBJECT
);
608 m_rStm
.WriteUInt32( mnTextHandle
);
613 void EMFWriter::ImplWriteColor( const Color
& rColor
)
615 sal_uInt32 nCol
= rColor
.GetRed();
617 nCol
|= ( (sal_uInt32
) rColor
.GetGreen() ) << 8;
618 nCol
|= ( (sal_uInt32
) rColor
.GetBlue() ) << 16;
620 m_rStm
.WriteUInt32( nCol
);
623 void EMFWriter::ImplWriteRasterOp( RasterOp eRop
)
629 case ROP_INVERT
: nROP2
= 6; break;
630 case ROP_XOR
: nROP2
= 7; break;
631 default: nROP2
= 13;break;
634 ImplBeginRecord( WIN_EMR_SETROP2
);
635 m_rStm
.WriteUInt32( nROP2
);
639 void EMFWriter::ImplWriteExtent( long nExtent
)
641 nExtent
= OutputDevice::LogicToLogic( Size( nExtent
, 0 ), maVDev
->GetMapMode(), maDestMapMode
).Width();
642 m_rStm
.WriteInt32( nExtent
);
645 void EMFWriter::ImplWritePoint( const Point
& rPoint
)
647 const Point
aPoint( OutputDevice::LogicToLogic( rPoint
, maVDev
->GetMapMode(), maDestMapMode
));
648 m_rStm
.WriteInt32( aPoint
.X() ).WriteInt32( aPoint
.Y() );
651 void EMFWriter::ImplWriteSize( const Size
& rSize
)
653 const Size
aSize( OutputDevice::LogicToLogic( rSize
, maVDev
->GetMapMode(), maDestMapMode
));
654 m_rStm
.WriteInt32( aSize
.Width() ).WriteInt32( aSize
.Height() );
657 void EMFWriter::ImplWriteRect( const Rectangle
& rRect
)
659 const Rectangle
aRect( OutputDevice::LogicToLogic ( rRect
, maVDev
->GetMapMode(), maDestMapMode
));
661 .WriteInt32( aRect
.Left() )
662 .WriteInt32( aRect
.Top() )
663 .WriteInt32( aRect
.Right() )
664 .WriteInt32( aRect
.Bottom() );
667 void EMFWriter::ImplWritePolygonRecord( const Polygon
& rPoly
, bool bClose
)
669 if( rPoly
.GetSize() )
671 if( rPoly
.HasFlags() )
672 ImplWritePath( rPoly
, bClose
);
680 ImplBeginRecord( bClose
? WIN_EMR_POLYGON
: WIN_EMR_POLYLINE
);
681 ImplWriteRect( rPoly
.GetBoundRect() );
682 m_rStm
.WriteUInt32( rPoly
.GetSize() );
684 for( sal_uInt16 i
= 0; i
< rPoly
.GetSize(); i
++ )
685 ImplWritePoint( rPoly
[ i
] );
692 void EMFWriter::ImplWritePolyPolygonRecord( const tools::PolyPolygon
& rPolyPoly
)
694 sal_uInt16 n
, i
, nPolyCount
= rPolyPoly
.Count();
698 if( 1 == nPolyCount
)
699 ImplWritePolygonRecord( rPolyPoly
[ 0 ], true );
702 bool bHasFlags
= false;
703 sal_uInt32 nTotalPoints
= 0;
705 for( i
= 0; i
< nPolyCount
; i
++ )
707 nTotalPoints
+= rPolyPoly
[ i
].GetSize();
708 if ( rPolyPoly
[ i
].HasFlags() )
714 ImplWritePath( rPolyPoly
, true );
720 ImplBeginRecord( WIN_EMR_POLYPOLYGON
);
721 ImplWriteRect( rPolyPoly
.GetBoundRect() );
722 m_rStm
.WriteUInt32( nPolyCount
).WriteUInt32( nTotalPoints
);
724 for( i
= 0; i
< nPolyCount
; i
++ )
725 m_rStm
.WriteUInt32( rPolyPoly
[ i
].GetSize() );
727 for( i
= 0; i
< nPolyCount
; i
++ )
729 const Polygon
& rPoly
= rPolyPoly
[ i
];
731 for( n
= 0; n
< rPoly
.GetSize(); n
++ )
732 ImplWritePoint( rPoly
[ n
] );
741 void EMFWriter::ImplWritePath( const tools::PolyPolygon
& rPolyPoly
, bool bClosed
)
747 ImplBeginRecord( WIN_EMR_BEGINPATH
);
750 sal_uInt16 i
, n
, o
, nPolyCount
= rPolyPoly
.Count();
751 for ( i
= 0; i
< nPolyCount
; i
++ )
754 const Polygon
& rPoly
= rPolyPoly
[ i
];
755 while ( n
< rPoly
.GetSize() )
759 ImplBeginRecord( WIN_EMR_MOVETOEX
);
760 ImplWritePoint( rPoly
[ 0 ] );
766 sal_uInt16 nBezPoints
= 0;
768 while ( ( ( nBezPoints
+ n
+ 2 ) < rPoly
.GetSize() ) && ( rPoly
.GetFlags( nBezPoints
+ n
) == POLY_CONTROL
) )
773 ImplBeginRecord( WIN_EMR_POLYBEZIERTO
);
774 Polygon
aNewPoly( nBezPoints
+ 1 );
775 aNewPoly
[ 0 ] = rPoly
[ n
- 1 ];
776 for ( o
= 0; o
< nBezPoints
; o
++ )
777 aNewPoly
[ o
+ 1 ] = rPoly
[ n
+ o
];
778 ImplWriteRect( aNewPoly
.GetBoundRect() );
779 m_rStm
.WriteUInt32( nBezPoints
);
780 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
781 ImplWritePoint( aNewPoly
[ o
] );
787 sal_uInt16 nPoints
= 1;
788 while( ( nPoints
+ n
) < rPoly
.GetSize() && ( rPoly
.GetFlags( nPoints
+ n
) != POLY_CONTROL
) )
793 ImplBeginRecord( WIN_EMR_POLYLINETO
);
794 Polygon
aNewPoly( nPoints
+ 1 );
795 aNewPoly
[ 0 ] = rPoly
[ n
- 1];
796 for ( o
= 1; o
<= nPoints
; o
++ )
797 aNewPoly
[ o
] = rPoly
[ n
- 1 + o
];
798 ImplWriteRect( aNewPoly
.GetBoundRect() );
799 m_rStm
.WriteUInt32( nPoints
);
800 for( o
= 1; o
< aNewPoly
.GetSize(); o
++ )
801 ImplWritePoint( aNewPoly
[ o
] );
806 ImplBeginRecord( WIN_EMR_LINETO
);
807 ImplWritePoint( rPoly
[ n
] );
812 if ( bClosed
&& ( n
== rPoly
.GetSize() ) )
814 ImplBeginRecord( WIN_EMR_CLOSEFIGURE
);
819 ImplBeginRecord( WIN_EMR_ENDPATH
);
821 ImplBeginRecord( bClosed
? WIN_EMR_FILLPATH
: WIN_EMR_STROKEPATH
);
822 ImplWriteRect( rPolyPoly
.GetBoundRect() );
826 void EMFWriter::ImplWriteBmpRecord( const Bitmap
& rBmp
, const Point
& rPt
,
827 const Size
& rSz
, sal_uInt32 nROP
)
831 SvMemoryStream
aMemStm( 65535, 65535 );
832 const Size
aBmpSizePixel( rBmp
.GetSizePixel() );
834 ImplBeginRecord( WIN_EMR_STRETCHDIBITS
);
835 ImplWriteRect( Rectangle( rPt
, rSz
) );
836 ImplWritePoint( rPt
);
837 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( aBmpSizePixel
.Width() ).WriteInt32( aBmpSizePixel
.Height() );
839 // write offset positions and sizes later
840 const sal_uLong nOffPos
= m_rStm
.Tell();
841 m_rStm
.SeekRel( 16 );
843 m_rStm
.WriteUInt32( 0 ).WriteInt32( ( ROP_XOR
== maVDev
->GetRasterOp() && WIN_SRCCOPY
== nROP
) ? WIN_SRCINVERT
: nROP
);
844 ImplWriteSize( rSz
);
846 WriteDIB(rBmp
, aMemStm
, true, false);
848 sal_uInt32 nDIBSize
= aMemStm
.Tell(), nHeaderSize
, nCompression
, nColsUsed
, nPalCount
, nImageSize
;
849 sal_uInt16 nBitCount
;
851 // get DIB parameters
853 aMemStm
.ReadUInt32( nHeaderSize
);
854 aMemStm
.SeekRel( 10 );
855 aMemStm
.ReadUInt16( nBitCount
).ReadUInt32( nCompression
).ReadUInt32( nImageSize
);
856 aMemStm
.SeekRel( 8 );
857 aMemStm
.ReadUInt32( nColsUsed
);
862 nPalCount
= nColsUsed
;
864 nPalCount
= 1 << (sal_uInt32
)nBitCount
;
868 if (nCompression
== BITFIELDS
)
874 sal_uInt32 nPalSize
= nPalCount
* 4;
876 m_rStm
.Write( aMemStm
.GetData(), nDIBSize
);
878 const sal_uLong nEndPos
= m_rStm
.Tell();
879 m_rStm
.Seek( nOffPos
);
880 m_rStm
.WriteUInt32( 80 ).WriteUInt32( nHeaderSize
+ nPalSize
);
881 m_rStm
.WriteUInt32( 80 + nHeaderSize
+ nPalSize
).WriteUInt32( nImageSize
);
882 m_rStm
.Seek( nEndPos
);
888 void EMFWriter::ImplWriteTextRecord( const Point
& rPos
, const OUString
& rText
, const long* pDXArray
, sal_uInt32 nWidth
)
890 sal_Int32 nLen
= rText
.getLength(), i
;
894 sal_uInt32 nNormWidth
;
895 boost::scoped_array
<long> pOwnArray
;
901 nNormWidth
= maVDev
->GetTextWidth( rText
);
902 pDX
= const_cast<long*>(pDXArray
);
906 pOwnArray
.reset(new long[ nLen
]);
907 nNormWidth
= maVDev
->GetTextArray( rText
, pOwnArray
.get() );
908 pDX
= pOwnArray
.get();
913 nNormWidth
= pDX
[ nLen
- 2 ] + maVDev
->GetTextWidth( OUString(rText
[ nLen
- 1 ]) );
915 if( nWidth
&& nNormWidth
&& ( nWidth
!= nNormWidth
) )
917 const double fFactor
= (double) nWidth
/ nNormWidth
;
919 for( i
= 0; i
< ( nLen
- 1 ); i
++ )
920 pDX
[ i
] = FRound( pDX
[ i
] * fFactor
);
925 ImplBeginRecord( WIN_EMR_EXTTEXTOUTW
);
927 ImplWriteRect( Rectangle( rPos
, Size( nNormWidth
, maVDev
->GetTextHeight() ) ) );
928 m_rStm
.WriteUInt32( 1 );
929 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 );
930 ImplWritePoint( rPos
);
931 m_rStm
.WriteUInt32( nLen
).WriteUInt32( 76 ).WriteUInt32( 2 );
932 m_rStm
.WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 ).WriteInt32( 0 );
933 m_rStm
.WriteUInt32( 76 + ( nLen
<< 1 ) + ( (nLen
& 1 ) ? 2 : 0 ) );
936 for( i
= 0; i
< nLen
; i
++ )
937 m_rStm
.WriteUInt16( rText
[ i
] );
941 m_rStm
.WriteUInt16( 0 );
944 ImplWriteExtent( pDX
[ 0 ] );
948 for( i
= 1; i
< ( nLen
- 1 ); i
++ )
949 ImplWriteExtent( pDX
[ i
] - pDX
[ i
- 1 ] );
951 ImplWriteExtent( pDX
[ nLen
- 2 ] / ( nLen
- 1 ) );
958 void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo
& rInfo
, const basegfx::B2DPolygon
& rLinePolygon
)
960 if(rLinePolygon
.count())
962 basegfx::B2DPolyPolygon
aLinePolyPolygon(rLinePolygon
);
963 basegfx::B2DPolyPolygon aFillPolyPolygon
;
965 rInfo
.applyToB2DPolyPolygon(aLinePolyPolygon
, aFillPolyPolygon
);
967 if(aLinePolyPolygon
.count())
969 for(sal_uInt32
a(0); a
< aLinePolyPolygon
.count(); a
++)
971 const basegfx::B2DPolygon
aCandidate(aLinePolyPolygon
.getB2DPolygon(a
));
972 ImplWritePolygonRecord( Polygon(aCandidate
), false );
976 if(aFillPolyPolygon
.count())
978 const Color
aOldLineColor(maVDev
->GetLineColor());
979 const Color
aOldFillColor(maVDev
->GetFillColor());
981 maVDev
->SetLineColor();
982 maVDev
->SetFillColor(aOldLineColor
);
984 for(sal_uInt32
a(0); a
< aFillPolyPolygon
.count(); a
++)
986 const Polygon
aPolygon(aFillPolyPolygon
.getB2DPolygon(a
));
987 ImplWritePolyPolygonRecord(tools::PolyPolygon(Polygon(aPolygon
)));
990 maVDev
->SetLineColor(aOldLineColor
);
991 maVDev
->SetFillColor(aOldFillColor
);
996 void EMFWriter::ImplWrite( const GDIMetaFile
& rMtf
)
998 for( size_t j
= 0, nActionCount
= rMtf
.GetActionSize(); j
< nActionCount
; j
++ )
1000 const MetaAction
* pAction
= rMtf
.GetAction( j
);
1001 const MetaActionType nType
= pAction
->GetType();
1005 case( MetaActionType::PIXEL
):
1007 const MetaPixelAction
* pA
= static_cast<const MetaPixelAction
*>(pAction
);
1009 ImplCheckLineAttr();
1010 ImplBeginRecord( WIN_EMR_SETPIXELV
);
1011 ImplWritePoint( pA
->GetPoint() );
1012 ImplWriteColor( pA
->GetColor() );
1017 case( MetaActionType::POINT
):
1019 if( maVDev
->IsLineColor() )
1021 const MetaPointAction
* pA
= static_cast<const MetaPointAction
*>(pAction
);
1023 ImplCheckLineAttr();
1024 ImplBeginRecord( WIN_EMR_SETPIXELV
);
1025 ImplWritePoint( pA
->GetPoint() );
1026 ImplWriteColor( maVDev
->GetLineColor() );
1032 case( MetaActionType::LINE
):
1034 if( maVDev
->IsLineColor() )
1036 const MetaLineAction
* pA
= static_cast<const MetaLineAction
*>(pAction
);
1038 if(pA
->GetLineInfo().IsDefault())
1040 ImplCheckLineAttr();
1042 ImplBeginRecord( WIN_EMR_MOVETOEX
);
1043 ImplWritePoint( pA
->GetStartPoint() );
1046 ImplBeginRecord( WIN_EMR_LINETO
);
1047 ImplWritePoint( pA
->GetEndPoint() );
1050 ImplBeginRecord( WIN_EMR_SETPIXELV
);
1051 ImplWritePoint( pA
->GetEndPoint() );
1052 ImplWriteColor( maVDev
->GetLineColor() );
1057 // LineInfo used; handle Dash/Dot and fat lines
1058 basegfx::B2DPolygon aPolygon
;
1059 aPolygon
.append(basegfx::B2DPoint(pA
->GetStartPoint().X(), pA
->GetStartPoint().Y()));
1060 aPolygon
.append(basegfx::B2DPoint(pA
->GetEndPoint().X(), pA
->GetEndPoint().Y()));
1061 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), aPolygon
);
1067 case( MetaActionType::RECT
):
1069 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1071 const MetaRectAction
* pA
= static_cast<const MetaRectAction
*>(pAction
);
1073 ImplCheckFillAttr();
1074 ImplCheckLineAttr();
1076 ImplBeginRecord( WIN_EMR_RECTANGLE
);
1077 ImplWriteRect( pA
->GetRect() );
1083 case( MetaActionType::ROUNDRECT
):
1085 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1087 const MetaRoundRectAction
* pA
= static_cast<const MetaRoundRectAction
*>(pAction
);
1089 ImplCheckFillAttr();
1090 ImplCheckLineAttr();
1092 ImplBeginRecord( WIN_EMR_ROUNDRECT
);
1093 ImplWriteRect( pA
->GetRect() );
1094 ImplWriteSize( Size( pA
->GetHorzRound(), pA
->GetVertRound() ) );
1100 case( MetaActionType::ELLIPSE
):
1102 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1104 const MetaEllipseAction
* pA
= static_cast<const MetaEllipseAction
*>(pAction
);
1106 ImplCheckFillAttr();
1107 ImplCheckLineAttr();
1109 ImplBeginRecord( WIN_EMR_ELLIPSE
);
1110 ImplWriteRect( pA
->GetRect() );
1116 case( MetaActionType::ARC
):
1117 case( MetaActionType::PIE
):
1118 case( MetaActionType::CHORD
):
1119 case( MetaActionType::POLYGON
):
1121 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1127 case( MetaActionType::ARC
):
1129 const MetaArcAction
* pA
= static_cast<const MetaArcAction
*>(pAction
);
1130 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_ARC
);
1134 case( MetaActionType::PIE
):
1136 const MetaPieAction
* pA
= static_cast<const MetaPieAction
*>(pAction
);
1137 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_PIE
);
1141 case( MetaActionType::CHORD
):
1143 const MetaChordAction
* pA
= static_cast<const MetaChordAction
*>(pAction
);
1144 aPoly
= Polygon( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint(), POLY_CHORD
);
1148 case( MetaActionType::POLYGON
):
1149 aPoly
= static_cast<const MetaPolygonAction
*>(pAction
)->GetPolygon();
1154 ImplWritePolygonRecord( aPoly
, nType
!= MetaActionType::ARC
);
1159 case( MetaActionType::POLYLINE
):
1161 if( maVDev
->IsLineColor() )
1163 const MetaPolyLineAction
* pA
= static_cast<const MetaPolyLineAction
*>(pAction
);
1164 const Polygon
& rPoly
= pA
->GetPolygon();
1166 if( rPoly
.GetSize() )
1168 if(pA
->GetLineInfo().IsDefault())
1170 ImplWritePolygonRecord( rPoly
, false );
1174 // LineInfo used; handle Dash/Dot and fat lines
1175 Impl_handleLineInfoPolyPolygons(pA
->GetLineInfo(), rPoly
.getB2DPolygon());
1182 case( MetaActionType::POLYPOLYGON
):
1184 if( maVDev
->IsLineColor() || maVDev
->IsFillColor() )
1185 ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction
*>(pAction
)->GetPolyPolygon() );
1189 case( MetaActionType::GRADIENT
):
1191 const MetaGradientAction
* pA
= static_cast<const MetaGradientAction
*>(pAction
);
1192 GDIMetaFile aTmpMtf
;
1194 maVDev
->AddGradientActions( pA
->GetRect(), pA
->GetGradient(), aTmpMtf
);
1195 ImplWrite( aTmpMtf
);
1199 case MetaActionType::HATCH
:
1201 const MetaHatchAction
* pA
= static_cast<const MetaHatchAction
*>(pAction
);
1202 GDIMetaFile aTmpMtf
;
1204 maVDev
->AddHatchActions( pA
->GetPolyPolygon(), pA
->GetHatch(), aTmpMtf
);
1205 ImplWrite( aTmpMtf
);
1209 case MetaActionType::Transparent
:
1211 const tools::PolyPolygon
& rPolyPoly
= static_cast<const MetaTransparentAction
*>(pAction
)->GetPolyPolygon();
1212 if( rPolyPoly
.Count() )
1213 ImplWritePlusFillPolygonRecord( rPolyPoly
[0], static_cast<const MetaTransparentAction
*>(pAction
)->GetTransparence() );
1214 ImplCheckFillAttr();
1215 ImplCheckLineAttr();
1216 ImplWritePolyPolygonRecord( rPolyPoly
);
1218 ImplBeginCommentRecord( WIN_EMR_COMMENT_EMFPLUS
);
1219 ImplPlusRecord( EmfPlusGetDC
, 0x00 );
1220 ImplEndCommentRecord();
1224 case MetaActionType::FLOATTRANSPARENT
:
1226 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pAction
);
1228 GDIMetaFile
aTmpMtf( pA
->GetGDIMetaFile() );
1229 Point
aSrcPt( aTmpMtf
.GetPrefMapMode().GetOrigin() );
1230 const Size
aSrcSize( aTmpMtf
.GetPrefSize() );
1231 const Point
aDestPt( pA
->GetPoint() );
1232 const Size
aDestSize( pA
->GetSize() );
1233 const double fScaleX
= aSrcSize
.Width() ? (double) aDestSize
.Width() / aSrcSize
.Width() : 1.0;
1234 const double fScaleY
= aSrcSize
.Height() ? (double) aDestSize
.Height() / aSrcSize
.Height() : 1.0;
1235 long nMoveX
, nMoveY
;
1237 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
1239 aTmpMtf
.Scale( fScaleX
, fScaleY
);
1240 aSrcPt
.X() = FRound( aSrcPt
.X() * fScaleX
), aSrcPt
.Y() = FRound( aSrcPt
.Y() * fScaleY
);
1243 nMoveX
= aDestPt
.X() - aSrcPt
.X(), nMoveY
= aDestPt
.Y() - aSrcPt
.Y();
1245 if( nMoveX
|| nMoveY
)
1246 aTmpMtf
.Move( nMoveX
, nMoveY
);
1248 ImplCheckFillAttr();
1249 ImplCheckLineAttr();
1250 ImplCheckTextAttr();
1251 ImplWrite( aTmpMtf
);
1255 case( MetaActionType::EPS
):
1257 const MetaEPSAction
* pA
= static_cast<const MetaEPSAction
*>(pAction
);
1258 const GDIMetaFile
aSubstitute( pA
->GetSubstitute() );
1260 for( size_t i
= 0, nCount
= aSubstitute
.GetActionSize(); i
< nCount
; i
++ )
1262 const MetaAction
* pSubstAct
= aSubstitute
.GetAction( i
);
1263 if( pSubstAct
->GetType() == MetaActionType::BMPSCALE
)
1265 maVDev
->Push( PushFlags::ALL
);
1266 ImplBeginRecord( WIN_EMR_SAVEDC
);
1269 MapMode
aMapMode( aSubstitute
.GetPrefMapMode() );
1270 Size
aOutSize( OutputDevice::LogicToLogic( pA
->GetSize(), maVDev
->GetMapMode(), aMapMode
) );
1271 aMapMode
.SetScaleX( Fraction( aOutSize
.Width(), aSubstitute
.GetPrefSize().Width() ) );
1272 aMapMode
.SetScaleY( Fraction( aOutSize
.Height(), aSubstitute
.GetPrefSize().Height() ) );
1273 aMapMode
.SetOrigin( OutputDevice::LogicToLogic( pA
->GetPoint(), maVDev
->GetMapMode(), aMapMode
) );
1274 maVDev
->SetMapMode( aMapMode
);
1275 ImplWrite( aSubstitute
);
1278 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1279 m_rStm
.WriteInt32( -1 );
1287 case MetaActionType::BMP
:
1289 const MetaBmpAction
* pA
= static_cast<const MetaBmpAction
*>(pAction
);
1290 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), maVDev
->PixelToLogic( pA
->GetBitmap().GetSizePixel() ), WIN_SRCCOPY
);
1294 case MetaActionType::BMPSCALE
:
1296 const MetaBmpScaleAction
* pA
= static_cast<const MetaBmpScaleAction
*>(pAction
);
1297 ImplWriteBmpRecord( pA
->GetBitmap(), pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1301 case MetaActionType::BMPSCALEPART
:
1303 const MetaBmpScalePartAction
* pA
= static_cast<const MetaBmpScalePartAction
*>(pAction
);
1304 Bitmap
aTmp( pA
->GetBitmap() );
1306 if( aTmp
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) ) )
1307 ImplWriteBmpRecord( aTmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1311 case MetaActionType::BMPEX
:
1313 const MetaBmpExAction
* pA
= static_cast<const MetaBmpExAction
*>(pAction
);
1314 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1315 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1319 aBmp
.Replace( aMsk
, COL_WHITE
);
1321 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), maVDev
->PixelToLogic( aMsk
.GetSizePixel() ), WIN_SRCPAINT
);
1322 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), maVDev
->PixelToLogic( aBmp
.GetSizePixel() ), WIN_SRCAND
);
1325 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), aBmp
.GetSizePixel(), WIN_SRCCOPY
);
1329 case MetaActionType::BMPEXSCALE
:
1331 const MetaBmpExScaleAction
* pA
= static_cast<const MetaBmpExScaleAction
*>(pAction
);
1332 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1333 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1337 aBmp
.Replace( aMsk
, COL_WHITE
);
1339 ImplWriteBmpRecord( aMsk
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCPAINT
);
1340 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCAND
);
1343 ImplWriteBmpRecord( aBmp
, pA
->GetPoint(), pA
->GetSize(), WIN_SRCCOPY
);
1347 case MetaActionType::BMPEXSCALEPART
:
1349 const MetaBmpExScalePartAction
* pA
= static_cast<const MetaBmpExScalePartAction
*>(pAction
);
1350 BitmapEx
aBmpEx( pA
->GetBitmapEx() );
1351 aBmpEx
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) );
1352 Bitmap
aBmp( aBmpEx
.GetBitmap() );
1353 Bitmap
aMsk( aBmpEx
.GetMask() );
1357 aBmp
.Replace( aMsk
, COL_WHITE
);
1359 ImplWriteBmpRecord( aMsk
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCPAINT
);
1360 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCAND
);
1363 ImplWriteBmpRecord( aBmp
, pA
->GetDestPoint(), pA
->GetDestSize(), WIN_SRCCOPY
);
1367 case MetaActionType::TEXT
:
1369 const MetaTextAction
* pA
= static_cast<const MetaTextAction
*>(pAction
);
1370 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1372 ImplCheckTextAttr();
1373 ImplWriteTextRecord( pA
->GetPoint(), aText
, NULL
, 0 );
1377 case MetaActionType::TEXTRECT
:
1379 const MetaTextRectAction
* pA
= static_cast<const MetaTextRectAction
*>(pAction
);
1380 const OUString
aText( pA
->GetText() );
1382 ImplCheckTextAttr();
1383 ImplWriteTextRecord( pA
->GetRect().TopLeft(), aText
, NULL
, 0 );
1387 case MetaActionType::TEXTARRAY
:
1389 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pAction
);
1390 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1392 ImplCheckTextAttr();
1393 ImplWriteTextRecord( pA
->GetPoint(), aText
, pA
->GetDXArray(), 0 );
1397 case MetaActionType::STRETCHTEXT
:
1399 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pAction
);
1400 const OUString aText
= pA
->GetText().copy( pA
->GetIndex(), std::min(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1402 ImplCheckTextAttr();
1403 ImplWriteTextRecord( pA
->GetPoint(), aText
, NULL
, pA
->GetWidth() );
1407 case( MetaActionType::LINECOLOR
):
1409 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1410 mbLineChanged
= true;
1414 case( MetaActionType::FILLCOLOR
):
1416 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1417 mbFillChanged
= true;
1421 case( MetaActionType::TEXTCOLOR
):
1422 case( MetaActionType::TEXTLINECOLOR
):
1423 case( MetaActionType::TEXTFILLCOLOR
):
1424 case( MetaActionType::TEXTALIGN
):
1425 case( MetaActionType::FONT
):
1427 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1428 mbTextChanged
= true;
1432 case( MetaActionType::ISECTRECTCLIPREGION
):
1434 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1436 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT
);
1437 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction
*>(pAction
)->GetRect() );
1442 case( MetaActionType::CLIPREGION
):
1443 case( MetaActionType::ISECTREGIONCLIPREGION
):
1444 case( MetaActionType::MOVECLIPREGION
):
1446 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1450 case( MetaActionType::REFPOINT
):
1451 case( MetaActionType::MAPMODE
):
1452 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1455 case( MetaActionType::PUSH
):
1457 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1459 ImplBeginRecord( WIN_EMR_SAVEDC
);
1464 case( MetaActionType::POP
):
1466 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1468 ImplBeginRecord( WIN_EMR_RESTOREDC
);
1469 m_rStm
.WriteInt32( -1 );
1472 ImplWriteRasterOp( maVDev
->GetRasterOp() );
1473 mbLineChanged
= mbFillChanged
= mbTextChanged
= true;
1477 case( MetaActionType::RASTEROP
):
1479 const_cast<MetaAction
*>(pAction
)->Execute( maVDev
);
1480 ImplWriteRasterOp( static_cast<const MetaRasterOpAction
*>(pAction
)->GetRasterOp() );
1484 case( MetaActionType::LAYOUTMODE
):
1486 ComplexTextLayoutMode nLayoutMode
= static_cast<const MetaLayoutModeAction
*>(pAction
)->GetLayoutMode();
1488 if ((nLayoutMode
& TEXT_LAYOUT_BIDI_RTL
) != TEXT_LAYOUT_DEFAULT
)
1490 mnHorTextAlign
= TA_RIGHT
| TA_RTLREADING
;
1492 if ((nLayoutMode
& TEXT_LAYOUT_TEXTORIGIN_RIGHT
) != TEXT_LAYOUT_DEFAULT
)
1493 mnHorTextAlign
|= TA_RIGHT
;
1494 else if ((nLayoutMode
& TEXT_LAYOUT_TEXTORIGIN_LEFT
) != TEXT_LAYOUT_DEFAULT
)
1495 mnHorTextAlign
&= ~TA_RIGHT
;
1499 case( MetaActionType::COMMENT
):
1501 MetaCommentAction
const*const pCommentAction(
1502 static_cast<MetaCommentAction
const*>(pAction
));
1503 if (pCommentAction
->GetComment() == "EMF_PLUS")
1505 ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS
);
1506 m_rStm
.Write(pCommentAction
->GetData(),
1507 pCommentAction
->GetDataSize());
1508 ImplEndCommentRecord();
1513 case( MetaActionType::MASK
):
1514 case( MetaActionType::MASKSCALE
):
1515 case( MetaActionType::MASKSCALEPART
):
1516 case( MetaActionType::WALLPAPER
):
1517 case( MetaActionType::TEXTLINE
):
1518 case( MetaActionType::GRADIENTEX
):
1520 // !!! >>> we don't want to support these actions
1525 OSL_FAIL(OStringBuffer(
1526 "EMFWriter::ImplWriteActions: unsupported MetaAction #" ).
1527 append(static_cast<sal_Int32
>(nType
)).getStr());
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */