1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svtools.hxx"
24
25 #include "emfwr.hxx"
26 #include <vcl/salbtype.hxx>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolypolygon.hxx>
29 #include <vcl/lineinfo.hxx>
30 #include <vcl/dibtools.hxx>
31
32 // -----------
33 // - Defines -
34 // -----------
35
36 #define WIN_EMR_HEADER 1
37 #define WIN_EMR_POLYBEZIER 2
38 #define WIN_EMR_POLYGON 3
39 #define WIN_EMR_POLYLINE 4
40 #define WIN_EMR_POLYBEZIERTO 5
41 #define WIN_EMR_POLYLINETO 6
42 #define WIN_EMR_POLYPOLYLINE 7
43 #define WIN_EMR_POLYPOLYGON 8
44 #define WIN_EMR_SETWINDOWEXTEX 9
45 #define WIN_EMR_SETWINDOWORGEX 10
46 #define WIN_EMR_SETVIEWPORTEXTEX 11
47 #define WIN_EMR_SETVIEWPORTORGEX 12
48 #define WIN_EMR_SETBRUSHORGEX 13
49 #define WIN_EMR_EOF 14
50 #define WIN_EMR_SETPIXELV 15
51 #define WIN_EMR_SETMAPPERFLAGS 16
52 #define WIN_EMR_SETMAPMODE 17
53 #define WIN_EMR_SETBKMODE 18
54 #define WIN_EMR_SETPOLYFILLMODE 19
55 #define WIN_EMR_SETROP2 20
56 #define WIN_EMR_SETSTRETCHBLTMODE 21
57 #define WIN_EMR_SETTEXTALIGN 22
58 #define WIN_EMR_SETCOLORADJUSTMENT 23
59 #define WIN_EMR_SETTEXTCOLOR 24
60 #define WIN_EMR_SETBKCOLOR 25
61 #define WIN_EMR_OFFSETCLIPRGN 26
62 #define WIN_EMR_MOVETOEX 27
63 #define WIN_EMR_SETMETARGN 28
64 #define WIN_EMR_EXCLUDECLIPRECT 29
65 #define WIN_EMR_INTERSECTCLIPRECT 30
66 #define WIN_EMR_SCALEVIEWPORTEXTEX 31
67 #define WIN_EMR_SCALEWINDOWEXTEX 32
68 #define WIN_EMR_SAVEDC 33
69 #define WIN_EMR_RESTOREDC 34
70 #define WIN_EMR_SETWORLDTRANSFORM 35
71 #define WIN_EMR_MODIFYWORLDTRANSFORM 36
72 #define WIN_EMR_SELECTOBJECT 37
73 #define WIN_EMR_CREATEPEN 38
74 #define WIN_EMR_CREATEBRUSHINDIRECT 39
75 #define WIN_EMR_DELETEOBJECT 40
76 #define WIN_EMR_ANGLEARC 41
77 #define WIN_EMR_ELLIPSE 42
78 #define WIN_EMR_RECTANGLE 43
79 #define WIN_EMR_ROUNDRECT 44
80 #define WIN_EMR_ARC 45
81 #define WIN_EMR_CHORD 46
82 #define WIN_EMR_PIE 47
83 #define WIN_EMR_SELECTPALETTE 48
84 #define WIN_EMR_CREATEPALETTE 49
85 #define WIN_EMR_SETPALETTEENTRIES 50
86 #define WIN_EMR_RESIZEPALETTE 51
87 #define WIN_EMR_REALIZEPALETTE 52
88 #define WIN_EMR_EXTFLOODFILL 53
89 #define WIN_EMR_LINETO 54
90 #define WIN_EMR_ARCTO 55
91 #define WIN_EMR_POLYDRAW 56
92 #define WIN_EMR_SETARCDIRECTION 57
93 #define WIN_EMR_SETMITERLIMIT 58
94 #define WIN_EMR_BEGINPATH 59
95 #define WIN_EMR_ENDPATH 60
96 #define WIN_EMR_CLOSEFIGURE 61
97 #define WIN_EMR_FILLPATH 62
98 #define WIN_EMR_STROKEANDFILLPATH 63
99 #define WIN_EMR_STROKEPATH 64
100 #define WIN_EMR_FLATTENPATH 65
101 #define WIN_EMR_WIDENPATH 66
102 #define WIN_EMR_SELECTCLIPPATH 67
103 #define WIN_EMR_ABORTPATH 68
104
105 #define WIN_EMR_GDICOMMENT 70
106 #define WIN_EMR_FILLRGN 71
107 #define WIN_EMR_FRAMERGN 72
108 #define WIN_EMR_INVERTRGN 73
109 #define WIN_EMR_PAINTRGN 74
110 #define WIN_EMR_EXTSELECTCLIPRGN 75
111 #define WIN_EMR_BITBLT 76
112 #define WIN_EMR_STRETCHBLT 77
113 #define WIN_EMR_MASKBLT 78
114 #define WIN_EMR_PLGBLT 79
115 #define WIN_EMR_SETDIBITSTODEVICE 80
116 #define WIN_EMR_STRETCHDIBITS 81
117 #define WIN_EMR_EXTCREATEFONTINDIRECTW 82
118 #define WIN_EMR_EXTTEXTOUTA 83
119 #define WIN_EMR_EXTTEXTOUTW 84
120 #define WIN_EMR_POLYBEZIER16 85
121 #define WIN_EMR_POLYGON16 86
122 #define WIN_EMR_POLYLINE16 87
123 #define WIN_EMR_POLYBEZIERTO16 88
124 #define WIN_EMR_POLYLINETO16 89
125 #define WIN_EMR_POLYPOLYLINE16 90
126 #define WIN_EMR_POLYPOLYGON16 91
127 #define WIN_EMR_POLYDRAW16 92
128 #define WIN_EMR_CREATEMONOBRUSH 93
129 #define WIN_EMR_CREATEDIBPATTERNBRUSHPT 94
130 #define WIN_EMR_EXTCREATEPEN 95
131 #define WIN_EMR_POLYTEXTOUTA 96
132 #define WIN_EMR_POLYTEXTOUTW 97
133
134 #define WIN_SRCCOPY 0x00CC0020L
135 #define WIN_SRCPAINT 0x00EE0086L
136 #define WIN_SRCAND 0x008800C6L
137 #define WIN_SRCINVERT 0x00660046L
138
139 #define HANDLE_INVALID 0xffffffff
140 #define MAXHANDLES 65000
141
142 #define LINE_SELECT 0x00000001
143 #define FILL_SELECT 0x00000002
144 #define TEXT_SELECT 0x00000004
145
146 /* Text Alignment Options */
147 #define TA_NOUPDATECP 0
148 #define TA_UPDATECP 1
149
150 #define TA_LEFT 0
151 #define TA_RIGHT 2
152 #define TA_CENTER 6
153
154 #define TA_TOP 0
155 #define TA_BOTTOM 8
156 #define TA_BASELINE 24
157 #define TA_RTLREADING 256
158 #define TA_MASK (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING)
159
160 #define MM_ANISOTROPIC 8
161
162 // -------------
163 // - EMFWriter -
164 // -------------
165
WriteEMF(const GDIMetaFile & rMtf,SvStream & rOStm,FilterConfigItem * pFilterConfigItem)166 sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, SvStream& rOStm, FilterConfigItem* pFilterConfigItem )
167 {
168 const sal_uLong nHeaderPos = rOStm.Tell();
169
170 mpHandlesUsed = new sal_Bool[ MAXHANDLES ];
171 memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( sal_Bool ) );
172 mnHorTextAlign = mnHandleCount = mnLastPercent = mnRecordPos = mnRecordCount = 0;
173 mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID;
174 mbRecordOpen = sal_False;
175
176 mpStm = &rOStm;
177 maVDev.EnableOutput( sal_False );
178 maVDev.SetMapMode( rMtf.GetPrefMapMode() );
179 mpFilterConfigItem = pFilterConfigItem;
180
181 // don't work with pixel as destination map mode -> higher resolution preferrable
182 maDestMapMode.SetMapUnit( MAP_100TH_MM );
183
184 const Size aMtfSizePix( maVDev.LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
185 const Size aMtfSizeLog( maVDev.LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
186
187 // seek over header
188 // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
189 rOStm.SeekRel( 108 );
190
191 // write initial values
192
193 // set 100th mm map mode in EMF
194 ImplBeginRecord( WIN_EMR_SETMAPMODE );
195 (*mpStm) << (sal_Int32) MM_ANISOTROPIC;
196 ImplEndRecord();
197
198 ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX );
199 (*mpStm) << (sal_Int32) maVDev.ImplGetDPIX() << (sal_Int32) maVDev.ImplGetDPIY();
200 ImplEndRecord();
201
202 ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX );
203 (*mpStm) << (sal_Int32) 2540 << (sal_Int32) 2540;
204 ImplEndRecord();
205
206 ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX );
207 (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
208 ImplEndRecord();
209
210 ImplBeginRecord( WIN_EMR_SETWINDOWORGEX );
211 (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
212 ImplEndRecord();
213
214 ImplWriteRasterOp( ROP_OVERPAINT );
215
216 ImplBeginRecord( WIN_EMR_SETBKMODE );
217 (*mpStm) << (sal_uInt32) 1; // TRANSPARENT
218 ImplEndRecord();
219
220 // write emf data
221 ImplWrite( rMtf );
222
223 ImplBeginRecord( WIN_EMR_EOF );
224 (*mpStm)<< (sal_uInt32)0 // nPalEntries
225 << (sal_uInt32)0x10 // offPalEntries
226 << (sal_uInt32)0x14; // nSizeLast
227 ImplEndRecord();
228
229
230 // write header
231 const sal_uLong nEndPos = mpStm->Tell(); mpStm->Seek( nHeaderPos );
232
233 (*mpStm) << (sal_uInt32) 0x00000001 << (sal_uInt32) 108 //use [MS-EMF 2.2.11] HeaderExtension2 Object
234 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizePix.Width() - 1 ) << (sal_Int32) ( aMtfSizePix.Height() - 1 )
235 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizeLog.Width() - 1 ) << (sal_Int32) ( aMtfSizeLog.Height() - 1 )
236 << (sal_uInt32) 0x464d4520 << (sal_uInt32) 0x10000 << (sal_uInt32) ( nEndPos - nHeaderPos )
237 << (sal_uInt32) mnRecordCount << (sal_uInt16) ( mnHandleCount + 1 ) << (sal_uInt16) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0
238 << (sal_Int32) aMtfSizePix.Width() << (sal_Int32) aMtfSizePix.Height()
239 << (sal_Int32) ( aMtfSizeLog.Width() / 100 ) << (sal_Int32) ( aMtfSizeLog.Height() / 100 )
240 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0
241 << (sal_Int32) ( aMtfSizeLog.Width() * 10 ) << (sal_Int32) ( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
242
243 mpStm->Seek( nEndPos );
244 delete[] mpHandlesUsed;
245
246 return( mpStm->GetError() == ERRCODE_NONE );
247 }
248
249 // -----------------------------------------------------------------------------
250
ImplAcquireHandle()251 sal_uLong EMFWriter::ImplAcquireHandle()
252 {
253 sal_uLong nHandle = HANDLE_INVALID;
254
255 for( sal_uLong i = 0; i < MAXHANDLES && ( HANDLE_INVALID == nHandle ); i++ )
256 {
257 if( !mpHandlesUsed[ i ] )
258 {
259 mpHandlesUsed[ i ] = sal_True;
260
261 if( ( nHandle = i ) == mnHandleCount )
262 mnHandleCount++;
263 }
264 }
265
266 DBG_ASSERT( nHandle != HANDLE_INVALID, "No more handles available" );
267 return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID );
268 }
269
270 // -----------------------------------------------------------------------------
271
ImplReleaseHandle(sal_uLong nHandle)272 void EMFWriter::ImplReleaseHandle( sal_uLong nHandle )
273 {
274 DBG_ASSERT( nHandle && ( nHandle < MAXHANDLES ), "Handle out of range" );
275 mpHandlesUsed[ nHandle - 1 ] = sal_False;
276 }
277
278 // -----------------------------------------------------------------------------
279
ImplBeginRecord(sal_uInt32 nType)280 void EMFWriter::ImplBeginRecord( sal_uInt32 nType )
281 {
282 DBG_ASSERT( !mbRecordOpen, "Another record is already opened!" );
283
284 if( !mbRecordOpen )
285 {
286 mbRecordOpen = sal_True;
287 mnRecordPos = mpStm->Tell();
288
289 (*mpStm) << nType;
290 mpStm->SeekRel( 4 );
291 }
292 }
293
294 // -----------------------------------------------------------------------------
295
ImplEndRecord()296 void EMFWriter::ImplEndRecord()
297 {
298 DBG_ASSERT( mbRecordOpen, "Record was not opened!" );
299
300 if( mbRecordOpen )
301 {
302 sal_Int32 nFillBytes, nActPos = mpStm->Tell();
303 mpStm->Seek( mnRecordPos + 4 );
304 nFillBytes = nActPos - mnRecordPos;
305 nFillBytes += 3; // each record has to be dword aligned
306 nFillBytes ^= 3;
307 nFillBytes &= 3;
308 *mpStm << (sal_uInt32)( ( nActPos - mnRecordPos ) + nFillBytes );
309 mpStm->Seek( nActPos );
310 while( nFillBytes-- )
311 *mpStm << (sal_uInt8)0;
312 mnRecordCount++;
313 mbRecordOpen = sal_False;
314 }
315 }
316
317 // -----------------------------------------------------------------------------
318
ImplPrepareHandleSelect(sal_uInt32 & rHandle,sal_uLong nSelectType)319 sal_Bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType )
320 {
321 if( rHandle != HANDLE_INVALID )
322 {
323 sal_uInt32 nStockObject = 0x80000000;
324
325 if( LINE_SELECT == nSelectType )
326 nStockObject |= 0x00000007;
327 else if( FILL_SELECT == nSelectType )
328 nStockObject |= 0x00000001;
329 else if( TEXT_SELECT == nSelectType )
330 nStockObject |= 0x0000000a;
331
332 // select stock object first
333 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
334 ( *mpStm ) << nStockObject;
335 ImplEndRecord();
336
337 // destroy handle of created object
338 ImplBeginRecord( WIN_EMR_DELETEOBJECT );
339 ( *mpStm ) << rHandle;
340 ImplEndRecord();
341
342 // mark handle as free
343 ImplReleaseHandle( rHandle );
344 }
345
346 rHandle = ImplAcquireHandle();
347
348 return( HANDLE_INVALID != rHandle );
349 }
350
351 // -----------------------------------------------------------------------------
352
ImplCheckLineAttr()353 void EMFWriter::ImplCheckLineAttr()
354 {
355 if( mbLineChanged && ImplPrepareHandleSelect( mnLineHandle, LINE_SELECT ) )
356 {
357 sal_uInt32 nStyle = maVDev.IsLineColor() ? 0 : 5;
358 sal_uInt32 nWidth = 0, nHeight = 0;
359
360 ImplBeginRecord( WIN_EMR_CREATEPEN );
361 (*mpStm) << mnLineHandle << nStyle << nWidth << nHeight;
362 ImplWriteColor( maVDev.GetLineColor() );
363 ImplEndRecord();
364
365 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
366 (*mpStm) << mnLineHandle;
367 ImplEndRecord();
368 }
369 }
370
371 // -----------------------------------------------------------------------------
372
ImplCheckFillAttr()373 void EMFWriter::ImplCheckFillAttr()
374 {
375 if( mbFillChanged && ImplPrepareHandleSelect( mnFillHandle, FILL_SELECT ) )
376 {
377 sal_uInt32 nStyle = maVDev.IsFillColor() ? 0 : 1;
378 sal_uInt32 nPatternStyle = 0;
379
380 ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT );
381 (*mpStm) << mnFillHandle << nStyle;
382 ImplWriteColor( maVDev.GetFillColor() );
383 (*mpStm) << nPatternStyle;
384 ImplEndRecord();
385
386 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
387 (*mpStm) << mnFillHandle;
388 ImplEndRecord();
389 }
390 }
391
392 // -----------------------------------------------------------------------------
393
ImplCheckTextAttr()394 void EMFWriter::ImplCheckTextAttr()
395 {
396 if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) )
397 {
398 const Font& rFont = maVDev.GetFont();
399 String aFontName( rFont.GetName() );
400 sal_Int32 nWeight;
401 sal_uInt16 i;
402 sal_uInt8 nPitchAndFamily;
403
404 ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW );
405 (*mpStm) << mnTextHandle;
406 ImplWriteExtent( -rFont.GetSize().Height() );
407 ImplWriteExtent( rFont.GetSize().Width() );
408 (*mpStm) << (sal_Int32) rFont.GetOrientation() << (sal_Int32) rFont.GetOrientation();
409
410 switch( rFont.GetWeight() )
411 {
412 case WEIGHT_THIN: nWeight = 100; break;
413 case WEIGHT_ULTRALIGHT: nWeight = 200; break;
414 case WEIGHT_LIGHT: nWeight = 300; break;
415 case WEIGHT_SEMILIGHT: nWeight = 300; break;
416 case WEIGHT_NORMAL: nWeight = 400; break;
417 case WEIGHT_MEDIUM: nWeight = 500; break;
418 case WEIGHT_SEMIBOLD: nWeight = 600; break;
419 case WEIGHT_BOLD: nWeight = 700; break;
420 case WEIGHT_ULTRABOLD: nWeight = 800; break;
421 case WEIGHT_BLACK: nWeight = 900; break;
422 default: nWeight = 0; break;
423 }
424
425 (*mpStm) << nWeight;
426 (*mpStm) << (sal_uInt8) ( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
427 (*mpStm) << (sal_uInt8) ( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
428 (*mpStm) << (sal_uInt8) ( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
429 (*mpStm) << (sal_uInt8) ( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
430 (*mpStm) << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0;
431
432 switch( rFont.GetPitch() )
433 {
434 case PITCH_FIXED: nPitchAndFamily = 0x01; break;
435 case PITCH_VARIABLE: nPitchAndFamily = 0x02; break;
436 default: nPitchAndFamily = 0x00; break;
437 }
438
439 switch( rFont.GetFamily() )
440 {
441 case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break;
442 case FAMILY_MODERN: nPitchAndFamily |= 0x30; break;
443 case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break;
444 case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break;
445 case FAMILY_SWISS: nPitchAndFamily |= 0x20; break;
446 default: break;
447 }
448
449 (*mpStm) << nPitchAndFamily;
450
451 for( i = 0; i < 32; i++ )
452 (*mpStm) << (sal_Unicode) ( ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0 );
453
454 // dummy elfFullName
455 for( i = 0; i < 64; i++ )
456 (*mpStm) << (sal_Unicode) 0;
457
458 // dummy elfStyle
459 for( i = 0; i < 32; i++ )
460 (*mpStm) << (sal_Unicode) 0;
461
462 // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
463 (*mpStm) << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 ;
464
465 // dummy elfVendorId
466 (*mpStm) << (sal_uInt32) 0;
467
468 // dummy elfCulture
469 (*mpStm) << (sal_uInt32) 0;
470
471 // dummy elfPanose
472 (*mpStm) << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0;
473
474 // fill record to get a record size divideable by 4
475 (*mpStm) << (sal_uInt16) 0;
476
477 ImplEndRecord();
478
479 // TextAlign
480 sal_uInt32 nTextAlign;
481
482 switch( rFont.GetAlign() )
483 {
484 case ALIGN_TOP: nTextAlign = TA_TOP; break;
485 case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break;
486 default: nTextAlign = TA_BASELINE; break;
487 }
488 nTextAlign |= mnHorTextAlign;
489
490 ImplBeginRecord( WIN_EMR_SETTEXTALIGN );
491 (*mpStm) << nTextAlign;
492 ImplEndRecord();
493
494 // Text color
495 ImplBeginRecord( WIN_EMR_SETTEXTCOLOR );
496 ImplWriteColor( maVDev.GetTextColor() );
497 ImplEndRecord();
498
499 ImplBeginRecord( WIN_EMR_SELECTOBJECT );
500 (*mpStm) << mnTextHandle;
501 ImplEndRecord();
502 }
503 }
504
505 // -----------------------------------------------------------------------------
506
ImplWriteColor(const Color & rColor)507 void EMFWriter::ImplWriteColor( const Color& rColor )
508 {
509 sal_uInt32 nCol = rColor.GetRed();
510
511 nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8;
512 nCol |= ( (sal_uInt32) rColor.GetBlue() ) << 16;
513
514 (*mpStm) << nCol;
515 }
516
517 // -----------------------------------------------------------------------------
518
ImplWriteRasterOp(RasterOp eRop)519 void EMFWriter::ImplWriteRasterOp( RasterOp eRop )
520 {
521 sal_uInt32 nROP2;
522
523 switch( eRop )
524 {
525 case ROP_INVERT: nROP2 = 6; break;
526 case ROP_XOR: nROP2 = 7; break;
527 default: nROP2 = 13;break;
528 }
529
530 ImplBeginRecord( WIN_EMR_SETROP2 );
531 (*mpStm) << nROP2;
532 ImplEndRecord();
533 }
534
535 // -----------------------------------------------------------------------------
536
ImplWriteExtent(long nExtent)537 void EMFWriter::ImplWriteExtent( long nExtent )
538 {
539 nExtent = maVDev.LogicToLogic( Size( nExtent, 0 ), maVDev.GetMapMode(), maDestMapMode ).Width();
540 (*mpStm) << (sal_Int32) nExtent;
541 }
542
543 // -----------------------------------------------------------------------------
544
ImplWritePoint(const Point & rPoint)545 void EMFWriter::ImplWritePoint( const Point& rPoint )
546 {
547 const Point aPoint( maVDev.LogicToLogic( rPoint, maVDev.GetMapMode(), maDestMapMode ));
548 (*mpStm) << (sal_Int32) aPoint.X() << (sal_Int32) aPoint.Y();
549 }
550
551 // -----------------------------------------------------------------------------
552
ImplWriteSize(const Size & rSize)553 void EMFWriter::ImplWriteSize( const Size& rSize)
554 {
555 const Size aSize( maVDev.LogicToLogic( rSize, maVDev.GetMapMode(), maDestMapMode ));
556 (*mpStm) << (sal_Int32) aSize.Width() << (sal_Int32) aSize.Height();
557 }
558
559 // -----------------------------------------------------------------------------
560
ImplWriteRect(const Rectangle & rRect)561 void EMFWriter::ImplWriteRect( const Rectangle& rRect )
562 {
563 const Rectangle aRect( maVDev.LogicToLogic ( rRect, maVDev.GetMapMode(), maDestMapMode ));
564 (*mpStm) << aRect.Left() << aRect.Top() << aRect.Right() << aRect.Bottom();
565 }
566
567 // -----------------------------------------------------------------------------
568
ImplWritePolygonRecord(const Polygon & rPoly,sal_Bool bClose)569 void EMFWriter::ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose )
570 {
571 if( rPoly.GetSize() )
572 {
573 if( rPoly.HasFlags() )
574 ImplWritePath( rPoly, bClose );
575 else
576 {
577 if( bClose )
578 ImplCheckFillAttr();
579
580 ImplCheckLineAttr();
581
582 ImplBeginRecord( bClose ? WIN_EMR_POLYGON : WIN_EMR_POLYLINE );
583 ImplWriteRect( rPoly.GetBoundRect() );
584 (*mpStm) << (sal_uInt32) rPoly.GetSize();
585
586 for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
587 ImplWritePoint( rPoly[ i ] );
588
589 ImplEndRecord();
590 }
591 }
592 }
593
594 // -----------------------------------------------------------------------------
595
ImplWritePolyPolygonRecord(const PolyPolygon & rPolyPoly)596 void EMFWriter::ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly )
597 {
598 sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
599
600 if( nPolyCount )
601 {
602 if( 1 == nPolyCount )
603 ImplWritePolygonRecord( rPolyPoly[ 0 ], sal_True );
604 else
605 {
606 sal_Bool bHasFlags = sal_False;
607 sal_uInt32 nTotalPoints = 0;
608
609 for( i = 0; i < nPolyCount; i++ )
610 {
611 nTotalPoints += rPolyPoly[ i ].GetSize();
612 if ( rPolyPoly[ i ].HasFlags() )
613 bHasFlags = sal_True;
614 }
615 if( nTotalPoints )
616 {
617 if ( bHasFlags )
618 ImplWritePath( rPolyPoly, sal_True );
619 else
620 {
621 ImplCheckFillAttr();
622 ImplCheckLineAttr();
623
624 ImplBeginRecord( WIN_EMR_POLYPOLYGON );
625 ImplWriteRect( rPolyPoly.GetBoundRect() );
626 (*mpStm) << (sal_uInt32)nPolyCount << nTotalPoints;
627
628 for( i = 0; i < nPolyCount; i++ )
629 (*mpStm) << (sal_uInt32)rPolyPoly[ i ].GetSize();
630
631 for( i = 0; i < nPolyCount; i++ )
632 {
633 const Polygon& rPoly = rPolyPoly[ i ];
634
635 for( n = 0; n < rPoly.GetSize(); n++ )
636 ImplWritePoint( rPoly[ n ] );
637 }
638 ImplEndRecord();
639 }
640 }
641 }
642 }
643 }
644
645 // -----------------------------------------------------------------------------
646
ImplWritePath(const PolyPolygon & rPolyPoly,sal_Bool bClosed)647 void EMFWriter::ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClosed )
648 {
649 if ( bClosed )
650 ImplCheckFillAttr();
651 ImplCheckLineAttr();
652
653 ImplBeginRecord( WIN_EMR_BEGINPATH );
654 ImplEndRecord();
655
656 sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
657 for ( i = 0; i < nPolyCount; i++ )
658 {
659 n = 0;
660 const Polygon& rPoly = rPolyPoly[ i ];
661 while ( n < rPoly.GetSize() )
662 {
663 if( n == 0 )
664 {
665 ImplBeginRecord( WIN_EMR_MOVETOEX );
666 ImplWritePoint( rPoly[ 0 ] );
667 ImplEndRecord();
668 n++;
669 continue;
670 }
671
672 sal_uInt16 nBezPoints = 0;
673
674 while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) )
675 nBezPoints += 3;
676
677 if ( nBezPoints )
678 {
679 ImplBeginRecord( WIN_EMR_POLYBEZIERTO );
680 Polygon aNewPoly( nBezPoints + 1 );
681 aNewPoly[ 0 ] = rPoly[ n - 1 ];
682 for ( o = 0; o < nBezPoints; o++ )
683 aNewPoly[ o + 1 ] = rPoly[ n + o ];
684 ImplWriteRect( aNewPoly.GetBoundRect() );
685 (*mpStm) << (sal_uInt32)nBezPoints;
686 for( o = 1; o < aNewPoly.GetSize(); o++ )
687 ImplWritePoint( aNewPoly[ o ] );
688 ImplEndRecord();
689 n = n + nBezPoints;
690 }
691 else
692 {
693 sal_uInt16 nPoints = 1;
694 while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) )
695 nPoints++;
696
697 if ( nPoints > 1 )
698 {
699 ImplBeginRecord( WIN_EMR_POLYLINETO );
700 Polygon aNewPoly( nPoints + 1 );
701 aNewPoly[ 0 ] = rPoly[ n - 1];
702 for ( o = 1; o <= nPoints; o++ )
703 aNewPoly[ o ] = rPoly[ n - 1 + o ];
704 ImplWriteRect( aNewPoly.GetBoundRect() );
705 (*mpStm) << (sal_uInt32)( nPoints );
706 for( o = 1; o < aNewPoly.GetSize(); o++ )
707 ImplWritePoint( aNewPoly[ o ] );
708 ImplEndRecord();
709 }
710 else
711 {
712 ImplBeginRecord( WIN_EMR_LINETO );
713 ImplWritePoint( rPoly[ n ] );
714 ImplEndRecord();
715 }
716 n = n + nPoints;
717 }
718 if ( bClosed && ( n == rPoly.GetSize() ) )
719 {
720 ImplBeginRecord( WIN_EMR_CLOSEFIGURE );
721 ImplEndRecord();
722 }
723 }
724 }
725 ImplBeginRecord( WIN_EMR_ENDPATH );
726 ImplEndRecord();
727 ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH );
728 ImplWriteRect( rPolyPoly.GetBoundRect() );
729 ImplEndRecord();
730 }
731
732 // -----------------------------------------------------------------------------
733
ImplWriteBmpRecord(const Bitmap & rBmp,const Point & rPt,const Size & rSz,sal_uInt32 nROP)734 void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
735 const Size& rSz, sal_uInt32 nROP )
736 {
737 if( !!rBmp )
738 {
739 SvMemoryStream aMemStm( 65535, 65535 );
740 const Size aBmpSizePixel( rBmp.GetSizePixel() );
741
742 ImplBeginRecord( WIN_EMR_STRETCHDIBITS );
743 ImplWriteRect( Rectangle( rPt, rSz ) );
744 ImplWritePoint( rPt );
745 (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) aBmpSizePixel.Width() << (sal_Int32) aBmpSizePixel.Height();
746
747 // write offset positions and sizes later
748 const sal_uLong nOffPos = mpStm->Tell();
749 mpStm->SeekRel( 16 );
750
751 (*mpStm) << (sal_uInt32) 0 << ( ( ROP_XOR == maVDev.GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
752 ImplWriteSize( rSz );
753
754 WriteDIB(rBmp, aMemStm, true, false);
755
756 sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize;
757 sal_uInt16 nBitCount;
758
759 // get DIB parameters
760 aMemStm.Seek( 0 );
761 aMemStm >> nHeaderSize;
762 aMemStm.SeekRel( 10 );
763 aMemStm >> nBitCount >> nCompression >> nImageSize;
764 aMemStm.SeekRel( 8 );
765 aMemStm >> nColsUsed;
766
767 nPalCount = ( nBitCount <= 8 ) ? ( nColsUsed ? nColsUsed : ( 1 << (sal_uInt32) nBitCount ) ) :
768 ( ( 3 == nCompression ) ? 12 : 0 );
769
770 mpStm->Write( aMemStm.GetData(), nDIBSize );
771
772 const sal_uLong nEndPos = mpStm->Tell();
773 mpStm->Seek( nOffPos );
774 (*mpStm) << (sal_uInt32) 80 << (sal_uInt32)( nHeaderSize + ( nPalCount << 2 ) );
775 (*mpStm) << (sal_uInt32)( 80 + ( nHeaderSize + ( nPalCount << 2 ) ) ) << nImageSize;
776 mpStm->Seek( nEndPos );
777
778 ImplEndRecord();
779 }
780 }
781
782 // -----------------------------------------------------------------------------
783
ImplWriteTextRecord(const Point & rPos,const String rText,const sal_Int32 * pDXArray,sal_uInt32 nWidth)784 void EMFWriter::ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth )
785 {
786 xub_StrLen nLen = rText.Len(), i;
787
788 if( nLen )
789 {
790 sal_uInt32 nNormWidth;
791 sal_Int32* pOwnArray;
792 sal_Int32* pDX;
793
794 // get text sizes
795 if( pDXArray )
796 {
797 pOwnArray = NULL;
798 nNormWidth = maVDev.GetTextWidth( rText );
799 pDX = (sal_Int32*) pDXArray;
800 }
801 else
802 {
803 pOwnArray = new sal_Int32[ nLen ];
804 nNormWidth = maVDev.GetTextArray( rText, pOwnArray );
805 pDX = pOwnArray;
806 }
807
808 if( nLen > 1 )
809 {
810 nNormWidth = pDX[ nLen - 2 ] + maVDev.GetTextWidth( rText.GetChar( nLen - 1 ) );
811
812 if( nWidth && nNormWidth && ( nWidth != nNormWidth ) )
813 {
814 const double fFactor = (double) nWidth / nNormWidth;
815
816 for( i = 0; i < ( nLen - 1 ); i++ )
817 pDX[ i ] = FRound( pDX[ i ] * fFactor );
818 }
819 }
820
821 // write text record
822 ImplBeginRecord( WIN_EMR_EXTTEXTOUTW );
823
824 ImplWriteRect( Rectangle( rPos, Size( nNormWidth, maVDev.GetTextHeight() ) ) );
825 (*mpStm) << (sal_uInt32)1;
826 (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0;
827 ImplWritePoint( rPos );
828 (*mpStm) << (sal_uInt32) nLen << (sal_uInt32) 76 << (sal_uInt32) 2;
829 (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0;
830 (*mpStm) << (sal_uInt32) ( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
831
832 // write text
833 for( i = 0; i < nLen; i++ )
834 (*mpStm) << (sal_Unicode)rText.GetChar( i );
835
836 // padding word
837 if( nLen & 1 )
838 (*mpStm) << (sal_uInt16) 0;
839
840 // write DX array
841 ImplWriteExtent( pDX[ 0 ] );
842
843 if( nLen > 1 )
844 {
845 for( i = 1; i < ( nLen - 1 ); i++ )
846 ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
847
848 ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
849 }
850
851 ImplEndRecord();
852 delete[] pOwnArray;
853 }
854 }
855
856 // -----------------------------------------------------------------------------
857
Impl_handleLineInfoPolyPolygons(const LineInfo & rInfo,const basegfx::B2DPolygon & rLinePolygon)858 void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
859 {
860 if(rLinePolygon.count())
861 {
862 basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
863 basegfx::B2DPolyPolygon aFillPolyPolygon;
864
865 rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
866
867 if(aLinePolyPolygon.count())
868 {
869 for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
870 {
871 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
872 ImplWritePolygonRecord( Polygon(aCandidate), sal_False );
873 }
874 }
875
876 if(aFillPolyPolygon.count())
877 {
878 const Color aOldLineColor(maVDev.GetLineColor());
879 const Color aOldFillColor(maVDev.GetFillColor());
880
881 maVDev.SetLineColor();
882 maVDev.SetFillColor(aOldLineColor);
883
884 for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
885 {
886 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
887 ImplWritePolyPolygonRecord(PolyPolygon(Polygon(aPolygon)));
888 }
889
890 maVDev.SetLineColor(aOldLineColor);
891 maVDev.SetFillColor(aOldFillColor);
892 }
893 }
894 }
895
896 // -----------------------------------------------------------------------------
897
ImplWrite(const GDIMetaFile & rMtf)898 void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
899 {
900 for( sal_uLong j = 0, nActionCount = rMtf.GetActionCount(); j < nActionCount; j++ )
901 {
902 const MetaAction* pAction = rMtf.GetAction( j );
903 const sal_uInt16 nType = pAction->GetType();
904
905 switch( nType )
906 {
907 case( META_PIXEL_ACTION ):
908 {
909 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
910
911 ImplCheckLineAttr();
912 ImplBeginRecord( WIN_EMR_SETPIXELV );
913 ImplWritePoint( pA->GetPoint() );
914 ImplWriteColor( pA->GetColor() );
915 ImplEndRecord();
916 }
917 break;
918
919 case( META_POINT_ACTION ):
920 {
921 if( maVDev.IsLineColor() )
922 {
923 const MetaPointAction* pA = (const MetaPointAction*) pAction;
924
925 ImplCheckLineAttr();
926 ImplBeginRecord( WIN_EMR_SETPIXELV );
927 ImplWritePoint( pA->GetPoint() );
928 ImplWriteColor( maVDev.GetLineColor() );
929 ImplEndRecord();
930 }
931 }
932 break;
933
934 case( META_LINE_ACTION ):
935 {
936 if( maVDev.IsLineColor() )
937 {
938 const MetaLineAction* pA = (const MetaLineAction*) pAction;
939
940 if(pA->GetLineInfo().IsDefault())
941 {
942 ImplCheckLineAttr();
943
944 ImplBeginRecord( WIN_EMR_MOVETOEX );
945 ImplWritePoint( pA->GetStartPoint() );
946 ImplEndRecord();
947
948 ImplBeginRecord( WIN_EMR_LINETO );
949 ImplWritePoint( pA->GetEndPoint() );
950 ImplEndRecord();
951
952 ImplBeginRecord( WIN_EMR_SETPIXELV );
953 ImplWritePoint( pA->GetEndPoint() );
954 ImplWriteColor( maVDev.GetLineColor() );
955 ImplEndRecord();
956 }
957 else
958 {
959 // LineInfo used; handle Dash/Dot and fat lines
960 basegfx::B2DPolygon aPolygon;
961 aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
962 aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
963 Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
964 }
965 }
966 }
967 break;
968
969 case( META_RECT_ACTION ):
970 {
971 if( maVDev.IsLineColor() || maVDev.IsFillColor() )
972 {
973 const MetaRectAction* pA = (const MetaRectAction*) pAction;
974
975 ImplCheckFillAttr();
976 ImplCheckLineAttr();
977
978 ImplBeginRecord( WIN_EMR_RECTANGLE );
979 ImplWriteRect( pA->GetRect() );
980 ImplEndRecord();
981 }
982 }
983 break;
984
985 case( META_ROUNDRECT_ACTION ):
986 {
987 if( maVDev.IsLineColor() || maVDev.IsFillColor() )
988 {
989 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
990
991 ImplCheckFillAttr();
992 ImplCheckLineAttr();
993
994 ImplBeginRecord( WIN_EMR_ROUNDRECT );
995 ImplWriteRect( pA->GetRect() );
996 ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
997 ImplEndRecord();
998 }
999 }
1000 break;
1001
1002 case( META_ELLIPSE_ACTION ):
1003 {
1004 if( maVDev.IsLineColor() || maVDev.IsFillColor() )
1005 {
1006 const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
1007
1008 ImplCheckFillAttr();
1009 ImplCheckLineAttr();
1010
1011 ImplBeginRecord( WIN_EMR_ELLIPSE );
1012 ImplWriteRect( pA->GetRect() );
1013 ImplEndRecord();
1014 }
1015 }
1016 break;
1017
1018 case( META_ARC_ACTION ):
1019 case( META_PIE_ACTION ):
1020 case( META_CHORD_ACTION ):
1021 case( META_POLYGON_ACTION ):
1022 {
1023 if( maVDev.IsLineColor() || maVDev.IsFillColor() )
1024 {
1025 Polygon aPoly;
1026
1027 switch( nType )
1028 {
1029 case( META_ARC_ACTION ):
1030 {
1031 const MetaArcAction* pA = (const MetaArcAction*) pAction;
1032 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
1033 }
1034 break;
1035
1036 case( META_PIE_ACTION ):
1037 {
1038 const MetaPieAction* pA = (const MetaPieAction*) pAction;
1039 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
1040 }
1041 break;
1042
1043 case( META_CHORD_ACTION ):
1044 {
1045 const MetaChordAction* pA = (const MetaChordAction*) pAction;
1046 aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
1047 }
1048 break;
1049
1050 case( META_POLYGON_ACTION ):
1051 aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
1052 break;
1053 }
1054
1055 ImplWritePolygonRecord( aPoly, nType != META_ARC_ACTION );
1056 }
1057 }
1058 break;
1059
1060 case( META_POLYLINE_ACTION ):
1061 {
1062 if( maVDev.IsLineColor() )
1063 {
1064 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
1065 const Polygon& rPoly = pA->GetPolygon();
1066
1067 if( rPoly.GetSize() )
1068 {
1069 if(pA->GetLineInfo().IsDefault())
1070 {
1071 ImplWritePolygonRecord( rPoly, sal_False );
1072 }
1073 else
1074 {
1075 // LineInfo used; handle Dash/Dot and fat lines
1076 Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1077 }
1078 }
1079 }
1080 }
1081 break;
1082
1083 case( META_POLYPOLYGON_ACTION ):
1084 {
1085 if( maVDev.IsLineColor() || maVDev.IsFillColor() )
1086 ImplWritePolyPolygonRecord( ( (const MetaPolyPolygonAction*) pAction )->GetPolyPolygon() );
1087 }
1088 break;
1089
1090 case( META_GRADIENT_ACTION ):
1091 {
1092 const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
1093 GDIMetaFile aTmpMtf;
1094
1095 maVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1096 ImplWrite( aTmpMtf );
1097 }
1098 break;
1099
1100 case META_HATCH_ACTION:
1101 {
1102 const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
1103 GDIMetaFile aTmpMtf;
1104
1105 maVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1106 ImplWrite( aTmpMtf );
1107 }
1108 break;
1109
1110 case META_TRANSPARENT_ACTION:
1111 {
1112 ImplCheckFillAttr();
1113 ImplCheckLineAttr();
1114 ImplWritePolyPolygonRecord( ( (MetaTransparentAction*) pAction )->GetPolyPolygon() );
1115 }
1116 break;
1117
1118 case META_FLOATTRANSPARENT_ACTION:
1119 {
1120 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
1121
1122 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1123 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1124 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1125 const Point aDestPt( pA->GetPoint() );
1126 const Size aDestSize( pA->GetSize() );
1127 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1128 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1129 long nMoveX, nMoveY;
1130
1131 if( fScaleX != 1.0 || fScaleY != 1.0 )
1132 {
1133 aTmpMtf.Scale( fScaleX, fScaleY );
1134 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1135 }
1136
1137 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1138
1139 if( nMoveX || nMoveY )
1140 aTmpMtf.Move( nMoveX, nMoveY );
1141
1142 ImplCheckFillAttr();
1143 ImplCheckLineAttr();
1144 ImplCheckTextAttr();
1145 ImplWrite( aTmpMtf );
1146 }
1147 break;
1148
1149 case( META_EPS_ACTION ):
1150 {
1151 const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
1152 const GDIMetaFile aSubstitute( pA->GetSubstitute() );
1153
1154 for( sal_uLong i = 0, nCount = aSubstitute.GetActionCount(); i < nCount; i++ )
1155 {
1156 const MetaAction* pSubstAct = aSubstitute.GetAction( i );
1157 if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
1158 {
1159 maVDev.Push( PUSH_ALL );
1160 ImplBeginRecord( WIN_EMR_SAVEDC );
1161 ImplEndRecord();
1162
1163 MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1164 Size aOutSize( maVDev.LogicToLogic( pA->GetSize(), maVDev.GetMapMode(), aMapMode ) );
1165 aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
1166 aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
1167 aMapMode.SetOrigin( maVDev.LogicToLogic( pA->GetPoint(), maVDev.GetMapMode(), aMapMode ) );
1168 maVDev.SetMapMode( aMapMode );
1169 ImplWrite( aSubstitute );
1170
1171 maVDev.Pop();
1172 ImplBeginRecord( WIN_EMR_RESTOREDC );
1173 (*mpStm) << (sal_Int32) -1;
1174 ImplEndRecord();
1175 break;
1176 }
1177 }
1178 }
1179 break;
1180
1181 case META_BMP_ACTION:
1182 {
1183 const MetaBmpAction* pA = (const MetaBmpAction *) pAction;
1184 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev.PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY );
1185 }
1186 break;
1187
1188 case META_BMPSCALE_ACTION:
1189 {
1190 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1191 ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1192 }
1193 break;
1194
1195 case META_BMPSCALEPART_ACTION:
1196 {
1197 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
1198 Bitmap aTmp( pA->GetBitmap() );
1199
1200 if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1201 ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1202 }
1203 break;
1204
1205 case META_BMPEX_ACTION:
1206 {
1207 const MetaBmpExAction* pA = (const MetaBmpExAction *) pAction;
1208 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1209 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1210
1211 if( !!aMsk )
1212 {
1213 aBmp.Replace( aMsk, COL_WHITE );
1214 aMsk.Invert();
1215 ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev.PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
1216 ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev.PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
1217 }
1218 else
1219 ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
1220 }
1221 break;
1222
1223 case META_BMPEXSCALE_ACTION:
1224 {
1225 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1226 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1227 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1228
1229 if( !!aMsk )
1230 {
1231 aBmp.Replace( aMsk, COL_WHITE );
1232 aMsk.Invert();
1233 ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
1234 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
1235 }
1236 else
1237 ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
1238 }
1239 break;
1240
1241 case META_BMPEXSCALEPART_ACTION:
1242 {
1243 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
1244 BitmapEx aBmpEx( pA->GetBitmapEx() );
1245 aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1246 Bitmap aBmp( aBmpEx.GetBitmap() );
1247 Bitmap aMsk( aBmpEx.GetMask() );
1248
1249 if( !!aMsk )
1250 {
1251 aBmp.Replace( aMsk, COL_WHITE );
1252 aMsk.Invert();
1253 ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT );
1254 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
1255 }
1256 else
1257 ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
1258 }
1259 break;
1260
1261 case META_TEXT_ACTION:
1262 {
1263 const MetaTextAction* pA = (const MetaTextAction*) pAction;
1264 const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1265
1266 ImplCheckTextAttr();
1267 ImplWriteTextRecord( pA->GetPoint(), aText, NULL, 0 );
1268 }
1269 break;
1270
1271 case META_TEXTRECT_ACTION:
1272 {
1273 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
1274 const String aText( pA->GetText() );
1275
1276 ImplCheckTextAttr();
1277 ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, NULL, 0 );
1278 }
1279 break;
1280
1281 case META_TEXTARRAY_ACTION:
1282 {
1283 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
1284 const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1285
1286 ImplCheckTextAttr();
1287 ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
1288 }
1289 break;
1290
1291 case META_STRETCHTEXT_ACTION:
1292 {
1293 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
1294 const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1295
1296 ImplCheckTextAttr();
1297 ImplWriteTextRecord( pA->GetPoint(), aText, NULL, pA->GetWidth() );
1298 }
1299 break;
1300
1301 case( META_LINECOLOR_ACTION ):
1302 {
1303 ( (MetaAction*) pAction )->Execute( &maVDev );
1304 mbLineChanged = sal_True;
1305 }
1306 break;
1307
1308 case( META_FILLCOLOR_ACTION ):
1309 {
1310 ( (MetaAction*) pAction )->Execute( &maVDev );
1311 mbFillChanged = sal_True;
1312 }
1313 break;
1314
1315 case( META_TEXTCOLOR_ACTION ):
1316 case( META_TEXTLINECOLOR_ACTION ):
1317 case( META_TEXTFILLCOLOR_ACTION ):
1318 case( META_TEXTALIGN_ACTION ):
1319 case( META_FONT_ACTION ):
1320 {
1321 ( (MetaAction*) pAction )->Execute( &maVDev );
1322 mbTextChanged = sal_True;
1323 }
1324 break;
1325
1326 case( META_ISECTRECTCLIPREGION_ACTION ):
1327 {
1328 ( (MetaAction*) pAction )->Execute( &maVDev );
1329
1330 ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT );
1331 ImplWriteRect( ( (MetaISectRectClipRegionAction*) pAction )->GetRect() );
1332 ImplEndRecord();
1333 }
1334 break;
1335
1336 case( META_CLIPREGION_ACTION ):
1337 case( META_ISECTREGIONCLIPREGION_ACTION ):
1338 case( META_MOVECLIPREGION_ACTION ):
1339 {
1340 ( (MetaAction*) pAction )->Execute( &maVDev );
1341 }
1342 break;
1343
1344 case( META_REFPOINT_ACTION ):
1345 case( META_MAPMODE_ACTION ):
1346 ( (MetaAction*) pAction )->Execute( &maVDev );
1347 break;
1348
1349 case( META_PUSH_ACTION ):
1350 {
1351 ( (MetaAction*) pAction )->Execute( &maVDev );
1352
1353 ImplBeginRecord( WIN_EMR_SAVEDC );
1354 ImplEndRecord();
1355 }
1356 break;
1357
1358 case( META_POP_ACTION ):
1359 {
1360 ( (MetaAction*) pAction )->Execute( &maVDev );
1361
1362 ImplBeginRecord( WIN_EMR_RESTOREDC );
1363 (*mpStm) << (sal_Int32) -1;
1364 ImplEndRecord();
1365
1366 ImplWriteRasterOp( maVDev.GetRasterOp() );
1367 mbLineChanged = mbFillChanged = mbTextChanged = sal_True;
1368 }
1369 break;
1370
1371 case( META_RASTEROP_ACTION ):
1372 {
1373 ( (MetaAction*) pAction )->Execute( &maVDev );
1374 ImplWriteRasterOp( ( (MetaRasterOpAction*) pAction )->GetRasterOp() );
1375 }
1376 break;
1377
1378 case( META_LAYOUTMODE_ACTION ):
1379 {
1380 sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pAction )->GetLayoutMode();
1381 mnHorTextAlign = 0;
1382 if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
1383 {
1384 mnHorTextAlign = TA_RIGHT | TA_RTLREADING;
1385 }
1386 if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
1387 mnHorTextAlign |= TA_RIGHT;
1388 else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
1389 mnHorTextAlign &= ~TA_RIGHT;
1390 break;
1391 }
1392
1393 case( META_MASK_ACTION ):
1394 case( META_MASKSCALE_ACTION ):
1395 case( META_MASKSCALEPART_ACTION ):
1396 case( META_WALLPAPER_ACTION ):
1397 case( META_TEXTLINE_ACTION ):
1398 case( META_COMMENT_ACTION ):
1399 case( META_GRADIENTEX_ACTION ):
1400 {
1401 // !!! >>> we don't want to support these actions
1402 }
1403 break;
1404
1405 default:
1406 DBG_ERROR( ( ByteString( "EMFWriter::ImplWriteActions: unsupported MetaAction #" ) += ByteString::CreateFromInt32( nType ) ).GetBuffer() );
1407 break;
1408 }
1409 }
1410 }
1411