1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: winwmf.cxx,v $
10 * $Revision: 1.36.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
35 #include <svtools/wmf.hxx>
37 #include <rtl/tencinfo.h>
38 #include <osl/endian.h>
40 //====================== MS-Windows-defines ===============================
42 #define W_META_SETBKCOLOR 0x0201
43 #define W_META_SETBKMODE 0x0102
44 #define W_META_SETMAPMODE 0x0103
45 #define W_META_SETROP2 0x0104
46 #define W_META_SETRELABS 0x0105
47 #define W_META_SETPOLYFILLMODE 0x0106
48 #define W_META_SETSTRETCHBLTMODE 0x0107
49 #define W_META_SETTEXTCHAREXTRA 0x0108
50 #define W_META_SETTEXTCOLOR 0x0209
51 #define W_META_SETTEXTJUSTIFICATION 0x020A
52 #define W_META_SETWINDOWORG 0x020B
53 #define W_META_SETWINDOWEXT 0x020C
54 #define W_META_SETVIEWPORTORG 0x020D
55 #define W_META_SETVIEWPORTEXT 0x020E
56 #define W_META_OFFSETWINDOWORG 0x020F
57 #define W_META_SCALEWINDOWEXT 0x0410
58 #define W_META_OFFSETVIEWPORTORG 0x0211
59 #define W_META_SCALEVIEWPORTEXT 0x0412
60 #define W_META_LINETO 0x0213
61 #define W_META_MOVETO 0x0214
62 #define W_META_EXCLUDECLIPRECT 0x0415
63 #define W_META_INTERSECTCLIPRECT 0x0416
64 #define W_META_ARC 0x0817
65 #define W_META_ELLIPSE 0x0418
66 #define W_META_FLOODFILL 0x0419
67 #define W_META_PIE 0x081A
68 #define W_META_RECTANGLE 0x041B
69 #define W_META_ROUNDRECT 0x061C
70 #define W_META_PATBLT 0x061D
71 #define W_META_SAVEDC 0x001E
72 #define W_META_SETPIXEL 0x041F
73 #define W_META_OFFSETCLIPRGN 0x0220
74 #define W_META_TEXTOUT 0x0521
75 #define W_META_BITBLT 0x0922
76 #define W_META_STRETCHBLT 0x0B23
77 #define W_META_POLYGON 0x0324
78 #define W_META_POLYLINE 0x0325
79 #define W_META_ESCAPE 0x0626
80 #define W_META_RESTOREDC 0x0127
81 #define W_META_FILLREGION 0x0228
82 #define W_META_FRAMEREGION 0x0429
83 #define W_META_INVERTREGION 0x012A
84 #define W_META_PAINTREGION 0x012B
85 #define W_META_SELECTCLIPREGION 0x012C
86 #define W_META_SELECTOBJECT 0x012D
87 #define W_META_SETTEXTALIGN 0x012E
88 #define W_META_DRAWTEXT 0x062F
89 #define W_META_CHORD 0x0830
90 #define W_META_SETMAPPERFLAGS 0x0231
91 #define W_META_EXTTEXTOUT 0x0a32
92 #define W_META_SETDIBTODEV 0x0d33
93 #define W_META_SELECTPALETTE 0x0234
94 #define W_META_REALIZEPALETTE 0x0035
95 #define W_META_ANIMATEPALETTE 0x0436
96 #define W_META_SETPALENTRIES 0x0037
97 #define W_META_POLYPOLYGON 0x0538
98 #define W_META_RESIZEPALETTE 0x0139
99 #define W_META_DIBBITBLT 0x0940
100 #define W_META_DIBSTRETCHBLT 0x0b41
101 #define W_META_DIBCREATEPATTERNBRUSH 0x0142
102 #define W_META_STRETCHDIB 0x0f43
103 #define W_META_EXTFLOODFILL 0x0548
104 #define W_META_RESETDC 0x014C
105 #define W_META_STARTDOC 0x014D
106 #define W_META_STARTPAGE 0x004F
107 #define W_META_ENDPAGE 0x0050
108 #define W_META_ABORTDOC 0x0052
109 #define W_META_ENDDOC 0x005E
110 #define W_META_DELETEOBJECT 0x01f0
111 #define W_META_CREATEPALETTE 0x00f7
112 #define W_META_CREATEBRUSH 0x00F8
113 #define W_META_CREATEPATTERNBRUSH 0x01F9
114 #define W_META_CREATEPENINDIRECT 0x02FA
115 #define W_META_CREATEFONTINDIRECT 0x02FB
116 #define W_META_CREATEBRUSHINDIRECT 0x02FC
117 #define W_META_CREATEBITMAPINDIRECT 0x02FD
118 #define W_META_CREATEBITMAP 0x06FE
119 #define W_META_CREATEREGION 0x06FF
121 //=================== Methoden von WMFReader ==============================
123 inline Point
WMFReader::ReadPoint()
127 return Point( nX
, nY
);
130 // ------------------------------------------------------------------------
132 inline Point
WMFReader::ReadYX()
136 return Point( nX
, nY
);
139 // ------------------------------------------------------------------------
141 Rectangle
WMFReader::ReadRectangle()
148 return Rectangle( aTL
, aBR
);
151 // ------------------------------------------------------------------------
153 Size
WMFReader::ReadYXExt()
157 return Size( nW
, nH
);
160 // ------------------------------------------------------------------------
162 void WMFReader::ReadRecordParams( USHORT nFunc
)
166 case W_META_SETBKCOLOR
:
168 pOut
->SetBkColor( ReadColor() );
172 case W_META_SETBKMODE
:
176 pOut
->SetBkMode( nDat
);
181 case W_META_SETMAPMODE
:
185 pOut
->SetMapMode( nMapMode
);
193 pOut
->SetRasterOp( nROP2
);
197 case W_META_SETTEXTCOLOR
:
199 pOut
->SetTextColor( ReadColor() );
203 case W_META_SETWINDOWORG
:
205 pOut
->SetWinOrg( ReadYX() );
209 case W_META_SETWINDOWEXT
:
211 short nWidth
, nHeight
;
212 *pWMF
>> nHeight
>> nWidth
;
213 pOut
->SetWinExt( Size( nWidth
, nHeight
) );
217 case W_META_OFFSETWINDOWORG
:
220 *pWMF
>> nYAdd
>> nXAdd
;
221 pOut
->SetWinOrgOffset( nXAdd
, nYAdd
);
225 case W_META_SCALEWINDOWEXT
:
227 short nXNum
, nXDenom
, nYNum
, nYDenom
;
228 *pWMF
>> nYDenom
>> nYNum
>> nXDenom
>> nXNum
;
229 pOut
->ScaleWinExt( (double)nXNum
/ nXDenom
, (double)nYNum
/ nYDenom
);
233 case W_META_SETVIEWPORTORG
:
234 case W_META_SETVIEWPORTEXT
:
237 case W_META_OFFSETVIEWPORTORG
:
240 *pWMF
>> nYAdd
>> nXAdd
;
241 pOut
->SetDevOrgOffset( nXAdd
, nYAdd
);
245 case W_META_SCALEVIEWPORTEXT
:
247 short nXNum
, nXDenom
, nYNum
, nYDenom
;
248 *pWMF
>> nYDenom
>> nYNum
>> nXDenom
>> nXNum
;
249 pOut
->ScaleDevExt( (double)nXNum
/ nXDenom
, (double)nYNum
/ nYDenom
);
255 pOut
->LineTo( ReadYX() );
261 pOut
->MoveTo( ReadYX() );
265 case W_META_INTERSECTCLIPRECT
:
267 pOut
->IntersectClipRect( ReadRectangle() );
271 case W_META_RECTANGLE
:
273 pOut
->DrawRect( ReadRectangle() );
277 case W_META_ROUNDRECT
:
279 Size
aSize( ReadYXExt() );
280 pOut
->DrawRoundRect( ReadRectangle(), Size( aSize
.Width() / 2, aSize
.Height() / 2 ) );
286 pOut
->DrawEllipse( ReadRectangle() );
292 Point
aEnd( ReadYX() );
293 Point
aStart( ReadYX() );
294 Rectangle
aRect( ReadRectangle() );
296 pOut
->DrawArc( aRect
, aStart
, aEnd
);
302 Point
aEnd( ReadYX() );
303 Point
aStart( ReadYX() );
304 Rectangle
aRect( ReadRectangle() );
307 // #i73608# OutputDevice deviates from WMF
308 // semantics. start==end means full ellipse here.
310 pOut
->DrawEllipse( aRect
);
312 pOut
->DrawPie( aRect
, aStart
, aEnd
);
318 Point
aEnd( ReadYX() );
319 Point
aStart( ReadYX() );
320 Rectangle
aRect( ReadRectangle() );
322 pOut
->DrawChord( aRect
, aStart
, aEnd
);
330 Polygon
aPoly( nPoints
);
331 for( i
= 0; i
< nPoints
; i
++ )
332 aPoly
[ i
] = ReadPoint();
333 pOut
->DrawPolygon( aPoly
);
337 case W_META_POLYPOLYGON
:
339 USHORT i
, nPoly
, nPoints
;
342 // Anzahl der Polygone:
344 // Anzahl der Punkte eines jeden Polygons holen, Gesammtzahl der Punkte ermitteln:
345 pnPoints
= new USHORT
[ nPoly
];
347 for( i
= 0; i
< nPoly
; i
++ )
349 *pWMF
>> pnPoints
[i
];
350 nPoints
= nPoints
+ pnPoints
[i
];
352 // Polygonpunkte holen:
353 pPtAry
= (Point
*) new char[ nPoints
* sizeof(Point
) ];
354 for ( i
= 0; i
< nPoints
; i
++ )
355 pPtAry
[ i
] = ReadPoint();
356 // PolyPolygon Actions erzeugen
357 PolyPolygon
aPolyPoly( nPoly
, pnPoints
, pPtAry
);
358 pOut
->DrawPolyPolygon( aPolyPoly
);
359 delete[] (char*) pPtAry
;
364 case W_META_POLYLINE
:
368 Polygon
aPoly( nPoints
);
369 for( i
= 0; i
< nPoints
; i
++ )
370 aPoly
[ i
] = ReadPoint();
371 pOut
->DrawPolyLine( aPoly
);
381 case W_META_RESTOREDC
:
387 case W_META_SETPIXEL
:
389 const Color aColor
= ReadColor();
390 pOut
->DrawPixel( ReadYX(), aColor
);
394 case W_META_OFFSETCLIPRGN
:
396 pOut
->MoveClipRegion( ReadYXExt() );
406 char* pChar
= new char[ ( nLength
+ 1 ) &~ 1 ];
407 pWMF
->Read( pChar
, ( nLength
+ 1 ) &~ 1 );
408 String
aText( pChar
, nLength
, pOut
->GetCharSet() );
410 Point
aPosition( ReadYX() );
411 pOut
->DrawText( aPosition
, aText
);
416 case W_META_EXTTEXTOUT
:
418 sal_Int16 nDx
, nDxTmp
;
419 sal_uInt16 i
, nLen
, nOptions
;
420 sal_Int32 nRecordPos
, nRecordSize
, nOriginalTextLen
, nNewTextLen
;
423 sal_Int32
* pDXAry
= NULL
;
426 nRecordPos
= pWMF
->Tell();
427 *pWMF
>> nRecordSize
;
429 aPosition
= ReadYX();
430 *pWMF
>> nLen
>> nOptions
;
432 sal_Int32 nTextLayoutMode
= TEXT_LAYOUT_DEFAULT
;
433 if ( nOptions
& ETO_RTLREADING
)
434 nTextLayoutMode
= TEXT_LAYOUT_BIDI_RTL
| TEXT_LAYOUT_TEXTORIGIN_LEFT
;
435 pOut
->SetTextLayoutMode( nTextLayoutMode
);
436 DBG_ASSERT( ( nOptions
& ( ETO_PDY
| ETO_GLYPH_INDEX
) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
438 // Nur wenn der Text auch Zeichen enthaelt, macht die Ausgabe Sinn
441 nOriginalTextLen
= nLen
;
442 if( nOptions
& ETO_CLIPPED
)
444 const Point
aPt1( ReadPoint() );
445 const Point
aPt2( ReadPoint() );
446 aRect
= Rectangle( aPt1
, aPt2
);
448 char* pChar
= new char[ ( nOriginalTextLen
+ 1 ) &~ 1 ];
449 pWMF
->Read( pChar
, ( nOriginalTextLen
+ 1 ) &~ 1 );
450 String
aText( pChar
, (sal_uInt16
)nOriginalTextLen
, pOut
->GetCharSet() );// after this conversion the text may contain
451 nNewTextLen
= aText
.Len(); // less character (japanese version), so the
452 delete[] pChar
; // dxAry will not fit
456 sal_uInt32 nMaxStreamPos
= nRecordPos
+ ( nRecordSize
<< 1 );
457 sal_Int32 nDxArySize
= nMaxStreamPos
- pWMF
->Tell();
458 sal_Int32 nDxAryEntries
= nDxArySize
>> 1;
459 sal_Bool bUseDXAry
= FALSE
;
461 if ( ( ( nDxAryEntries
% nOriginalTextLen
) == 0 ) && ( nNewTextLen
<= nOriginalTextLen
) )
463 pDXAry
= new sal_Int32
[ nNewTextLen
];
464 for ( i
= 0; i
< nNewTextLen
; i
++ )
466 if ( pWMF
->Tell() >= nMaxStreamPos
)
469 if ( nNewTextLen
!= nOriginalTextLen
)
471 ByteString
aTmp( aText
.GetChar( i
), pOut
->GetCharSet() );
472 if ( aTmp
.Len() > 1 )
474 sal_Int32 nDxCount
= aTmp
.Len() - 1;
475 if ( ( ( nDxCount
* 2 ) + pWMF
->Tell() ) > nMaxStreamPos
)
486 if ( i
== nNewTextLen
)
489 if ( pDXAry
&& bUseDXAry
)
490 pOut
->DrawText( aPosition
, aText
, pDXAry
);
492 pOut
->DrawText( aPosition
, aText
);
500 case W_META_SELECTOBJECT
:
504 pOut
->SelectObject( nObjIndex
);
508 case W_META_SETTEXTALIGN
:
512 pOut
->SetTextAlign( nAlign
);
518 // 0-3 : nWinROP #93454#
519 // 4-5 : y offset of source bitmap
520 // 6-7 : x offset of source bitmap
521 // 8-9 : used height of source bitmap
522 // 10-11 : used width of source bitmap
523 // 12-13 : destination position y (in pixel)
524 // 14-15 : destination position x (in pixel)
526 // 18-19 : Width Bitmap in Pixel
527 // 20-21 : Height Bitmap in Pixel
528 // 22-23 : bytes per scanline
533 sal_uInt16 nSx
, nSy
, nSxe
, nSye
, nDontKnow
, nWidth
, nHeight
, nBytesPerScan
;
534 sal_uInt8 nPlanes
, nBitCount
;
537 >> nSy
>> nSx
>> nSye
>> nSxe
;
538 Point
aPoint( ReadYX() );
539 *pWMF
>> nDontKnow
>> nWidth
>> nHeight
>> nBytesPerScan
>> nPlanes
>> nBitCount
;
541 if ( nWidth
&& nHeight
&& ( nPlanes
== 1 ) && ( nBitCount
== 1 ) )
543 Bitmap
aBmp( Size( nWidth
, nHeight
), nBitCount
);
544 BitmapWriteAccess
* pAcc
;
545 pAcc
= aBmp
.AcquireWriteAccess();
548 sal_uInt16 y
, x
, scan
;
549 sal_Int8 i
, nEightPixels
;
550 for ( y
= 0; y
< nHeight
; y
++ )
553 for ( scan
= 0; scan
< nBytesPerScan
; scan
++ )
555 *pWMF
>> nEightPixels
;
556 for ( i
= 7; i
>= 0; i
-- )
560 pAcc
->SetPixel( y
, x
, (nEightPixels
>>i
)&1 );
566 aBmp
.ReleaseAccess( pAcc
);
568 ( ( nSx
+ nSxe
) <= aBmp
.GetSizePixel().Width() ) &&
569 ( ( nSy
+ nSye
<= aBmp
.GetSizePixel().Height() ) ) )
571 Rectangle
aCropRect( Point( nSx
, nSy
), Size( nSxe
, nSye
) );
572 aBmp
.Crop( aCropRect
);
574 Rectangle
aDestRect( aPoint
, Size( nSxe
, nSye
) );
575 aBmpSaveList
.Insert( new BSaveStruct( aBmp
, aDestRect
, nWinROP
, pOut
->GetFillStyle () ), LIST_APPEND
);
581 case W_META_STRETCHBLT
:
582 case W_META_DIBBITBLT
:
583 case W_META_DIBSTRETCHBLT
:
584 case W_META_STRETCHDIB
:
587 sal_uInt16 nSx
, nSy
, nSxe
, nSye
, nUsage
;
592 if( nFunc
== W_META_STRETCHDIB
)
595 // nSye and nSxe is the number of pixels that has to been used
596 if( nFunc
== W_META_STRETCHDIB
|| nFunc
== W_META_STRETCHBLT
|| nFunc
== W_META_DIBSTRETCHBLT
)
597 *pWMF
>> nSye
>> nSxe
;
599 nSye
= nSxe
= 0; // set this to zero as indicator not to scale the bitmap later
601 // nSy and nx is the offset of the first pixel
604 if( nFunc
== W_META_STRETCHDIB
|| nFunc
== W_META_DIBBITBLT
|| nFunc
== W_META_DIBSTRETCHBLT
)
606 if ( nWinROP
== PATCOPY
)
607 *pWMF
>> nUsage
; // i don't know anything of this parameter, so its called nUsage
608 // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), FALSE );
610 Size
aDestSize( ReadYXExt() );
611 if ( aDestSize
.Width() && aDestSize
.Height() ) // #92623# do not try to read buggy bitmaps
613 Rectangle
aDestRect( ReadYX(), aDestSize
);
614 if ( nWinROP
!= PATCOPY
)
615 aBmp
.Read( *pWMF
, FALSE
);
617 // test if it is sensible to crop
619 ( ( nSx
+ nSxe
) <= aBmp
.GetSizePixel().Width() ) &&
620 ( ( nSy
+ nSye
<= aBmp
.GetSizePixel().Height() ) ) )
622 Rectangle
aCropRect( Point( nSx
, nSy
), Size( nSxe
, nSye
) );
623 aBmp
.Crop( aCropRect
);
625 aBmpSaveList
.Insert( new BSaveStruct( aBmp
, aDestRect
, nWinROP
, pOut
->GetFillStyle () ), LIST_APPEND
);
631 case W_META_DIBCREATEPATTERNBRUSH
:
634 BitmapReadAccess
* pBmp
;
635 UINT32 nRed
= 0, nGreen
= 0, nBlue
= 0, nCount
= 1;
638 *pWMF
>> nFunction
>> nFunction
;
640 aBmp
.Read( *pWMF
, FALSE
);
641 pBmp
= aBmp
.AcquireReadAccess();
644 for ( INT32 y
= 0; y
< pBmp
->Height(); y
++ )
646 for ( INT32 x
= 0; x
< pBmp
->Width(); x
++ )
648 const BitmapColor
aColor( pBmp
->GetColor( y
, x
) );
650 nRed
+= aColor
.GetRed();
651 nGreen
+= aColor
.GetGreen();
652 nBlue
+= aColor
.GetBlue();
655 nCount
= pBmp
->Height() * pBmp
->Width();
658 aBmp
.ReleaseAccess( pBmp
);
660 Color
aColor( (BYTE
)( nRed
/ nCount
), (BYTE
)( nGreen
/ nCount
), (BYTE
)( nBlue
/ nCount
) );
661 pOut
->CreateObject( GDI_BRUSH
, new WinMtfFillStyle( aColor
, FALSE
) );
665 case W_META_DELETEOBJECT
:
669 pOut
->DeleteObject( nIndex
);
673 case W_META_CREATEPALETTE
:
675 pOut
->CreateObject( GDI_DUMMY
);
679 case W_META_CREATEBRUSH
:
681 pOut
->CreateObject( GDI_BRUSH
, new WinMtfFillStyle( Color( COL_WHITE
), FALSE
) );
685 case W_META_CREATEPATTERNBRUSH
:
687 pOut
->CreateObject( GDI_BRUSH
, new WinMtfFillStyle( Color( COL_WHITE
), FALSE
) );
691 case W_META_CREATEPENINDIRECT
:
694 USHORT nStyle
, nWidth
, nHeight
;
696 *pWMF
>> nStyle
>> nWidth
>> nHeight
;
699 aLineInfo
.SetWidth( nWidth
);
701 BOOL bTransparent
= FALSE
;
702 UINT16 nDashCount
= 0;
703 UINT16 nDotCount
= 0;
718 aLineInfo
.SetStyle( LINE_NONE
);
721 case PS_INSIDEFRAME
:
723 aLineInfo
.SetStyle( LINE_SOLID
);
725 if ( nDashCount
| nDotCount
)
727 aLineInfo
.SetStyle( LINE_DASH
);
728 aLineInfo
.SetDashCount( nDashCount
);
729 aLineInfo
.SetDotCount( nDotCount
);
731 pOut
->CreateObject( GDI_PEN
, new WinMtfLineStyle( ReadColor(), aLineInfo
, bTransparent
) );
735 case W_META_CREATEBRUSHINDIRECT
:
739 pOut
->CreateObject( GDI_BRUSH
, new WinMtfFillStyle( ReadColor(), ( nStyle
== BS_HOLLOW
) ? TRUE
: FALSE
) );
743 case W_META_CREATEFONTINDIRECT
:
746 char lfFaceName
[ LF_FACESIZE
];
747 INT16 lfEscapement
, lfOrientation
, lfWeight
; // ( ehemals USHORT )
750 aFontSize
= ReadYXExt();
751 *pWMF
>> lfEscapement
>> lfOrientation
>> lfWeight
752 >> aLogFont
.lfItalic
>> aLogFont
.lfUnderline
>> aLogFont
.lfStrikeOut
>> aLogFont
.lfCharSet
>> aLogFont
.lfOutPrecision
753 >> aLogFont
.lfClipPrecision
>> aLogFont
.lfQuality
>> aLogFont
.lfPitchAndFamily
;
754 pWMF
->Read( lfFaceName
, LF_FACESIZE
);
755 aLogFont
.lfWidth
= aFontSize
.Width();
756 aLogFont
.lfHeight
= aFontSize
.Height();
757 aLogFont
.lfEscapement
= lfEscapement
;
758 aLogFont
.lfOrientation
= lfOrientation
;
759 aLogFont
.lfWeight
= lfWeight
;
762 if ( ( aLogFont
.lfCharSet
== OEM_CHARSET
) || ( aLogFont
.lfCharSet
== DEFAULT_CHARSET
) )
763 eCharSet
= gsl_getSystemTextEncoding();
765 eCharSet
= rtl_getTextEncodingFromWindowsCharset( aLogFont
.lfCharSet
);
766 if ( eCharSet
== RTL_TEXTENCODING_DONTKNOW
)
767 eCharSet
= gsl_getSystemTextEncoding();
768 if ( eCharSet
== RTL_TEXTENCODING_SYMBOL
)
769 eCharSet
= RTL_TEXTENCODING_MS_1252
;
770 aLogFont
.alfFaceName
= UniString( lfFaceName
, eCharSet
);
772 pOut
->CreateObject( GDI_FONT
, new WinMtfFontStyle( aLogFont
) );
776 case W_META_CREATEBITMAPINDIRECT
:
778 pOut
->CreateObject( GDI_DUMMY
);
782 case W_META_CREATEBITMAP
:
784 pOut
->CreateObject( GDI_DUMMY
);
788 case W_META_CREATEREGION
:
790 pOut
->CreateObject( GDI_DUMMY
);
794 case W_META_EXCLUDECLIPRECT
:
796 pOut
->ExcludeClipRect( ReadRectangle() );
802 UINT32 nROP
, nOldROP
;
804 Size aSize
= ReadYXExt();
805 nOldROP
= pOut
->SetRasterOp( nROP
);
806 pOut
->DrawRect( Rectangle( ReadYX(), aSize
), FALSE
);
807 pOut
->SetRasterOp( nOldROP
);
811 case W_META_SELECTCLIPREGION
:
817 PolyPolygon aEmptyPolyPoly
;
818 pOut
->SetClipPath( aEmptyPolyPoly
, RGN_COPY
, sal_True
);
825 // nRecSize has been checked previously to be greater than 3
826 sal_uInt64 nMetaRecSize
= static_cast< sal_uInt64
>( nRecSize
- 2 ) * 2;
827 sal_uInt64 nMetaRecEndPos
= pWMF
->Tell() + nMetaRecSize
;
829 // taking care that nRecSize does not exceed the maximal stream position
830 if ( nMetaRecEndPos
> nEndPos
)
832 pWMF
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
835 if ( nRecSize
>= 12 ) // minimal escape lenght
837 sal_uInt16 nMode
, nLen
, OO
;
838 sal_uInt32 Magic
, nCheck
,nEsc
;
845 if ( ( nMode
== W_MFCOMMENT
) && ( nLen
>= 14 ) && ( OO
== 0x4f4f ) && ( Magic
== 0xa2c2a ) )
847 sal_uInt32 nEscLen
= nLen
- 14;
848 if ( nEscLen
<= ( nRecSize
* 2 ) )
851 sal_uInt32 nTmp
= SWAPLONG( nEsc
);
852 sal_uInt32 nCheckSum
= rtl_crc32( 0, &nTmp
, 4 );
854 sal_uInt32 nCheckSum
= rtl_crc32( 0, &nEsc
, 4 );
856 sal_Int8
* pData
= NULL
;
858 if ( ( static_cast< sal_uInt64
>( nEscLen
) + pWMF
->Tell() ) > nMetaRecEndPos
)
860 pWMF
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
865 pData
= new sal_Int8
[ nEscLen
];
866 pWMF
->Read( pData
, nEscLen
);
867 nCheckSum
= rtl_crc32( nCheckSum
, pData
, nEscLen
);
869 if ( nCheck
== nCheckSum
)
873 case PRIVATE_ESCAPE_UNICODE
:
874 { // we will use text instead of polygons only if we have the correct font
875 if ( aVDev
.IsFontAvailable( pOut
->GetFont().GetName() ) )
879 sal_uInt32 i
, nStringLen
, nDXCount
;
880 sal_Int32
* pDXAry
= NULL
;
881 SvMemoryStream
aMemoryStream( nEscLen
);
882 aMemoryStream
.Write( pData
, nEscLen
);
883 aMemoryStream
.Seek( STREAM_SEEK_TO_BEGIN
);
884 aMemoryStream
>> aPt
.X()
888 if ( ( static_cast< sal_uInt64
>( nStringLen
) * sizeof( sal_Unicode
) ) < ( nEscLen
- aMemoryStream
.Tell() ) )
890 sal_Unicode
* pBuf
= aString
.AllocBuffer( (xub_StrLen
)nStringLen
);
891 for ( i
= 0; i
< nStringLen
; i
++ )
892 aMemoryStream
>> pBuf
[ i
];
893 aMemoryStream
>> nDXCount
;
894 if ( ( static_cast< sal_uInt64
>( nDXCount
) * sizeof( sal_Int32
) ) >= ( nEscLen
- aMemoryStream
.Tell() ) )
897 pDXAry
= new sal_Int32
[ nDXCount
];
898 for ( i
= 0; i
< nDXCount
; i
++ )
899 aMemoryStream
>> pDXAry
[ i
];
900 aMemoryStream
>> nSkipActions
;
901 pOut
->DrawText( aPt
, aString
, pDXAry
);
916 case W_META_SETRELABS
:
917 case W_META_SETPOLYFILLMODE
:
918 case W_META_SETSTRETCHBLTMODE
:
919 case W_META_SETTEXTCHAREXTRA
:
920 case W_META_SETTEXTJUSTIFICATION
:
921 case W_META_FLOODFILL
:
922 case W_META_FILLREGION
:
923 case W_META_FRAMEREGION
:
924 case W_META_INVERTREGION
:
925 case W_META_PAINTREGION
:
926 case W_META_DRAWTEXT
:
927 case W_META_SETMAPPERFLAGS
:
928 case W_META_SETDIBTODEV
:
929 case W_META_SELECTPALETTE
:
930 case W_META_REALIZEPALETTE
:
931 case W_META_ANIMATEPALETTE
:
932 case W_META_SETPALENTRIES
:
933 case W_META_RESIZEPALETTE
:
934 case W_META_EXTFLOODFILL
:
936 case W_META_STARTDOC
:
937 case W_META_STARTPAGE
:
939 case W_META_ABORTDOC
:
945 // ------------------------------------------------------------------------
947 BOOL
WMFReader::ReadHeader(WMF_APMFILEHEADER
*pAPMHeader
)
949 Rectangle aPlaceableBound
;
950 sal_uInt32 nl
, nStrmPos
= pWMF
->Tell();
952 // Einlesen des METAFILEHEADER, falls vorhanden
956 if ( nl
== 0x9ac6cdd7L
)
960 // hmf (Unused) ueberlesen wir
964 *pWMF
>> nVal
; aPlaceableBound
.Left() = nVal
;
965 *pWMF
>> nVal
; aPlaceableBound
.Top() = nVal
;
966 *pWMF
>> nVal
; aPlaceableBound
.Right() = nVal
;
967 *pWMF
>> nVal
; aPlaceableBound
.Bottom() = nVal
;
970 *pWMF
>> nUnitsPerInch
;
975 // checksum pruefen wir lieber nicht
980 nUnitsPerInch
= (pAPMHeader
!=NULL
?pAPMHeader
->inch
:96);
981 pWMF
->Seek( nStrmPos
+ 18 ); // set the streampos to the start of the the metaactions
982 GetPlaceableBound( aPlaceableBound
, pWMF
);
983 pWMF
->Seek( nStrmPos
);
984 if (pAPMHeader
!=NULL
) {
985 // #n417818#: If we have an external header then overwrite the bounds!
986 aPlaceableBound
=Rectangle(pAPMHeader
->left
*567*nUnitsPerInch
/1440/1000,
987 pAPMHeader
->top
*567*nUnitsPerInch
/1440/1000,
988 pAPMHeader
->right
*567*nUnitsPerInch
/1440/1000,
989 pAPMHeader
->bottom
*567*nUnitsPerInch
/1440/1000);
993 pOut
->SetUnitsPerInch( nUnitsPerInch
);
994 pOut
->SetWinOrg( aPlaceableBound
.TopLeft() );
995 aWMFSize
= Size( labs( aPlaceableBound
.GetWidth() ), labs( aPlaceableBound
.GetHeight() ) );
996 pOut
->SetWinExt( aWMFSize
);
998 Size
aDevExt( 10000, 10000 );
999 if( ( labs( aWMFSize
.Width() ) > 1 ) && ( labs( aWMFSize
.Height() ) > 1 ) )
1001 const Fraction
aFrac( 1, nUnitsPerInch
);
1002 MapMode
aWMFMap( MAP_INCH
, Point(), aFrac
, aFrac
);
1003 Size
aSize100( OutputDevice::LogicToLogic( aWMFSize
, aWMFMap
, MAP_100TH_MM
) );
1004 aDevExt
= Size( labs( aSize100
.Width() ), labs( aSize100
.Height() ) );
1006 pOut
->SetDevExt( aDevExt
);
1008 // Einlesen des METAHEADER
1009 *pWMF
>> nl
; // Typ und Headergroesse
1011 if( nl
!= 0x00090001 )
1013 pWMF
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
1017 pWMF
->SeekRel( 2 ); // Version (von Windows)
1018 pWMF
->SeekRel( 4 ); // Size (der Datei in Words)
1019 pWMF
->SeekRel( 2 ); // NoObjects (Maximale Anzahl der gleichzeitigen Objekte)
1020 pWMF
->SeekRel( 4 ); // MaxRecord (Groesse des groessten Records in Words)
1021 pWMF
->SeekRel( 2 ); // NoParameters (Unused
1026 void WMFReader::ReadWMF(WMF_APMFILEHEADER
*pAPMHeader
)
1029 ULONG nPos
, nPercent
, nLastPercent
;
1033 nUnicodeEscapeAction
= 0;
1035 pOut
->SetMapMode( MM_ANISOTROPIC
);
1036 pOut
->SetWinOrg( Point() );
1037 pOut
->SetWinExt( Size( 1, 1 ) );
1038 pOut
->SetDevExt( Size( 10000, 10000 ) );
1040 nEndPos
=pWMF
->Seek( STREAM_SEEK_TO_END
);
1041 pWMF
->Seek( nStartPos
);
1042 Callback( (USHORT
) ( nLastPercent
= 0 ) );
1044 if ( ReadHeader( pAPMHeader
) )
1047 nPos
= pWMF
->Tell();
1049 if( nEndPos
- nStartPos
)
1054 nPercent
= ( nPos
- nStartPos
) * 100 / ( nEndPos
- nStartPos
);
1056 if( nLastPercent
+ 4 <= nPercent
)
1058 Callback( (USHORT
) nPercent
);
1059 nLastPercent
= nPercent
;
1061 *pWMF
>> nRecSize
>> nFunction
;
1063 if( pWMF
->GetError() || ( nRecSize
< 3 ) || ( nRecSize
==3 && nFunction
==0 ) || pWMF
->IsEof() )
1067 pWMF
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
1071 if( aBmpSaveList
.Count() &&
1072 ( nFunction
!= W_META_STRETCHDIB
) &&
1073 ( nFunction
!= W_META_DIBBITBLT
) &&
1074 ( nFunction
!= W_META_DIBSTRETCHBLT
) )
1076 pOut
->ResolveBitmapActions( aBmpSaveList
);
1078 if ( !nSkipActions
)
1079 ReadRecordParams( nFunction
);
1082 nPos
+= nRecSize
* 2;
1083 if ( nPos
<= nEndPos
)
1086 pWMF
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
1091 pWMF
->SetError( SVSTREAM_GENERALERROR
);
1093 if( !pWMF
->GetError() && aBmpSaveList
.Count() )
1094 pOut
->ResolveBitmapActions( aBmpSaveList
);
1096 if ( pWMF
->GetError() )
1097 pWMF
->Seek( nStartPos
);
1100 // ------------------------------------------------------------------------
1102 static void GetWinExtMax( const Point
& rSource
, Rectangle
& rPlaceableBound
, const sal_Int16 nMapMode
)
1104 Point
aSource( rSource
);
1105 if ( nMapMode
== MM_HIMETRIC
)
1106 aSource
.Y() = -rSource
.Y();
1107 if ( aSource
.X() < rPlaceableBound
.Left() )
1108 rPlaceableBound
.Left() = aSource
.X();
1109 if ( aSource
.X() > rPlaceableBound
.Right() )
1110 rPlaceableBound
.Right() = aSource
.X();
1111 if ( aSource
.Y() < rPlaceableBound
.Top() )
1112 rPlaceableBound
.Top() = aSource
.Y();
1113 if ( aSource
.Y() > rPlaceableBound
.Bottom() )
1114 rPlaceableBound
.Bottom() = aSource
.Y();
1117 static void GetWinExtMax( const Rectangle
& rSource
, Rectangle
& rPlaceableBound
, const sal_Int16 nMapMode
)
1119 GetWinExtMax( rSource
.TopLeft(), rPlaceableBound
, nMapMode
);
1120 GetWinExtMax( rSource
.BottomRight(), rPlaceableBound
, nMapMode
);
1123 sal_Bool
WMFReader::GetPlaceableBound( Rectangle
& rPlaceableBound
, SvStream
* pStm
)
1125 sal_Bool bRet
= sal_True
;
1127 rPlaceableBound
.Left() = (sal_Int32
)0x7fffffff;
1128 rPlaceableBound
.Top() = (sal_Int32
)0x7fffffff;
1129 rPlaceableBound
.Right() = (sal_Int32
)0x80000000;
1130 rPlaceableBound
.Bottom() = (sal_Int32
)0x80000000;
1132 sal_Int16 nMapMode
= MM_ANISOTROPIC
;
1134 sal_uInt16 nFunction
;
1136 sal_uInt32 nPos
= pStm
->Tell();
1137 sal_uInt32 nEnd
= pStm
->Seek( STREAM_SEEK_TO_END
);
1145 *pStm
>> nRSize
>> nFunction
;
1147 if( pStm
->GetError() || ( nRSize
< 3 ) || ( nRSize
==3 && nFunction
==0 ) || pStm
->IsEof() )
1151 pStm
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
1158 case W_META_SETWINDOWORG
:
1162 rPlaceableBound
.SetPos( aWinOrg
);
1166 case W_META_SETWINDOWEXT
:
1168 Point
aPos0( 0, 0 );
1169 sal_Int16 nWidth
, nHeight
;
1170 *pStm
>> nHeight
>> nWidth
;
1171 rPlaceableBound
.SetSize( Size( nWidth
, nHeight
) );
1175 case W_META_SETMAPMODE
:
1181 GetWinExtMax( ReadYX(), rPlaceableBound
, nMapMode
);
1184 case W_META_RECTANGLE
:
1185 case W_META_INTERSECTCLIPRECT
:
1186 case W_META_EXCLUDECLIPRECT
:
1187 case W_META_ELLIPSE
:
1188 GetWinExtMax( ReadRectangle(), rPlaceableBound
, nMapMode
);
1191 case W_META_ROUNDRECT
:
1193 Size
aSize( ReadYXExt() );
1194 GetWinExtMax( ReadRectangle(), rPlaceableBound
, nMapMode
);
1202 Point
aEnd( ReadYX() );
1203 Point
aStart( ReadYX() );
1204 GetWinExtMax( ReadRectangle(), rPlaceableBound
, nMapMode
);
1208 case W_META_POLYGON
:
1212 for( i
= 0; i
< nPoints
; i
++ )
1213 GetWinExtMax( ReadPoint(), rPlaceableBound
, nMapMode
);
1217 case W_META_POLYPOLYGON
:
1219 USHORT i
, nPoly
, nPoints
= 0;
1221 for( i
= 0; i
< nPoly
; i
++ )
1225 nPoints
= nPoints
+ nP
;
1227 for ( i
= 0; i
< nPoints
; i
++ )
1228 GetWinExtMax( ReadPoint(), rPlaceableBound
, nMapMode
);
1232 case W_META_POLYLINE
:
1236 for( i
= 0; i
< nPoints
; i
++ )
1237 GetWinExtMax( ReadPoint(), rPlaceableBound
, nMapMode
);
1241 case W_META_SETPIXEL
:
1243 const Color aColor
= ReadColor();
1244 GetWinExtMax( ReadYX(), rPlaceableBound
, nMapMode
);
1248 case W_META_TEXTOUT
:
1252 // todo: we also have to take care of the text width
1255 pStm
->SeekRel( ( nLength
+ 1 ) &~ 1 );
1256 GetWinExtMax( ReadYX(), rPlaceableBound
, nMapMode
);
1261 case W_META_EXTTEXTOUT
:
1263 sal_uInt16 nLen
, nOptions
;
1264 sal_Int32 nRecordPos
, nRecordSize
;
1269 nRecordPos
= pStm
->Tell();
1270 *pStm
>> nRecordSize
;
1272 aPosition
= ReadYX();
1273 *pStm
>> nLen
>> nOptions
;
1274 // todo: we also have to take care of the text width
1276 GetWinExtMax( aPosition
, rPlaceableBound
, nMapMode
);
1280 case W_META_STRETCHBLT
:
1281 case W_META_DIBBITBLT
:
1282 case W_META_DIBSTRETCHBLT
:
1283 case W_META_STRETCHDIB
:
1286 sal_uInt16 nSx
, nSy
, nSxe
, nSye
, nUsage
;
1289 if( nFunction
== W_META_STRETCHDIB
)
1292 // nSye and nSxe is the number of pixels that has to been used
1293 if( nFunction
== W_META_STRETCHDIB
|| nFunction
== W_META_STRETCHBLT
|| nFunction
== W_META_DIBSTRETCHBLT
)
1294 *pStm
>> nSye
>> nSxe
;
1296 nSye
= nSxe
= 0; // set this to zero as indicator not to scale the bitmap later
1298 // nSy and nx is the offset of the first pixel
1299 *pStm
>> nSy
>> nSx
;
1301 if( nFunction
== W_META_STRETCHDIB
|| nFunction
== W_META_DIBBITBLT
|| nFunction
== W_META_DIBSTRETCHBLT
)
1303 if ( nWinROP
== PATCOPY
)
1304 *pStm
>> nUsage
; // i don't know anything of this parameter, so its called nUsage
1305 // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), FALSE );
1307 Size
aDestSize( ReadYXExt() );
1308 if ( aDestSize
.Width() && aDestSize
.Height() ) // #92623# do not try to read buggy bitmaps
1310 Rectangle
aDestRect( ReadYX(), aDestSize
);
1311 GetWinExtMax( aDestRect
, rPlaceableBound
, nMapMode
);
1321 Size aSize
= ReadYXExt();
1322 GetWinExtMax( Rectangle( ReadYX(), aSize
), rPlaceableBound
, nMapMode
);
1331 pStm
->SetError( SVSTREAM_FILEFORMAT_ERROR
);
1339 pStm
->SetError( SVSTREAM_GENERALERROR
);