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