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