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