Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / filter / wmf / emfwr.cxx
blob86ad5de1f19a57cee8e1d9e05006c60d4664ea6f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include <algorithm>
24 #include "emfwr.hxx"
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 */
87 #define TA_RIGHT 2
89 #define TA_TOP 0
90 #define TA_BOTTOM 8
91 #define TA_BASELINE 24
92 #define TA_RTLREADING 256
94 #define MM_ANISOTROPIC 8
96 typedef enum
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
156 } EmfPlusRecordType;
158 void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType )
160 ImplBeginRecord( WIN_EMR_GDICOMMENT );
161 m_rStm.SeekRel( 4 );
162 m_rStm.WriteInt32( nCommentType );
165 void EMFWriter::ImplEndCommentRecord()
167 if( mbRecordOpen )
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 );
174 ImplEndRecord();
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 );
187 m_rStm.SeekRel( 8 );
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 );
210 ImplEndPlusRecord();
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;
219 if (nDivX)
220 nDPIX /= nDivX; // DPI X
222 sal_Int32 nDPIY = rMtfSizePix.Height()*25;
223 sal_Int32 nDivY = rMtfSizeLog.Height()/100;
224 if (nDivY)
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
233 .WriteInt32( nDPIX )
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 )
268 // Convert to pixels
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 ] );
283 ImplEndPlusRecord();
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;
302 mnHorTextAlign = 0;
304 const Size aMtfSizePix( maVDev->LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
305 const Size aMtfSizeLog( OutputDevice::LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
307 // seek over header
308 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
309 m_rStm.SeekRel( 108 );
311 // Write EMF+ Header
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 );
319 ImplEndRecord();
321 ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX );
322 m_rStm.WriteInt32( maVDev->GetDPIX() ).WriteInt32( maVDev->GetDPIY() );
323 ImplEndRecord();
325 ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX );
326 m_rStm.WriteInt32( 2540 ).WriteInt32( 2540 );
327 ImplEndRecord();
329 ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX );
330 m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
331 ImplEndRecord();
333 ImplBeginRecord( WIN_EMR_SETWINDOWORGEX );
334 m_rStm.WriteInt32( 0 ).WriteInt32( 0 );
335 ImplEndRecord();
337 ImplWriteRasterOp( ROP_OVERPAINT );
339 ImplBeginRecord( WIN_EMR_SETBKMODE );
340 m_rStm.WriteUInt32( 1 ); // TRANSPARENT
341 ImplEndRecord();
343 // write emf data
344 ImplWrite( rMtf );
346 ImplWritePlusEOF();
348 ImplBeginRecord( WIN_EMR_EOF );
349 m_rStm.WriteUInt32( 0 ) // nPalEntries
350 .WriteUInt32( 0x10 ) // offPalEntries
351 .WriteUInt32( 0x14 ); // nSizeLast
352 ImplEndRecord();
354 // write header
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 )
384 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!" );
402 if( !mbRecordOpen )
404 mbRecordOpen = true;
405 mnRecordPos = m_rStm.Tell();
407 m_rStm.WriteUInt32( nType );
408 m_rStm.SeekRel( 4 );
412 void EMFWriter::ImplEndRecord()
414 DBG_ASSERT( mbRecordOpen, "Record was not opened!" );
416 if( mbRecordOpen )
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
422 nFillBytes ^= 3;
423 nFillBytes &= 3;
424 m_rStm.WriteUInt32( ( nActPos - mnRecordPos ) + nFillBytes );
425 m_rStm.Seek( nActPos );
426 while( nFillBytes-- )
427 m_rStm.WriteUChar( 0 );
428 mnRecordCount++;
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 );
449 ImplEndRecord();
451 // destroy handle of created object
452 ImplBeginRecord( WIN_EMR_DELETEOBJECT );
453 m_rStm.WriteUInt32( rHandle );
454 ImplEndRecord();
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() );
475 ImplEndRecord();
477 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
478 m_rStm.WriteUInt32( mnLineHandle );
479 ImplEndRecord();
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 );
494 ImplEndRecord();
496 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
497 m_rStm.WriteUInt32( mnFillHandle );
498 ImplEndRecord();
502 void EMFWriter::ImplCheckTextAttr()
504 if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) )
506 const vcl::Font& rFont = maVDev->GetFont();
507 OUString aFontName( rFont.GetName() );
508 sal_Int32 nWeight;
509 sal_uInt16 i;
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;
554 default: break;
557 m_rStm.WriteUChar( nPitchAndFamily );
559 for( i = 0; i < 32; i++ )
560 m_rStm.WriteUInt16( ( i < aFontName.getLength() ) ? aFontName[ i ] : 0 );
562 // dummy elfFullName
563 for( i = 0; i < 64; i++ )
564 m_rStm.WriteUInt16( 0 );
566 // dummy elfStyle
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 ) ;
573 // dummy elfVendorId
574 m_rStm.WriteUInt32( 0 );
576 // dummy elfCulture
577 m_rStm.WriteUInt32( 0 );
579 // dummy elfPanose
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 );
585 ImplEndRecord();
587 // TextAlign
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 );
600 ImplEndRecord();
602 // Text color
603 ImplBeginRecord( WIN_EMR_SETTEXTCOLOR );
604 ImplWriteColor( maVDev->GetTextColor() );
605 ImplEndRecord();
607 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
608 m_rStm.WriteUInt32( mnTextHandle );
609 ImplEndRecord();
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 )
625 sal_uInt32 nROP2;
627 switch( 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 );
636 ImplEndRecord();
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 ));
660 m_rStm
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 );
673 else
675 if( bClose )
676 ImplCheckFillAttr();
678 ImplCheckLineAttr();
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 ] );
687 ImplEndRecord();
692 void EMFWriter::ImplWritePolyPolygonRecord( const tools::PolyPolygon& rPolyPoly )
694 sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
696 if( nPolyCount )
698 if( 1 == nPolyCount )
699 ImplWritePolygonRecord( rPolyPoly[ 0 ], true );
700 else
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() )
709 bHasFlags = true;
711 if( nTotalPoints )
713 if ( bHasFlags )
714 ImplWritePath( rPolyPoly, true );
715 else
717 ImplCheckFillAttr();
718 ImplCheckLineAttr();
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 ] );
734 ImplEndRecord();
741 void EMFWriter::ImplWritePath( const tools::PolyPolygon& rPolyPoly, bool bClosed )
743 if ( bClosed )
744 ImplCheckFillAttr();
745 ImplCheckLineAttr();
747 ImplBeginRecord( WIN_EMR_BEGINPATH );
748 ImplEndRecord();
750 sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
751 for ( i = 0; i < nPolyCount; i++ )
753 n = 0;
754 const Polygon& rPoly = rPolyPoly[ i ];
755 while ( n < rPoly.GetSize() )
757 if( n == 0 )
759 ImplBeginRecord( WIN_EMR_MOVETOEX );
760 ImplWritePoint( rPoly[ 0 ] );
761 ImplEndRecord();
762 n++;
763 continue;
766 sal_uInt16 nBezPoints = 0;
768 while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) )
769 nBezPoints += 3;
771 if ( nBezPoints )
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 ] );
782 ImplEndRecord();
783 n = n + nBezPoints;
785 else
787 sal_uInt16 nPoints = 1;
788 while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) )
789 nPoints++;
791 if ( nPoints > 1 )
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 ] );
802 ImplEndRecord();
804 else
806 ImplBeginRecord( WIN_EMR_LINETO );
807 ImplWritePoint( rPoly[ n ] );
808 ImplEndRecord();
810 n = n + nPoints;
812 if ( bClosed && ( n == rPoly.GetSize() ) )
814 ImplBeginRecord( WIN_EMR_CLOSEFIGURE );
815 ImplEndRecord();
819 ImplBeginRecord( WIN_EMR_ENDPATH );
820 ImplEndRecord();
821 ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH );
822 ImplWriteRect( rPolyPoly.GetBoundRect() );
823 ImplEndRecord();
826 void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
827 const Size& rSz, sal_uInt32 nROP )
829 if( !!rBmp )
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
852 aMemStm.Seek( 0 );
853 aMemStm.ReadUInt32( nHeaderSize );
854 aMemStm.SeekRel( 10 );
855 aMemStm.ReadUInt16( nBitCount ).ReadUInt32( nCompression ).ReadUInt32( nImageSize );
856 aMemStm.SeekRel( 8 );
857 aMemStm.ReadUInt32( nColsUsed );
859 if (nBitCount <= 8)
861 if (nColsUsed)
862 nPalCount = nColsUsed;
863 else
864 nPalCount = 1 << (sal_uInt32)nBitCount;
866 else
868 if (nCompression == BITFIELDS)
869 nPalCount = 3;
870 else
871 nPalCount = 0;
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 );
884 ImplEndRecord();
888 void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, const long* pDXArray, sal_uInt32 nWidth )
890 sal_Int32 nLen = rText.getLength(), i;
892 if( nLen )
894 sal_uInt32 nNormWidth;
895 boost::scoped_array<long> pOwnArray;
896 long* pDX;
898 // get text sizes
899 if( pDXArray )
901 nNormWidth = maVDev->GetTextWidth( rText );
902 pDX = const_cast<long*>(pDXArray);
904 else
906 pOwnArray.reset(new long[ nLen ]);
907 nNormWidth = maVDev->GetTextArray( rText, pOwnArray.get() );
908 pDX = pOwnArray.get();
911 if( nLen > 1 )
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 );
924 // write text record
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 ) );
935 // write text
936 for( i = 0; i < nLen; i++ )
937 m_rStm.WriteUInt16( rText[ i ] );
939 // padding word
940 if( nLen & 1 )
941 m_rStm.WriteUInt16( 0 );
943 // write DX array
944 ImplWriteExtent( pDX[ 0 ] );
946 if( nLen > 1 )
948 for( i = 1; i < ( nLen - 1 ); i++ )
949 ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
951 ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
954 ImplEndRecord();
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();
1003 switch( nType )
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() );
1013 ImplEndRecord();
1015 break;
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() );
1027 ImplEndRecord();
1030 break;
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() );
1044 ImplEndRecord();
1046 ImplBeginRecord( WIN_EMR_LINETO );
1047 ImplWritePoint( pA->GetEndPoint() );
1048 ImplEndRecord();
1050 ImplBeginRecord( WIN_EMR_SETPIXELV );
1051 ImplWritePoint( pA->GetEndPoint() );
1052 ImplWriteColor( maVDev->GetLineColor() );
1053 ImplEndRecord();
1055 else
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);
1065 break;
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() );
1078 ImplEndRecord();
1081 break;
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() ) );
1095 ImplEndRecord();
1098 break;
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() );
1111 ImplEndRecord();
1114 break;
1116 case( MetaActionType::ARC ):
1117 case( MetaActionType::PIE ):
1118 case( MetaActionType::CHORD ):
1119 case( MetaActionType::POLYGON ):
1121 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1123 Polygon aPoly;
1125 switch( nType )
1127 case( MetaActionType::ARC ):
1129 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
1130 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
1132 break;
1134 case( MetaActionType::PIE ):
1136 const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
1137 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
1139 break;
1141 case( MetaActionType::CHORD ):
1143 const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
1144 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
1146 break;
1148 case( MetaActionType::POLYGON ):
1149 aPoly = static_cast<const MetaPolygonAction*>(pAction)->GetPolygon();
1150 break;
1151 default: break;
1154 ImplWritePolygonRecord( aPoly, nType != MetaActionType::ARC );
1157 break;
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 );
1172 else
1174 // LineInfo used; handle Dash/Dot and fat lines
1175 Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1180 break;
1182 case( MetaActionType::POLYPOLYGON ):
1184 if( maVDev->IsLineColor() || maVDev->IsFillColor() )
1185 ImplWritePolyPolygonRecord( static_cast<const MetaPolyPolygonAction*>(pAction)->GetPolyPolygon() );
1187 break;
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 );
1197 break;
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 );
1207 break;
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();
1222 break;
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 );
1253 break;
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 );
1267 ImplEndRecord();
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 );
1277 maVDev->Pop();
1278 ImplBeginRecord( WIN_EMR_RESTOREDC );
1279 m_rStm.WriteInt32( -1 );
1280 ImplEndRecord();
1281 break;
1285 break;
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 );
1292 break;
1294 case MetaActionType::BMPSCALE:
1296 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
1297 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1299 break;
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 );
1309 break;
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() );
1317 if( !!aMsk )
1319 aBmp.Replace( aMsk, COL_WHITE );
1320 aMsk.Invert();
1321 ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev->PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
1322 ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev->PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
1324 else
1325 ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
1327 break;
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() );
1335 if( !!aMsk )
1337 aBmp.Replace( aMsk, COL_WHITE );
1338 aMsk.Invert();
1339 ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
1340 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
1342 else
1343 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1345 break;
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() );
1355 if( !!aMsk )
1357 aBmp.Replace( aMsk, COL_WHITE );
1358 aMsk.Invert();
1359 ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT );
1360 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
1362 else
1363 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1365 break;
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 );
1375 break;
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 );
1385 break;
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 );
1395 break;
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() );
1405 break;
1407 case( MetaActionType::LINECOLOR ):
1409 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1410 mbLineChanged = true;
1412 break;
1414 case( MetaActionType::FILLCOLOR ):
1416 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1417 mbFillChanged = true;
1419 break;
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;
1430 break;
1432 case( MetaActionType::ISECTRECTCLIPREGION ):
1434 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1436 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT );
1437 ImplWriteRect( static_cast<const MetaISectRectClipRegionAction*>(pAction)->GetRect() );
1438 ImplEndRecord();
1440 break;
1442 case( MetaActionType::CLIPREGION ):
1443 case( MetaActionType::ISECTREGIONCLIPREGION ):
1444 case( MetaActionType::MOVECLIPREGION ):
1446 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1448 break;
1450 case( MetaActionType::REFPOINT ):
1451 case( MetaActionType::MAPMODE ):
1452 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1453 break;
1455 case( MetaActionType::PUSH ):
1457 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1459 ImplBeginRecord( WIN_EMR_SAVEDC );
1460 ImplEndRecord();
1462 break;
1464 case( MetaActionType::POP ):
1466 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1468 ImplBeginRecord( WIN_EMR_RESTOREDC );
1469 m_rStm.WriteInt32( -1 );
1470 ImplEndRecord();
1472 ImplWriteRasterOp( maVDev->GetRasterOp() );
1473 mbLineChanged = mbFillChanged = mbTextChanged = true;
1475 break;
1477 case( MetaActionType::RASTEROP ):
1479 const_cast<MetaAction*>(pAction)->Execute( maVDev );
1480 ImplWriteRasterOp( static_cast<const MetaRasterOpAction*>(pAction)->GetRasterOp() );
1482 break;
1484 case( MetaActionType::LAYOUTMODE ):
1486 ComplexTextLayoutMode nLayoutMode = static_cast<const MetaLayoutModeAction*>(pAction)->GetLayoutMode();
1487 mnHorTextAlign = 0;
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;
1496 break;
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();
1511 break;
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
1522 break;
1524 default:
1525 OSL_FAIL(OStringBuffer(
1526 "EMFWriter::ImplWriteActions: unsupported MetaAction #" ).
1527 append(static_cast<sal_Int32>(nType)).getStr());
1528 break;
1533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */