merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / filter.vcl / wmf / wmfwr.cxx
blobdbf6ead41f1ac69eb00770587ead0a3b6a859f33
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wmfwr.cxx,v $
10 * $Revision: 1.31 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <vcl/salbtype.hxx>
35 #include "wmfwr.hxx"
36 #include <vcl/fontcvt.hxx>
37 #include <rtl/crc.h>
38 #include <rtl/tencinfo.h>
39 #include <tools/tenccvt.hxx>
40 #include <osl/endian.h>
41 #ifndef INCLUDED_I18NUTIL_UNICODE_HXX
42 #include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
43 #endif
46 #include <vcl/metric.hxx>
48 //====================== MS-Windows-defines ===============================
50 #define W_META_SETBKCOLOR 0x0201
51 #define W_META_SETBKMODE 0x0102
52 #define W_META_SETMAPMODE 0x0103
53 #define W_META_SETROP2 0x0104
54 #define W_META_SETRELABS 0x0105
55 #define W_META_SETPOLYFILLMODE 0x0106
56 #define W_META_SETSTRETCHBLTMODE 0x0107
57 #define W_META_SETTEXTCHAREXTRA 0x0108
58 #define W_META_SETTEXTCOLOR 0x0209
59 #define W_META_SETTEXTJUSTIFICATION 0x020A
60 #define W_META_SETWINDOWORG 0x020B
61 #define W_META_SETWINDOWEXT 0x020C
62 #define W_META_SETVIEWPORTORG 0x020D
63 #define W_META_SETVIEWPORTEXT 0x020E
64 #define W_META_OFFSETWINDOWORG 0x020F
65 #define W_META_SCALEWINDOWEXT 0x0410
66 #define W_META_OFFSETVIEWPORTORG 0x0211
67 #define W_META_SCALEVIEWPORTEXT 0x0412
68 #define W_META_LINETO 0x0213
69 #define W_META_MOVETO 0x0214
70 #define W_META_EXCLUDECLIPRECT 0x0415
71 #define W_META_INTERSECTCLIPRECT 0x0416
72 #define W_META_ARC 0x0817
73 #define W_META_ELLIPSE 0x0418
74 #define W_META_FLOODFILL 0x0419
75 #define W_META_PIE 0x081A
76 #define W_META_RECTANGLE 0x041B
77 #define W_META_ROUNDRECT 0x061C
78 #define W_META_PATBLT 0x061D
79 #define W_META_SAVEDC 0x001E
80 #define W_META_SETPIXEL 0x041F
81 #define W_META_OFFSETCLIPRGN 0x0220
82 #define W_META_TEXTOUT 0x0521
83 #define W_META_BITBLT 0x0922
84 #define W_META_STRETCHBLT 0x0B23
85 #define W_META_POLYGON 0x0324
86 #define W_META_POLYLINE 0x0325
87 #define W_META_ESCAPE 0x0626
88 #define W_META_RESTOREDC 0x0127
89 #define W_META_FILLREGION 0x0228
90 #define W_META_FRAMEREGION 0x0429
91 #define W_META_INVERTREGION 0x012A
92 #define W_META_PAINTREGION 0x012B
93 #define W_META_SELECTCLIPREGION 0x012C
94 #define W_META_SELECTOBJECT 0x012D
95 #define W_META_SETTEXTALIGN 0x012E
96 #define W_META_DRAWTEXT 0x062F
97 #define W_META_CHORD 0x0830
98 #define W_META_SETMAPPERFLAGS 0x0231
99 #define W_META_EXTTEXTOUT 0x0a32
100 #define W_META_SETDIBTODEV 0x0d33
101 #define W_META_SELECTPALETTE 0x0234
102 #define W_META_REALIZEPALETTE 0x0035
103 #define W_META_ANIMATEPALETTE 0x0436
104 #define W_META_SETPALENTRIES 0x0037
105 #define W_META_POLYPOLYGON 0x0538
106 #define W_META_RESIZEPALETTE 0x0139
107 #define W_META_DIBBITBLT 0x0940
108 #define W_META_DIBSTRETCHBLT 0x0b41
109 #define W_META_DIBCREATEPATTERNBRUSH 0x0142
110 #define W_META_STRETCHDIB 0x0f43
111 #define W_META_EXTFLOODFILL 0x0548
112 #define W_META_RESETDC 0x014C
113 #define W_META_STARTDOC 0x014D
114 #define W_META_STARTPAGE 0x004F
115 #define W_META_ENDPAGE 0x0050
116 #define W_META_ABORTDOC 0x0052
117 #define W_META_ENDDOC 0x005E
118 #define W_META_DELETEOBJECT 0x01f0
119 #define W_META_CREATEPALETTE 0x00f7
120 #define W_META_CREATEBRUSH 0x00F8
121 #define W_META_CREATEPATTERNBRUSH 0x01F9
122 #define W_META_CREATEPENINDIRECT 0x02FA
123 #define W_META_CREATEFONTINDIRECT 0x02FB
124 #define W_META_CREATEBRUSHINDIRECT 0x02FC
125 #define W_META_CREATEBITMAPINDIRECT 0x02FD
126 #define W_META_CREATEBITMAP 0x06FE
127 #define W_META_CREATEREGION 0x06FF
129 #define W_TRANSPARENT 1
130 #define W_OPAQUE 2
132 #define W_R2_BLACK 1
133 #define W_R2_NOTMERGEPEN 2
134 #define W_R2_MASKNOTPEN 3
135 #define W_R2_NOTCOPYPEN 4
136 #define W_R2_MASKPENNOT 5
137 #define W_R2_NOT 6
138 #define W_R2_XORPEN 7
139 #define W_R2_NOTMASKPEN 8
140 #define W_R2_MASKPEN 9
141 #define W_R2_NOTXORPEN 10
142 #define W_R2_NOP 11
143 #define W_R2_MERGENOTPEN 12
144 #define W_R2_COPYPEN 13
145 #define W_R2_MERGEPENNOT 14
146 #define W_R2_MERGEPEN 15
147 #define W_R2_WHITE 16
149 #define W_TA_NOUPDATECP 0x0000
150 #define W_TA_UPDATECP 0x0001
151 #define W_TA_LEFT 0x0000
152 #define W_TA_RIGHT 0x0002
153 #define W_TA_CENTER 0x0006
154 #define W_TA_TOP 0x0000
155 #define W_TA_BOTTOM 0x0008
156 #define W_TA_BASELINE 0x0018
157 #define W_TA_RTLREADING 0x0100
159 #define W_SRCCOPY 0x00CC0020L
160 #define W_SRCPAINT 0x00EE0086L
161 #define W_SRCAND 0x008800C6L
162 #define W_SRCINVERT 0x00660046L
163 #define W_SRCERASE 0x00440328L
164 #define W_NOTSRCCOPY 0x00330008L
165 #define W_NOTSRCERASE 0x001100A6L
166 #define W_MERGECOPY 0x00C000CAL
167 #define W_MERGEPAINT 0x00BB0226L
168 #define W_PATCOPY 0x00F00021L
169 #define W_PATPAINT 0x00FB0A09L
170 #define W_PATINVERT 0x005A0049L
171 #define W_DSTINVERT 0x00550009L
172 #define W_BLACKNESS 0x00000042L
173 #define W_WHITENESS 0x00FF0062L
175 #define W_PS_SOLID 0
176 #define W_PS_DASH 1
177 #define W_PS_DOT 2
178 #define W_PS_DASHDOT 3
179 #define W_PS_DASHDOTDOT 4
180 #define W_PS_NULL 5
181 #define W_PS_INSIDEFRAME 6
183 #define W_LF_FACESIZE 32
185 #define W_ANSI_CHARSET 0
186 #define W_DEFAULT_CHARSET 1
187 #define W_SYMBOL_CHARSET 2
188 #define W_SHIFTJIS_CHARSET 128
189 #define W_HANGEUL_CHARSET 129
190 #define W_GB2312_CHARSET 134
191 #define W_CHINESEBIG5_CHARSET 136
192 #define W_OEM_CHARSET 255
193 /*WINVER >= 0x0400*/
194 #define W_JOHAB_CHARSET 130
195 #define W_HEBREW_CHARSET 177
196 #define W_ARABIC_CHARSET 178
197 #define W_GREEK_CHARSET 161
198 #define W_TURKISH_CHARSET 162
199 #define W_VIETNAMESE_CHARSET 163
200 #define W_THAI_CHARSET 222
201 #define W_EASTEUROPE_CHARSET 238
202 #define W_RUSSIAN_CHARSET 204
203 #define W_MAC_CHARSET 77
204 #define W_BALTIC_CHARSET 186
206 #define W_DEFAULT_PITCH 0x00
207 #define W_FIXED_PITCH 0x01
208 #define W_VARIABLE_PITCH 0x02
210 #define W_FF_DONTCARE 0x00
211 #define W_FF_ROMAN 0x10
212 #define W_FF_SWISS 0x20
213 #define W_FF_MODERN 0x30
214 #define W_FF_SCRIPT 0x40
215 #define W_FF_DECORATIVE 0x50
217 #define W_FW_DONTCARE 0
218 #define W_FW_THIN 100
219 #define W_FW_EXTRALIGHT 200
220 #define W_FW_LIGHT 300
221 #define W_FW_NORMAL 400
222 #define W_FW_MEDIUM 500
223 #define W_FW_SEMIBOLD 600
224 #define W_FW_BOLD 700
225 #define W_FW_EXTRABOLD 800
226 #define W_FW_HEAVY 900
227 #define W_FW_ULTRALIGHT 200
228 #define W_FW_REGULAR 400
229 #define W_FW_DEMIBOLD 600
230 #define W_FW_ULTRABOLD 800
231 #define W_FW_BLACK 900
233 #define W_BS_SOLID 0
234 #define W_BS_HOLLOW 1
235 #define W_BS_HATCHED 2
236 #define W_BS_PATTERN 3
237 #define W_BS_INDEXED 4
238 #define W_BS_DIBPATTERN 5
240 #define W_HS_HORIZONTAL 0
241 #define W_HS_VERTICAL 1
242 #define W_HS_FDIAGONAL 2
243 #define W_HS_BDIAGONAL 3
244 #define W_HS_CROSS 4
245 #define W_HS_DIAGCROSS 5
247 #define W_MFCOMMENT 15
249 #define PRIVATE_ESCAPE_UNICODE 2
251 /// copied from writerwordglue.cxx
254 Utility to categorize unicode characters into the best fit windows charset
255 range for exporting to ww6, or as a hint to non \u unicode token aware rtf
256 readers
258 rtl_TextEncoding getScriptClass(sal_Unicode cChar)
260 using namespace com::sun::star::i18n;
262 static ScriptTypeList aScripts[] =
264 { UnicodeScript_kBasicLatin, UnicodeScript_kBasicLatin, RTL_TEXTENCODING_MS_1252},
265 { UnicodeScript_kLatin1Supplement, UnicodeScript_kLatin1Supplement, RTL_TEXTENCODING_MS_1252},
266 { UnicodeScript_kLatinExtendedA, UnicodeScript_kLatinExtendedA, RTL_TEXTENCODING_MS_1250},
267 { UnicodeScript_kLatinExtendedB, UnicodeScript_kLatinExtendedB, RTL_TEXTENCODING_MS_1257},
268 { UnicodeScript_kGreek, UnicodeScript_kGreek, RTL_TEXTENCODING_MS_1253},
269 { UnicodeScript_kCyrillic, UnicodeScript_kCyrillic, RTL_TEXTENCODING_MS_1251},
270 { UnicodeScript_kHebrew, UnicodeScript_kHebrew, RTL_TEXTENCODING_MS_1255},
271 { UnicodeScript_kArabic, UnicodeScript_kArabic, RTL_TEXTENCODING_MS_1256},
272 { UnicodeScript_kThai, UnicodeScript_kThai, RTL_TEXTENCODING_MS_1258},
273 { UnicodeScript_kScriptCount, UnicodeScript_kScriptCount, RTL_TEXTENCODING_MS_1252}
275 return unicode::getUnicodeScriptType(cChar, aScripts,
276 RTL_TEXTENCODING_MS_1252);
279 //========================== Methoden von WMFWriter ==========================
281 void WMFWriter::MayCallback()
283 if ( xStatusIndicator.is() )
285 ULONG nPercent;
287 // Wir gehen mal einfach so davon aus, dass 16386 Actions einer Bitmap entsprechen
288 // (in der Regel wird ein Metafile entweder nur Actions oder einige Bitmaps und fast
289 // keine Actions enthalten. Dann ist das Verhaeltnis ziemlich unwichtig)
291 nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
292 *100
293 /((nNumberOfBitmaps<<14)+nNumberOfActions);
295 if ( nPercent >= nLastPercent + 3 )
297 nLastPercent = nPercent;
298 if( nPercent <= 100 )
299 xStatusIndicator->setValue( nPercent );
304 void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
306 ULONG nAction, nActionCount;
308 nActionCount = rMTF.GetActionCount();
310 for ( nAction=0; nAction<nActionCount; nAction++ )
312 MetaAction* pMA = rMTF.GetAction( nAction );
314 switch( pMA->GetType() )
316 case META_BMP_ACTION:
317 case META_BMPSCALE_ACTION:
318 case META_BMPSCALEPART_ACTION:
319 case META_BMPEX_ACTION:
320 case META_BMPEXSCALE_ACTION:
321 case META_BMPEXSCALEPART_ACTION:
322 nNumberOfBitmaps++;
323 break;
325 nNumberOfActions++;
330 void WMFWriter::WritePointXY(const Point & rPoint)
332 Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
333 *pWMF << ((short)aPt.X()) << ((short)aPt.Y());
337 void WMFWriter::WritePointYX(const Point & rPoint)
339 Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
340 *pWMF << ((short)aPt.Y()) << ((short)aPt.X());
344 sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
346 Size aSz( pVirDev->LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
347 return aSz.Width();
351 void WMFWriter::WriteSize(const Size & rSize)
353 Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
354 *pWMF << ((short)aSz.Width()) << ((short)aSz.Height());
358 void WMFWriter::WriteHeightWidth(const Size & rSize)
360 Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
361 *pWMF << ((short)aSz.Height()) << ((short)aSz.Width());
365 void WMFWriter::WriteRectangle(const Rectangle & rRect)
367 WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
368 WritePointYX(rRect.TopLeft());
372 void WMFWriter::WriteColor(const Color & rColor)
374 *pWMF << (BYTE) rColor.GetRed() << (BYTE) rColor.GetGreen() << (BYTE) rColor.GetBlue() << (BYTE) 0;
378 void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
380 nActRecordPos=pWMF->Tell();
381 if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
382 *pWMF << nSizeWords << nType;
386 void WMFWriter::UpdateRecordHeader()
388 ULONG nPos;
389 sal_uInt32 nSize;
391 nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
392 if ((nSize & 1)!=0) {
393 *pWMF << (BYTE)0;
394 nPos++; nSize++;
396 nSize/=2;
397 if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
398 pWMF->Seek(nActRecordPos);
399 *pWMF << nSize;
400 pWMF->Seek(nPos);
404 void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
406 WriteRecordHeader(0x0000000b,W_META_ARC);
407 WritePointYX(rEndPt);
408 WritePointYX(rStartPt);
409 WriteRectangle(rRect);
412 void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
414 WriteRecordHeader(0x0000000b,W_META_CHORD);
415 WritePointYX(rEndPt);
416 WritePointYX(rStartPt);
417 WriteRectangle(rRect);
421 void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
423 WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
425 if( rColor==Color(COL_TRANSPARENT) )
426 *pWMF << (UINT16) W_BS_HOLLOW;
427 else
428 *pWMF << (UINT16) W_BS_SOLID;
430 WriteColor( rColor );
431 *pWMF << (UINT16) 0;
435 void WMFWriter::WMFRecord_CreateFontIndirect(const Font & rFont)
437 USHORT nWeight,i;
438 BYTE nPitchFamily;
440 WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
441 WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
442 *pWMF << (short)rFont.GetOrientation() << (short)rFont.GetOrientation();
444 switch (rFont.GetWeight()) {
445 case WEIGHT_THIN: nWeight=W_FW_THIN; break;
446 case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
447 case WEIGHT_LIGHT: nWeight=W_FW_LIGHT; break;
448 case WEIGHT_SEMILIGHT: nWeight=W_FW_LIGHT; break;
449 case WEIGHT_NORMAL: nWeight=W_FW_NORMAL; break;
450 case WEIGHT_MEDIUM: nWeight=W_FW_MEDIUM; break;
451 case WEIGHT_SEMIBOLD: nWeight=W_FW_SEMIBOLD; break;
452 case WEIGHT_BOLD: nWeight=W_FW_BOLD; break;
453 case WEIGHT_ULTRABOLD: nWeight=W_FW_ULTRABOLD; break;
454 case WEIGHT_BLACK: nWeight=W_FW_BLACK; break;
455 default: nWeight=W_FW_DONTCARE;
457 *pWMF << nWeight;
459 if (rFont.GetItalic()==ITALIC_NONE) *pWMF << (BYTE)0; else *pWMF << (BYTE)1;
460 if (rFont.GetUnderline()==UNDERLINE_NONE) *pWMF << (BYTE)0; else *pWMF << (BYTE)1;
461 if (rFont.GetStrikeout()==STRIKEOUT_NONE) *pWMF << (BYTE)0; else *pWMF << (BYTE)1;
463 CharSet eFontNameEncoding = rFont.GetCharSet();
464 sal_uInt8 nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
465 if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
466 eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
467 if ( nCharSet == 1 )
468 nCharSet = W_ANSI_CHARSET;
469 *pWMF << nCharSet;
471 *pWMF << (BYTE)0 << (BYTE)0 << (BYTE)0;
473 switch (rFont.GetPitch()) {
474 case PITCH_FIXED: nPitchFamily=W_FIXED_PITCH; break;
475 case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
476 default: nPitchFamily=W_DEFAULT_PITCH;
478 switch (rFont.GetFamily()) {
479 case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
480 case FAMILY_MODERN: nPitchFamily|=W_FF_MODERN; break;
481 case FAMILY_ROMAN: nPitchFamily|=W_FF_ROMAN; break;
482 case FAMILY_SCRIPT: nPitchFamily|=W_FF_SCRIPT; break;
483 case FAMILY_SWISS: nPitchFamily|=W_FF_SWISS; break;
484 default: nPitchFamily|=W_FF_DONTCARE;
486 *pWMF << nPitchFamily;
488 ByteString aFontName( rFont.GetName(), eFontNameEncoding );
489 for ( i = 0; i < W_LF_FACESIZE; i++ )
491 sal_Char nChar = ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0;
492 *pWMF << nChar;
494 UpdateRecordHeader();
497 void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
499 WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
500 USHORT nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
501 switch( rLineInfo.GetStyle() )
503 case LINE_DASH :
505 if ( rLineInfo.GetDotCount() )
507 if ( !rLineInfo.GetDashCount() )
508 nStyle = W_PS_DOT;
509 else
511 if ( !rLineInfo.GetDotCount() == 1 )
512 nStyle = W_PS_DASHDOT;
513 else
514 nStyle = W_PS_DASHDOTDOT;
517 else
518 nStyle = W_PS_DASH;
520 break;
521 case LINE_NONE :
522 nStyle = W_PS_NULL;
523 break;
524 default:
525 break;
527 *pWMF << nStyle;
529 WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
530 WriteColor( rColor );
533 void WMFWriter::WMFRecord_DeleteObject(USHORT nObjectHandle)
535 WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
536 *pWMF << nObjectHandle;
540 void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
542 WriteRecordHeader(0x00000007,W_META_ELLIPSE);
543 WriteRectangle(rRect);
546 bool IsStarSymbol(const String &rStr)
548 return rStr.EqualsIgnoreCaseAscii("starsymbol") ||
549 rStr.EqualsIgnoreCaseAscii("opensymbol");
552 void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
554 #ifdef OSL_BIGENDIAN
555 sal_uInt32 nTmp = SWAPLONG( nEsc );
556 sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
557 #else
558 sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
559 #endif
560 if ( nLen )
561 nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
563 WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
564 *pWMF << (sal_uInt16)W_MFCOMMENT
565 << (sal_uInt16)( nLen + 14 ) // we will always have a fourteen byte escape header:
566 << (sal_uInt16)0x4f4f // OO
567 << (sal_uInt32)0xa2c2a // evil magic number
568 << (sal_uInt32)nCheckSum // crc32 checksum about nEsc & pData
569 << (sal_uInt32)nEsc; // escape number
570 pWMF->Write( pData, nLen );
571 if ( nLen & 1 )
572 *pWMF << (sal_uInt8)0; // pad byte
575 /* if return value is true, then a complete unicode string and also a polygon replacement has been written,
576 so there is no more action necessary
578 sal_Bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const String& rUniStr, const sal_Int32* pDXAry )
580 sal_Bool bEscapeUsed = sal_False;
582 sal_uInt32 i, nStringLen = rUniStr.Len();
583 if ( nStringLen )
585 // first we will check if a comment is necessary
586 if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) // symbol is always byte character, so there is no unicode loss
588 const sal_Unicode* pBuf = rUniStr.GetBuffer();
589 const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
590 ByteString aByteStr( rUniStr, aTextEncodingOrg );
591 String aUniStr2( aByteStr, aTextEncodingOrg );
592 const sal_Unicode* pConversion = aUniStr2.GetBuffer(); // this is the unicode array after bytestring <-> unistring conversion
593 for ( i = 0; i < nStringLen; i++ )
595 if ( *pBuf++ != *pConversion++ )
596 break;
599 if ( i != nStringLen ) // after conversion the characters are not original,
600 { // try again, with determining a better charset from unicode char
601 pBuf = rUniStr.GetBuffer();
602 const sal_Unicode* pCheckChar = pBuf;
603 rtl_TextEncoding aTextEncoding = getScriptClass (*pCheckChar); // try the first character
604 for ( i = 1; i < nStringLen; i++)
606 if (aTextEncoding != aTextEncodingOrg) // found something
607 break;
608 pCheckChar++;
609 aTextEncoding = getScriptClass (*pCheckChar); // try the next character
612 aByteStr = ByteString ( rUniStr, aTextEncoding );
613 aUniStr2 = String ( aByteStr, aTextEncoding );
614 pConversion = aUniStr2.GetBuffer(); // this is the unicode array after bytestring <-> unistring conversion
615 for ( i = 0; i < nStringLen; i++ )
617 if ( *pBuf++ != *pConversion++ )
618 break;
620 if (i == nStringLen)
622 aSrcFont.SetCharSet (aTextEncoding);
623 SetAllAttr();
627 if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) ) // after conversion the characters are not original, so we
628 { // will store the unicode string and a polypoly replacement
629 Color aOldFillColor( aSrcFillColor );
630 Color aOldLineColor( aSrcLineColor );
631 aSrcLineInfo = LineInfo();
632 aSrcFillColor = aSrcTextColor;
633 aSrcLineColor = Color( COL_TRANSPARENT );
634 SetLineAndFillAttr();
635 pVirDev->SetFont( aSrcFont );
636 std::vector<PolyPolygon> aPolyPolyVec;
637 if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
639 sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
640 sal_uInt32 nSkipActions = aPolyPolyVec.size();
641 sal_Int32 nStrmLen = 8 +
642 + sizeof( nStringLen ) + ( nStringLen * 2 )
643 + sizeof( nDXCount ) + ( nDXCount * 4 )
644 + sizeof( nSkipActions );
646 SvMemoryStream aMemoryStream( nStrmLen );
647 Point aPt( pVirDev->LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
648 aMemoryStream << aPt.X()
649 << aPt.Y()
650 << nStringLen;
651 for ( i = 0; i < nStringLen; i++ )
652 aMemoryStream << rUniStr.GetChar( (sal_uInt16)i );
653 aMemoryStream << nDXCount;
654 for ( i = 0; i < nDXCount; i++ )
655 aMemoryStream << pDXAry[ i ];
656 aMemoryStream << nSkipActions;
657 WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
659 std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
660 while ( aIter != aPolyPolyVec.end() )
662 PolyPolygon aPolyPoly( *aIter++ );
663 aPolyPoly.Move( rPoint.X(), rPoint.Y() );
664 WMFRecord_PolyPolygon( aPolyPoly );
666 aSrcFillColor = aOldFillColor;
667 aSrcLineColor = aOldLineColor;
668 bEscapeUsed = sal_True;
673 return bEscapeUsed;
676 void WMFWriter::WMFRecord_ExtTextOut( const Point & rPoint,
677 const String & rString, const sal_Int32 * pDXAry )
679 sal_uInt16 nOriginalTextLen = rString.Len();
681 if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
683 WMFRecord_TextOut(rPoint, rString);
684 return;
686 rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
687 ByteString aByteString(rString, eChrSet);
688 TrueExtTextOut(rPoint,rString,aByteString,pDXAry);
691 void WMFWriter::TrueExtTextOut( const Point & rPoint, const String & rString,
692 const ByteString & rByteString, const sal_Int32 * pDXAry )
694 WriteRecordHeader( 0, W_META_EXTTEXTOUT );
695 WritePointYX( rPoint );
696 sal_uInt16 nNewTextLen = rByteString.Len();
697 *pWMF << nNewTextLen << (sal_uInt16)0;
699 sal_uInt16 i;
700 for ( i = 0; i < nNewTextLen; i++ )
701 *pWMF << (sal_uInt8)rByteString.GetChar( i );
702 if ( nNewTextLen & 1 )
703 *pWMF << (sal_uInt8)0;
705 sal_uInt16 nOriginalTextLen = rString.Len();
706 sal_Int16* pConvertedDXAry = new sal_Int16[ nOriginalTextLen ];
707 sal_Int32 j = 0;
708 pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
709 for ( i = 1; i < ( nOriginalTextLen - 1 ); i++ )
710 pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
711 pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
713 for ( i = 0; i < nOriginalTextLen; i++ )
715 sal_Int16 nDx = pConvertedDXAry[ i ];
716 *pWMF << nDx;
717 if ( nOriginalTextLen < nNewTextLen )
719 ByteString aTemp( rString.GetChar( i ), aSrcFont.GetCharSet());
720 j = aTemp.Len();
721 while ( --j > 0 )
722 *pWMF << (sal_uInt16)0;
725 delete[] pConvertedDXAry;
726 UpdateRecordHeader();
729 void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
731 WriteRecordHeader(0x00000005,W_META_LINETO);
732 WritePointYX(rPoint);
736 void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
738 WriteRecordHeader(0x00000005,W_META_MOVETO);
739 WritePointYX(rPoint);
743 void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
745 WriteRecordHeader(0x0000000b,W_META_PIE);
746 WritePointYX(rEndPt);
747 WritePointYX(rStartPt);
748 WriteRectangle(rRect);
752 void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
754 USHORT nSize,i;
756 Polygon aSimplePoly;
757 if ( rPoly.HasFlags() )
758 rPoly.GetSimple( aSimplePoly );
759 else
760 aSimplePoly = rPoly;
761 nSize = aSimplePoly.GetSize();
762 WriteRecordHeader(((ULONG)nSize)*2+4,W_META_POLYGON);
763 *pWMF << nSize;
764 for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
768 void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
770 USHORT nSize,i;
771 Polygon aSimplePoly;
772 if ( rPoly.HasFlags() )
773 rPoly.GetSimple( aSimplePoly );
774 else
775 aSimplePoly = rPoly;
776 nSize=aSimplePoly.GetSize();
777 WriteRecordHeader(((ULONG)nSize)*2+4,W_META_POLYLINE);
778 *pWMF << nSize;
779 for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
783 void WMFWriter::WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly)
785 const Polygon * pPoly;
786 USHORT nCount,nSize,i,j;
788 nCount=rPolyPoly.Count();
789 PolyPolygon aSimplePolyPoly( rPolyPoly );
790 for ( i = 0; i < nCount; i++ )
792 if ( aSimplePolyPoly[ i ].HasFlags() )
794 Polygon aSimplePoly;
795 aSimplePolyPoly[ i ].GetSimple( aSimplePoly );
796 aSimplePolyPoly[ i ] = aSimplePoly;
799 WriteRecordHeader(0,W_META_POLYPOLYGON);
800 *pWMF << nCount;
801 for (i=0; i<nCount; i++) *pWMF << ((USHORT)(aSimplePolyPoly.GetObject(i).GetSize()));
802 for (i=0; i<nCount; i++) {
803 pPoly=&(aSimplePolyPoly.GetObject(i));
804 nSize=pPoly->GetSize();
805 for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
807 UpdateRecordHeader();
811 void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
813 WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
814 WriteRectangle( rRect );
818 void WMFWriter::WMFRecord_RestoreDC()
820 WriteRecordHeader(0x00000004,W_META_RESTOREDC);
821 *pWMF << (short)-1;
825 void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
827 WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
828 WriteHeightWidth(Size(nHorzRound,nVertRound));
829 WriteRectangle(rRect);
833 void WMFWriter::WMFRecord_SaveDC()
835 WriteRecordHeader(0x00000003,W_META_SAVEDC);
839 void WMFWriter::WMFRecord_SelectObject(USHORT nObjectHandle)
841 WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
842 *pWMF << nObjectHandle;
846 void WMFWriter::WMFRecord_SetBkColor(const Color & rColor)
848 WriteRecordHeader(0x00000005,W_META_SETBKCOLOR);
849 WriteColor(rColor);
853 void WMFWriter::WMFRecord_SetBkMode(BOOL bTransparent)
855 WriteRecordHeader(0x00000004,W_META_SETBKMODE);
856 if (bTransparent==TRUE) *pWMF << (USHORT)W_TRANSPARENT;
857 else *pWMF << (USHORT)W_OPAQUE;
860 void WMFWriter::WMFRecord_SetStretchBltMode()
862 WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
863 *pWMF << (USHORT) 3; // STRETCH_DELETESCANS
866 void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
868 WriteRecordHeader(0x00000007,W_META_SETPIXEL);
869 WriteColor(rColor);
870 WritePointYX(rPoint);
874 void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
876 USHORT nROP2;
878 switch (eROP) {
879 case ROP_INVERT: nROP2=W_R2_NOT; break;
880 case ROP_XOR: nROP2=W_R2_XORPEN; break;
881 default: nROP2=W_R2_COPYPEN;
883 WriteRecordHeader(0x00000004,W_META_SETROP2);
884 *pWMF << nROP2;
888 void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, UINT32 eHorTextAlign)
890 USHORT nAlign;
892 switch (eFontAlign) {
893 case ALIGN_TOP: nAlign=W_TA_TOP; break;
894 case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
895 default: nAlign=W_TA_BASELINE;
897 nAlign|=eHorTextAlign;
898 nAlign|=W_TA_NOUPDATECP;
900 WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
901 *pWMF << nAlign;
905 void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
907 WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
908 WriteColor(rColor);
912 void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
914 WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
915 WriteHeightWidth(rSize);
919 void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
921 WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
922 WritePointYX(rPoint);
926 void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
927 const Bitmap & rBitmap, sal_uInt32 nROP )
929 ULONG nPosAnf,nPosEnd;
931 nActBitmapPercent=50;
932 MayCallback();
934 WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
936 // Die Reihenfolge im Metafile soll jetzt sein:
937 // einige Parameter (laenge 22), dann die Bitmap ohne FILEHEADER.
938 // Da aber *pWMF << rBitmap einen FILEHEADER der Laenge 14
939 // erzeugt, schreiben wir zuerst die Bitmap an die richtige Position
940 // Und ueberschreiben hinterher den FILEHEADER mit den Parametern.
941 nPosAnf=pWMF->Tell(); // Position merken, wo Parameter hin sollen
942 *pWMF << (long)0 << (long)0; // 8 bytes auffuellen (diese 8 bytes +
943 // 14 bytes ueberfluessigen FILEHEADER
944 // = 22 bytes Parameter)
945 *pWMF << rBitmap; // Bitmap schreiben
947 // Parameter schreiben:
948 nPosEnd=pWMF->Tell();
949 pWMF->Seek(nPosAnf);
951 // Raster-Op bestimmen, falls nichts uebergeben wurde
952 if( !nROP )
954 switch( eSrcRasterOp )
956 case ROP_INVERT: nROP = W_DSTINVERT; break;
957 case ROP_XOR: nROP = W_SRCINVERT; break;
958 default: nROP = W_SRCCOPY;
962 *pWMF << nROP <<
963 (short) 0 <<
964 (short) rBitmap.GetSizePixel().Height() <<
965 (short) rBitmap.GetSizePixel().Width() <<
966 (short) 0 <<
967 (short) 0;
969 WriteHeightWidth(rSize);
970 WritePointYX(rPoint);
971 pWMF->Seek(nPosEnd);
973 UpdateRecordHeader();
975 nWrittenBitmaps++;
976 nActBitmapPercent=0;
980 void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const String & rStr)
982 rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
983 ByteString aString( rStr, eChrSet );
984 TrueTextOut(rPoint, aString);
987 void WMFWriter::TrueTextOut(const Point & rPoint, const ByteString& rString)
989 USHORT nLen,i;
991 WriteRecordHeader(0,W_META_TEXTOUT);
992 nLen=rString.Len();
993 *pWMF << nLen;
994 for ( i = 0; i < nLen; i++ )
995 *pWMF << (BYTE)rString.GetChar( i );
996 if ((nLen&1)!=0) *pWMF << (BYTE)0;
997 WritePointYX(rPoint);
998 UpdateRecordHeader();
1001 void WMFWriter::WMFRecord_EndOfFile()
1003 WriteRecordHeader(0x00000003,0x0000);
1007 void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
1009 WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
1010 WriteRectangle(rRect);
1014 USHORT WMFWriter::AllocHandle()
1016 USHORT i;
1018 for (i=0; i<MAXOBJECTHANDLES; i++) {
1019 if (bHandleAllocated[i]==FALSE) {
1020 bHandleAllocated[i]=TRUE;
1021 return i;
1024 bStatus=FALSE;
1025 return 0xffff;
1029 void WMFWriter::FreeHandle(USHORT nObjectHandle)
1031 if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=FALSE;
1035 void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
1037 USHORT nOldHandle;
1039 nOldHandle=nDstPenHandle;
1040 nDstPenHandle=AllocHandle();
1041 WMFRecord_CreatePenIndirect( rColor, rLineInfo );
1042 WMFRecord_SelectObject(nDstPenHandle);
1043 if (nOldHandle<MAXOBJECTHANDLES) {
1044 WMFRecord_DeleteObject(nOldHandle);
1045 FreeHandle(nOldHandle);
1050 void WMFWriter::CreateSelectDeleteFont(const Font & rFont)
1052 USHORT nOldHandle;
1054 nOldHandle=nDstFontHandle;
1055 nDstFontHandle=AllocHandle();
1056 WMFRecord_CreateFontIndirect(rFont);
1057 WMFRecord_SelectObject(nDstFontHandle);
1058 if (nOldHandle<MAXOBJECTHANDLES) {
1059 WMFRecord_DeleteObject(nOldHandle);
1060 FreeHandle(nOldHandle);
1065 void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
1067 USHORT nOldHandle;
1069 nOldHandle=nDstBrushHandle;
1070 nDstBrushHandle=AllocHandle();
1071 WMFRecord_CreateBrushIndirect(rColor);
1072 WMFRecord_SelectObject(nDstBrushHandle);
1073 if (nOldHandle<MAXOBJECTHANDLES) {
1074 WMFRecord_DeleteObject(nOldHandle);
1075 FreeHandle(nOldHandle);
1080 void WMFWriter::SetLineAndFillAttr()
1082 if ( eDstROP2 != eSrcRasterOp )
1084 eDstROP2=eSrcRasterOp;
1085 WMFRecord_SetROP2(eDstROP2);
1087 if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
1089 aDstLineColor = aSrcLineColor;
1090 aDstLineInfo = aSrcLineInfo;
1091 CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
1093 if ( aDstFillColor != aSrcFillColor )
1095 aDstFillColor = aSrcFillColor;
1096 CreateSelectDeleteBrush( aDstFillColor );
1098 if ( bDstIsClipping != bSrcIsClipping ||
1099 (bSrcIsClipping==TRUE && aDstClipRegion!=aSrcClipRegion)) {
1100 bDstIsClipping=bSrcIsClipping;
1101 aDstClipRegion=aSrcClipRegion;
1105 void WMFWriter::SetAllAttr()
1107 SetLineAndFillAttr();
1108 if ( aDstTextColor != aSrcTextColor )
1110 aDstTextColor = aSrcTextColor;
1111 WMFRecord_SetTextColor(aDstTextColor);
1113 if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
1115 eDstTextAlign = eSrcTextAlign;
1116 eDstHorTextAlign = eSrcHorTextAlign;
1117 WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
1119 if ( aDstFont != aSrcFont )
1121 pVirDev->SetFont(aSrcFont);
1122 if ( aDstFont.GetName() != aSrcFont.GetName() )
1124 FontCharMap aFontCharMap;
1125 if ( pVirDev->GetFontCharMap( aFontCharMap ) )
1127 if ( ( aFontCharMap.GetFirstChar() & 0xff00 ) == 0xf000 )
1128 aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
1129 else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1130 aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1133 aDstFont = aSrcFont;
1134 CreateSelectDeleteFont(aDstFont);
1139 void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
1141 ULONG nA, nACount;
1142 MetaAction* pMA;
1144 if( bStatus )
1146 nACount = rMTF.GetActionCount();
1148 WMFRecord_SetStretchBltMode();
1150 for( nA=0; nA<nACount; nA++ )
1152 pMA = rMTF.GetAction( nA );
1154 switch( pMA->GetType() )
1156 case META_PIXEL_ACTION:
1158 const MetaPixelAction* pA = (const MetaPixelAction *) pMA;
1159 aSrcLineInfo = LineInfo();
1160 SetLineAndFillAttr();
1161 WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
1163 break;
1165 case META_POINT_ACTION:
1167 const MetaPointAction* pA = (const MetaPointAction*) pMA;
1168 const Point& rPt = pA->GetPoint();
1169 aSrcLineInfo = LineInfo();
1170 SetLineAndFillAttr();
1171 WMFRecord_MoveTo( rPt);
1172 WMFRecord_LineTo( rPt );
1174 break;
1176 case META_LINE_ACTION:
1178 const MetaLineAction* pA = (const MetaLineAction *) pMA;
1179 aSrcLineInfo = pA->GetLineInfo();
1180 SetLineAndFillAttr();
1181 WMFRecord_MoveTo( pA->GetStartPoint() );
1182 WMFRecord_LineTo( pA->GetEndPoint() );
1184 break;
1186 case META_RECT_ACTION:
1188 const MetaRectAction* pA = (const MetaRectAction*) pMA;
1189 aSrcLineInfo = LineInfo();
1190 SetLineAndFillAttr();
1191 WMFRecord_Rectangle( pA->GetRect() );
1193 break;
1195 case META_ROUNDRECT_ACTION:
1197 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
1198 aSrcLineInfo = LineInfo();
1199 SetLineAndFillAttr();
1200 WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
1202 break;
1204 case META_ELLIPSE_ACTION:
1206 const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
1207 aSrcLineInfo = LineInfo();
1208 SetLineAndFillAttr();
1209 WMFRecord_Ellipse( pA->GetRect() );
1211 break;
1213 case META_ARC_ACTION:
1215 const MetaArcAction* pA = (const MetaArcAction*) pMA;
1216 aSrcLineInfo = LineInfo();
1217 SetLineAndFillAttr();
1218 WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
1220 break;
1222 case META_PIE_ACTION:
1224 const MetaPieAction* pA = (const MetaPieAction*) pMA;
1225 aSrcLineInfo = LineInfo();
1226 SetLineAndFillAttr();
1227 WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1229 break;
1232 case META_CHORD_ACTION:
1234 const MetaChordAction* pA = (const MetaChordAction*) pMA;
1235 aSrcLineInfo = LineInfo();
1236 SetLineAndFillAttr();
1237 WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
1239 break;
1241 case META_POLYLINE_ACTION:
1243 const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
1244 aSrcLineInfo = pA->GetLineInfo();
1245 SetLineAndFillAttr();
1246 WMFRecord_PolyLine( pA->GetPolygon() );
1248 break;
1250 case META_POLYGON_ACTION:
1252 const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
1253 aSrcLineInfo = LineInfo();
1254 SetLineAndFillAttr();
1255 WMFRecord_Polygon( pA->GetPolygon() );
1257 break;
1259 case META_POLYPOLYGON_ACTION:
1261 const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
1262 aSrcLineInfo = LineInfo();
1263 SetLineAndFillAttr();
1264 WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
1266 break;
1268 case META_TEXTRECT_ACTION:
1270 const MetaTextRectAction * pA = (const MetaTextRectAction*)pMA;
1271 String aTemp( pA->GetText() );
1272 aSrcLineInfo = LineInfo();
1273 SetAllAttr();
1275 Point aPos( pA->GetRect().TopLeft() );
1276 if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
1277 WMFRecord_TextOut( aPos, aTemp );
1279 break;
1281 case META_TEXT_ACTION:
1283 const MetaTextAction * pA = (const MetaTextAction*) pMA;
1284 String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1285 aSrcLineInfo = LineInfo();
1286 SetAllAttr();
1287 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
1288 WMFRecord_TextOut( pA->GetPoint(), aTemp );
1290 break;
1292 case META_TEXTARRAY_ACTION:
1294 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
1296 String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1297 aSrcLineInfo = LineInfo();
1298 SetAllAttr();
1299 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
1300 WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
1302 break;
1304 case META_STRETCHTEXT_ACTION:
1306 const MetaStretchTextAction* pA = (const MetaStretchTextAction *) pMA;
1307 String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
1309 sal_uInt16 nLen,i;
1310 sal_Int32 nNormSize;
1312 pVirDev->SetFont( aSrcFont );
1313 nLen = aTemp.Len();
1314 sal_Int32* pDXAry = nLen ? new sal_Int32[ nLen ] : NULL;
1315 nNormSize = pVirDev->GetTextArray( aTemp, pDXAry );
1316 for ( i = 0; i < ( nLen - 1 ); i++ )
1317 pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
1318 if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
1319 delete[] pDXAry, pDXAry = NULL;
1320 aSrcLineInfo = LineInfo();
1321 SetAllAttr();
1322 if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry ) )
1323 WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry );
1324 delete[] pDXAry;
1326 break;
1328 case META_BMP_ACTION:
1330 const MetaBmpAction* pA = (const MetaBmpAction *) pMA;
1331 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
1333 break;
1335 case META_BMPSCALE_ACTION:
1337 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
1338 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
1340 break;
1342 case META_BMPSCALEPART_ACTION:
1344 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
1345 Bitmap aTmp( pA->GetBitmap() );
1347 if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
1348 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
1350 break;
1352 case META_BMPEX_ACTION:
1354 const MetaBmpExAction* pA = (const MetaBmpExAction *) pMA;
1355 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1356 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1358 if( !!aMsk )
1360 aBmp.Replace( aMsk, COL_WHITE );
1361 aMsk.Invert();
1362 WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
1363 WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
1365 else
1366 WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
1368 break;
1370 case META_BMPEXSCALE_ACTION:
1372 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
1373 Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
1374 Bitmap aMsk( pA->GetBitmapEx().GetMask() );
1376 if( !!aMsk )
1378 aBmp.Replace( aMsk, COL_WHITE );
1379 aMsk.Invert();
1380 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
1381 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
1383 else
1384 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
1386 break;
1388 case META_BMPEXSCALEPART_ACTION:
1390 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
1391 BitmapEx aBmpEx( pA->GetBitmapEx() );
1392 aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
1393 Bitmap aBmp( aBmpEx.GetBitmap() );
1394 Bitmap aMsk( aBmpEx.GetMask() );
1396 if( !!aMsk )
1398 aBmp.Replace( aMsk, COL_WHITE );
1399 aMsk.Invert();
1400 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
1401 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
1403 else
1404 WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
1406 break;
1408 case META_GRADIENT_ACTION:
1410 const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
1411 GDIMetaFile aTmpMtf;
1413 pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
1414 WriteRecords( aTmpMtf );
1416 break;
1418 case META_HATCH_ACTION:
1420 const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
1421 GDIMetaFile aTmpMtf;
1423 pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
1424 WriteRecords( aTmpMtf );
1426 break;
1428 case META_WALLPAPER_ACTION:
1430 const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pMA;
1431 const Color& rColor = pA->GetWallpaper().GetColor();
1432 const Color aOldLineColor( aSrcLineColor );
1433 const Color aOldFillColor( aSrcFillColor );
1435 aSrcLineColor = rColor;
1436 aSrcFillColor = rColor;
1437 aSrcLineInfo = LineInfo();
1438 SetLineAndFillAttr();
1439 WMFRecord_Rectangle( pA->GetRect() );
1440 aSrcLineColor = aOldLineColor;
1441 aSrcFillColor = aOldFillColor;
1443 break;
1445 case META_ISECTRECTCLIPREGION_ACTION:
1447 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
1448 WMFRecord_IntersectClipRect( pA->GetRect() );
1450 break;
1452 case META_LINECOLOR_ACTION:
1454 const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
1456 if( pA->IsSetting() )
1457 aSrcLineColor = pA->GetColor();
1458 else
1459 aSrcLineColor = Color( COL_TRANSPARENT );
1461 break;
1463 case META_FILLCOLOR_ACTION:
1465 const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
1467 if( pA->IsSetting() )
1468 aSrcFillColor = pA->GetColor();
1469 else
1470 aSrcFillColor = Color( COL_TRANSPARENT );
1472 break;
1474 case META_TEXTCOLOR_ACTION:
1476 const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
1477 aSrcTextColor = pA->GetColor();
1479 break;
1481 case META_TEXTFILLCOLOR_ACTION:
1483 const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
1484 if( pA->IsSetting() )
1485 aSrcFont.SetFillColor( pA->GetColor() );
1486 else
1487 aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
1489 break;
1491 case META_TEXTALIGN_ACTION:
1493 const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pMA;
1494 eSrcTextAlign = pA->GetTextAlign();
1496 break;
1498 case META_MAPMODE_ACTION:
1500 const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
1502 if (aSrcMapMode!=pA->GetMapMode())
1504 if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
1506 MapMode aMM = pA->GetMapMode();
1507 Fraction aScaleX = aMM.GetScaleX();
1508 Fraction aScaleY = aMM.GetScaleY();
1510 Point aOrigin = aSrcMapMode.GetOrigin();
1511 BigInt aX( aOrigin.X() );
1512 aX *= BigInt( aScaleX.GetDenominator() );
1513 if( aOrigin.X() >= 0 )
1514 if( aScaleX.GetNumerator() >= 0 )
1515 aX += BigInt( aScaleX.GetNumerator()/2 );
1516 else
1517 aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
1518 else
1519 if( aScaleX.GetNumerator() >= 0 )
1520 aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
1521 else
1522 aX += BigInt( aScaleX.GetNumerator()/2 );
1523 aX /= BigInt( aScaleX.GetNumerator() );
1524 aOrigin.X() = (long)aX + aMM.GetOrigin().X();
1525 BigInt aY( aOrigin.Y() );
1526 aY *= BigInt( aScaleY.GetDenominator() );
1527 if( aOrigin.Y() >= 0 )
1528 if( aScaleY.GetNumerator() >= 0 )
1529 aY += BigInt( aScaleY.GetNumerator()/2 );
1530 else
1531 aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
1532 else
1533 if( aScaleY.GetNumerator() >= 0 )
1534 aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
1535 else
1536 aY += BigInt( aScaleY.GetNumerator()/2 );
1537 aY /= BigInt( aScaleY.GetNumerator() );
1538 aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
1539 aSrcMapMode.SetOrigin( aOrigin );
1541 aScaleX *= aSrcMapMode.GetScaleX();
1542 aScaleY *= aSrcMapMode.GetScaleY();
1543 aSrcMapMode.SetScaleX( aScaleX );
1544 aSrcMapMode.SetScaleY( aScaleY );
1546 else
1547 aSrcMapMode=pA->GetMapMode();
1550 break;
1552 case META_FONT_ACTION:
1554 const MetaFontAction* pA = (const MetaFontAction*) pMA;
1555 aSrcFont = pA->GetFont();
1557 if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW )
1558 aSrcFont.SetCharSet( GetExtendedTextEncoding( gsl_getSystemTextEncoding() ) );
1559 if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE )
1560 aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1561 eSrcTextAlign = aSrcFont.GetAlign();
1562 aSrcTextColor = aSrcFont.GetColor();
1563 aSrcFont.SetAlign( ALIGN_BASELINE );
1564 aSrcFont.SetColor( COL_WHITE );
1566 break;
1568 case META_PUSH_ACTION:
1570 const MetaPushAction* pA = (const MetaPushAction*)pMA;
1572 WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
1573 pAt->nFlags = pA->GetFlags();
1574 pAt->aClipRegion = aSrcClipRegion;
1575 pAt->aLineColor=aSrcLineColor;
1576 pAt->aFillColor=aSrcFillColor;
1577 pAt->eRasterOp=eSrcRasterOp;
1578 pAt->aFont=aSrcFont;
1579 pAt->eTextAlign=eSrcTextAlign;
1580 pAt->aTextColor=aSrcTextColor;
1581 pAt->aMapMode=aSrcMapMode;
1582 pAt->aLineInfo=aDstLineInfo;
1583 pAt->pSucc=pAttrStack;
1584 pAttrStack=pAt;
1586 SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
1587 WMFRecord_SaveDC();
1590 break;
1592 case META_POP_ACTION:
1594 WMFWriterAttrStackMember * pAt=pAttrStack;
1596 if( pAt )
1598 aDstLineInfo = pAt->aLineInfo;
1599 aDstLineColor = pAt->aLineColor;
1600 if ( pAt->nFlags & PUSH_LINECOLOR )
1601 aSrcLineColor = pAt->aLineColor;
1602 aDstFillColor = pAt->aFillColor;
1603 if ( pAt->nFlags & PUSH_FILLCOLOR )
1604 aSrcFillColor = pAt->aFillColor;
1605 eDstROP2 = pAt->eRasterOp;
1606 if ( pAt->nFlags & PUSH_RASTEROP )
1607 eSrcRasterOp = pAt->eRasterOp;
1608 aDstFont = pAt->aFont;
1609 if ( pAt->nFlags & PUSH_FONT )
1610 aSrcFont = pAt->aFont;
1611 eDstTextAlign = pAt->eTextAlign;
1612 if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTALIGN ) )
1613 eSrcTextAlign = pAt->eTextAlign;
1614 aDstTextColor = pAt->aTextColor;
1615 if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTCOLOR ) )
1616 aSrcTextColor = pAt->aTextColor;
1617 if ( pAt->nFlags & PUSH_MAPMODE )
1618 aSrcMapMode = pAt->aMapMode;
1619 aDstClipRegion = pAt->aClipRegion;
1620 if ( pAt->nFlags & PUSH_CLIPREGION )
1621 aSrcClipRegion = pAt->aClipRegion;
1623 WMFRecord_RestoreDC();
1624 pAttrStack = pAt->pSucc;
1625 delete pAt;
1628 break;
1630 case META_EPS_ACTION :
1632 const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
1633 const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
1635 INT32 nCount = aGDIMetaFile.GetActionCount();
1636 for ( INT32 i = 0; i < nCount; i++ )
1638 const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
1639 if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
1641 const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
1642 WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
1643 break;
1647 break;
1649 case META_RASTEROP_ACTION:
1651 const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
1652 eSrcRasterOp=pA->GetRasterOp();
1654 break;
1656 case META_TRANSPARENT_ACTION:
1658 aSrcLineInfo = LineInfo();
1659 SetLineAndFillAttr();
1660 WMFRecord_PolyPolygon( ( (MetaTransparentAction*) pMA )->GetPolyPolygon() );
1662 break;
1664 case META_FLOATTRANSPARENT_ACTION:
1666 const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
1668 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1669 Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1670 const Size aSrcSize( aTmpMtf.GetPrefSize() );
1671 const Point aDestPt( pA->GetPoint() );
1672 const Size aDestSize( pA->GetSize() );
1673 const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1674 const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1675 long nMoveX, nMoveY;
1677 aSrcLineInfo = LineInfo();
1678 SetAllAttr();
1680 if( fScaleX != 1.0 || fScaleY != 1.0 )
1682 aTmpMtf.Scale( fScaleX, fScaleY );
1683 aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1686 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1688 if( nMoveX || nMoveY )
1689 aTmpMtf.Move( nMoveX, nMoveY );
1691 WriteRecords( aTmpMtf );
1693 break;
1695 case( META_LAYOUTMODE_ACTION ):
1697 sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pMA )->GetLayoutMode();
1698 eSrcHorTextAlign = 0; // TA_LEFT
1699 if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
1701 eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
1703 if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
1704 eSrcHorTextAlign |= W_TA_RIGHT;
1705 else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
1706 eSrcHorTextAlign &= ~W_TA_RIGHT;
1707 break;
1710 // Unsupported Actions
1711 case META_MASK_ACTION:
1712 case META_MASKSCALE_ACTION:
1713 case META_MASKSCALEPART_ACTION:
1715 DBG_ERROR( "Unsupported action: MetaMask...Action!" );
1717 break;
1719 case META_CLIPREGION_ACTION:
1720 break;
1722 case META_ISECTREGIONCLIPREGION_ACTION:
1724 DBG_ERROR( "Unsupported action: MetaISectRegionClipRegionAction!" );
1726 break;
1728 case META_MOVECLIPREGION_ACTION:
1730 DBG_ERROR( "Unsupported action: MetaMoveClipRegionAction!" );
1732 break;
1735 nWrittenActions++;
1736 MayCallback();
1738 if (pWMF->GetError())
1739 bStatus=FALSE;
1741 if(bStatus==FALSE)
1742 break;
1747 // ------------------------------------------------------------------------
1749 void WMFWriter::WriteHeader( const GDIMetaFile &, BOOL bPlaceable )
1751 if( bPlaceable )
1753 USHORT nCheckSum, nValue;
1754 Size aSize( pVirDev->LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
1755 USHORT nUnitsPerInch = (USHORT) ( ( aSize.Width() + aSize.Height() ) >> 1 );
1757 nCheckSum=0;
1758 nValue=0xcdd7; nCheckSum^=nValue; *pWMF << nValue;
1759 nValue=0x9ac6; nCheckSum^=nValue; *pWMF << nValue;
1760 nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1761 nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1762 nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1763 nValue=(USHORT) aTargetSize.Width(); nCheckSum^=nValue; *pWMF << nValue;
1764 nValue=(USHORT) aTargetSize.Height(); nCheckSum^=nValue; *pWMF << nValue;
1765 nValue=nUnitsPerInch; nCheckSum^=nValue; *pWMF << nValue;
1766 nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1767 nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
1768 *pWMF << nCheckSum;
1771 nMetafileHeaderPos=pWMF->Tell();
1772 *pWMF << (sal_uInt16)0x0001 // Typ: Datei
1773 << (sal_uInt16)0x0009 // Headerlaenge in Worten
1774 << (sal_uInt16)0x0300 // Version als BCD-Zahl
1775 << (sal_uInt32) 0x00000000 // Dateilaenge (ohne 1. Header), wird spaeter durch UpdateHeader() berichtigt
1776 << (sal_uInt16)MAXOBJECTHANDLES // Maximalezahl der gleichzeitigen Objekte
1777 << (sal_uInt32) 0x00000000 // Maximale Record-laenge, wird spaeter durch UpdateHeader() berichtigt
1778 << (sal_uInt16)0x0000; // Reserved
1781 // ------------------------------------------------------------------------
1783 void WMFWriter::UpdateHeader()
1785 ULONG nPos;
1786 sal_uInt32 nFileSize;
1788 nPos=pWMF->Tell(); // Endposition = Gesammtgroesse der Datei
1789 nFileSize=nPos-nMetafileHeaderPos; // Groesse des 1. Headers abziehen
1790 if ((nFileSize&1)!=0) { // ggf. auf ganze Worte aufrunden
1791 *pWMF << (BYTE)0;
1792 nPos++;
1793 nFileSize++;
1795 nFileSize>>=1; // In Anzahl Worte umrechnen
1796 pWMF->Seek(nMetafileHeaderPos+6); // Zum Dateigroessen-Eintrag im zweiten Header
1797 *pWMF << nFileSize; // Dateigroesse berichtigen
1798 pWMF->SeekRel(2); // Zum Max-Record-Laenge-Eintrag im zweiten Header
1799 *pWMF << nMaxRecordSize; // und berichtigen
1800 pWMF->Seek(nPos);
1803 // ------------------------------------------------------------------------
1805 BOOL WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
1806 FilterConfigItem* pFConfigItem, BOOL bPlaceable )
1808 WMFWriterAttrStackMember * pAt;
1810 bStatus=TRUE;
1811 pConvert = 0;
1812 pVirDev = new VirtualDevice;
1814 pFilterConfigItem = pFConfigItem;
1815 if ( pFilterConfigItem )
1817 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
1818 if ( xStatusIndicator.is() )
1820 rtl::OUString aMsg;
1821 xStatusIndicator->start( aMsg, 100 );
1824 nLastPercent=0;
1826 pWMF=&rTargetStream;
1827 pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1829 nMaxRecordSize=0;
1831 aSrcMapMode=rMTF.GetPrefMapMode();
1833 if( bPlaceable )
1835 aTargetMapMode = aSrcMapMode;
1836 aTargetSize = rMTF.GetPrefSize();
1837 nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
1838 aTargetSize.Width() /= nTargetDivisor;
1839 aTargetSize.Height() /= nTargetDivisor;
1841 else
1843 aTargetMapMode = MapMode( MAP_INCH );
1845 const long nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
1846 const Fraction aFrac( 1, nUnit );
1848 aTargetMapMode.SetScaleX( aFrac );
1849 aTargetMapMode.SetScaleY( aFrac );
1850 aTargetSize = pVirDev->LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
1853 pVirDev->SetMapMode( aTargetMapMode );
1855 pAttrStack=NULL;
1857 for (USHORT i=0; i<MAXOBJECTHANDLES; i++)
1858 bHandleAllocated[i]=FALSE;
1860 nDstPenHandle=0xffff;
1861 nDstFontHandle=0xffff;
1862 nDstBrushHandle=0xffff;
1864 nNumberOfActions=0;
1865 nNumberOfBitmaps=0;
1866 nWrittenActions=0;
1867 nWrittenBitmaps=0;
1868 nActBitmapPercent=0;
1870 CountActionsAndBitmaps(rMTF);
1872 WriteHeader(rMTF,bPlaceable);
1873 WMFRecord_SetWindowOrg(Point(0,0));
1874 WMFRecord_SetWindowExt(rMTF.GetPrefSize());
1875 WMFRecord_SetBkMode( TRUE );
1877 eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
1878 WMFRecord_SetROP2(eDstROP2);
1880 aDstLineInfo = LineInfo();
1881 aDstLineColor = aSrcLineColor = Color( COL_BLACK );
1882 CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
1884 aDstFillColor = aSrcFillColor = Color( COL_WHITE );
1885 CreateSelectDeleteBrush( aDstFillColor );
1887 aDstClipRegion = aSrcClipRegion = Region();
1888 bDstIsClipping = bSrcIsClipping = FALSE;
1890 Font aFont;
1891 aFont.SetCharSet( GetExtendedTextEncoding( gsl_getSystemTextEncoding() ) );
1892 aFont.SetColor( Color( COL_WHITE ) );
1893 aFont.SetAlign( ALIGN_BASELINE );
1894 aDstFont = aSrcFont = aFont;
1895 CreateSelectDeleteFont(aDstFont);
1897 eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
1898 eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
1899 WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
1901 aDstTextColor = aSrcTextColor = Color( COL_WHITE );
1902 WMFRecord_SetTextColor(aDstTextColor);
1904 // Write records
1905 WriteRecords(rMTF);
1907 WMFRecord_EndOfFile();
1908 UpdateHeader();
1910 while(pAttrStack)
1912 pAt=pAttrStack;
1913 pAttrStack=pAt->pSucc;
1914 delete pAt;
1917 delete pVirDev;
1918 delete pConvert;
1920 if ( xStatusIndicator.is() )
1921 xStatusIndicator->end();
1923 return bStatus;
1926 // ------------------------------------------------------------------------
1928 USHORT WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
1929 const Size& rPrefSize)
1931 Fraction aDivFrac(2, 1);
1932 USHORT nDivisor = 1;
1934 Size aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1936 while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
1938 Fraction aFrac = rMapMode.GetScaleX();
1940 aFrac *= aDivFrac;
1941 rMapMode.SetScaleX(aFrac);
1942 aFrac = rMapMode.GetScaleY();
1943 aFrac *= aDivFrac;
1944 rMapMode.SetScaleY(aFrac);
1945 nDivisor <<= 1;
1946 aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
1949 return nDivisor;