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