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