1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sal/config.h"
25 #include <unotools/fontcvt.hxx>
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>
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
75 #define W_TRANSPARENT 1
80 #define W_R2_COPYPEN 13
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
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
99 #define W_PS_DASHDOT 3
100 #define W_PS_DASHDOTDOT 4
103 #define W_LF_FACESIZE 32
105 #define W_ANSI_CHARSET 0
107 #define W_DEFAULT_PITCH 0x00
108 #define W_FIXED_PITCH 0x01
109 #define W_VARIABLE_PITCH 0x02
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
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
130 #define W_BS_HOLLOW 1
132 #define W_MFCOMMENT 15
134 #define PRIVATE_ESCAPE_UNICODE 2
136 WMFWriter::WMFWriter()
141 , nMetafileHeaderPos(0)
144 , eSrcRasterOp(ROP_OVERPAINT
)
145 , eSrcTextAlign(ALIGN_BASELINE
)
146 , bSrcIsClipping(false)
148 , eSrcHorTextAlign(W_TA_LEFT
)
149 , eDstROP2(ROP_OVERPAINT
)
150 , eDstTextAlign(ALIGN_BASELINE
)
151 , eDstHorTextAlign(W_TA_LEFT
)
152 , bDstIsClipping(false)
156 , nNumberOfActions(0)
157 , nNumberOfBitmaps(0)
160 , nActBitmapPercent(0)
165 void WMFWriter::MayCallback()
167 if ( xStatusIndicator
.is() )
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)
175 nPercent
=((nWrittenBitmaps
<<14)+(nActBitmapPercent
<<14)/100+nWrittenActions
)
177 /((nNumberOfBitmaps
<<14)+nNumberOfActions
);
179 if ( nPercent
>= nLastPercent
+ 3 )
181 nLastPercent
= nPercent
;
182 if( nPercent
<= 100 )
183 xStatusIndicator
->setValue( nPercent
);
188 void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile
& rMTF
)
190 size_t nAction
, nActionCount
;
192 nActionCount
= rMTF
.GetActionSize();
194 for ( nAction
=0; nAction
< nActionCount
; nAction
++ )
196 MetaAction
* pMA
= rMTF
.GetAction( nAction
);
198 switch( pMA
->GetType() )
200 case MetaActionType::BMP
:
201 case MetaActionType::BMPSCALE
:
202 case MetaActionType::BMPSCALEPART
:
203 case MetaActionType::BMPEX
:
204 case MetaActionType::BMPEXSCALE
:
205 case MetaActionType::BMPEXSCALEPART
:
214 void WMFWriter::WritePointXY(const Point
& rPoint
)
216 Point
aPt( OutputDevice::LogicToLogic(rPoint
,aSrcMapMode
,aTargetMapMode
) );
217 pWMF
->WriteInt16( aPt
.X() ).WriteInt16( aPt
.Y() );
220 void WMFWriter::WritePointYX(const Point
& rPoint
)
222 Point
aPt( OutputDevice::LogicToLogic(rPoint
,aSrcMapMode
,aTargetMapMode
) );
223 pWMF
->WriteInt16( aPt
.Y() ).WriteInt16( aPt
.X() );
226 sal_Int32
WMFWriter::ScaleWidth( sal_Int32 nDX
)
228 Size
aSz( OutputDevice::LogicToLogic(Size(nDX
,0),aSrcMapMode
,aTargetMapMode
) );
232 void WMFWriter::WriteSize(const Size
& rSize
)
234 Size
aSz( OutputDevice::LogicToLogic(rSize
,aSrcMapMode
,aTargetMapMode
) );
235 pWMF
->WriteInt16( aSz
.Width() ).WriteInt16( aSz
.Height() );
238 void WMFWriter::WriteHeightWidth(const Size
& rSize
)
240 Size
aSz( OutputDevice::LogicToLogic(rSize
,aSrcMapMode
,aTargetMapMode
) );
241 pWMF
->WriteInt16( aSz
.Height() ).WriteInt16( aSz
.Width() );
244 void WMFWriter::WriteRectangle(const Rectangle
& rRect
)
246 WritePointYX(Point(rRect
.Right()+1,rRect
.Bottom()+1));
247 WritePointYX(rRect
.TopLeft());
250 void WMFWriter::WriteColor(const Color
& rColor
)
252 pWMF
->WriteUChar( rColor
.GetRed() ).WriteUChar( rColor
.GetGreen() ).WriteUChar( rColor
.GetBlue() ).WriteUChar( 0 );
255 void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords
, sal_uInt16 nType
)
257 nActRecordPos
=pWMF
->Tell();
258 if (nSizeWords
>nMaxRecordSize
) nMaxRecordSize
=nSizeWords
;
259 pWMF
->WriteUInt32( nSizeWords
).WriteUInt16( nType
);
262 void WMFWriter::UpdateRecordHeader()
267 nPos
=pWMF
->Tell(); nSize
=nPos
-nActRecordPos
;
268 if ((nSize
& 1)!=0) {
269 pWMF
->WriteUChar( 0 );
273 if (nSize
>nMaxRecordSize
) nMaxRecordSize
=nSize
;
274 pWMF
->Seek(nActRecordPos
);
275 pWMF
->WriteUInt32( nSize
);
279 void WMFWriter::WMFRecord_Arc(const Rectangle
& rRect
, const Point
& rStartPt
, const Point
& rEndPt
)
281 WriteRecordHeader(0x0000000b,W_META_ARC
);
282 WritePointYX(rEndPt
);
283 WritePointYX(rStartPt
);
284 WriteRectangle(rRect
);
287 void WMFWriter::WMFRecord_Chord(const Rectangle
& rRect
, const Point
& rStartPt
, const Point
& rEndPt
)
289 WriteRecordHeader(0x0000000b,W_META_CHORD
);
290 WritePointYX(rEndPt
);
291 WritePointYX(rStartPt
);
292 WriteRectangle(rRect
);
295 void WMFWriter::WMFRecord_CreateBrushIndirect(const Color
& rColor
)
297 WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT
);
299 if( rColor
==Color(COL_TRANSPARENT
) )
300 pWMF
->WriteUInt16( W_BS_HOLLOW
);
302 pWMF
->WriteUInt16( W_BS_SOLID
);
304 WriteColor( rColor
);
305 pWMF
->WriteUInt16( 0 );
308 void WMFWriter::WMFRecord_CreateFontIndirect(const vcl::Font
& rFont
)
310 sal_uInt16 nWeight
,i
;
311 sal_uInt8 nPitchFamily
;
313 WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT
);
314 WriteHeightWidth(Size(rFont
.GetSize().Width(),-rFont
.GetSize().Height()));
315 pWMF
->WriteInt16( rFont
.GetOrientation() ).WriteInt16( rFont
.GetOrientation() );
317 switch (rFont
.GetWeight()) {
318 case WEIGHT_THIN
: nWeight
=W_FW_THIN
; break;
319 case WEIGHT_ULTRALIGHT
: nWeight
=W_FW_ULTRALIGHT
; break;
320 case WEIGHT_LIGHT
: nWeight
=W_FW_LIGHT
; break;
321 case WEIGHT_SEMILIGHT
: nWeight
=W_FW_LIGHT
; break;
322 case WEIGHT_NORMAL
: nWeight
=W_FW_NORMAL
; break;
323 case WEIGHT_MEDIUM
: nWeight
=W_FW_MEDIUM
; break;
324 case WEIGHT_SEMIBOLD
: nWeight
=W_FW_SEMIBOLD
; break;
325 case WEIGHT_BOLD
: nWeight
=W_FW_BOLD
; break;
326 case WEIGHT_ULTRABOLD
: nWeight
=W_FW_ULTRABOLD
; break;
327 case WEIGHT_BLACK
: nWeight
=W_FW_BLACK
; break;
328 default: nWeight
=W_FW_DONTCARE
;
330 pWMF
->WriteUInt16( nWeight
);
332 if (rFont
.GetItalic()==ITALIC_NONE
) pWMF
->WriteUChar( 0 ); else pWMF
->WriteUChar( 1 );
333 if (rFont
.GetUnderline()==UNDERLINE_NONE
) pWMF
->WriteUChar( 0 ); else pWMF
->WriteUChar( 1 );
334 if (rFont
.GetStrikeout()==STRIKEOUT_NONE
) pWMF
->WriteUChar( 0 ); else pWMF
->WriteUChar( 1 );
336 rtl_TextEncoding eFontNameEncoding
= rFont
.GetCharSet();
337 sal_uInt8 nCharSet
= rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding
);
338 if ( eFontNameEncoding
== RTL_TEXTENCODING_SYMBOL
)
339 eFontNameEncoding
= RTL_TEXTENCODING_MS_1252
;
341 nCharSet
= W_ANSI_CHARSET
;
342 pWMF
->WriteUChar( nCharSet
);
344 pWMF
->WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
346 switch (rFont
.GetPitch()) {
347 case PITCH_FIXED
: nPitchFamily
=W_FIXED_PITCH
; break;
348 case PITCH_VARIABLE
: nPitchFamily
=W_VARIABLE_PITCH
; break;
349 default: nPitchFamily
=W_DEFAULT_PITCH
;
351 switch (rFont
.GetFamily()) {
352 case FAMILY_DECORATIVE
: nPitchFamily
|=W_FF_DECORATIVE
; break;
353 case FAMILY_MODERN
: nPitchFamily
|=W_FF_MODERN
; break;
354 case FAMILY_ROMAN
: nPitchFamily
|=W_FF_ROMAN
; break;
355 case FAMILY_SCRIPT
: nPitchFamily
|=W_FF_SCRIPT
; break;
356 case FAMILY_SWISS
: nPitchFamily
|=W_FF_SWISS
; break;
357 default: nPitchFamily
|=W_FF_DONTCARE
;
359 pWMF
->WriteUChar( nPitchFamily
);
361 OString
aFontName(OUStringToOString(rFont
.GetName(), eFontNameEncoding
));
362 for ( i
= 0; i
< W_LF_FACESIZE
; i
++ )
364 sal_Char nChar
= ( i
< aFontName
.getLength() ) ? aFontName
[i
] : 0;
365 pWMF
->WriteChar( nChar
);
367 UpdateRecordHeader();
370 void WMFWriter::WMFRecord_CreatePenIndirect(const Color
& rColor
, const LineInfo
& rLineInfo
)
372 WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT
);
373 sal_uInt16 nStyle
= rColor
== Color( COL_TRANSPARENT
) ? W_PS_NULL
: W_PS_SOLID
;
374 switch( rLineInfo
.GetStyle() )
378 if ( rLineInfo
.GetDotCount() )
380 if ( !rLineInfo
.GetDashCount() )
384 if ( rLineInfo
.GetDotCount() == 1 )
385 nStyle
= W_PS_DASHDOT
;
387 nStyle
= W_PS_DASHDOTDOT
;
400 pWMF
->WriteUInt16( nStyle
);
402 WriteSize( Size( rLineInfo
.GetWidth(), 0 ) );
403 WriteColor( rColor
);
406 void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle
)
408 WriteRecordHeader(0x00000004,W_META_DELETEOBJECT
);
409 pWMF
->WriteUInt16( nObjectHandle
);
412 void WMFWriter::WMFRecord_Ellipse(const Rectangle
& rRect
)
414 WriteRecordHeader(0x00000007,W_META_ELLIPSE
);
415 WriteRectangle(rRect
);
418 void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc
, sal_uInt32 nLen
, const sal_Int8
* pData
)
421 sal_uInt32 nTmp
= OSL_SWAPDWORD( nEsc
);
422 sal_uInt32 nCheckSum
= rtl_crc32( 0, &nTmp
, 4 );
424 sal_uInt32 nCheckSum
= rtl_crc32( 0, &nEsc
, 4 );
427 nCheckSum
= rtl_crc32( nCheckSum
, pData
, nLen
);
429 WriteRecordHeader( 3 + 9 + ( ( nLen
+ 1 ) >> 1 ), W_META_ESCAPE
);
430 pWMF
->WriteUInt16( W_MFCOMMENT
)
431 .WriteUInt16( nLen
+ 14 ) // we will always have a fourteen byte escape header:
432 .WriteUInt16( 0x4f4f ) // OO
433 .WriteUInt32( 0xa2c2a ) // evil magic number
434 .WriteUInt32( nCheckSum
) // crc32 checksum about nEsc & pData
435 .WriteUInt32( nEsc
); // escape number
436 pWMF
->Write( pData
, nLen
);
438 pWMF
->WriteUChar( 0 ); // pad byte
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
444 bool WMFWriter::WMFRecord_Escape_Unicode( const Point
& rPoint
, const OUString
& rUniStr
, const long* pDXAry
)
446 bool bEscapeUsed
= false;
448 sal_uInt32 i
, nStringLen
= rUniStr
.getLength();
451 // first we will check if a comment is necessary
452 if ( aSrcFont
.GetCharSet() != RTL_TEXTENCODING_SYMBOL
) // symbol is always byte character, so there is no unicode loss
454 const sal_Unicode
* pBuf
= rUniStr
.getStr();
455 const rtl_TextEncoding aTextEncodingOrg
= aSrcFont
.GetCharSet();
456 OString
aByteStr(OUStringToOString(rUniStr
, aTextEncodingOrg
));
457 OUString
aUniStr2(OStringToOUString(aByteStr
, aTextEncodingOrg
));
458 const sal_Unicode
* pConversion
= aUniStr2
.getStr(); // this is the unicode array after bytestring <-> unistring conversion
459 for ( i
= 0; i
< nStringLen
; i
++ )
461 if ( *pBuf
++ != *pConversion
++ )
465 if ( i
!= nStringLen
) // after conversion the characters are not original,
466 { // try again, with determining a better charset from unicode char
467 pBuf
= rUniStr
.getStr();
468 const sal_Unicode
* pCheckChar
= pBuf
;
469 rtl_TextEncoding aTextEncoding
= getBestMSEncodingByChar(*pCheckChar
); // try the first character
470 for ( i
= 1; i
< nStringLen
; i
++)
472 if (aTextEncoding
!= aTextEncodingOrg
) // found something
475 aTextEncoding
= getBestMSEncodingByChar(*pCheckChar
); // try the next character
478 aByteStr
= OUStringToOString(rUniStr
, aTextEncoding
);
479 aUniStr2
= OStringToOUString(aByteStr
, aTextEncoding
);
480 pConversion
= aUniStr2
.getStr(); // this is the unicode array after bytestring <-> unistring conversion
481 for ( i
= 0; i
< nStringLen
; i
++ )
483 if ( *pBuf
++ != *pConversion
++ )
488 aSrcFont
.SetCharSet (aTextEncoding
);
493 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 Color
aOldFillColor( aSrcFillColor
);
496 Color
aOldLineColor( aSrcLineColor
);
497 aSrcLineInfo
= LineInfo();
498 aSrcFillColor
= aSrcTextColor
;
499 aSrcLineColor
= Color( COL_TRANSPARENT
);
500 SetLineAndFillAttr();
501 pVirDev
->SetFont( aSrcFont
);
502 std::vector
<tools::PolyPolygon
> aPolyPolyVec
;
503 if ( pVirDev
->GetTextOutlines( aPolyPolyVec
, rUniStr
) )
505 sal_uInt32 nDXCount
= pDXAry
? nStringLen
: 0;
506 sal_uInt32 nSkipActions
= aPolyPolyVec
.size();
507 sal_Int32 nStrmLen
= 8 +
508 + sizeof( nStringLen
) + ( nStringLen
* 2 )
509 + sizeof( nDXCount
) + ( nDXCount
* 4 )
510 + sizeof( nSkipActions
);
512 SvMemoryStream
aMemoryStream( nStrmLen
);
513 Point
aPt( OutputDevice::LogicToLogic( rPoint
, aSrcMapMode
, aTargetMapMode
) );
514 aMemoryStream
.WriteInt32( aPt
.X() )
515 .WriteInt32( aPt
.Y() )
516 .WriteUInt32( nStringLen
);
517 for ( i
= 0; i
< nStringLen
; i
++ )
518 aMemoryStream
.WriteUInt16( rUniStr
[ i
] );
519 aMemoryStream
.WriteUInt32( nDXCount
);
520 for ( i
= 0; i
< nDXCount
; i
++ )
521 aMemoryStream
.WriteInt32( pDXAry
[ i
] );
522 aMemoryStream
.WriteUInt32( nSkipActions
);
523 WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE
, nStrmLen
, static_cast<const sal_Int8
*>(aMemoryStream
.GetData()) );
525 std::vector
<tools::PolyPolygon
>::iterator
aIter( aPolyPolyVec
.begin() );
526 while ( aIter
!= aPolyPolyVec
.end() )
528 tools::PolyPolygon
aPolyPoly( *aIter
++ );
529 aPolyPoly
.Move( rPoint
.X(), rPoint
.Y() );
530 WMFRecord_PolyPolygon( aPolyPoly
);
532 aSrcFillColor
= aOldFillColor
;
533 aSrcLineColor
= aOldLineColor
;
542 void WMFWriter::WMFRecord_ExtTextOut( const Point
& rPoint
,
543 const OUString
& rString
,
546 sal_Int32 nOriginalTextLen
= rString
.getLength();
548 if ( (nOriginalTextLen
<= 1) || (pDXAry
== NULL
) )
550 WMFRecord_TextOut(rPoint
, rString
);
553 rtl_TextEncoding eChrSet
= aSrcFont
.GetCharSet();
554 OString
aByteString(OUStringToOString(rString
, eChrSet
));
555 TrueExtTextOut(rPoint
, rString
, aByteString
, pDXAry
);
558 void WMFWriter::TrueExtTextOut( const Point
& rPoint
, const OUString
& rString
,
559 const OString
& rByteString
, const long* pDXAry
)
561 WriteRecordHeader( 0, W_META_EXTTEXTOUT
);
562 WritePointYX( rPoint
);
563 sal_uInt16 nNewTextLen
= static_cast<sal_uInt16
>(rByteString
.getLength());
564 pWMF
->WriteUInt16( nNewTextLen
).WriteUInt16( 0 );
565 write_uInt8s_FromOString(*pWMF
, rByteString
, nNewTextLen
);
566 if ( nNewTextLen
& 1 )
567 pWMF
->WriteUChar( 0 );
569 sal_Int32 nOriginalTextLen
= rString
.getLength();
570 boost::scoped_array
<sal_Int16
> pConvertedDXAry(new sal_Int16
[ nOriginalTextLen
]);
572 pConvertedDXAry
[ j
++ ] = (sal_Int16
)ScaleWidth( pDXAry
[ 0 ] );
573 for (sal_uInt16 i
= 1; i
< ( nOriginalTextLen
- 1 ); ++i
)
574 pConvertedDXAry
[ j
++ ] = (sal_Int16
)ScaleWidth( pDXAry
[ i
] - pDXAry
[ i
- 1 ] );
575 pConvertedDXAry
[ j
] = (sal_Int16
)ScaleWidth( pDXAry
[ nOriginalTextLen
- 2 ] / ( nOriginalTextLen
- 1 ) );
577 for (sal_uInt16 i
= 0; i
< nOriginalTextLen
; ++i
)
579 sal_Int16 nDx
= pConvertedDXAry
[ i
];
580 pWMF
->WriteInt16( nDx
);
581 if ( nOriginalTextLen
< nNewTextLen
)
583 sal_Unicode nUniChar
= rString
[i
];
584 OString
aTemp(&nUniChar
, 1, aSrcFont
.GetCharSet());
585 j
= aTemp
.getLength();
587 pWMF
->WriteUInt16( 0 );
590 pConvertedDXAry
.reset();
591 UpdateRecordHeader();
594 void WMFWriter::WMFRecord_LineTo(const Point
& rPoint
)
596 WriteRecordHeader(0x00000005,W_META_LINETO
);
597 WritePointYX(rPoint
);
600 void WMFWriter::WMFRecord_MoveTo(const Point
& rPoint
)
602 WriteRecordHeader(0x00000005,W_META_MOVETO
);
603 WritePointYX(rPoint
);
606 void WMFWriter::WMFRecord_Pie(const Rectangle
& rRect
, const Point
& rStartPt
, const Point
& rEndPt
)
608 WriteRecordHeader(0x0000000b,W_META_PIE
);
609 WritePointYX(rEndPt
);
610 WritePointYX(rStartPt
);
611 WriteRectangle(rRect
);
614 void WMFWriter::WMFRecord_Polygon(const Polygon
& rPoly
)
619 if ( rPoly
.HasFlags() )
620 rPoly
.AdaptiveSubdivide( aSimplePoly
);
623 nSize
= aSimplePoly
.GetSize();
624 WriteRecordHeader(((sal_uLong
)nSize
)*2+4,W_META_POLYGON
);
625 pWMF
->WriteUInt16( nSize
);
626 for (i
=0; i
<nSize
; i
++) WritePointXY(aSimplePoly
.GetPoint(i
));
629 void WMFWriter::WMFRecord_PolyLine(const Polygon
& rPoly
)
633 if ( rPoly
.HasFlags() )
634 rPoly
.AdaptiveSubdivide( aSimplePoly
);
637 nSize
=aSimplePoly
.GetSize();
638 WriteRecordHeader(((sal_uLong
)nSize
)*2+4,W_META_POLYLINE
);
639 pWMF
->WriteUInt16( nSize
);
640 for (i
=0; i
<nSize
; i
++) WritePointXY(aSimplePoly
.GetPoint(i
));
643 void WMFWriter::WMFRecord_PolyPolygon(const tools::PolyPolygon
& rPolyPoly
)
645 const Polygon
* pPoly
;
646 sal_uInt16 nCount
,nSize
,i
,j
;
648 nCount
=rPolyPoly
.Count();
649 tools::PolyPolygon
aSimplePolyPoly( rPolyPoly
);
650 for ( i
= 0; i
< nCount
; i
++ )
652 if ( aSimplePolyPoly
[ i
].HasFlags() )
655 aSimplePolyPoly
[ i
].AdaptiveSubdivide( aSimplePoly
);
656 aSimplePolyPoly
[ i
] = aSimplePoly
;
659 WriteRecordHeader(0,W_META_POLYPOLYGON
);
660 pWMF
->WriteUInt16( nCount
);
661 for (i
=0; i
<nCount
; i
++) pWMF
->WriteUInt16( (aSimplePolyPoly
.GetObject(i
).GetSize()) );
662 for (i
=0; i
<nCount
; i
++) {
663 pPoly
=&(aSimplePolyPoly
.GetObject(i
));
664 nSize
=pPoly
->GetSize();
665 for (j
=0; j
<nSize
; j
++) WritePointXY(pPoly
->GetPoint(j
));
667 UpdateRecordHeader();
670 void WMFWriter::WMFRecord_Rectangle(const Rectangle
& rRect
)
672 WriteRecordHeader( 0x00000007,W_META_RECTANGLE
);
673 WriteRectangle( rRect
);
676 void WMFWriter::WMFRecord_RestoreDC()
678 WriteRecordHeader(0x00000004,W_META_RESTOREDC
);
679 pWMF
->WriteInt16( -1 );
682 void WMFWriter::WMFRecord_RoundRect(const Rectangle
& rRect
, long nHorzRound
, long nVertRound
)
684 WriteRecordHeader(0x00000009,W_META_ROUNDRECT
);
685 WriteHeightWidth(Size(nHorzRound
,nVertRound
));
686 WriteRectangle(rRect
);
689 void WMFWriter::WMFRecord_SaveDC()
691 WriteRecordHeader(0x00000003,W_META_SAVEDC
);
694 void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle
)
696 WriteRecordHeader(0x00000004,W_META_SELECTOBJECT
);
697 pWMF
->WriteUInt16( nObjectHandle
);
700 void WMFWriter::WMFRecord_SetBkMode(bool bTransparent
)
702 WriteRecordHeader(0x00000004,W_META_SETBKMODE
);
703 if (bTransparent
) pWMF
->WriteUInt16( W_TRANSPARENT
);
704 else pWMF
->WriteUInt16( W_OPAQUE
);
707 void WMFWriter::WMFRecord_SetStretchBltMode()
709 WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE
);
710 pWMF
->WriteUInt16( 3 ); // STRETCH_DELETESCANS
713 void WMFWriter::WMFRecord_SetPixel(const Point
& rPoint
, const Color
& rColor
)
715 WriteRecordHeader(0x00000007,W_META_SETPIXEL
);
717 WritePointYX(rPoint
);
720 void WMFWriter::WMFRecord_SetROP2(RasterOp eROP
)
725 case ROP_INVERT
: nROP2
=W_R2_NOT
; break;
726 case ROP_XOR
: nROP2
=W_R2_XORPEN
; break;
727 default: nROP2
=W_R2_COPYPEN
;
729 WriteRecordHeader(0x00000004,W_META_SETROP2
);
730 pWMF
->WriteUInt16( nROP2
);
733 void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign
, sal_uInt32 eHorTextAlign
)
737 switch (eFontAlign
) {
738 case ALIGN_TOP
: nAlign
=W_TA_TOP
; break;
739 case ALIGN_BOTTOM
: nAlign
=W_TA_BOTTOM
; break;
740 default: nAlign
=W_TA_BASELINE
;
742 nAlign
|=eHorTextAlign
;
743 nAlign
|=W_TA_NOUPDATECP
;
745 WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN
);
746 pWMF
->WriteUInt16( nAlign
);
749 void WMFWriter::WMFRecord_SetTextColor(const Color
& rColor
)
751 WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR
);
755 void WMFWriter::WMFRecord_SetWindowExt(const Size
& rSize
)
757 WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT
);
758 WriteHeightWidth(rSize
);
761 void WMFWriter::WMFRecord_SetWindowOrg(const Point
& rPoint
)
763 WriteRecordHeader(0x00000005,W_META_SETWINDOWORG
);
764 WritePointYX(rPoint
);
767 void WMFWriter::WMFRecord_StretchDIB( const Point
& rPoint
, const Size
& rSize
,
768 const Bitmap
& rBitmap
, sal_uInt32 nROP
)
770 sal_uLong nPosAnf
,nPosEnd
;
772 nActBitmapPercent
=50;
775 WriteRecordHeader(0x00000000,W_META_STRETCHDIB
);
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 nPosAnf
=pWMF
->Tell(); // remember position, where parameters should be stored
783 pWMF
->WriteInt32( 0 ).WriteInt32( 0 ); // replenish 8 bytes (these 8 bytes +
784 // 14 bytes superfluous FILEHEADER
785 // = 22 bytes parameter)
788 WriteDIB(rBitmap
, *pWMF
, false, true);
790 // write the parameters:
791 nPosEnd
=pWMF
->Tell();
794 // determine raster-op, if nothing was passed
797 switch( eSrcRasterOp
)
799 case ROP_INVERT
: nROP
= W_DSTINVERT
; break;
800 case ROP_XOR
: nROP
= W_SRCINVERT
; break;
801 default: nROP
= W_SRCCOPY
;
805 pWMF
->WriteUInt32( nROP
). WriteInt16( 0 ). WriteInt16( rBitmap
.GetSizePixel().Height() ). WriteInt16( rBitmap
.GetSizePixel().Width() ). WriteInt16( 0 ). WriteInt16( 0 );
807 WriteHeightWidth(rSize
);
808 WritePointYX(rPoint
);
811 UpdateRecordHeader();
817 void WMFWriter::WMFRecord_TextOut(const Point
& rPoint
, const OUString
& rStr
)
819 rtl_TextEncoding eChrSet
= aSrcFont
.GetCharSet();
820 OString
aString(OUStringToOString(rStr
, eChrSet
));
821 TrueTextOut(rPoint
, aString
);
824 void WMFWriter::TrueTextOut(const Point
& rPoint
, const OString
& rString
)
826 WriteRecordHeader(0,W_META_TEXTOUT
);
828 write_uInt16_lenPrefixed_uInt8s_FromOString(*pWMF
, rString
);
829 sal_Int32 nLen
= rString
.getLength();
830 if ((nLen
&1)!=0) pWMF
->WriteUChar( 0 );
831 WritePointYX(rPoint
);
832 UpdateRecordHeader();
835 void WMFWriter::WMFRecord_EndOfFile()
837 WriteRecordHeader(0x00000003,0x0000);
840 void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle
& rRect
)
842 WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT
);
843 WriteRectangle(rRect
);
846 sal_uInt16
WMFWriter::AllocHandle()
850 for (i
=0; i
<MAXOBJECTHANDLES
; i
++) {
851 if (!bHandleAllocated
[i
]) {
852 bHandleAllocated
[i
]=true;
860 void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle
)
862 if (nObjectHandle
<MAXOBJECTHANDLES
) bHandleAllocated
[nObjectHandle
]=false;
865 void WMFWriter::CreateSelectDeletePen( const Color
& rColor
, const LineInfo
& rLineInfo
)
867 sal_uInt16 nOldHandle
;
869 nOldHandle
=nDstPenHandle
;
870 nDstPenHandle
=AllocHandle();
871 WMFRecord_CreatePenIndirect( rColor
, rLineInfo
);
872 WMFRecord_SelectObject(nDstPenHandle
);
873 if (nOldHandle
<MAXOBJECTHANDLES
) {
874 WMFRecord_DeleteObject(nOldHandle
);
875 FreeHandle(nOldHandle
);
879 void WMFWriter::CreateSelectDeleteFont(const vcl::Font
& rFont
)
881 sal_uInt16 nOldHandle
;
883 nOldHandle
=nDstFontHandle
;
884 nDstFontHandle
=AllocHandle();
885 WMFRecord_CreateFontIndirect(rFont
);
886 WMFRecord_SelectObject(nDstFontHandle
);
887 if (nOldHandle
<MAXOBJECTHANDLES
) {
888 WMFRecord_DeleteObject(nOldHandle
);
889 FreeHandle(nOldHandle
);
893 void WMFWriter::CreateSelectDeleteBrush(const Color
& rColor
)
895 sal_uInt16 nOldHandle
;
897 nOldHandle
=nDstBrushHandle
;
898 nDstBrushHandle
=AllocHandle();
899 WMFRecord_CreateBrushIndirect(rColor
);
900 WMFRecord_SelectObject(nDstBrushHandle
);
901 if (nOldHandle
<MAXOBJECTHANDLES
) {
902 WMFRecord_DeleteObject(nOldHandle
);
903 FreeHandle(nOldHandle
);
907 void WMFWriter::SetLineAndFillAttr()
909 if ( eDstROP2
!= eSrcRasterOp
)
911 eDstROP2
=eSrcRasterOp
;
912 WMFRecord_SetROP2(eDstROP2
);
914 if ( ( aDstLineColor
!= aSrcLineColor
) || ( aDstLineInfo
!= aSrcLineInfo
) )
916 aDstLineColor
= aSrcLineColor
;
917 aDstLineInfo
= aSrcLineInfo
;
918 CreateSelectDeletePen( aDstLineColor
, aDstLineInfo
);
920 if ( aDstFillColor
!= aSrcFillColor
)
922 aDstFillColor
= aSrcFillColor
;
923 CreateSelectDeleteBrush( aDstFillColor
);
925 if ( bDstIsClipping
!= bSrcIsClipping
||
926 (bSrcIsClipping
&& aDstClipRegion
!=aSrcClipRegion
)) {
927 bDstIsClipping
=bSrcIsClipping
;
928 aDstClipRegion
=aSrcClipRegion
;
932 void WMFWriter::SetAllAttr()
934 SetLineAndFillAttr();
935 if ( aDstTextColor
!= aSrcTextColor
)
937 aDstTextColor
= aSrcTextColor
;
938 WMFRecord_SetTextColor(aDstTextColor
);
940 if ( eDstTextAlign
!= eSrcTextAlign
|| eDstHorTextAlign
!= eSrcHorTextAlign
)
942 eDstTextAlign
= eSrcTextAlign
;
943 eDstHorTextAlign
= eSrcHorTextAlign
;
944 WMFRecord_SetTextAlign( eDstTextAlign
, eDstHorTextAlign
);
946 if ( aDstFont
!= aSrcFont
)
948 pVirDev
->SetFont(aSrcFont
);
949 if ( aDstFont
.GetName() != aSrcFont
.GetName() )
951 FontCharMapPtr pFontCharMap
;
952 if ( pVirDev
->GetFontCharMap( pFontCharMap
) )
954 if ( ( pFontCharMap
->GetFirstChar() & 0xff00 ) == 0xf000 )
955 aSrcFont
.SetCharSet( RTL_TEXTENCODING_SYMBOL
);
956 else if ( aSrcFont
.GetCharSet() == RTL_TEXTENCODING_SYMBOL
)
957 aSrcFont
.SetCharSet( RTL_TEXTENCODING_MS_1252
);
964 CreateSelectDeleteFont(aDstFont
);
968 void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo
& rInfo
, const basegfx::B2DPolygon
& rLinePolygon
)
970 if(rLinePolygon
.count())
972 basegfx::B2DPolyPolygon
aLinePolyPolygon(rLinePolygon
);
973 basegfx::B2DPolyPolygon aFillPolyPolygon
;
975 rInfo
.applyToB2DPolyPolygon(aLinePolyPolygon
, aFillPolyPolygon
);
977 if(aLinePolyPolygon
.count())
979 aSrcLineInfo
= rInfo
;
980 SetLineAndFillAttr();
982 for(sal_uInt32
a(0); a
< aLinePolyPolygon
.count(); a
++)
984 const basegfx::B2DPolygon
aCandidate(aLinePolyPolygon
.getB2DPolygon(a
));
985 WMFRecord_PolyLine(Polygon(aCandidate
));
989 if(aFillPolyPolygon
.count())
991 const Color
aOldLineColor(aSrcLineColor
);
992 const Color
aOldFillColor(aSrcFillColor
);
994 aSrcLineColor
= Color( COL_TRANSPARENT
);
995 aSrcFillColor
= aOldLineColor
;
996 SetLineAndFillAttr();
998 for(sal_uInt32
a(0); a
< aFillPolyPolygon
.count(); a
++)
1000 const Polygon
aPolygon(aFillPolyPolygon
.getB2DPolygon(a
));
1001 WMFRecord_Polygon(Polygon(aPolygon
));
1004 aSrcLineColor
= aOldLineColor
;
1005 aSrcFillColor
= aOldFillColor
;
1006 SetLineAndFillAttr();
1011 void WMFWriter::WriteRecords( const GDIMetaFile
& rMTF
)
1015 size_t nACount
= rMTF
.GetActionSize();
1017 WMFRecord_SetStretchBltMode();
1019 for( size_t nA
= 0; nA
< nACount
; nA
++ )
1021 MetaAction
* pMA
= rMTF
.GetAction( nA
);
1023 switch( pMA
->GetType() )
1025 case MetaActionType::PIXEL
:
1027 const MetaPixelAction
* pA
= static_cast<const MetaPixelAction
*>(pMA
);
1028 aSrcLineInfo
= LineInfo();
1029 SetLineAndFillAttr();
1030 WMFRecord_SetPixel( pA
->GetPoint(), pA
->GetColor() );
1034 case MetaActionType::POINT
:
1036 const MetaPointAction
* pA
= static_cast<const MetaPointAction
*>(pMA
);
1037 const Point
& rPt
= pA
->GetPoint();
1038 aSrcLineInfo
= LineInfo();
1039 SetLineAndFillAttr();
1040 WMFRecord_MoveTo( rPt
);
1041 WMFRecord_LineTo( rPt
);
1045 case MetaActionType::LINE
:
1047 const MetaLineAction
* pA
= static_cast<const MetaLineAction
*>(pMA
);
1048 if(pA
->GetLineInfo().IsDefault())
1050 aSrcLineInfo
= pA
->GetLineInfo();
1051 SetLineAndFillAttr();
1052 WMFRecord_MoveTo( pA
->GetStartPoint() );
1053 WMFRecord_LineTo( pA
->GetEndPoint() );
1057 // LineInfo used; handle Dash/Dot and fat lines
1058 basegfx::B2DPolygon aPolygon
;
1059 aPolygon
.append(basegfx::B2DPoint(pA
->GetStartPoint().X(), pA
->GetStartPoint().Y()));
1060 aPolygon
.append(basegfx::B2DPoint(pA
->GetEndPoint().X(), pA
->GetEndPoint().Y()));
1061 HandleLineInfoPolyPolygons(pA
->GetLineInfo(), aPolygon
);
1066 case MetaActionType::RECT
:
1068 const MetaRectAction
* pA
= static_cast<const MetaRectAction
*>(pMA
);
1069 aSrcLineInfo
= LineInfo();
1070 SetLineAndFillAttr();
1071 WMFRecord_Rectangle( pA
->GetRect() );
1075 case MetaActionType::ROUNDRECT
:
1077 const MetaRoundRectAction
* pA
= static_cast<const MetaRoundRectAction
*>(pMA
);
1078 aSrcLineInfo
= LineInfo();
1079 SetLineAndFillAttr();
1080 WMFRecord_RoundRect( pA
->GetRect(), pA
->GetHorzRound(), pA
->GetVertRound() );
1084 case MetaActionType::ELLIPSE
:
1086 const MetaEllipseAction
* pA
= static_cast<const MetaEllipseAction
*>(pMA
);
1087 aSrcLineInfo
= LineInfo();
1088 SetLineAndFillAttr();
1089 WMFRecord_Ellipse( pA
->GetRect() );
1093 case MetaActionType::ARC
:
1095 const MetaArcAction
* pA
= static_cast<const MetaArcAction
*>(pMA
);
1096 aSrcLineInfo
= LineInfo();
1097 SetLineAndFillAttr();
1098 WMFRecord_Arc( pA
->GetRect(),pA
->GetStartPoint(),pA
->GetEndPoint() );
1102 case MetaActionType::PIE
:
1104 const MetaPieAction
* pA
= static_cast<const MetaPieAction
*>(pMA
);
1105 aSrcLineInfo
= LineInfo();
1106 SetLineAndFillAttr();
1107 WMFRecord_Pie( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint() );
1111 case MetaActionType::CHORD
:
1113 const MetaChordAction
* pA
= static_cast<const MetaChordAction
*>(pMA
);
1114 aSrcLineInfo
= LineInfo();
1115 SetLineAndFillAttr();
1116 WMFRecord_Chord( pA
->GetRect(), pA
->GetStartPoint(), pA
->GetEndPoint() );
1120 case MetaActionType::POLYLINE
:
1122 const MetaPolyLineAction
* pA
= static_cast<const MetaPolyLineAction
*>(pMA
);
1123 const Polygon
& rPoly
= pA
->GetPolygon();
1125 if( rPoly
.GetSize() )
1127 if(pA
->GetLineInfo().IsDefault())
1129 aSrcLineInfo
= pA
->GetLineInfo();
1130 SetLineAndFillAttr();
1131 WMFRecord_PolyLine( rPoly
);
1135 // LineInfo used; handle Dash/Dot and fat lines
1136 HandleLineInfoPolyPolygons(pA
->GetLineInfo(), rPoly
.getB2DPolygon());
1142 case MetaActionType::POLYGON
:
1144 const MetaPolygonAction
* pA
= static_cast<const MetaPolygonAction
*>(pMA
);
1145 aSrcLineInfo
= LineInfo();
1146 SetLineAndFillAttr();
1147 WMFRecord_Polygon( pA
->GetPolygon() );
1151 case MetaActionType::POLYPOLYGON
:
1153 const MetaPolyPolygonAction
* pA
= static_cast<const MetaPolyPolygonAction
*>(pMA
);
1154 aSrcLineInfo
= LineInfo();
1155 SetLineAndFillAttr();
1156 WMFRecord_PolyPolygon( pA
->GetPolyPolygon() );
1160 case MetaActionType::TEXTRECT
:
1162 const MetaTextRectAction
* pA
= static_cast<const MetaTextRectAction
*>(pMA
);
1163 OUString
aTemp( pA
->GetText() );
1164 aSrcLineInfo
= LineInfo();
1167 Point
aPos( pA
->GetRect().TopLeft() );
1168 if ( !WMFRecord_Escape_Unicode( aPos
, aTemp
, NULL
) )
1169 WMFRecord_TextOut( aPos
, aTemp
);
1173 case MetaActionType::TEXT
:
1175 const MetaTextAction
* pA
= static_cast<const MetaTextAction
*>(pMA
);
1176 OUString aTemp
= pA
->GetText().copy( pA
->GetIndex(), std::min
<sal_Int32
>(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1177 aSrcLineInfo
= LineInfo();
1179 if ( !WMFRecord_Escape_Unicode( pA
->GetPoint(), aTemp
, NULL
) )
1180 WMFRecord_TextOut( pA
->GetPoint(), aTemp
);
1184 case MetaActionType::TEXTARRAY
:
1186 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pMA
);
1188 OUString aTemp
= pA
->GetText().copy( pA
->GetIndex(), std::min
<sal_Int32
>(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1189 aSrcLineInfo
= LineInfo();
1191 if ( !WMFRecord_Escape_Unicode( pA
->GetPoint(), aTemp
, pA
->GetDXArray() ) )
1192 WMFRecord_ExtTextOut( pA
->GetPoint(), aTemp
, pA
->GetDXArray() );
1196 case MetaActionType::STRETCHTEXT
:
1198 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pMA
);
1199 OUString aTemp
= pA
->GetText().copy( pA
->GetIndex(), std::min
<sal_Int32
>(pA
->GetText().getLength() - pA
->GetIndex(), pA
->GetLen()) );
1202 sal_Int32 nNormSize
;
1204 pVirDev
->SetFont( aSrcFont
);
1205 nLen
= aTemp
.getLength();
1206 boost::scoped_array
<long> pDXAry(nLen
? new long[ nLen
] : NULL
);
1207 nNormSize
= pVirDev
->GetTextArray( aTemp
, pDXAry
.get() );
1208 if (nLen
&& nNormSize
== 0)
1210 OSL_FAIL("Impossible div by 0 action: MetaStretchTextAction!");
1214 for ( i
= 0; i
< ( nLen
- 1 ); i
++ )
1215 pDXAry
[ i
] = pDXAry
[ i
] * (sal_Int32
)pA
->GetWidth() / nNormSize
;
1216 if ( ( nLen
<= 1 ) || ( (sal_Int32
)pA
->GetWidth() == nNormSize
) )
1218 aSrcLineInfo
= LineInfo();
1220 if ( !WMFRecord_Escape_Unicode( pA
->GetPoint(), aTemp
, pDXAry
.get() ) )
1221 WMFRecord_ExtTextOut( pA
->GetPoint(), aTemp
, pDXAry
.get() );
1226 case MetaActionType::BMP
:
1228 const MetaBmpAction
* pA
= static_cast<const MetaBmpAction
*>(pMA
);
1229 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetBitmap().GetSizePixel(), pA
->GetBitmap() );
1233 case MetaActionType::BMPSCALE
:
1235 const MetaBmpScaleAction
* pA
= static_cast<const MetaBmpScaleAction
*>(pMA
);
1236 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetSize(), pA
->GetBitmap() );
1240 case MetaActionType::BMPSCALEPART
:
1242 const MetaBmpScalePartAction
* pA
= static_cast<const MetaBmpScalePartAction
*>(pMA
);
1243 Bitmap
aTmp( pA
->GetBitmap() );
1245 if( aTmp
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) ) )
1246 WMFRecord_StretchDIB( pA
->GetDestPoint(), pA
->GetDestSize(), aTmp
);
1250 case MetaActionType::BMPEX
:
1252 const MetaBmpExAction
* pA
= static_cast<const MetaBmpExAction
*>(pMA
);
1253 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1254 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1258 aBmp
.Replace( aMsk
, COL_WHITE
);
1260 WMFRecord_StretchDIB( pA
->GetPoint(), aMsk
.GetSizePixel(), aBmp
, W_SRCPAINT
);
1261 WMFRecord_StretchDIB( pA
->GetPoint(), aBmp
.GetSizePixel(), aBmp
, W_SRCAND
);
1264 WMFRecord_StretchDIB( pA
->GetPoint(), aBmp
.GetSizePixel(), aBmp
);
1268 case MetaActionType::BMPEXSCALE
:
1270 const MetaBmpExScaleAction
* pA
= static_cast<const MetaBmpExScaleAction
*>(pMA
);
1271 Bitmap
aBmp( pA
->GetBitmapEx().GetBitmap() );
1272 Bitmap
aMsk( pA
->GetBitmapEx().GetMask() );
1276 aBmp
.Replace( aMsk
, COL_WHITE
);
1278 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetSize(), aMsk
, W_SRCPAINT
);
1279 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetSize(), aBmp
, W_SRCAND
);
1282 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetSize(), aBmp
);
1286 case MetaActionType::BMPEXSCALEPART
:
1288 const MetaBmpExScalePartAction
* pA
= static_cast<const MetaBmpExScalePartAction
*>(pMA
);
1289 BitmapEx
aBmpEx( pA
->GetBitmapEx() );
1290 aBmpEx
.Crop( Rectangle( pA
->GetSrcPoint(), pA
->GetSrcSize() ) );
1291 Bitmap
aBmp( aBmpEx
.GetBitmap() );
1292 Bitmap
aMsk( aBmpEx
.GetMask() );
1296 aBmp
.Replace( aMsk
, COL_WHITE
);
1298 WMFRecord_StretchDIB( pA
->GetDestPoint(), pA
->GetDestSize(), aMsk
, W_SRCPAINT
);
1299 WMFRecord_StretchDIB( pA
->GetDestPoint(), pA
->GetDestSize(), aBmp
, W_SRCAND
);
1302 WMFRecord_StretchDIB( pA
->GetDestPoint(), pA
->GetDestSize(), aBmp
);
1306 case MetaActionType::GRADIENT
:
1308 const MetaGradientAction
* pA
= static_cast<const MetaGradientAction
*>(pMA
);
1309 GDIMetaFile aTmpMtf
;
1311 pVirDev
->AddGradientActions( pA
->GetRect(), pA
->GetGradient(), aTmpMtf
);
1312 WriteRecords( aTmpMtf
);
1316 case MetaActionType::HATCH
:
1318 const MetaHatchAction
* pA
= static_cast<const MetaHatchAction
*>(pMA
);
1319 GDIMetaFile aTmpMtf
;
1321 pVirDev
->AddHatchActions( pA
->GetPolyPolygon(), pA
->GetHatch(), aTmpMtf
);
1322 WriteRecords( aTmpMtf
);
1326 case MetaActionType::WALLPAPER
:
1328 const MetaWallpaperAction
* pA
= static_cast<const MetaWallpaperAction
*>(pMA
);
1329 const Color
& rColor
= pA
->GetWallpaper().GetColor();
1330 const Color
aOldLineColor( aSrcLineColor
);
1331 const Color
aOldFillColor( aSrcFillColor
);
1333 aSrcLineColor
= rColor
;
1334 aSrcFillColor
= rColor
;
1335 aSrcLineInfo
= LineInfo();
1336 SetLineAndFillAttr();
1337 WMFRecord_Rectangle( pA
->GetRect() );
1338 aSrcLineColor
= aOldLineColor
;
1339 aSrcFillColor
= aOldFillColor
;
1343 case MetaActionType::ISECTRECTCLIPREGION
:
1345 const MetaISectRectClipRegionAction
* pA
= static_cast<const MetaISectRectClipRegionAction
*>(pMA
);
1346 WMFRecord_IntersectClipRect( pA
->GetRect() );
1350 case MetaActionType::LINECOLOR
:
1352 const MetaLineColorAction
* pA
= static_cast<const MetaLineColorAction
*>(pMA
);
1354 if( pA
->IsSetting() )
1355 aSrcLineColor
= pA
->GetColor();
1357 aSrcLineColor
= Color( COL_TRANSPARENT
);
1361 case MetaActionType::FILLCOLOR
:
1363 const MetaFillColorAction
* pA
= static_cast<const MetaFillColorAction
*>(pMA
);
1365 if( pA
->IsSetting() )
1366 aSrcFillColor
= pA
->GetColor();
1368 aSrcFillColor
= Color( COL_TRANSPARENT
);
1372 case MetaActionType::TEXTCOLOR
:
1374 const MetaTextColorAction
* pA
= static_cast<const MetaTextColorAction
*>(pMA
);
1375 aSrcTextColor
= pA
->GetColor();
1379 case MetaActionType::TEXTFILLCOLOR
:
1381 const MetaTextFillColorAction
* pA
= static_cast<const MetaTextFillColorAction
*>(pMA
);
1382 if( pA
->IsSetting() )
1383 aSrcFont
.SetFillColor( pA
->GetColor() );
1385 aSrcFont
.SetFillColor( Color( COL_TRANSPARENT
) );
1389 case MetaActionType::TEXTALIGN
:
1391 const MetaTextAlignAction
* pA
= static_cast<const MetaTextAlignAction
*>(pMA
);
1392 eSrcTextAlign
= pA
->GetTextAlign();
1396 case MetaActionType::MAPMODE
:
1398 const MetaMapModeAction
* pA
= static_cast<const MetaMapModeAction
*>(pMA
);
1400 if (aSrcMapMode
!=pA
->GetMapMode())
1402 if( pA
->GetMapMode().GetMapUnit() == MAP_RELATIVE
)
1404 MapMode aMM
= pA
->GetMapMode();
1405 Fraction aScaleX
= aMM
.GetScaleX();
1406 Fraction aScaleY
= aMM
.GetScaleY();
1408 Point aOrigin
= aSrcMapMode
.GetOrigin();
1409 BigInt
aX( aOrigin
.X() );
1410 aX
*= BigInt( aScaleX
.GetDenominator() );
1411 if( aOrigin
.X() >= 0 )
1412 if( aScaleX
.GetNumerator() >= 0 )
1413 aX
+= BigInt( aScaleX
.GetNumerator()/2 );
1415 aX
-= BigInt( (aScaleX
.GetNumerator()+1)/2 );
1417 if( aScaleX
.GetNumerator() >= 0 )
1418 aX
-= BigInt( (aScaleX
.GetNumerator()-1)/2 );
1420 aX
+= BigInt( aScaleX
.GetNumerator()/2 );
1421 aX
/= BigInt( aScaleX
.GetNumerator() );
1422 aOrigin
.X() = (long)aX
+ aMM
.GetOrigin().X();
1423 BigInt
aY( aOrigin
.Y() );
1424 aY
*= BigInt( aScaleY
.GetDenominator() );
1425 if( aOrigin
.Y() >= 0 )
1426 if( aScaleY
.GetNumerator() >= 0 )
1427 aY
+= BigInt( aScaleY
.GetNumerator()/2 );
1429 aY
-= BigInt( (aScaleY
.GetNumerator()+1)/2 );
1431 if( aScaleY
.GetNumerator() >= 0 )
1432 aY
-= BigInt( (aScaleY
.GetNumerator()-1)/2 );
1434 aY
+= BigInt( aScaleY
.GetNumerator()/2 );
1435 aY
/= BigInt( aScaleY
.GetNumerator() );
1436 aOrigin
.Y() = (long)aY
+ aMM
.GetOrigin().Y();
1437 aSrcMapMode
.SetOrigin( aOrigin
);
1439 aScaleX
*= aSrcMapMode
.GetScaleX();
1440 aScaleY
*= aSrcMapMode
.GetScaleY();
1441 aSrcMapMode
.SetScaleX( aScaleX
);
1442 aSrcMapMode
.SetScaleY( aScaleY
);
1445 aSrcMapMode
=pA
->GetMapMode();
1450 case MetaActionType::FONT
:
1452 const MetaFontAction
* pA
= static_cast<const MetaFontAction
*>(pMA
);
1453 aSrcFont
= pA
->GetFont();
1455 if ( (aSrcFont
.GetCharSet() == RTL_TEXTENCODING_DONTKNOW
)
1456 || (aSrcFont
.GetCharSet() == RTL_TEXTENCODING_UNICODE
) )
1458 aSrcFont
.SetCharSet( RTL_TEXTENCODING_MS_1252
);
1460 eSrcTextAlign
= aSrcFont
.GetAlign();
1461 aSrcTextColor
= aSrcFont
.GetColor();
1462 aSrcFont
.SetAlign( ALIGN_BASELINE
);
1463 aSrcFont
.SetColor( COL_WHITE
);
1467 case MetaActionType::PUSH
:
1469 const MetaPushAction
* pA
= static_cast<const MetaPushAction
*>(pMA
);
1471 WMFWriterAttrStackMember
* pAt
= new WMFWriterAttrStackMember
;
1472 pAt
->nFlags
= pA
->GetFlags();
1473 pAt
->aClipRegion
= aSrcClipRegion
;
1474 pAt
->aLineColor
=aSrcLineColor
;
1475 pAt
->aFillColor
=aSrcFillColor
;
1476 pAt
->eRasterOp
=eSrcRasterOp
;
1477 pAt
->aFont
=aSrcFont
;
1478 pAt
->eTextAlign
=eSrcTextAlign
;
1479 pAt
->aTextColor
=aSrcTextColor
;
1480 pAt
->aMapMode
=aSrcMapMode
;
1481 pAt
->aLineInfo
=aDstLineInfo
;
1482 pAt
->pSucc
=pAttrStack
;
1485 SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
1491 case MetaActionType::POP
:
1493 WMFWriterAttrStackMember
* pAt
=pAttrStack
;
1497 aDstLineInfo
= pAt
->aLineInfo
;
1498 aDstLineColor
= pAt
->aLineColor
;
1499 if ( pAt
->nFlags
& PushFlags::LINECOLOR
)
1500 aSrcLineColor
= pAt
->aLineColor
;
1501 aDstFillColor
= pAt
->aFillColor
;
1502 if ( pAt
->nFlags
& PushFlags::FILLCOLOR
)
1503 aSrcFillColor
= pAt
->aFillColor
;
1504 eDstROP2
= pAt
->eRasterOp
;
1505 if ( pAt
->nFlags
& PushFlags::RASTEROP
)
1506 eSrcRasterOp
= pAt
->eRasterOp
;
1507 aDstFont
= pAt
->aFont
;
1508 if ( pAt
->nFlags
& PushFlags::FONT
)
1509 aSrcFont
= pAt
->aFont
;
1510 eDstTextAlign
= pAt
->eTextAlign
;
1511 if ( pAt
->nFlags
& ( PushFlags::FONT
| PushFlags::TEXTALIGN
) )
1512 eSrcTextAlign
= pAt
->eTextAlign
;
1513 aDstTextColor
= pAt
->aTextColor
;
1514 if ( pAt
->nFlags
& ( PushFlags::FONT
| PushFlags::TEXTCOLOR
) )
1515 aSrcTextColor
= pAt
->aTextColor
;
1516 if ( pAt
->nFlags
& PushFlags::MAPMODE
)
1517 aSrcMapMode
= pAt
->aMapMode
;
1518 aDstClipRegion
= pAt
->aClipRegion
;
1519 if ( pAt
->nFlags
& PushFlags::CLIPREGION
)
1520 aSrcClipRegion
= pAt
->aClipRegion
;
1522 WMFRecord_RestoreDC();
1523 pAttrStack
= pAt
->pSucc
;
1529 case MetaActionType::EPS
:
1531 const MetaEPSAction
* pA
= static_cast<const MetaEPSAction
*>(pMA
);
1532 const GDIMetaFile
aGDIMetaFile( pA
->GetSubstitute() );
1534 size_t nCount
= aGDIMetaFile
.GetActionSize();
1535 for ( size_t i
= 0; i
< nCount
; i
++ )
1537 const MetaAction
* pMetaAct
= aGDIMetaFile
.GetAction( i
);
1538 if ( pMetaAct
->GetType() == MetaActionType::BMPSCALE
)
1540 const MetaBmpScaleAction
* pBmpScaleAction
= static_cast<const MetaBmpScaleAction
*>(pMetaAct
);
1541 WMFRecord_StretchDIB( pA
->GetPoint(), pA
->GetSize(), pBmpScaleAction
->GetBitmap() );
1548 case MetaActionType::RASTEROP
:
1550 const MetaRasterOpAction
* pA
= static_cast<const MetaRasterOpAction
*>(pMA
);
1551 eSrcRasterOp
=pA
->GetRasterOp();
1555 case MetaActionType::Transparent
:
1557 aSrcLineInfo
= LineInfo();
1558 SetLineAndFillAttr();
1559 WMFRecord_PolyPolygon( static_cast<const MetaTransparentAction
*>(pMA
)->GetPolyPolygon() );
1563 case MetaActionType::FLOATTRANSPARENT
:
1565 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pMA
);
1567 GDIMetaFile
aTmpMtf( pA
->GetGDIMetaFile() );
1568 Point
aSrcPt( aTmpMtf
.GetPrefMapMode().GetOrigin() );
1569 const Size
aSrcSize( aTmpMtf
.GetPrefSize() );
1570 const Point
aDestPt( pA
->GetPoint() );
1571 const Size
aDestSize( pA
->GetSize() );
1572 const double fScaleX
= aSrcSize
.Width() ? (double) aDestSize
.Width() / aSrcSize
.Width() : 1.0;
1573 const double fScaleY
= aSrcSize
.Height() ? (double) aDestSize
.Height() / aSrcSize
.Height() : 1.0;
1574 long nMoveX
, nMoveY
;
1576 aSrcLineInfo
= LineInfo();
1579 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
1581 aTmpMtf
.Scale( fScaleX
, fScaleY
);
1582 aSrcPt
.X() = FRound( aSrcPt
.X() * fScaleX
), aSrcPt
.Y() = FRound( aSrcPt
.Y() * fScaleY
);
1585 nMoveX
= aDestPt
.X() - aSrcPt
.X(), nMoveY
= aDestPt
.Y() - aSrcPt
.Y();
1587 if( nMoveX
|| nMoveY
)
1588 aTmpMtf
.Move( nMoveX
, nMoveY
);
1590 WriteRecords( aTmpMtf
);
1594 case( MetaActionType::LAYOUTMODE
):
1596 ComplexTextLayoutMode nLayoutMode
= static_cast<const MetaLayoutModeAction
*>(pMA
)->GetLayoutMode();
1597 eSrcHorTextAlign
= 0; // TA_LEFT
1598 if ((nLayoutMode
& TEXT_LAYOUT_BIDI_RTL
) != TEXT_LAYOUT_DEFAULT
)
1600 eSrcHorTextAlign
= W_TA_RIGHT
| W_TA_RTLREADING
;
1602 if ((nLayoutMode
& TEXT_LAYOUT_TEXTORIGIN_RIGHT
) != TEXT_LAYOUT_DEFAULT
)
1603 eSrcHorTextAlign
|= W_TA_RIGHT
;
1604 else if ((nLayoutMode
& TEXT_LAYOUT_TEXTORIGIN_LEFT
) != TEXT_LAYOUT_DEFAULT
)
1605 eSrcHorTextAlign
&= ~W_TA_RIGHT
;
1609 // Unsupported Actions
1610 case MetaActionType::MASK
:
1611 case MetaActionType::MASKSCALE
:
1612 case MetaActionType::MASKSCALEPART
:
1614 OSL_FAIL( "Unsupported action: MetaMask...Action!" );
1618 case MetaActionType::CLIPREGION
:
1621 case MetaActionType::ISECTREGIONCLIPREGION
:
1623 OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
1627 case MetaActionType::MOVECLIPREGION
:
1629 OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
1635 OSL_FAIL(OStringBuffer(
1636 "WMFWriter::WriteRecords: unsupported MetaAction #" ).
1637 append(static_cast<sal_Int32
>(pMA
->GetType())).getStr());
1645 if (pWMF
->GetError())
1654 void WMFWriter::WriteHeader( const GDIMetaFile
&, bool bPlaceable
)
1658 sal_uInt16 nCheckSum
, nValue
;
1659 Size
aSize( OutputDevice::LogicToLogic(Size(1,1),MapMode(MAP_INCH
), aTargetMapMode
) );
1660 sal_uInt16 nUnitsPerInch
= (sal_uInt16
) ( ( aSize
.Width() + aSize
.Height() ) >> 1 );
1663 nValue
=0xcdd7; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1664 nValue
=0x9ac6; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1665 nValue
=0x0000; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1666 nValue
=0x0000; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1667 nValue
=0x0000; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1668 nValue
=(sal_uInt16
) aTargetSize
.Width(); nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1669 nValue
=(sal_uInt16
) aTargetSize
.Height(); nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1670 nValue
=nUnitsPerInch
; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1671 nValue
=0x0000; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1672 nValue
=0x0000; nCheckSum
^=nValue
; pWMF
->WriteUInt16( nValue
);
1673 pWMF
->WriteUInt16( nCheckSum
);
1676 nMetafileHeaderPos
=pWMF
->Tell();
1677 pWMF
->WriteUInt16( 0x0001 ) // type: file
1678 .WriteUInt16( 0x0009 ) // header length in words
1679 .WriteUInt16( 0x0300 ) // Version as BCD number
1680 .WriteUInt32( 0x00000000 ) // file length (without 1st header), is later corrected by UpdateHeader()
1681 .WriteUInt16( MAXOBJECTHANDLES
) // maxmimum number of simultaneous objects
1682 .WriteUInt32( 0x00000000 ) // maximum record length, is later corrected by UpdateHeader()
1683 .WriteUInt16( 0x0000 ); // reserved
1686 void WMFWriter::UpdateHeader()
1689 sal_uInt32 nFileSize
;
1691 nPos
=pWMF
->Tell(); // endposition = total size of file
1692 nFileSize
=nPos
-nMetafileHeaderPos
; // subtract size of 1st header
1693 if ((nFileSize
&1)!=0) { // if needed round to words
1694 pWMF
->WriteUChar( 0 );
1698 nFileSize
>>=1; // convert to number of words
1699 pWMF
->Seek(nMetafileHeaderPos
+6); // to filesize entry in second header
1700 pWMF
->WriteUInt32( nFileSize
); // rectify file size
1701 pWMF
->SeekRel(2); // to max-recond-length-entry in second header
1702 pWMF
->WriteUInt32( nMaxRecordSize
); // and rectify
1706 bool WMFWriter::WriteWMF( const GDIMetaFile
& rMTF
, SvStream
& rTargetStream
,
1707 FilterConfigItem
* pFConfigItem
, bool bPlaceable
)
1709 WMFWriterAttrStackMember
* pAt
;
1713 pVirDev
= VclPtr
<VirtualDevice
>::Create();
1717 xStatusIndicator
= pFConfigItem
->GetStatusIndicator();
1718 if ( xStatusIndicator
.is() )
1721 xStatusIndicator
->start( aMsg
, 100 );
1726 pWMF
=&rTargetStream
;
1727 pWMF
->SetEndian(SvStreamEndian::LITTLE
);
1731 aSrcMapMode
=rMTF
.GetPrefMapMode();
1735 aTargetMapMode
= aSrcMapMode
;
1736 aTargetSize
= rMTF
.GetPrefSize();
1737 sal_uInt16 nTargetDivisor
= CalcSaveTargetMapMode(aTargetMapMode
, aTargetSize
);
1738 aTargetSize
.Width() /= nTargetDivisor
;
1739 aTargetSize
.Height() /= nTargetDivisor
;
1743 aTargetMapMode
= MapMode( MAP_INCH
);
1745 const long nUnit
= pVirDev
->LogicToPixel( Size( 1, 1 ), aTargetMapMode
).Width();
1746 const Fraction
aFrac( 1, nUnit
);
1748 aTargetMapMode
.SetScaleX( aFrac
);
1749 aTargetMapMode
.SetScaleY( aFrac
);
1750 aTargetSize
= OutputDevice::LogicToLogic( rMTF
.GetPrefSize(), aSrcMapMode
, aTargetMapMode
);
1753 pVirDev
->SetMapMode( aTargetMapMode
);
1757 for (sal_uInt16 i
=0; i
<MAXOBJECTHANDLES
; i
++)
1758 bHandleAllocated
[i
]=false;
1760 nDstPenHandle
=0xffff;
1761 nDstFontHandle
=0xffff;
1762 nDstBrushHandle
=0xffff;
1768 nActBitmapPercent
=0;
1770 CountActionsAndBitmaps(rMTF
);
1772 WriteHeader(rMTF
,bPlaceable
);
1774 WriteEmbeddedEMF( rMTF
);
1775 WMFRecord_SetWindowOrg(Point(0,0));
1776 WMFRecord_SetWindowExt(rMTF
.GetPrefSize());
1777 WMFRecord_SetBkMode( true );
1779 eDstROP2
= eSrcRasterOp
= ROP_OVERPAINT
;
1780 WMFRecord_SetROP2(eDstROP2
);
1782 aDstLineInfo
= LineInfo();
1783 aDstLineColor
= aSrcLineColor
= Color( COL_BLACK
);
1784 CreateSelectDeletePen( aDstLineColor
, aDstLineInfo
);
1786 aDstFillColor
= aSrcFillColor
= Color( COL_WHITE
);
1787 CreateSelectDeleteBrush( aDstFillColor
);
1789 aDstClipRegion
= aSrcClipRegion
= vcl::Region();
1790 bDstIsClipping
= bSrcIsClipping
= false;
1793 aFont
.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252
) );
1794 aFont
.SetColor( Color( COL_WHITE
) );
1795 aFont
.SetAlign( ALIGN_BASELINE
);
1796 aDstFont
= aSrcFont
= aFont
;
1797 CreateSelectDeleteFont(aDstFont
);
1799 eDstTextAlign
= eSrcTextAlign
= ALIGN_BASELINE
;
1800 eDstHorTextAlign
= eSrcHorTextAlign
= W_TA_LEFT
;
1801 WMFRecord_SetTextAlign( eDstTextAlign
, eDstHorTextAlign
);
1803 aDstTextColor
= aSrcTextColor
= Color( COL_WHITE
);
1804 WMFRecord_SetTextColor(aDstTextColor
);
1809 WMFRecord_EndOfFile();
1815 pAttrStack
=pAt
->pSucc
;
1819 pVirDev
.disposeAndClear();
1821 if ( xStatusIndicator
.is() )
1822 xStatusIndicator
->end();
1827 sal_uInt16
WMFWriter::CalcSaveTargetMapMode(MapMode
& rMapMode
,
1828 const Size
& rPrefSize
)
1830 Fraction
aDivFrac(2, 1);
1831 sal_uInt16 nDivisor
= 1;
1833 Size aSize
= OutputDevice::LogicToLogic( rPrefSize
, aSrcMapMode
, rMapMode
);
1835 while( nDivisor
<= 64 && (aSize
.Width() > 32767 || aSize
.Height() > 32767) )
1837 Fraction aFrac
= rMapMode
.GetScaleX();
1840 rMapMode
.SetScaleX(aFrac
);
1841 aFrac
= rMapMode
.GetScaleY();
1843 rMapMode
.SetScaleY(aFrac
);
1845 aSize
= OutputDevice::LogicToLogic( rPrefSize
, aSrcMapMode
, rMapMode
);
1851 void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile
& rMTF
)
1853 SvMemoryStream aStream
;
1854 EMFWriter
aEMFWriter(aStream
);
1856 if( aEMFWriter
.WriteEMF( rMTF
) )
1858 sal_Size nTotalSize
= aStream
.Tell();
1859 if( nTotalSize
> SAL_MAX_UINT32
)
1862 sal_uInt32 nRemainingSize
= static_cast< sal_uInt32
>( nTotalSize
);
1863 sal_uInt32 nRecCounts
= ( (nTotalSize
- 1) / 0x2000 ) + 1;
1864 sal_uInt16 nCheckSum
= 0, nWord
;
1866 sal_uInt32 nPos
= 0;
1868 while( nPos
+ 1 < nTotalSize
)
1870 aStream
.ReadUInt16( nWord
);
1875 nCheckSum
= static_cast< sal_uInt16
>( nCheckSum
* -1 );
1878 while( nRemainingSize
> 0 )
1880 sal_uInt32 nCurSize
;
1881 if( nRemainingSize
> 0x2000 )
1884 nRemainingSize
-= 0x2000;
1888 nCurSize
= nRemainingSize
;
1891 WriteEMFRecord( aStream
,
1902 void WMFWriter::WriteEMFRecord( SvMemoryStream
& rStream
, sal_uInt32 nCurSize
, sal_uInt32 nRemainingSize
,
1903 sal_uInt32 nTotalSize
, sal_uInt32 nRecCounts
, sal_uInt16 nCheckSum
)
1905 // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
1906 WriteRecordHeader( 0, W_META_ESCAPE
);
1907 pWMF
->WriteUInt16( W_MFCOMMENT
) // same as META_ESCAPE_ENHANCED_METAFILE
1908 .WriteUInt16( nCurSize
+ 34 ) // we will always have a 34 byte escape header:
1909 .WriteUInt32( 0x43464D57 ) // WMFC
1910 .WriteUInt32( 0x00000001 ) // Comment type
1911 .WriteUInt32( 0x00010000 ) // version
1912 .WriteUInt16( nCheckSum
) // check sum
1913 .WriteUInt32( 0 ) // flags = 0
1914 .WriteUInt32( nRecCounts
) // total number of records
1915 .WriteUInt32( nCurSize
) // size of this record's data
1916 .WriteUInt32( nRemainingSize
) // remaining size of data in following records, missing in MSDN documentation
1917 .WriteUInt32( nTotalSize
); // total size of EMF stream
1919 pWMF
->Write( static_cast< const sal_Char
* >( rStream
.GetData() ) + rStream
.Tell(), nCurSize
);
1920 rStream
.SeekRel( nCurSize
);
1921 UpdateRecordHeader();
1924 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */