Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "wmfwr.hxx"
21 : #include <unotools/fontcvt.hxx>
22 : #include "emfwr.hxx"
23 : #include <rtl/crc.h>
24 : #include <rtl/tencinfo.h>
25 : #include <tools/bigint.hxx>
26 : #include <tools/helpers.hxx>
27 : #include <tools/tenccvt.hxx>
28 : #include <osl/endian.h>
29 : #include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
30 :
31 : #include <vcl/metric.hxx>
32 : #include <basegfx/polygon/b2dpolygon.hxx>
33 : #include <basegfx/polygon/b2dpolypolygon.hxx>
34 :
35 : //====================== MS-Windows-defines ===============================
36 :
37 : #define W_META_SETBKCOLOR 0x0201
38 : #define W_META_SETBKMODE 0x0102
39 : #define W_META_SETMAPMODE 0x0103
40 : #define W_META_SETROP2 0x0104
41 : #define W_META_SETRELABS 0x0105
42 : #define W_META_SETPOLYFILLMODE 0x0106
43 : #define W_META_SETSTRETCHBLTMODE 0x0107
44 : #define W_META_SETTEXTCHAREXTRA 0x0108
45 : #define W_META_SETTEXTCOLOR 0x0209
46 : #define W_META_SETTEXTJUSTIFICATION 0x020A
47 : #define W_META_SETWINDOWORG 0x020B
48 : #define W_META_SETWINDOWEXT 0x020C
49 : #define W_META_SETVIEWPORTORG 0x020D
50 : #define W_META_SETVIEWPORTEXT 0x020E
51 : #define W_META_OFFSETWINDOWORG 0x020F
52 : #define W_META_SCALEWINDOWEXT 0x0410
53 : #define W_META_OFFSETVIEWPORTORG 0x0211
54 : #define W_META_SCALEVIEWPORTEXT 0x0412
55 : #define W_META_LINETO 0x0213
56 : #define W_META_MOVETO 0x0214
57 : #define W_META_EXCLUDECLIPRECT 0x0415
58 : #define W_META_INTERSECTCLIPRECT 0x0416
59 : #define W_META_ARC 0x0817
60 : #define W_META_ELLIPSE 0x0418
61 : #define W_META_FLOODFILL 0x0419
62 : #define W_META_PIE 0x081A
63 : #define W_META_RECTANGLE 0x041B
64 : #define W_META_ROUNDRECT 0x061C
65 : #define W_META_PATBLT 0x061D
66 : #define W_META_SAVEDC 0x001E
67 : #define W_META_SETPIXEL 0x041F
68 : #define W_META_OFFSETCLIPRGN 0x0220
69 : #define W_META_TEXTOUT 0x0521
70 : #define W_META_BITBLT 0x0922
71 : #define W_META_STRETCHBLT 0x0B23
72 : #define W_META_POLYGON 0x0324
73 : #define W_META_POLYLINE 0x0325
74 : #define W_META_ESCAPE 0x0626
75 : #define W_META_RESTOREDC 0x0127
76 : #define W_META_FILLREGION 0x0228
77 : #define W_META_FRAMEREGION 0x0429
78 : #define W_META_INVERTREGION 0x012A
79 : #define W_META_PAINTREGION 0x012B
80 : #define W_META_SELECTCLIPREGION 0x012C
81 : #define W_META_SELECTOBJECT 0x012D
82 : #define W_META_SETTEXTALIGN 0x012E
83 : #define W_META_DRAWTEXT 0x062F
84 : #define W_META_CHORD 0x0830
85 : #define W_META_SETMAPPERFLAGS 0x0231
86 : #define W_META_EXTTEXTOUT 0x0a32
87 : #define W_META_SETDIBTODEV 0x0d33
88 : #define W_META_SELECTPALETTE 0x0234
89 : #define W_META_REALIZEPALETTE 0x0035
90 : #define W_META_ANIMATEPALETTE 0x0436
91 : #define W_META_SETPALENTRIES 0x0037
92 : #define W_META_POLYPOLYGON 0x0538
93 : #define W_META_RESIZEPALETTE 0x0139
94 : #define W_META_DIBBITBLT 0x0940
95 : #define W_META_DIBSTRETCHBLT 0x0b41
96 : #define W_META_DIBCREATEPATTERNBRUSH 0x0142
97 : #define W_META_STRETCHDIB 0x0f43
98 : #define W_META_EXTFLOODFILL 0x0548
99 : #define W_META_RESETDC 0x014C
100 : #define W_META_STARTDOC 0x014D
101 : #define W_META_STARTPAGE 0x004F
102 : #define W_META_ENDPAGE 0x0050
103 : #define W_META_ABORTDOC 0x0052
104 : #define W_META_ENDDOC 0x005E
105 : #define W_META_DELETEOBJECT 0x01f0
106 : #define W_META_CREATEPALETTE 0x00f7
107 : #define W_META_CREATEBRUSH 0x00F8
108 : #define W_META_CREATEPATTERNBRUSH 0x01F9
109 : #define W_META_CREATEPENINDIRECT 0x02FA
110 : #define W_META_CREATEFONTINDIRECT 0x02FB
111 : #define W_META_CREATEBRUSHINDIRECT 0x02FC
112 : #define W_META_CREATEBITMAPINDIRECT 0x02FD
113 : #define W_META_CREATEBITMAP 0x06FE
114 : #define W_META_CREATEREGION 0x06FF
115 :
116 : #define W_TRANSPARENT 1
117 : #define W_OPAQUE 2
118 :
119 : #define W_R2_BLACK 1
120 : #define W_R2_NOTMERGEPEN 2
121 : #define W_R2_MASKNOTPEN 3
122 : #define W_R2_NOTCOPYPEN 4
123 : #define W_R2_MASKPENNOT 5
124 : #define W_R2_NOT 6
125 : #define W_R2_XORPEN 7
126 : #define W_R2_NOTMASKPEN 8
127 : #define W_R2_MASKPEN 9
128 : #define W_R2_NOTXORPEN 10
129 : #define W_R2_NOP 11
130 : #define W_R2_MERGENOTPEN 12
131 : #define W_R2_COPYPEN 13
132 : #define W_R2_MERGEPENNOT 14
133 : #define W_R2_MERGEPEN 15
134 : #define W_R2_WHITE 16
135 :
136 : #define W_TA_NOUPDATECP 0x0000
137 : #define W_TA_UPDATECP 0x0001
138 : #define W_TA_LEFT 0x0000
139 : #define W_TA_RIGHT 0x0002
140 : #define W_TA_CENTER 0x0006
141 : #define W_TA_TOP 0x0000
142 : #define W_TA_BOTTOM 0x0008
143 : #define W_TA_BASELINE 0x0018
144 : #define W_TA_RTLREADING 0x0100
145 :
146 : #define W_SRCCOPY 0x00CC0020L
147 : #define W_SRCPAINT 0x00EE0086L
148 : #define W_SRCAND 0x008800C6L
149 : #define W_SRCINVERT 0x00660046L
150 : #define W_SRCERASE 0x00440328L
151 : #define W_NOTSRCCOPY 0x00330008L
152 : #define W_NOTSRCERASE 0x001100A6L
153 : #define W_MERGECOPY 0x00C000CAL
154 : #define W_MERGEPAINT 0x00BB0226L
155 : #define W_PATCOPY 0x00F00021L
156 : #define W_PATPAINT 0x00FB0A09L
157 : #define W_PATINVERT 0x005A0049L
158 : #define W_DSTINVERT 0x00550009L
159 : #define W_BLACKNESS 0x00000042L
160 : #define W_WHITENESS 0x00FF0062L
161 :
162 : #define W_PS_SOLID 0
163 : #define W_PS_DASH 1
164 : #define W_PS_DOT 2
165 : #define W_PS_DASHDOT 3
166 : #define W_PS_DASHDOTDOT 4
167 : #define W_PS_NULL 5
168 : #define W_PS_INSIDEFRAME 6
169 :
170 : #define W_LF_FACESIZE 32
171 :
172 : #define W_ANSI_CHARSET 0
173 : #define W_DEFAULT_CHARSET 1
174 : #define W_SYMBOL_CHARSET 2
175 : #define W_SHIFTJIS_CHARSET 128
176 : #define W_HANGEUL_CHARSET 129
177 : #define W_GB2312_CHARSET 134
178 : #define W_CHINESEBIG5_CHARSET 136
179 : #define W_OEM_CHARSET 255
180 : /*WINVER >= 0x0400*/
181 : #define W_JOHAB_CHARSET 130
182 : #define W_HEBREW_CHARSET 177
183 : #define W_ARABIC_CHARSET 178
184 : #define W_GREEK_CHARSET 161
185 : #define W_TURKISH_CHARSET 162
186 : #define W_VIETNAMESE_CHARSET 163
187 : #define W_THAI_CHARSET 222
188 : #define W_EASTEUROPE_CHARSET 238
189 : #define W_RUSSIAN_CHARSET 204
190 : #define W_MAC_CHARSET 77
191 : #define W_BALTIC_CHARSET 186
192 :
193 : #define W_DEFAULT_PITCH 0x00
194 : #define W_FIXED_PITCH 0x01
195 : #define W_VARIABLE_PITCH 0x02
196 :
197 : #define W_FF_DONTCARE 0x00
198 : #define W_FF_ROMAN 0x10
199 : #define W_FF_SWISS 0x20
200 : #define W_FF_MODERN 0x30
201 : #define W_FF_SCRIPT 0x40
202 : #define W_FF_DECORATIVE 0x50
203 :
204 : #define W_FW_DONTCARE 0
205 : #define W_FW_THIN 100
206 : #define W_FW_EXTRALIGHT 200
207 : #define W_FW_LIGHT 300
208 : #define W_FW_NORMAL 400
209 : #define W_FW_MEDIUM 500
210 : #define W_FW_SEMIBOLD 600
211 : #define W_FW_BOLD 700
212 : #define W_FW_EXTRABOLD 800
213 : #define W_FW_HEAVY 900
214 : #define W_FW_ULTRALIGHT 200
215 : #define W_FW_REGULAR 400
216 : #define W_FW_DEMIBOLD 600
217 : #define W_FW_ULTRABOLD 800
218 : #define W_FW_BLACK 900
219 :
220 : #define W_BS_SOLID 0
221 : #define W_BS_HOLLOW 1
222 : #define W_BS_HATCHED 2
223 : #define W_BS_PATTERN 3
224 : #define W_BS_INDEXED 4
225 : #define W_BS_DIBPATTERN 5
226 :
227 : #define W_HS_HORIZONTAL 0
228 : #define W_HS_VERTICAL 1
229 : #define W_HS_FDIAGONAL 2
230 : #define W_HS_BDIAGONAL 3
231 : #define W_HS_CROSS 4
232 : #define W_HS_DIAGCROSS 5
233 :
234 : #define W_MFCOMMENT 15
235 :
236 : #define PRIVATE_ESCAPE_UNICODE 2
237 :
238 : //========================== Methoden von WMFWriter ==========================
239 :
240 2723 : void WMFWriter::MayCallback()
241 : {
242 2723 : if ( xStatusIndicator.is() )
243 : {
244 : sal_uLong nPercent;
245 :
246 : // Wir gehen mal einfach so davon aus, dass 16386 Actions einer Bitmap entsprechen
247 : // (in der Regel wird ein Metafile entweder nur Actions oder einige Bitmaps und fast
248 : // keine Actions enthalten. Dann ist das Verhaeltnis ziemlich unwichtig)
249 :
250 : nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
251 : *100
252 0 : /((nNumberOfBitmaps<<14)+nNumberOfActions);
253 :
254 0 : if ( nPercent >= nLastPercent + 3 )
255 : {
256 0 : nLastPercent = nPercent;
257 0 : if( nPercent <= 100 )
258 0 : xStatusIndicator->setValue( nPercent );
259 : }
260 : }
261 2723 : }
262 :
263 29 : void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
264 : {
265 : size_t nAction, nActionCount;
266 :
267 29 : nActionCount = rMTF.GetActionSize();
268 :
269 2752 : for ( nAction=0; nAction < nActionCount; nAction++ )
270 : {
271 2723 : MetaAction* pMA = rMTF.GetAction( nAction );
272 :
273 2723 : switch( pMA->GetType() )
274 : {
275 : case META_BMP_ACTION:
276 : case META_BMPSCALE_ACTION:
277 : case META_BMPSCALEPART_ACTION:
278 : case META_BMPEX_ACTION:
279 : case META_BMPEXSCALE_ACTION:
280 : case META_BMPEXSCALEPART_ACTION:
281 0 : nNumberOfBitmaps++;
282 0 : break;
283 : }
284 2723 : nNumberOfActions++;
285 : }
286 29 : }
287 :
288 :
289 8498 : void WMFWriter::WritePointXY(const Point & rPoint)
290 : {
291 8498 : Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
292 8498 : *pWMF << ((short)aPt.X()) << ((short)aPt.Y());
293 8498 : }
294 :
295 :
296 337 : void WMFWriter::WritePointYX(const Point & rPoint)
297 : {
298 337 : Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
299 337 : *pWMF << ((short)aPt.Y()) << ((short)aPt.X());
300 337 : }
301 :
302 :
303 61 : sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
304 : {
305 61 : Size aSz( pVirDev->LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
306 61 : return aSz.Width();
307 : }
308 :
309 :
310 167 : void WMFWriter::WriteSize(const Size & rSize)
311 : {
312 167 : Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
313 167 : *pWMF << ((short)aSz.Width()) << ((short)aSz.Height());
314 167 : }
315 :
316 :
317 428 : void WMFWriter::WriteHeightWidth(const Size & rSize)
318 : {
319 428 : Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
320 428 : *pWMF << ((short)aSz.Height()) << ((short)aSz.Width());
321 428 : }
322 :
323 :
324 48 : void WMFWriter::WriteRectangle(const Rectangle & rRect)
325 : {
326 48 : WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
327 48 : WritePointYX(rRect.TopLeft());
328 48 : }
329 :
330 :
331 694 : void WMFWriter::WriteColor(const Color & rColor)
332 : {
333 694 : *pWMF << (sal_uInt8) rColor.GetRed() << (sal_uInt8) rColor.GetGreen() << (sal_uInt8) rColor.GetBlue() << (sal_uInt8) 0;
334 694 : }
335 :
336 :
337 3925 : void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
338 : {
339 3925 : nActRecordPos=pWMF->Tell();
340 3925 : if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
341 3925 : *pWMF << nSizeWords << nType;
342 3925 : }
343 :
344 :
345 724 : void WMFWriter::UpdateRecordHeader()
346 : {
347 : sal_uLong nPos;
348 : sal_uInt32 nSize;
349 :
350 724 : nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
351 724 : if ((nSize & 1)!=0) {
352 0 : *pWMF << (sal_uInt8)0;
353 0 : nPos++; nSize++;
354 : }
355 724 : nSize/=2;
356 724 : if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
357 724 : pWMF->Seek(nActRecordPos);
358 724 : *pWMF << nSize;
359 724 : pWMF->Seek(nPos);
360 724 : }
361 :
362 :
363 0 : void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
364 : {
365 0 : WriteRecordHeader(0x0000000b,W_META_ARC);
366 0 : WritePointYX(rEndPt);
367 0 : WritePointYX(rStartPt);
368 0 : WriteRectangle(rRect);
369 0 : }
370 :
371 0 : void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
372 : {
373 0 : WriteRecordHeader(0x0000000b,W_META_CHORD);
374 0 : WritePointYX(rEndPt);
375 0 : WritePointYX(rStartPt);
376 0 : WriteRectangle(rRect);
377 0 : }
378 :
379 :
380 167 : void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
381 : {
382 167 : WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
383 :
384 167 : if( rColor==Color(COL_TRANSPARENT) )
385 0 : *pWMF << (sal_uInt16) W_BS_HOLLOW;
386 : else
387 167 : *pWMF << (sal_uInt16) W_BS_SOLID;
388 :
389 167 : WriteColor( rColor );
390 167 : *pWMF << (sal_uInt16) 0;
391 167 : }
392 :
393 :
394 399 : void WMFWriter::WMFRecord_CreateFontIndirect(const Font & rFont)
395 : {
396 : sal_uInt16 nWeight,i;
397 : sal_uInt8 nPitchFamily;
398 :
399 399 : WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
400 399 : WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
401 399 : *pWMF << (short)rFont.GetOrientation() << (short)rFont.GetOrientation();
402 :
403 399 : switch (rFont.GetWeight()) {
404 0 : case WEIGHT_THIN: nWeight=W_FW_THIN; break;
405 0 : case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
406 0 : case WEIGHT_LIGHT: nWeight=W_FW_LIGHT; break;
407 0 : case WEIGHT_SEMILIGHT: nWeight=W_FW_LIGHT; break;
408 370 : case WEIGHT_NORMAL: nWeight=W_FW_NORMAL; break;
409 0 : case WEIGHT_MEDIUM: nWeight=W_FW_MEDIUM; break;
410 0 : case WEIGHT_SEMIBOLD: nWeight=W_FW_SEMIBOLD; break;
411 0 : case WEIGHT_BOLD: nWeight=W_FW_BOLD; break;
412 0 : case WEIGHT_ULTRABOLD: nWeight=W_FW_ULTRABOLD; break;
413 0 : case WEIGHT_BLACK: nWeight=W_FW_BLACK; break;
414 29 : default: nWeight=W_FW_DONTCARE;
415 : }
416 399 : *pWMF << nWeight;
417 :
418 399 : if (rFont.GetItalic()==ITALIC_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
419 399 : if (rFont.GetUnderline()==UNDERLINE_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
420 399 : if (rFont.GetStrikeout()==STRIKEOUT_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
421 :
422 399 : CharSet eFontNameEncoding = rFont.GetCharSet();
423 399 : sal_uInt8 nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
424 399 : if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
425 0 : eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
426 399 : if ( nCharSet == 1 )
427 0 : nCharSet = W_ANSI_CHARSET;
428 399 : *pWMF << nCharSet;
429 :
430 399 : *pWMF << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0;
431 :
432 399 : switch (rFont.GetPitch()) {
433 0 : case PITCH_FIXED: nPitchFamily=W_FIXED_PITCH; break;
434 0 : case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
435 399 : default: nPitchFamily=W_DEFAULT_PITCH;
436 : }
437 399 : switch (rFont.GetFamily()) {
438 0 : case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
439 0 : case FAMILY_MODERN: nPitchFamily|=W_FF_MODERN; break;
440 232 : case FAMILY_ROMAN: nPitchFamily|=W_FF_ROMAN; break;
441 0 : case FAMILY_SCRIPT: nPitchFamily|=W_FF_SCRIPT; break;
442 0 : case FAMILY_SWISS: nPitchFamily|=W_FF_SWISS; break;
443 167 : default: nPitchFamily|=W_FF_DONTCARE;
444 : }
445 399 : *pWMF << nPitchFamily;
446 :
447 399 : rtl::OString aFontName(rtl::OUStringToOString(rFont.GetName(), eFontNameEncoding));
448 13167 : for ( i = 0; i < W_LF_FACESIZE; i++ )
449 : {
450 12768 : sal_Char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
451 12768 : *pWMF << nChar;
452 : }
453 399 : UpdateRecordHeader();
454 399 : }
455 :
456 167 : void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
457 : {
458 167 : WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
459 167 : sal_uInt16 nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
460 167 : switch( rLineInfo.GetStyle() )
461 : {
462 : case LINE_DASH :
463 : {
464 0 : if ( rLineInfo.GetDotCount() )
465 : {
466 0 : if ( !rLineInfo.GetDashCount() )
467 0 : nStyle = W_PS_DOT;
468 : else
469 : {
470 0 : if ( !rLineInfo.GetDotCount() == 1 )
471 0 : nStyle = W_PS_DASHDOT;
472 : else
473 0 : nStyle = W_PS_DASHDOTDOT;
474 : }
475 : }
476 : else
477 0 : nStyle = W_PS_DASH;
478 : }
479 0 : break;
480 : case LINE_NONE :
481 0 : nStyle = W_PS_NULL;
482 0 : break;
483 : default:
484 167 : break;
485 : }
486 167 : *pWMF << nStyle;
487 :
488 167 : WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
489 167 : WriteColor( rColor );
490 167 : }
491 :
492 646 : void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
493 : {
494 646 : WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
495 646 : *pWMF << nObjectHandle;
496 646 : }
497 :
498 :
499 0 : void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
500 : {
501 0 : WriteRecordHeader(0x00000007,W_META_ELLIPSE);
502 0 : WriteRectangle(rRect);
503 0 : }
504 :
505 305 : bool IsStarSymbol(const String &rStr)
506 : {
507 305 : return rStr.EqualsIgnoreCaseAscii("starsymbol") ||
508 305 : rStr.EqualsIgnoreCaseAscii("opensymbol");
509 : }
510 :
511 119 : void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
512 : {
513 : #ifdef OSL_BIGENDIAN
514 : sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
515 : sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
516 : #else
517 119 : sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
518 : #endif
519 119 : if ( nLen )
520 119 : nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
521 :
522 119 : WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
523 119 : *pWMF << (sal_uInt16)W_MFCOMMENT
524 238 : << (sal_uInt16)( nLen + 14 ) // we will always have a fourteen byte escape header:
525 119 : << (sal_uInt16)0x4f4f // OO
526 119 : << (sal_uInt32)0xa2c2a // evil magic number
527 119 : << (sal_uInt32)nCheckSum // crc32 checksum about nEsc & pData
528 238 : << (sal_uInt32)nEsc; // escape number
529 119 : pWMF->Write( pData, nLen );
530 119 : if ( nLen & 1 )
531 0 : *pWMF << (sal_uInt8)0; // pad byte
532 119 : }
533 :
534 : /* if return value is true, then a complete unicode string and also a polygon replacement has been written,
535 : so there is no more action necessary
536 : */
537 331 : sal_Bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const String& rUniStr, const sal_Int32* pDXAry )
538 : {
539 331 : sal_Bool bEscapeUsed = sal_False;
540 :
541 331 : sal_uInt32 i, nStringLen = rUniStr.Len();
542 331 : if ( nStringLen )
543 : {
544 : // first we will check if a comment is necessary
545 331 : if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) // symbol is always byte character, so there is no unicode loss
546 : {
547 331 : const sal_Unicode* pBuf = rUniStr.GetBuffer();
548 331 : const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
549 331 : rtl::OString aByteStr(rtl::OUStringToOString(rUniStr, aTextEncodingOrg));
550 331 : rtl::OUString aUniStr2(rtl::OStringToOUString(aByteStr, aTextEncodingOrg));
551 331 : const sal_Unicode* pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
552 638 : for ( i = 0; i < nStringLen; i++ )
553 : {
554 372 : if ( *pBuf++ != *pConversion++ )
555 65 : break;
556 : }
557 :
558 331 : if ( i != nStringLen ) // after conversion the characters are not original,
559 : { // try again, with determining a better charset from unicode char
560 65 : pBuf = rUniStr.GetBuffer();
561 65 : const sal_Unicode* pCheckChar = pBuf;
562 65 : rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
563 67 : for ( i = 1; i < nStringLen; i++)
564 : {
565 4 : if (aTextEncoding != aTextEncodingOrg) // found something
566 2 : break;
567 2 : pCheckChar++;
568 2 : aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
569 : }
570 :
571 65 : aByteStr = rtl::OUStringToOString(rUniStr, aTextEncoding);
572 65 : aUniStr2 = rtl::OStringToOUString(aByteStr, aTextEncoding);
573 65 : pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
574 108 : for ( i = 0; i < nStringLen; i++ )
575 : {
576 69 : if ( *pBuf++ != *pConversion++ )
577 26 : break;
578 : }
579 65 : if (i == nStringLen)
580 : {
581 39 : aSrcFont.SetCharSet (aTextEncoding);
582 39 : SetAllAttr();
583 : }
584 : }
585 :
586 331 : if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) ) // after conversion the characters are not original, so we
587 : { // will store the unicode string and a polypoly replacement
588 119 : Color aOldFillColor( aSrcFillColor );
589 119 : Color aOldLineColor( aSrcLineColor );
590 119 : aSrcLineInfo = LineInfo();
591 119 : aSrcFillColor = aSrcTextColor;
592 119 : aSrcLineColor = Color( COL_TRANSPARENT );
593 119 : SetLineAndFillAttr();
594 119 : pVirDev->SetFont( aSrcFont );
595 119 : std::vector<PolyPolygon> aPolyPolyVec;
596 119 : if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
597 : {
598 119 : sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
599 119 : sal_uInt32 nSkipActions = aPolyPolyVec.size();
600 : sal_Int32 nStrmLen = 8 +
601 : + sizeof( nStringLen ) + ( nStringLen * 2 )
602 : + sizeof( nDXCount ) + ( nDXCount * 4 )
603 119 : + sizeof( nSkipActions );
604 :
605 119 : SvMemoryStream aMemoryStream( nStrmLen );
606 119 : Point aPt( pVirDev->LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
607 119 : aMemoryStream << static_cast<sal_Int32>(aPt.X())
608 238 : << static_cast<sal_Int32>(aPt.Y())
609 119 : << nStringLen;
610 238 : for ( i = 0; i < nStringLen; i++ )
611 119 : aMemoryStream << rUniStr.GetChar( (sal_uInt16)i );
612 119 : aMemoryStream << nDXCount;
613 119 : for ( i = 0; i < nDXCount; i++ )
614 0 : aMemoryStream << pDXAry[ i ];
615 119 : aMemoryStream << nSkipActions;
616 119 : WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
617 :
618 119 : std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
619 311 : while ( aIter != aPolyPolyVec.end() )
620 : {
621 73 : PolyPolygon aPolyPoly( *aIter++ );
622 73 : aPolyPoly.Move( rPoint.X(), rPoint.Y() );
623 73 : WMFRecord_PolyPolygon( aPolyPoly );
624 73 : }
625 119 : aSrcFillColor = aOldFillColor;
626 119 : aSrcLineColor = aOldLineColor;
627 119 : bEscapeUsed = sal_True;
628 119 : }
629 331 : }
630 : }
631 : }
632 331 : return bEscapeUsed;
633 : }
634 :
635 212 : void WMFWriter::WMFRecord_ExtTextOut( const Point & rPoint,
636 : const String & rString, const sal_Int32 * pDXAry )
637 : {
638 212 : sal_uInt16 nOriginalTextLen = rString.Len();
639 :
640 212 : if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
641 : {
642 192 : WMFRecord_TextOut(rPoint, rString);
643 212 : return;
644 : }
645 20 : rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
646 20 : rtl::OString aByteString(rtl::OUStringToOString(rString, eChrSet));
647 20 : TrueExtTextOut(rPoint,rString,aByteString,pDXAry);
648 : }
649 :
650 20 : void WMFWriter::TrueExtTextOut( const Point & rPoint, const String & rString,
651 : const rtl::OString& rByteString, const sal_Int32 * pDXAry )
652 : {
653 20 : WriteRecordHeader( 0, W_META_EXTTEXTOUT );
654 20 : WritePointYX( rPoint );
655 20 : sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
656 20 : *pWMF << nNewTextLen << (sal_uInt16)0;
657 20 : write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
658 20 : if ( nNewTextLen & 1 )
659 15 : *pWMF << (sal_uInt8)0;
660 :
661 20 : sal_uInt16 nOriginalTextLen = rString.Len();
662 20 : sal_Int16* pConvertedDXAry = new sal_Int16[ nOriginalTextLen ];
663 20 : sal_Int32 j = 0;
664 20 : pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
665 41 : for (sal_uInt16 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
666 21 : pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
667 20 : pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
668 :
669 81 : for (sal_uInt16 i = 0; i < nOriginalTextLen; ++i)
670 : {
671 61 : sal_Int16 nDx = pConvertedDXAry[ i ];
672 61 : *pWMF << nDx;
673 61 : if ( nOriginalTextLen < nNewTextLen )
674 : {
675 0 : sal_Unicode nUniChar = rString.GetChar(i);
676 0 : rtl::OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
677 0 : j = aTemp.getLength();
678 0 : while ( --j > 0 )
679 0 : *pWMF << (sal_uInt16)0;
680 : }
681 : }
682 20 : delete[] pConvertedDXAry;
683 20 : UpdateRecordHeader();
684 20 : }
685 :
686 0 : void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
687 : {
688 0 : WriteRecordHeader(0x00000005,W_META_LINETO);
689 0 : WritePointYX(rPoint);
690 0 : }
691 :
692 :
693 0 : void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
694 : {
695 0 : WriteRecordHeader(0x00000005,W_META_MOVETO);
696 0 : WritePointYX(rPoint);
697 0 : }
698 :
699 :
700 0 : void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
701 : {
702 0 : WriteRecordHeader(0x0000000b,W_META_PIE);
703 0 : WritePointYX(rEndPt);
704 0 : WritePointYX(rStartPt);
705 0 : WriteRectangle(rRect);
706 0 : }
707 :
708 :
709 0 : void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
710 : {
711 : sal_uInt16 nSize,i;
712 :
713 0 : Polygon aSimplePoly;
714 0 : if ( rPoly.HasFlags() )
715 0 : rPoly.AdaptiveSubdivide( aSimplePoly );
716 : else
717 0 : aSimplePoly = rPoly;
718 0 : nSize = aSimplePoly.GetSize();
719 0 : WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYGON);
720 0 : *pWMF << nSize;
721 0 : for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
722 0 : }
723 :
724 :
725 0 : void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
726 : {
727 : sal_uInt16 nSize,i;
728 0 : Polygon aSimplePoly;
729 0 : if ( rPoly.HasFlags() )
730 0 : rPoly.AdaptiveSubdivide( aSimplePoly );
731 : else
732 0 : aSimplePoly = rPoly;
733 0 : nSize=aSimplePoly.GetSize();
734 0 : WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYLINE);
735 0 : *pWMF << nSize;
736 0 : for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
737 0 : }
738 :
739 :
740 73 : void WMFWriter::WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly)
741 : {
742 : const Polygon * pPoly;
743 : sal_uInt16 nCount,nSize,i,j;
744 :
745 73 : nCount=rPolyPoly.Count();
746 73 : PolyPolygon aSimplePolyPoly( rPolyPoly );
747 338 : for ( i = 0; i < nCount; i++ )
748 : {
749 265 : if ( aSimplePolyPoly[ i ].HasFlags() )
750 : {
751 178 : Polygon aSimplePoly;
752 178 : aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
753 178 : aSimplePolyPoly[ i ] = aSimplePoly;
754 : }
755 : }
756 73 : WriteRecordHeader(0,W_META_POLYPOLYGON);
757 73 : *pWMF << nCount;
758 73 : for (i=0; i<nCount; i++) *pWMF << ((sal_uInt16)(aSimplePolyPoly.GetObject(i).GetSize()));
759 338 : for (i=0; i<nCount; i++) {
760 265 : pPoly=&(aSimplePolyPoly.GetObject(i));
761 265 : nSize=pPoly->GetSize();
762 265 : for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
763 : }
764 73 : UpdateRecordHeader();
765 73 : }
766 :
767 :
768 19 : void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
769 : {
770 19 : WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
771 19 : WriteRectangle( rRect );
772 19 : }
773 :
774 :
775 379 : void WMFWriter::WMFRecord_RestoreDC()
776 : {
777 379 : WriteRecordHeader(0x00000004,W_META_RESTOREDC);
778 379 : *pWMF << (short)-1;
779 379 : }
780 :
781 :
782 0 : void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
783 : {
784 0 : WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
785 0 : WriteHeightWidth(Size(nHorzRound,nVertRound));
786 0 : WriteRectangle(rRect);
787 0 : }
788 :
789 :
790 379 : void WMFWriter::WMFRecord_SaveDC()
791 : {
792 379 : WriteRecordHeader(0x00000003,W_META_SAVEDC);
793 379 : }
794 :
795 :
796 733 : void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
797 : {
798 733 : WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
799 733 : *pWMF << nObjectHandle;
800 733 : }
801 :
802 :
803 29 : void WMFWriter::WMFRecord_SetBkMode(sal_Bool bTransparent)
804 : {
805 29 : WriteRecordHeader(0x00000004,W_META_SETBKMODE);
806 29 : if (bTransparent==sal_True) *pWMF << (sal_uInt16)W_TRANSPARENT;
807 0 : else *pWMF << (sal_uInt16)W_OPAQUE;
808 29 : }
809 :
810 29 : void WMFWriter::WMFRecord_SetStretchBltMode()
811 : {
812 29 : WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
813 29 : *pWMF << (sal_uInt16) 3; // STRETCH_DELETESCANS
814 29 : }
815 :
816 0 : void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
817 : {
818 0 : WriteRecordHeader(0x00000007,W_META_SETPIXEL);
819 0 : WriteColor(rColor);
820 0 : WritePointYX(rPoint);
821 0 : }
822 :
823 :
824 29 : void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
825 : {
826 : sal_uInt16 nROP2;
827 :
828 29 : switch (eROP) {
829 0 : case ROP_INVERT: nROP2=W_R2_NOT; break;
830 0 : case ROP_XOR: nROP2=W_R2_XORPEN; break;
831 29 : default: nROP2=W_R2_COPYPEN;
832 : }
833 29 : WriteRecordHeader(0x00000004,W_META_SETROP2);
834 29 : *pWMF << nROP2;
835 29 : }
836 :
837 :
838 29 : void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign)
839 : {
840 : sal_uInt16 nAlign;
841 :
842 29 : switch (eFontAlign) {
843 0 : case ALIGN_TOP: nAlign=W_TA_TOP; break;
844 0 : case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
845 29 : default: nAlign=W_TA_BASELINE;
846 : }
847 29 : nAlign|=eHorTextAlign;
848 29 : nAlign|=W_TA_NOUPDATECP;
849 :
850 29 : WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
851 29 : *pWMF << nAlign;
852 29 : }
853 :
854 :
855 360 : void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
856 : {
857 360 : WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
858 360 : WriteColor(rColor);
859 360 : }
860 :
861 :
862 29 : void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
863 : {
864 29 : WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
865 29 : WriteHeightWidth(rSize);
866 29 : }
867 :
868 :
869 29 : void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
870 : {
871 29 : WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
872 29 : WritePointYX(rPoint);
873 29 : }
874 :
875 :
876 0 : void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
877 : const Bitmap & rBitmap, sal_uInt32 nROP )
878 : {
879 : sal_uLong nPosAnf,nPosEnd;
880 :
881 0 : nActBitmapPercent=50;
882 0 : MayCallback();
883 :
884 0 : WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
885 :
886 : // Die Reihenfolge im Metafile soll jetzt sein:
887 : // einige Parameter (laenge 22), dann die Bitmap ohne FILEHEADER.
888 : // Da aber *pWMF << rBitmap einen FILEHEADER der Laenge 14
889 : // erzeugt, schreiben wir zuerst die Bitmap an die richtige Position
890 : // Und ueberschreiben hinterher den FILEHEADER mit den Parametern.
891 0 : nPosAnf=pWMF->Tell(); // Position merken, wo Parameter hin sollen
892 0 : *pWMF << (sal_Int32)0 << (sal_Int32)0; // 8 bytes auffuellen (diese 8 bytes +
893 : // 14 bytes ueberfluessigen FILEHEADER
894 : // = 22 bytes Parameter)
895 0 : *pWMF << rBitmap; // Bitmap schreiben
896 :
897 : // Parameter schreiben:
898 0 : nPosEnd=pWMF->Tell();
899 0 : pWMF->Seek(nPosAnf);
900 :
901 : // Raster-Op bestimmen, falls nichts uebergeben wurde
902 0 : if( !nROP )
903 : {
904 0 : switch( eSrcRasterOp )
905 : {
906 0 : case ROP_INVERT: nROP = W_DSTINVERT; break;
907 0 : case ROP_XOR: nROP = W_SRCINVERT; break;
908 0 : default: nROP = W_SRCCOPY;
909 : }
910 : }
911 :
912 0 : *pWMF << nROP <<
913 0 : (short) 0 <<
914 0 : (short) rBitmap.GetSizePixel().Height() <<
915 0 : (short) rBitmap.GetSizePixel().Width() <<
916 0 : (short) 0 <<
917 0 : (short) 0;
918 :
919 0 : WriteHeightWidth(rSize);
920 0 : WritePointYX(rPoint);
921 0 : pWMF->Seek(nPosEnd);
922 :
923 0 : UpdateRecordHeader();
924 :
925 0 : nWrittenBitmaps++;
926 0 : nActBitmapPercent=0;
927 0 : }
928 :
929 :
930 192 : void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const String & rStr)
931 : {
932 192 : rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
933 192 : rtl::OString aString(rtl::OUStringToOString(rStr, eChrSet));
934 192 : TrueTextOut(rPoint, aString);
935 192 : }
936 :
937 192 : void WMFWriter::TrueTextOut(const Point & rPoint, const rtl::OString& rString)
938 : {
939 192 : WriteRecordHeader(0,W_META_TEXTOUT);
940 :
941 192 : write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(*pWMF, rString);
942 192 : sal_Int32 nLen = rString.getLength();
943 192 : if ((nLen&1)!=0) *pWMF << (sal_uInt8)0;
944 192 : WritePointYX(rPoint);
945 192 : UpdateRecordHeader();
946 192 : }
947 :
948 29 : void WMFWriter::WMFRecord_EndOfFile()
949 : {
950 29 : WriteRecordHeader(0x00000003,0x0000);
951 29 : }
952 :
953 :
954 29 : void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
955 : {
956 29 : WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
957 29 : WriteRectangle(rRect);
958 29 : }
959 :
960 :
961 733 : sal_uInt16 WMFWriter::AllocHandle()
962 : {
963 : sal_uInt16 i;
964 :
965 1853 : for (i=0; i<MAXOBJECTHANDLES; i++) {
966 1853 : if (bHandleAllocated[i]==sal_False) {
967 733 : bHandleAllocated[i]=sal_True;
968 733 : return i;
969 : }
970 : }
971 0 : bStatus=sal_False;
972 0 : return 0xffff;
973 : }
974 :
975 :
976 646 : void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
977 : {
978 646 : if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=sal_False;
979 646 : }
980 :
981 :
982 167 : void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
983 : {
984 : sal_uInt16 nOldHandle;
985 :
986 167 : nOldHandle=nDstPenHandle;
987 167 : nDstPenHandle=AllocHandle();
988 167 : WMFRecord_CreatePenIndirect( rColor, rLineInfo );
989 167 : WMFRecord_SelectObject(nDstPenHandle);
990 167 : if (nOldHandle<MAXOBJECTHANDLES) {
991 138 : WMFRecord_DeleteObject(nOldHandle);
992 138 : FreeHandle(nOldHandle);
993 : }
994 167 : }
995 :
996 :
997 399 : void WMFWriter::CreateSelectDeleteFont(const Font & rFont)
998 : {
999 : sal_uInt16 nOldHandle;
1000 :
1001 399 : nOldHandle=nDstFontHandle;
1002 399 : nDstFontHandle=AllocHandle();
1003 399 : WMFRecord_CreateFontIndirect(rFont);
1004 399 : WMFRecord_SelectObject(nDstFontHandle);
1005 399 : if (nOldHandle<MAXOBJECTHANDLES) {
1006 370 : WMFRecord_DeleteObject(nOldHandle);
1007 370 : FreeHandle(nOldHandle);
1008 : }
1009 399 : }
1010 :
1011 :
1012 167 : void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
1013 : {
1014 : sal_uInt16 nOldHandle;
1015 :
1016 167 : nOldHandle=nDstBrushHandle;
1017 167 : nDstBrushHandle=AllocHandle();
1018 167 : WMFRecord_CreateBrushIndirect(rColor);
1019 167 : WMFRecord_SelectObject(nDstBrushHandle);
1020 167 : if (nOldHandle<MAXOBJECTHANDLES) {
1021 138 : WMFRecord_DeleteObject(nOldHandle);
1022 138 : FreeHandle(nOldHandle);
1023 : }
1024 167 : }
1025 :
1026 :
1027 887 : void WMFWriter::SetLineAndFillAttr()
1028 : {
1029 887 : if ( eDstROP2 != eSrcRasterOp )
1030 : {
1031 0 : eDstROP2=eSrcRasterOp;
1032 0 : WMFRecord_SetROP2(eDstROP2);
1033 : }
1034 887 : if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
1035 : {
1036 138 : aDstLineColor = aSrcLineColor;
1037 138 : aDstLineInfo = aSrcLineInfo;
1038 138 : CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
1039 : }
1040 887 : if ( aDstFillColor != aSrcFillColor )
1041 : {
1042 138 : aDstFillColor = aSrcFillColor;
1043 138 : CreateSelectDeleteBrush( aDstFillColor );
1044 : }
1045 887 : if ( bDstIsClipping != bSrcIsClipping ||
1046 0 : (bSrcIsClipping==sal_True && aDstClipRegion!=aSrcClipRegion)) {
1047 0 : bDstIsClipping=bSrcIsClipping;
1048 0 : aDstClipRegion=aSrcClipRegion;
1049 : }
1050 887 : }
1051 :
1052 749 : void WMFWriter::SetAllAttr()
1053 : {
1054 749 : SetLineAndFillAttr();
1055 749 : if ( aDstTextColor != aSrcTextColor )
1056 : {
1057 331 : aDstTextColor = aSrcTextColor;
1058 331 : WMFRecord_SetTextColor(aDstTextColor);
1059 : }
1060 749 : if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
1061 : {
1062 0 : eDstTextAlign = eSrcTextAlign;
1063 0 : eDstHorTextAlign = eSrcHorTextAlign;
1064 0 : WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
1065 : }
1066 749 : if ( aDstFont != aSrcFont )
1067 : {
1068 370 : pVirDev->SetFont(aSrcFont);
1069 370 : if ( aDstFont.GetName() != aSrcFont.GetName() )
1070 : {
1071 331 : FontCharMap aFontCharMap;
1072 331 : if ( pVirDev->GetFontCharMap( aFontCharMap ) )
1073 : {
1074 331 : if ( ( aFontCharMap.GetFirstChar() & 0xff00 ) == 0xf000 )
1075 0 : aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
1076 331 : else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1077 0 : aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1078 331 : }
1079 : }
1080 370 : aDstFont = aSrcFont;
1081 370 : CreateSelectDeleteFont(aDstFont);
1082 : }
1083 749 : }
1084 :
1085 :
1086 0 : void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
1087 : {
1088 0 : if(rLinePolygon.count())
1089 : {
1090 0 : basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
1091 0 : basegfx::B2DPolyPolygon aFillPolyPolygon;
1092 :
1093 0 : rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
1094 :
1095 0 : if(aLinePolyPolygon.count())
1096 : {
1097 0 : aSrcLineInfo = rInfo;
1098 0 : SetLineAndFillAttr();
1099 :
1100 0 : for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
1101 : {
1102 0 : const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
1103 0 : WMFRecord_PolyLine(Polygon(aCandidate));
1104 0 : }
1105 : }
1106 :
1107 0 : if(aFillPolyPolygon.count())
1108 : {
1109 0 : const Color aOldLineColor(aSrcLineColor);
1110 0 : const Color aOldFillColor(aSrcFillColor);
1111 :
1112 0 : aSrcLineColor = Color( COL_TRANSPARENT );
1113 0 : aSrcFillColor = aOldLineColor;
1114 0 : SetLineAndFillAttr();
1115 :
1116 0 : for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
1117 : {
1118 0 : const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
1119 0 : WMFRecord_Polygon(Polygon(aPolygon));
1120 0 : }
1121 :
1122 0 : aSrcLineColor = aOldLineColor;
1123 0 : aSrcFillColor = aOldFillColor;
1124 0 : SetLineAndFillAttr();
1125 0 : }
1126 : }
1127 0 : }
1128 :
1129 29 : void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
1130 : {
1131 : MetaAction* pMA;
1132 :
1133 29 : if( bStatus )
1134 : {
1135 29 : size_t nACount = rMTF.GetActionSize();
1136 :
1137 29 : WMFRecord_SetStretchBltMode();
1138 :
1139 2752 : for( size_t nA = 0; nA < nACount; nA++ )
1140 : {
1141 2723 : pMA = rMTF.GetAction( nA );
1142 :
1143 2723 : switch( pMA->GetType() )
1144 : {
1145 : case META_PIXEL_ACTION:
1146 : {
1147 0 : const MetaPixelAction* pA = (const MetaPixelAction *) pMA;
1148 0 : aSrcLineInfo = LineInfo();
1149 0 : SetLineAndFillAttr();
1150 0 : WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
1151 : }
1152 0 : break;
1153 :
1154 : case META_POINT_ACTION:
1155 : {
1156 0 : const MetaPointAction* pA = (const MetaPointAction*) pMA;
1157 0 : const Point& rPt = pA->GetPoint();
1158 0 : aSrcLineInfo = LineInfo();
1159 0 : SetLineAndFillAttr();
1160 0 : WMFRecord_MoveTo( rPt);
1161 0 : WMFRecord_LineTo( rPt );
1162 : }
1163 0 : break;
1164 :
1165 : case META_LINE_ACTION:
1166 : {
1167 0 : const MetaLineAction* pA = (const MetaLineAction *) pMA;
1168 0 : if(pA->GetLineInfo().IsDefault())
1169 : {
1170 0 : aSrcLineInfo = pA->GetLineInfo();
1171 0 : SetLineAndFillAttr();
1172 0 : WMFRecord_MoveTo( pA->GetStartPoint() );
1173 0 : WMFRecord_LineTo( pA->GetEndPoint() );
1174 : }
1175 : else
1176 : {
1177 : // LineInfo used; handle Dash/Dot and fat lines
1178 0 : basegfx::B2DPolygon aPolygon;
1179 0 : aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
1180 0 : aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
1181 0 : HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
1182 : }
1183 : }
1184 0 : break;
1185 :
1186 : case META_RECT_ACTION:
1187 : {
1188 19 : const MetaRectAction* pA = (const MetaRectAction*) pMA;
1189 19 : aSrcLineInfo = LineInfo();
1190 19 : SetLineAndFillAttr();
1191 19 : WMFRecord_Rectangle( pA->GetRect() );
1192 : }
1193 19 : break;
1194 :
1195 : case META_ROUNDRECT_ACTION:
1196 : {
1197 0 : const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1198 0 : aSrcLineInfo = LineInfo();
1199 0 : SetLineAndFillAttr();
1200 0 : WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1201 : }
1202 0 : break;
1203 :
1204 : case META_ELLIPSE_ACTION:
1205 : {
1206 0 : const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
1207 0 : aSrcLineInfo = LineInfo();
1208 0 : SetLineAndFillAttr();
1209 0 : WMFRecord_Ellipse( pA->GetRect() );
1210 : }
1211 0 : break;
1212 :
1213 : case META_ARC_ACTION:
1214 : {
1215 0 : const MetaArcAction* pA = (const MetaArcAction*) pMA;
1216 0 : aSrcLineInfo = LineInfo();
1217 0 : SetLineAndFillAttr();
1218 0 : WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
1219 : }
1220 0 : break;
1221 :
1222 : case META_PIE_ACTION:
1223 : {
1224 0 : const MetaPieAction* pA = (const MetaPieAction*) pMA;
1225 0 : aSrcLineInfo = LineInfo();
1226 0 : SetLineAndFillAttr();
1227 0 : WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1228 : }
1229 0 : break;
1230 :
1231 :
1232 : case META_CHORD_ACTION:
1233 : {
1234 0 : const MetaChordAction* pA = (const MetaChordAction*) pMA;
1235 0 : aSrcLineInfo = LineInfo();
1236 0 : SetLineAndFillAttr();
1237 0 : WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1238 : }
1239 0 : break;
1240 :
1241 : case META_POLYLINE_ACTION:
1242 : {
1243 0 : const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1244 0 : const Polygon& rPoly = pA->GetPolygon();
1245 :
1246 0 : if( rPoly.GetSize() )
1247 : {
1248 0 : if(pA->GetLineInfo().IsDefault())
1249 : {
1250 0 : aSrcLineInfo = pA->GetLineInfo();
1251 0 : SetLineAndFillAttr();
1252 0 : WMFRecord_PolyLine( rPoly );
1253 : }
1254 : else
1255 : {
1256 : // LineInfo used; handle Dash/Dot and fat lines
1257 0 : HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
1258 : }
1259 : }
1260 : }
1261 0 : break;
1262 :
1263 : case META_POLYGON_ACTION:
1264 : {
1265 0 : const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1266 0 : aSrcLineInfo = LineInfo();
1267 0 : SetLineAndFillAttr();
1268 0 : WMFRecord_Polygon( pA->GetPolygon() );
1269 : }
1270 0 : break;
1271 :
1272 : case META_POLYPOLYGON_ACTION:
1273 : {
1274 0 : const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1275 0 : aSrcLineInfo = LineInfo();
1276 0 : SetLineAndFillAttr();
1277 0 : WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
1278 : }
1279 0 : break;
1280 :
1281 : case META_TEXTRECT_ACTION:
1282 : {
1283 0 : const MetaTextRectAction * pA = (const MetaTextRectAction*)pMA;
1284 0 : String aTemp( pA->GetText() );
1285 0 : aSrcLineInfo = LineInfo();
1286 0 : SetAllAttr();
1287 :
1288 0 : Point aPos( pA->GetRect().TopLeft() );
1289 0 : if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
1290 0 : WMFRecord_TextOut( aPos, aTemp );
1291 : }
1292 0 : break;
1293 :
1294 : case META_TEXT_ACTION:
1295 : {
1296 0 : const MetaTextAction * pA = (const MetaTextAction*) pMA;
1297 0 : String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1298 0 : aSrcLineInfo = LineInfo();
1299 0 : SetAllAttr();
1300 0 : if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
1301 0 : WMFRecord_TextOut( pA->GetPoint(), aTemp );
1302 : }
1303 0 : break;
1304 :
1305 : case META_TEXTARRAY_ACTION:
1306 : {
1307 0 : const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
1308 :
1309 0 : String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1310 0 : aSrcLineInfo = LineInfo();
1311 0 : SetAllAttr();
1312 0 : if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
1313 0 : WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
1314 : }
1315 0 : break;
1316 :
1317 : case META_STRETCHTEXT_ACTION:
1318 : {
1319 331 : const MetaStretchTextAction* pA = (const MetaStretchTextAction *) pMA;
1320 331 : String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1321 :
1322 : sal_uInt16 nLen,i;
1323 : sal_Int32 nNormSize;
1324 :
1325 331 : pVirDev->SetFont( aSrcFont );
1326 331 : nLen = aTemp.Len();
1327 331 : sal_Int32* pDXAry = nLen ? new sal_Int32[ nLen ] : NULL;
1328 331 : nNormSize = pVirDev->GetTextArray( aTemp, pDXAry );
1329 374 : for ( i = 0; i < ( nLen - 1 ); i++ )
1330 43 : pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
1331 331 : if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
1332 311 : delete[] pDXAry, pDXAry = NULL;
1333 331 : aSrcLineInfo = LineInfo();
1334 331 : SetAllAttr();
1335 331 : if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry ) )
1336 212 : WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry );
1337 331 : delete[] pDXAry;
1338 : }
1339 331 : break;
1340 :
1341 : case META_BMP_ACTION:
1342 : {
1343 0 : const MetaBmpAction* pA = (const MetaBmpAction *) pMA;
1344 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
1345 : }
1346 0 : break;
1347 :
1348 : case META_BMPSCALE_ACTION:
1349 : {
1350 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1351 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1352 : }
1353 0 : break;
1354 :
1355 : case META_BMPSCALEPART_ACTION:
1356 : {
1357 0 : const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
1358 0 : Bitmap aTmp( pA->GetBitmap() );
1359 :
1360 0 : if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1361 0 : WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
1362 : }
1363 0 : break;
1364 :
1365 : case META_BMPEX_ACTION:
1366 : {
1367 0 : const MetaBmpExAction* pA = (const MetaBmpExAction *) pMA;
1368 0 : Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1369 0 : Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1370 :
1371 0 : if( !!aMsk )
1372 : {
1373 0 : aBmp.Replace( aMsk, COL_WHITE );
1374 0 : aMsk.Invert();
1375 0 : WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
1376 0 : WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
1377 : }
1378 : else
1379 0 : WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
1380 : }
1381 0 : break;
1382 :
1383 : case META_BMPEXSCALE_ACTION:
1384 : {
1385 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
1386 0 : Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1387 0 : Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1388 :
1389 0 : if( !!aMsk )
1390 : {
1391 0 : aBmp.Replace( aMsk, COL_WHITE );
1392 0 : aMsk.Invert();
1393 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
1394 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
1395 : }
1396 : else
1397 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
1398 : }
1399 0 : break;
1400 :
1401 : case META_BMPEXSCALEPART_ACTION:
1402 : {
1403 0 : const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
1404 0 : BitmapEx aBmpEx( pA->GetBitmapEx() );
1405 0 : aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1406 0 : Bitmap aBmp( aBmpEx.GetBitmap() );
1407 0 : Bitmap aMsk( aBmpEx.GetMask() );
1408 :
1409 0 : if( !!aMsk )
1410 : {
1411 0 : aBmp.Replace( aMsk, COL_WHITE );
1412 0 : aMsk.Invert();
1413 0 : WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
1414 0 : WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
1415 : }
1416 : else
1417 0 : WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1418 : }
1419 0 : break;
1420 :
1421 : case META_GRADIENT_ACTION:
1422 : {
1423 0 : const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
1424 0 : GDIMetaFile aTmpMtf;
1425 :
1426 0 : pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1427 0 : WriteRecords( aTmpMtf );
1428 : }
1429 0 : break;
1430 :
1431 : case META_HATCH_ACTION:
1432 : {
1433 0 : const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
1434 0 : GDIMetaFile aTmpMtf;
1435 :
1436 0 : pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1437 0 : WriteRecords( aTmpMtf );
1438 : }
1439 0 : break;
1440 :
1441 : case META_WALLPAPER_ACTION:
1442 : {
1443 0 : const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pMA;
1444 0 : const Color& rColor = pA->GetWallpaper().GetColor();
1445 0 : const Color aOldLineColor( aSrcLineColor );
1446 0 : const Color aOldFillColor( aSrcFillColor );
1447 :
1448 0 : aSrcLineColor = rColor;
1449 0 : aSrcFillColor = rColor;
1450 0 : aSrcLineInfo = LineInfo();
1451 0 : SetLineAndFillAttr();
1452 0 : WMFRecord_Rectangle( pA->GetRect() );
1453 0 : aSrcLineColor = aOldLineColor;
1454 0 : aSrcFillColor = aOldFillColor;
1455 : }
1456 0 : break;
1457 :
1458 : case META_ISECTRECTCLIPREGION_ACTION:
1459 : {
1460 29 : const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
1461 29 : WMFRecord_IntersectClipRect( pA->GetRect() );
1462 : }
1463 29 : break;
1464 :
1465 : case META_LINECOLOR_ACTION:
1466 : {
1467 19 : const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
1468 :
1469 19 : if( pA->IsSetting() )
1470 0 : aSrcLineColor = pA->GetColor();
1471 : else
1472 19 : aSrcLineColor = Color( COL_TRANSPARENT );
1473 : }
1474 19 : break;
1475 :
1476 : case META_FILLCOLOR_ACTION:
1477 : {
1478 19 : const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
1479 :
1480 19 : if( pA->IsSetting() )
1481 19 : aSrcFillColor = pA->GetColor();
1482 : else
1483 0 : aSrcFillColor = Color( COL_TRANSPARENT );
1484 : }
1485 19 : break;
1486 :
1487 : case META_TEXTCOLOR_ACTION:
1488 : {
1489 353 : const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
1490 353 : aSrcTextColor = pA->GetColor();
1491 : }
1492 353 : break;
1493 :
1494 : case META_TEXTFILLCOLOR_ACTION:
1495 : {
1496 350 : const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
1497 350 : if( pA->IsSetting() )
1498 0 : aSrcFont.SetFillColor( pA->GetColor() );
1499 : else
1500 350 : aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
1501 : }
1502 350 : break;
1503 :
1504 : case META_TEXTALIGN_ACTION:
1505 : {
1506 350 : const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pMA;
1507 350 : eSrcTextAlign = pA->GetTextAlign();
1508 : }
1509 350 : break;
1510 :
1511 : case META_MAPMODE_ACTION:
1512 : {
1513 0 : const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
1514 :
1515 0 : if (aSrcMapMode!=pA->GetMapMode())
1516 : {
1517 0 : if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
1518 : {
1519 0 : MapMode aMM = pA->GetMapMode();
1520 0 : Fraction aScaleX = aMM.GetScaleX();
1521 0 : Fraction aScaleY = aMM.GetScaleY();
1522 :
1523 0 : Point aOrigin = aSrcMapMode.GetOrigin();
1524 0 : BigInt aX( aOrigin.X() );
1525 0 : aX *= BigInt( aScaleX.GetDenominator() );
1526 0 : if( aOrigin.X() >= 0 )
1527 0 : if( aScaleX.GetNumerator() >= 0 )
1528 0 : aX += BigInt( aScaleX.GetNumerator()/2 );
1529 : else
1530 0 : aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
1531 : else
1532 0 : if( aScaleX.GetNumerator() >= 0 )
1533 0 : aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
1534 : else
1535 0 : aX += BigInt( aScaleX.GetNumerator()/2 );
1536 0 : aX /= BigInt( aScaleX.GetNumerator() );
1537 0 : aOrigin.X() = (long)aX + aMM.GetOrigin().X();
1538 0 : BigInt aY( aOrigin.Y() );
1539 0 : aY *= BigInt( aScaleY.GetDenominator() );
1540 0 : if( aOrigin.Y() >= 0 )
1541 0 : if( aScaleY.GetNumerator() >= 0 )
1542 0 : aY += BigInt( aScaleY.GetNumerator()/2 );
1543 : else
1544 0 : aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
1545 : else
1546 0 : if( aScaleY.GetNumerator() >= 0 )
1547 0 : aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
1548 : else
1549 0 : aY += BigInt( aScaleY.GetNumerator()/2 );
1550 0 : aY /= BigInt( aScaleY.GetNumerator() );
1551 0 : aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
1552 0 : aSrcMapMode.SetOrigin( aOrigin );
1553 :
1554 0 : aScaleX *= aSrcMapMode.GetScaleX();
1555 0 : aScaleY *= aSrcMapMode.GetScaleY();
1556 0 : aSrcMapMode.SetScaleX( aScaleX );
1557 0 : aSrcMapMode.SetScaleY( aScaleY );
1558 : }
1559 : else
1560 0 : aSrcMapMode=pA->GetMapMode();
1561 : }
1562 : }
1563 0 : break;
1564 :
1565 : case META_FONT_ACTION:
1566 : {
1567 350 : const MetaFontAction* pA = (const MetaFontAction*) pMA;
1568 350 : aSrcFont = pA->GetFont();
1569 :
1570 487 : if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW)
1571 137 : || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE) )
1572 : {
1573 350 : aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1574 : }
1575 350 : eSrcTextAlign = aSrcFont.GetAlign();
1576 350 : aSrcTextColor = aSrcFont.GetColor();
1577 350 : aSrcFont.SetAlign( ALIGN_BASELINE );
1578 350 : aSrcFont.SetColor( COL_WHITE );
1579 : }
1580 350 : break;
1581 :
1582 : case META_PUSH_ACTION:
1583 : {
1584 379 : const MetaPushAction* pA = (const MetaPushAction*)pMA;
1585 :
1586 379 : WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
1587 379 : pAt->nFlags = pA->GetFlags();
1588 379 : pAt->aClipRegion = aSrcClipRegion;
1589 379 : pAt->aLineColor=aSrcLineColor;
1590 379 : pAt->aFillColor=aSrcFillColor;
1591 379 : pAt->eRasterOp=eSrcRasterOp;
1592 379 : pAt->aFont=aSrcFont;
1593 379 : pAt->eTextAlign=eSrcTextAlign;
1594 379 : pAt->aTextColor=aSrcTextColor;
1595 379 : pAt->aMapMode=aSrcMapMode;
1596 379 : pAt->aLineInfo=aDstLineInfo;
1597 379 : pAt->pSucc=pAttrStack;
1598 379 : pAttrStack=pAt;
1599 :
1600 379 : SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
1601 379 : WMFRecord_SaveDC();
1602 :
1603 : }
1604 379 : break;
1605 :
1606 : case META_POP_ACTION:
1607 : {
1608 379 : WMFWriterAttrStackMember * pAt=pAttrStack;
1609 :
1610 379 : if( pAt )
1611 : {
1612 379 : aDstLineInfo = pAt->aLineInfo;
1613 379 : aDstLineColor = pAt->aLineColor;
1614 379 : if ( pAt->nFlags & PUSH_LINECOLOR )
1615 379 : aSrcLineColor = pAt->aLineColor;
1616 379 : aDstFillColor = pAt->aFillColor;
1617 379 : if ( pAt->nFlags & PUSH_FILLCOLOR )
1618 379 : aSrcFillColor = pAt->aFillColor;
1619 379 : eDstROP2 = pAt->eRasterOp;
1620 379 : if ( pAt->nFlags & PUSH_RASTEROP )
1621 29 : eSrcRasterOp = pAt->eRasterOp;
1622 379 : aDstFont = pAt->aFont;
1623 379 : if ( pAt->nFlags & PUSH_FONT )
1624 379 : aSrcFont = pAt->aFont;
1625 379 : eDstTextAlign = pAt->eTextAlign;
1626 379 : if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTALIGN ) )
1627 379 : eSrcTextAlign = pAt->eTextAlign;
1628 379 : aDstTextColor = pAt->aTextColor;
1629 379 : if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTCOLOR ) )
1630 379 : aSrcTextColor = pAt->aTextColor;
1631 379 : if ( pAt->nFlags & PUSH_MAPMODE )
1632 379 : aSrcMapMode = pAt->aMapMode;
1633 379 : aDstClipRegion = pAt->aClipRegion;
1634 379 : if ( pAt->nFlags & PUSH_CLIPREGION )
1635 29 : aSrcClipRegion = pAt->aClipRegion;
1636 :
1637 379 : WMFRecord_RestoreDC();
1638 379 : pAttrStack = pAt->pSucc;
1639 379 : delete pAt;
1640 : }
1641 : }
1642 379 : break;
1643 :
1644 : case META_EPS_ACTION :
1645 : {
1646 0 : const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
1647 0 : const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1648 :
1649 0 : size_t nCount = aGDIMetaFile.GetActionSize();
1650 0 : for ( size_t i = 0; i < nCount; i++ )
1651 : {
1652 0 : const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1653 0 : if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
1654 : {
1655 0 : const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
1656 0 : WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1657 0 : break;
1658 : }
1659 0 : }
1660 : }
1661 0 : break;
1662 :
1663 : case META_RASTEROP_ACTION:
1664 : {
1665 0 : const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
1666 0 : eSrcRasterOp=pA->GetRasterOp();
1667 : }
1668 0 : break;
1669 :
1670 : case META_TRANSPARENT_ACTION:
1671 : {
1672 0 : aSrcLineInfo = LineInfo();
1673 0 : SetLineAndFillAttr();
1674 0 : WMFRecord_PolyPolygon( ( (MetaTransparentAction*) pMA )->GetPolyPolygon() );
1675 : }
1676 0 : break;
1677 :
1678 : case META_FLOATTRANSPARENT_ACTION:
1679 : {
1680 0 : const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
1681 :
1682 0 : GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1683 0 : Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1684 0 : const Size aSrcSize( aTmpMtf.GetPrefSize() );
1685 0 : const Point aDestPt( pA->GetPoint() );
1686 0 : const Size aDestSize( pA->GetSize() );
1687 0 : const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1688 0 : const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1689 : long nMoveX, nMoveY;
1690 :
1691 0 : aSrcLineInfo = LineInfo();
1692 0 : SetAllAttr();
1693 :
1694 0 : if( fScaleX != 1.0 || fScaleY != 1.0 )
1695 : {
1696 0 : aTmpMtf.Scale( fScaleX, fScaleY );
1697 0 : aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1698 : }
1699 :
1700 0 : nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1701 :
1702 0 : if( nMoveX || nMoveY )
1703 0 : aTmpMtf.Move( nMoveX, nMoveY );
1704 :
1705 0 : WriteRecords( aTmpMtf );
1706 : }
1707 0 : break;
1708 :
1709 : case( META_LAYOUTMODE_ACTION ):
1710 : {
1711 58 : sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pMA )->GetLayoutMode();
1712 58 : eSrcHorTextAlign = 0; // TA_LEFT
1713 58 : if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
1714 : {
1715 0 : eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
1716 : }
1717 58 : if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
1718 0 : eSrcHorTextAlign |= W_TA_RIGHT;
1719 58 : else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
1720 0 : eSrcHorTextAlign &= ~W_TA_RIGHT;
1721 58 : break;
1722 : }
1723 :
1724 : // Unsupported Actions
1725 : case META_MASK_ACTION:
1726 : case META_MASKSCALE_ACTION:
1727 : case META_MASKSCALEPART_ACTION:
1728 : {
1729 : OSL_FAIL( "Unsupported action: MetaMask...Action!" );
1730 : }
1731 0 : break;
1732 :
1733 : case META_CLIPREGION_ACTION:
1734 0 : break;
1735 :
1736 : case META_ISECTREGIONCLIPREGION_ACTION:
1737 : {
1738 : OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
1739 : }
1740 0 : break;
1741 :
1742 : case META_MOVECLIPREGION_ACTION:
1743 : {
1744 : OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
1745 : }
1746 0 : break;
1747 :
1748 : default:
1749 : {
1750 : OSL_FAIL( "Unsupported meta action!" );
1751 : }
1752 87 : break;
1753 : }
1754 :
1755 2723 : nWrittenActions++;
1756 2723 : MayCallback();
1757 :
1758 2723 : if (pWMF->GetError())
1759 0 : bStatus=sal_False;
1760 :
1761 2723 : if(bStatus==sal_False)
1762 0 : break;
1763 : }
1764 : }
1765 29 : }
1766 :
1767 : // ------------------------------------------------------------------------
1768 :
1769 29 : void WMFWriter::WriteHeader( const GDIMetaFile &, sal_Bool bPlaceable )
1770 : {
1771 29 : if( bPlaceable )
1772 : {
1773 : sal_uInt16 nCheckSum, nValue;
1774 29 : Size aSize( pVirDev->LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
1775 29 : sal_uInt16 nUnitsPerInch = (sal_uInt16) ( ( aSize.Width() + aSize.Height() ) >> 1 );
1776 :
1777 29 : nCheckSum=0;
1778 29 : nValue=0xcdd7; nCheckSum^=nValue; *pWMF << nValue;
1779 29 : nValue=0x9ac6; nCheckSum^=nValue; *pWMF << nValue;
1780 29 : nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1781 29 : nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1782 29 : nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1783 29 : nValue=(sal_uInt16) aTargetSize.Width(); nCheckSum^=nValue; *pWMF << nValue;
1784 29 : nValue=(sal_uInt16) aTargetSize.Height(); nCheckSum^=nValue; *pWMF << nValue;
1785 29 : nValue=nUnitsPerInch; nCheckSum^=nValue; *pWMF << nValue;
1786 29 : nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1787 29 : nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1788 29 : *pWMF << nCheckSum;
1789 : }
1790 :
1791 29 : nMetafileHeaderPos=pWMF->Tell();
1792 29 : *pWMF << (sal_uInt16)0x0001 // Typ: Datei
1793 29 : << (sal_uInt16)0x0009 // Headerlaenge in Worten
1794 29 : << (sal_uInt16)0x0300 // Version als BCD-Zahl
1795 29 : << (sal_uInt32) 0x00000000 // Dateilaenge (ohne 1. Header), wird spaeter durch UpdateHeader() berichtigt
1796 29 : << (sal_uInt16)MAXOBJECTHANDLES // Maximalezahl der gleichzeitigen Objekte
1797 29 : << (sal_uInt32) 0x00000000 // Maximale Record-laenge, wird spaeter durch UpdateHeader() berichtigt
1798 29 : << (sal_uInt16)0x0000; // Reserved
1799 29 : }
1800 :
1801 : // ------------------------------------------------------------------------
1802 :
1803 29 : void WMFWriter::UpdateHeader()
1804 : {
1805 : sal_uLong nPos;
1806 : sal_uInt32 nFileSize;
1807 :
1808 29 : nPos=pWMF->Tell(); // Endposition = Gesammtgroesse der Datei
1809 29 : nFileSize=nPos-nMetafileHeaderPos; // Groesse des 1. Headers abziehen
1810 29 : if ((nFileSize&1)!=0) { // ggf. auf ganze Worte aufrunden
1811 0 : *pWMF << (sal_uInt8)0;
1812 0 : nPos++;
1813 0 : nFileSize++;
1814 : }
1815 29 : nFileSize>>=1; // In Anzahl Worte umrechnen
1816 29 : pWMF->Seek(nMetafileHeaderPos+6); // Zum Dateigroessen-Eintrag im zweiten Header
1817 29 : *pWMF << nFileSize; // Dateigroesse berichtigen
1818 29 : pWMF->SeekRel(2); // Zum Max-Record-Laenge-Eintrag im zweiten Header
1819 29 : *pWMF << nMaxRecordSize; // und berichtigen
1820 29 : pWMF->Seek(nPos);
1821 29 : }
1822 :
1823 : // ------------------------------------------------------------------------
1824 :
1825 29 : sal_Bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
1826 : FilterConfigItem* pFConfigItem, sal_Bool bPlaceable )
1827 : {
1828 : WMFWriterAttrStackMember * pAt;
1829 :
1830 29 : bEmbedEMF = sal_True;
1831 29 : bStatus=sal_True;
1832 29 : pConvert = 0;
1833 29 : pVirDev = new VirtualDevice;
1834 :
1835 29 : pFilterConfigItem = pFConfigItem;
1836 29 : if ( pFilterConfigItem )
1837 : {
1838 29 : xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
1839 29 : if ( xStatusIndicator.is() )
1840 : {
1841 0 : rtl::OUString aMsg;
1842 0 : xStatusIndicator->start( aMsg, 100 );
1843 : }
1844 : }
1845 29 : nLastPercent=0;
1846 :
1847 29 : pWMF=&rTargetStream;
1848 29 : pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1849 :
1850 29 : nMaxRecordSize=0;
1851 :
1852 29 : aSrcMapMode=rMTF.GetPrefMapMode();
1853 :
1854 29 : if( bPlaceable )
1855 : {
1856 29 : aTargetMapMode = aSrcMapMode;
1857 29 : aTargetSize = rMTF.GetPrefSize();
1858 29 : nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
1859 29 : aTargetSize.Width() /= nTargetDivisor;
1860 29 : aTargetSize.Height() /= nTargetDivisor;
1861 : }
1862 : else
1863 : {
1864 0 : aTargetMapMode = MapMode( MAP_INCH );
1865 :
1866 0 : const long nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
1867 0 : const Fraction aFrac( 1, nUnit );
1868 :
1869 0 : aTargetMapMode.SetScaleX( aFrac );
1870 0 : aTargetMapMode.SetScaleY( aFrac );
1871 0 : aTargetSize = pVirDev->LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
1872 : }
1873 :
1874 29 : pVirDev->SetMapMode( aTargetMapMode );
1875 :
1876 29 : pAttrStack=NULL;
1877 :
1878 493 : for (sal_uInt16 i=0; i<MAXOBJECTHANDLES; i++)
1879 464 : bHandleAllocated[i]=sal_False;
1880 :
1881 29 : nDstPenHandle=0xffff;
1882 29 : nDstFontHandle=0xffff;
1883 29 : nDstBrushHandle=0xffff;
1884 :
1885 29 : nNumberOfActions=0;
1886 29 : nNumberOfBitmaps=0;
1887 29 : nWrittenActions=0;
1888 29 : nWrittenBitmaps=0;
1889 29 : nActBitmapPercent=0;
1890 :
1891 29 : CountActionsAndBitmaps(rMTF);
1892 :
1893 29 : WriteHeader(rMTF,bPlaceable);
1894 29 : if( bEmbedEMF )
1895 29 : WriteEmbeddedEMF( rMTF );
1896 29 : WMFRecord_SetWindowOrg(Point(0,0));
1897 29 : WMFRecord_SetWindowExt(rMTF.GetPrefSize());
1898 29 : WMFRecord_SetBkMode( sal_True );
1899 :
1900 29 : eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
1901 29 : WMFRecord_SetROP2(eDstROP2);
1902 :
1903 29 : aDstLineInfo = LineInfo();
1904 29 : aDstLineColor = aSrcLineColor = Color( COL_BLACK );
1905 29 : CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
1906 :
1907 29 : aDstFillColor = aSrcFillColor = Color( COL_WHITE );
1908 29 : CreateSelectDeleteBrush( aDstFillColor );
1909 :
1910 29 : aDstClipRegion = aSrcClipRegion = Region();
1911 29 : bDstIsClipping = bSrcIsClipping = sal_False;
1912 :
1913 29 : Font aFont;
1914 29 : aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252 ) );
1915 29 : aFont.SetColor( Color( COL_WHITE ) );
1916 29 : aFont.SetAlign( ALIGN_BASELINE );
1917 29 : aDstFont = aSrcFont = aFont;
1918 29 : CreateSelectDeleteFont(aDstFont);
1919 :
1920 29 : eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
1921 29 : eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
1922 29 : WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
1923 :
1924 29 : aDstTextColor = aSrcTextColor = Color( COL_WHITE );
1925 29 : WMFRecord_SetTextColor(aDstTextColor);
1926 :
1927 : // Write records
1928 29 : WriteRecords(rMTF);
1929 :
1930 29 : WMFRecord_EndOfFile();
1931 29 : UpdateHeader();
1932 :
1933 58 : while(pAttrStack)
1934 : {
1935 0 : pAt=pAttrStack;
1936 0 : pAttrStack=pAt->pSucc;
1937 0 : delete pAt;
1938 : }
1939 :
1940 29 : delete pVirDev;
1941 29 : delete pConvert;
1942 :
1943 29 : if ( xStatusIndicator.is() )
1944 0 : xStatusIndicator->end();
1945 :
1946 29 : return bStatus;
1947 : }
1948 :
1949 : // ------------------------------------------------------------------------
1950 :
1951 29 : sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
1952 : const Size& rPrefSize)
1953 : {
1954 29 : Fraction aDivFrac(2, 1);
1955 29 : sal_uInt16 nDivisor = 1;
1956 :
1957 29 : Size aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1958 :
1959 58 : while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
1960 : {
1961 0 : Fraction aFrac = rMapMode.GetScaleX();
1962 :
1963 0 : aFrac *= aDivFrac;
1964 0 : rMapMode.SetScaleX(aFrac);
1965 0 : aFrac = rMapMode.GetScaleY();
1966 0 : aFrac *= aDivFrac;
1967 0 : rMapMode.SetScaleY(aFrac);
1968 0 : nDivisor <<= 1;
1969 0 : aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1970 : }
1971 :
1972 29 : return nDivisor;
1973 : }
1974 :
1975 : // ------------------------------------------------------------------------
1976 :
1977 29 : void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
1978 : {
1979 29 : SvMemoryStream aStream;
1980 29 : EMFWriter aEMFWriter(aStream);
1981 :
1982 29 : if( aEMFWriter.WriteEMF( rMTF ) )
1983 : {
1984 29 : sal_Size nTotalSize = aStream.Tell();
1985 : if( nTotalSize > SAL_MAX_UINT32 )
1986 29 : return;
1987 29 : aStream.Seek( 0 );
1988 29 : sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
1989 29 : sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
1990 29 : sal_uInt16 nCheckSum = 0, nWord;
1991 :
1992 29 : sal_uInt32 nPos = 0;
1993 :
1994 91792 : while( nPos + 1 < nTotalSize )
1995 : {
1996 91734 : aStream >> nWord;
1997 91734 : nCheckSum ^= nWord;
1998 91734 : nPos += 2;
1999 : }
2000 :
2001 29 : nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
2002 :
2003 29 : aStream.Seek( 0 );
2004 98 : while( nRemainingSize > 0 )
2005 : {
2006 : sal_uInt32 nCurSize;
2007 40 : if( nRemainingSize > 0x2000 )
2008 : {
2009 11 : nCurSize = 0x2000;
2010 11 : nRemainingSize -= 0x2000;
2011 : }
2012 : else
2013 : {
2014 29 : nCurSize = nRemainingSize;
2015 29 : nRemainingSize = 0;
2016 : }
2017 : WriteEMFRecord( aStream,
2018 : nCurSize,
2019 : nRemainingSize,
2020 : nTotalSize,
2021 : nRecCounts,
2022 40 : nCheckSum );
2023 40 : nCheckSum = 0;
2024 : }
2025 29 : }
2026 : }
2027 :
2028 : // ------------------------------------------------------------------------
2029 :
2030 40 : void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
2031 : sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
2032 : {
2033 : // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
2034 40 : WriteRecordHeader( 0, W_META_ESCAPE );
2035 40 : *pWMF << (sal_uInt16)W_MFCOMMENT // same as META_ESCAPE_ENHANCED_METAFILE
2036 80 : << (sal_uInt16)( nCurSize + 34 ) // we will always have a 34 byte escape header:
2037 40 : << (sal_uInt32) 0x43464D57 // WMFC
2038 40 : << (sal_uInt32) 0x00000001 // Comment type
2039 40 : << (sal_uInt32) 0x00010000 // version
2040 80 : << nCheckSum // check sum
2041 40 : << (sal_uInt32) 0 // flags = 0
2042 40 : << nRecCounts // total number of records
2043 40 : << nCurSize // size of this record's data
2044 40 : << nRemainingSize // remaining size of data in following records, missing in MSDN documentation
2045 40 : << nTotalSize; // total size of EMF stream
2046 :
2047 40 : pWMF->Write( static_cast< const sal_Char* >( rStream.GetData() ) + rStream.Tell(), nCurSize );
2048 40 : rStream.SeekRel( nCurSize );
2049 40 : UpdateRecordHeader();
2050 40 : }
2051 :
2052 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|