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 .
21 #include <osl/endian.h>
22 #include <basegfx/matrix/b2dhommatrix.hxx>
23 #include <boost/bind.hpp>
24 #include <vcl/dibtools.hxx>
25 #include <boost/scoped_array.hpp>
32 #define EMR_POLYBEZIER 2
34 #define EMR_POLYLINE 4
35 #define EMR_POLYBEZIERTO 5
36 #define EMR_POLYLINETO 6
37 #define EMR_POLYPOLYLINE 7
38 #define EMR_POLYPOLYGON 8
39 #define EMR_SETWINDOWEXTEX 9
40 #define EMR_SETWINDOWORGEX 10
41 #define EMR_SETVIEWPORTEXTEX 11
42 #define EMR_SETVIEWPORTORGEX 12
43 #define EMR_SETBRUSHORGEX 13
45 #define EMR_SETPIXELV 15
46 #define EMR_SETMAPPERFLAGS 16
47 #define EMR_SETMAPMODE 17
48 #define EMR_SETBKMODE 18
49 #define EMR_SETPOLYFILLMODE 19
50 #define EMR_SETROP2 20
51 #define EMR_SETSTRETCHBLTMODE 21
52 #define EMR_SETTEXTALIGN 22
53 #define EMR_SETCOLORADJUSTMENT 23
54 #define EMR_SETTEXTCOLOR 24
55 #define EMR_SETBKCOLOR 25
56 #define EMR_OFFSETCLIPRGN 26
57 #define EMR_MOVETOEX 27
58 #define EMR_SETMETARGN 28
59 #define EMR_EXCLUDECLIPRECT 29
60 #define EMR_INTERSECTCLIPRECT 30
61 #define EMR_SCALEVIEWPORTEXTEX 31
62 #define EMR_SCALEWINDOWEXTEX 32
64 #define EMR_RESTOREDC 34
65 #define EMR_SETWORLDTRANSFORM 35
66 #define EMR_MODIFYWORLDTRANSFORM 36
67 #define EMR_SELECTOBJECT 37
68 #define EMR_CREATEPEN 38
69 #define EMR_CREATEBRUSHINDIRECT 39
70 #define EMR_DELETEOBJECT 40
71 #define EMR_ANGLEARC 41
72 #define EMR_ELLIPSE 42
73 #define EMR_RECTANGLE 43
74 #define EMR_ROUNDRECT 44
78 #define EMR_SELECTPALETTE 48
79 #define EMR_CREATEPALETTE 49
80 #define EMR_SETPALETTEENTRIES 50
81 #define EMR_RESIZEPALETTE 51
82 #define EMR_REALIZEPALETTE 52
83 #define EMR_EXTFLOODFILL 53
86 #define EMR_POLYDRAW 56
87 #define EMR_SETARCDIRECTION 57
88 #define EMR_SETMITERLIMIT 58
89 #define EMR_BEGINPATH 59
90 #define EMR_ENDPATH 60
91 #define EMR_CLOSEFIGURE 61
92 #define EMR_FILLPATH 62
93 #define EMR_STROKEANDFILLPATH 63
94 #define EMR_STROKEPATH 64
95 #define EMR_FLATTENPATH 65
96 #define EMR_WIDENPATH 66
97 #define EMR_SELECTCLIPPATH 67
98 #define EMR_ABORTPATH 68
100 #define EMR_GDICOMMENT 70
101 #define EMR_FILLRGN 71
102 #define EMR_FRAMERGN 72
103 #define EMR_INVERTRGN 73
104 #define EMR_PAINTRGN 74
105 #define EMR_EXTSELECTCLIPRGN 75
106 #define EMR_BITBLT 76
107 #define EMR_STRETCHBLT 77
108 #define EMR_MASKBLT 78
109 #define EMR_PLGBLT 79
110 #define EMR_SETDIBITSTODEVICE 80
111 #define EMR_STRETCHDIBITS 81
112 #define EMR_EXTCREATEFONTINDIRECTW 82
113 #define EMR_EXTTEXTOUTA 83
114 #define EMR_EXTTEXTOUTW 84
115 #define EMR_POLYBEZIER16 85
116 #define EMR_POLYGON16 86
117 #define EMR_POLYLINE16 87
118 #define EMR_POLYBEZIERTO16 88
119 #define EMR_POLYLINETO16 89
120 #define EMR_POLYPOLYLINE16 90
121 #define EMR_POLYPOLYGON16 91
122 #define EMR_POLYDRAW16 92
123 #define EMR_CREATEMONOBRUSH 93
124 #define EMR_CREATEDIBPATTERNBRUSHPT 94
125 #define EMR_EXTCREATEPEN 95
126 #define EMR_POLYTEXTOUTA 96
127 #define EMR_POLYTEXTOUTW 97
129 // WINDOWS VERSION >= 0x400
130 #define EMR_SETICMMODE 98
131 #define EMR_CREATECOLORSPACE 99
132 #define EMR_SETCOLORSPACE 100
133 #define EMR_DELETECOLORSPACE 101
134 #define EMR_GLSRECORD 102
135 #define EMR_GLSBOUNDEDRECORD 103
136 #define EMR_PIXELFORMAT 104
138 // WINDOWS VERSION >= 0x500
139 #define EMR_DRAWESCAPE 105
140 #define EMR_EXTESCAPE 106
141 #define EMR_STARTDOC 107
142 #define EMR_SMALLTEXTOUT 108
143 #define EMR_FORCEUFIMAPPING 109
144 #define EMR_NAMEDESCAPE 110
145 #define EMR_COLORCORRECTPALETTE 111
146 #define EMR_SETICMPROFILEA 112
147 #define EMR_SETICMPROFILEW 113
148 #define EMR_ALPHABLEND 114
149 #define EMR_ALPHADIBBLEND 115
150 #define EMR_TRANSPARENTBLT 116
151 #define EMR_TRANSPARENTDIB 117
152 #define EMR_GRADIENTFILL 118
153 #define EMR_SETLINKEDUFIS 119
154 #define EMR_SETTEXTJUSTIFICATION 120
160 record_type_name(sal_uInt32 nRecType
)
168 case EMR_HEADER
: return "HEADER";
169 case EMR_POLYBEZIER
: return "POLYBEZIER";
170 case EMR_POLYGON
: return "POLYGON";
171 case EMR_POLYLINE
: return "POLYLINE";
172 case EMR_POLYBEZIERTO
: return "POLYBEZIERTO";
173 case EMR_POLYLINETO
: return "POLYLINETO";
174 case EMR_POLYPOLYLINE
: return "POLYPOLYLINE";
175 case EMR_POLYPOLYGON
: return "POLYPOLYGON";
176 case EMR_SETWINDOWEXTEX
: return "SETWINDOWEXTEX";
177 case EMR_SETWINDOWORGEX
: return "SETWINDOWORGEX";
178 case EMR_SETVIEWPORTEXTEX
: return "SETVIEWPORTEXTEX";
179 case EMR_SETVIEWPORTORGEX
: return "SETVIEWPORTORGEX";
180 case EMR_SETBRUSHORGEX
: return "SETBRUSHORGEX";
181 case EMR_EOF
: return "EOF";
182 case EMR_SETPIXELV
: return "SETPIXELV";
183 case EMR_SETMAPPERFLAGS
: return "SETMAPPERFLAGS";
184 case EMR_SETMAPMODE
: return "SETMAPMODE";
185 case EMR_SETBKMODE
: return "SETBKMODE";
186 case EMR_SETPOLYFILLMODE
: return "SETPOLYFILLMODE";
187 case EMR_SETROP2
: return "SETROP2";
188 case EMR_SETSTRETCHBLTMODE
: return "SETSTRETCHBLTMODE";
189 case EMR_SETTEXTALIGN
: return "SETTEXTALIGN";
190 case EMR_SETCOLORADJUSTMENT
: return "SETCOLORADJUSTMENT";
191 case EMR_SETTEXTCOLOR
: return "SETTEXTCOLOR";
192 case EMR_SETBKCOLOR
: return "SETBKCOLOR";
193 case EMR_OFFSETCLIPRGN
: return "OFFSETCLIPRGN";
194 case EMR_MOVETOEX
: return "MOVETOEX";
195 case EMR_SETMETARGN
: return "SETMETARGN";
196 case EMR_EXCLUDECLIPRECT
: return "EXCLUDECLIPRECT";
197 case EMR_INTERSECTCLIPRECT
: return "INTERSECTCLIPRECT";
198 case EMR_SCALEVIEWPORTEXTEX
: return "SCALEVIEWPORTEXTEX";
199 case EMR_SCALEWINDOWEXTEX
: return "SCALEWINDOWEXTEX";
200 case EMR_SAVEDC
: return "SAVEDC";
201 case EMR_RESTOREDC
: return "RESTOREDC";
202 case EMR_SETWORLDTRANSFORM
: return "SETWORLDTRANSFORM";
203 case EMR_MODIFYWORLDTRANSFORM
: return "MODIFYWORLDTRANSFORM";
204 case EMR_SELECTOBJECT
: return "SELECTOBJECT";
205 case EMR_CREATEPEN
: return "CREATEPEN";
206 case EMR_CREATEBRUSHINDIRECT
: return "CREATEBRUSHINDIRECT";
207 case EMR_DELETEOBJECT
: return "DELETEOBJECT";
208 case EMR_ANGLEARC
: return "ANGLEARC";
209 case EMR_ELLIPSE
: return "ELLIPSE";
210 case EMR_RECTANGLE
: return "RECTANGLE";
211 case EMR_ROUNDRECT
: return "ROUNDRECT";
212 case EMR_ARC
: return "ARC";
213 case EMR_CHORD
: return "CHORD";
214 case EMR_PIE
: return "PIE";
215 case EMR_SELECTPALETTE
: return "SELECTPALETTE";
216 case EMR_CREATEPALETTE
: return "CREATEPALETTE";
217 case EMR_SETPALETTEENTRIES
: return "SETPALETTEENTRIES";
218 case EMR_RESIZEPALETTE
: return "RESIZEPALETTE";
219 case EMR_REALIZEPALETTE
: return "REALIZEPALETTE";
220 case EMR_EXTFLOODFILL
: return "EXTFLOODFILL";
221 case EMR_LINETO
: return "LINETO";
222 case EMR_ARCTO
: return "ARCTO";
223 case EMR_POLYDRAW
: return "POLYDRAW";
224 case EMR_SETARCDIRECTION
: return "SETARCDIRECTION";
225 case EMR_SETMITERLIMIT
: return "SETMITERLIMIT";
226 case EMR_BEGINPATH
: return "BEGINPATH";
227 case EMR_ENDPATH
: return "ENDPATH";
228 case EMR_CLOSEFIGURE
: return "CLOSEFIGURE";
229 case EMR_FILLPATH
: return "FILLPATH";
230 case EMR_STROKEANDFILLPATH
: return "STROKEANDFILLPATH";
231 case EMR_STROKEPATH
: return "STROKEPATH";
232 case EMR_FLATTENPATH
: return "FLATTENPATH";
233 case EMR_WIDENPATH
: return "WIDENPATH";
234 case EMR_SELECTCLIPPATH
: return "SELECTCLIPPATH";
235 case EMR_ABORTPATH
: return "ABORTPATH";
236 case EMR_GDICOMMENT
: return "GDICOMMENT";
237 case EMR_FILLRGN
: return "FILLRGN";
238 case EMR_FRAMERGN
: return "FRAMERGN";
239 case EMR_INVERTRGN
: return "INVERTRGN";
240 case EMR_PAINTRGN
: return "PAINTRGN";
241 case EMR_EXTSELECTCLIPRGN
: return "EXTSELECTCLIPRGN";
242 case EMR_BITBLT
: return "BITBLT";
243 case EMR_STRETCHBLT
: return "STRETCHBLT";
244 case EMR_MASKBLT
: return "MASKBLT";
245 case EMR_PLGBLT
: return "PLGBLT";
246 case EMR_SETDIBITSTODEVICE
: return "SETDIBITSTODEVICE";
247 case EMR_STRETCHDIBITS
: return "STRETCHDIBITS";
248 case EMR_EXTCREATEFONTINDIRECTW
: return "EXTCREATEFONTINDIRECTW";
249 case EMR_EXTTEXTOUTA
: return "EXTTEXTOUTA";
250 case EMR_EXTTEXTOUTW
: return "EXTTEXTOUTW";
251 case EMR_POLYBEZIER16
: return "POLYBEZIER16";
252 case EMR_POLYGON16
: return "POLYGON16";
253 case EMR_POLYLINE16
: return "POLYLINE16";
254 case EMR_POLYBEZIERTO16
: return "POLYBEZIERTO16";
255 case EMR_POLYLINETO16
: return "POLYLINETO16";
256 case EMR_POLYPOLYLINE16
: return "POLYPOLYLINE16";
257 case EMR_POLYPOLYGON16
: return "POLYPOLYGON16";
258 case EMR_POLYDRAW16
: return "POLYDRAW16";
259 case EMR_CREATEMONOBRUSH
: return "CREATEMONOBRUSH";
260 case EMR_CREATEDIBPATTERNBRUSHPT
: return "CREATEDIBPATTERNBRUSHPT";
261 case EMR_EXTCREATEPEN
: return "EXTCREATEPEN";
262 case EMR_POLYTEXTOUTA
: return "POLYTEXTOUTA";
263 case EMR_POLYTEXTOUTW
: return "POLYTEXTOUTW";
264 case EMR_SETICMMODE
: return "SETICMMODE";
265 case EMR_CREATECOLORSPACE
: return "CREATECOLORSPACE";
266 case EMR_SETCOLORSPACE
: return "SETCOLORSPACE";
267 case EMR_DELETECOLORSPACE
: return "DELETECOLORSPACE";
268 case EMR_GLSRECORD
: return "GLSRECORD";
269 case EMR_GLSBOUNDEDRECORD
: return "GLSBOUNDEDRECORD";
270 case EMR_PIXELFORMAT
: return "PIXELFORMAT";
271 case EMR_DRAWESCAPE
: return "DRAWESCAPE";
272 case EMR_EXTESCAPE
: return "EXTESCAPE";
273 case EMR_STARTDOC
: return "STARTDOC";
274 case EMR_SMALLTEXTOUT
: return "SMALLTEXTOUT";
275 case EMR_FORCEUFIMAPPING
: return "FORCEUFIMAPPING";
276 case EMR_NAMEDESCAPE
: return "NAMEDESCAPE";
277 case EMR_COLORCORRECTPALETTE
: return "COLORCORRECTPALETTE";
278 case EMR_SETICMPROFILEA
: return "SETICMPROFILEA";
279 case EMR_SETICMPROFILEW
: return "SETICMPROFILEW";
280 case EMR_ALPHABLEND
: return "ALPHABLEND";
281 case EMR_ALPHADIBBLEND
: return "ALPHADIBBLEND";
282 case EMR_TRANSPARENTBLT
: return "TRANSPARENTBLT";
283 case EMR_TRANSPARENTDIB
: return "TRANSPARENTDIB";
284 case EMR_GRADIENTFILL
: return "GRADIENTFILL";
285 case EMR_SETLINKEDUFIS
: return "SETLINKEDUFIS";
286 case EMR_SETTEXTJUSTIFICATION
: return "SETTEXTJUSTIFICATION";
288 // Yes, return a pointer to a static buffer. This is a very
289 // local debugging output function, so no big deal.
290 static char buffer
[11];
291 sprintf(buffer
, "0x%08" SAL_PRIxUINT32
, nRecType
);
298 // little endian <-> big endian switch
299 static float GetSwapFloat(SvStream
& rStream
)
302 sal_Int8
* pPtr
= (sal_Int8
*)&fTmp
;
303 rStream
.ReadSChar(pPtr
[3]);
304 rStream
.ReadSChar(pPtr
[2]);
305 rStream
.ReadSChar(pPtr
[1]);
306 rStream
.ReadSChar(pPtr
[0]);
313 unsigned char aBlendOperation
;
314 unsigned char aBlendFlags
;
315 unsigned char aSrcConstantAlpha
;
316 unsigned char aAlphaFormat
;
318 friend SvStream
& operator>>(SvStream
& rInStream
, BLENDFUNCTION
& rBlendFun
);
321 SvStream
& operator>>(SvStream
& rInStream
, BLENDFUNCTION
& rBlendFun
)
323 rInStream
.ReadUChar(rBlendFun
.aBlendOperation
);
324 rInStream
.ReadUChar(rBlendFun
.aBlendFlags
);
325 rInStream
.ReadUChar(rBlendFun
.aSrcConstantAlpha
);
326 rInStream
.ReadUChar(rBlendFun
.aAlphaFormat
);
330 SvStream
& operator>>(SvStream
& rInStream
, XForm
& rXForm
)
332 if (sizeof(float) != 4)
334 OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
340 rXForm
.eM11
= GetSwapFloat(rInStream
);
341 rXForm
.eM12
= GetSwapFloat(rInStream
);
342 rXForm
.eM21
= GetSwapFloat(rInStream
);
343 rXForm
.eM22
= GetSwapFloat(rInStream
);
344 rXForm
.eDx
= GetSwapFloat(rInStream
);
345 rXForm
.eDy
= GetSwapFloat(rInStream
);
347 rInStream
.ReadFloat(rXForm
.eM11
);
348 rInStream
.ReadFloat(rXForm
.eM12
);
349 rInStream
.ReadFloat(rXForm
.eM21
);
350 rInStream
.ReadFloat(rXForm
.eM22
);
351 rInStream
.ReadFloat(rXForm
.eDx
);
352 rInStream
.ReadFloat(rXForm
.eDy
);
358 static bool ImplReadRegion( tools::PolyPolygon
& rPolyPoly
, SvStream
& rStream
, sal_uInt32 nLen
)
363 sal_uInt32 nHdSize
, nType
, nCount
, nRgnSize
, i
;
364 rStream
.ReadUInt32(nHdSize
);
365 rStream
.ReadUInt32(nType
);
366 rStream
.ReadUInt32(nCount
);
367 rStream
.ReadUInt32(nRgnSize
);
370 && nType
== RDH_RECTANGLES
371 && nLen
>= ((nCount
<< 4) + (nHdSize
- 16)))
373 sal_Int32 nx1
, ny1
, nx2
, ny2
;
375 for (i
= 0; i
< nCount
; i
++)
377 rStream
.ReadInt32(nx1
);
378 rStream
.ReadInt32(ny1
);
379 rStream
.ReadInt32(nx2
);
380 rStream
.ReadInt32(ny2
);
382 Rectangle
aRectangle(Point(nx1
, ny1
), Point(nx2
, ny2
));
384 Polygon
aPolygon(aRectangle
);
385 tools::PolyPolygon
aPolyPolyOr1(aPolygon
);
386 tools::PolyPolygon
aPolyPolyOr2(rPolyPoly
);
387 rPolyPoly
.GetUnion(aPolyPolyOr1
, aPolyPolyOr2
);
388 rPolyPoly
= aPolyPolyOr2
;
395 } // anonymous namespace
397 EnhWMFReader::EnhWMFReader(SvStream
& rStream
,GDIMetaFile
& rGDIMetaFile
,FilterConfigItem
* pConfigItem
)
398 : WinMtf(new WinMtfOutput(rGDIMetaFile
), rStream
, pConfigItem
)
404 EnhWMFReader::~EnhWMFReader()
407 void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length
, bool& bHaveDC
)
410 pOut
->PassEMFPlusHeaderInfo();
412 #if OSL_DEBUG_LEVEL > 1
413 // debug code - write the stream to debug file /tmp/emf-stream.emf
414 int pos
= pWMF
->Tell();
416 SvFileStream
file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE
| StreamMode::TRUNC
);
418 pWMF
->WriteStream(file
);
428 sal_Size pos
= pWMF
->Tell();
429 void *buffer
= malloc( length
);
430 pOut
->PassEMFPlus( buffer
, pWMF
->Read( buffer
, length
) );
436 // skip in SeekRel if impossibly unavailable
437 sal_uInt32 nRemainder
= length
;
439 const size_t nRequiredHeaderSize
= 12;
440 while (nRemainder
>= nRequiredHeaderSize
)
442 sal_uInt16
type(0), flags(0);
443 sal_uInt32
size(0), dataSize(0);
445 pWMF
->ReadUInt16( type
).ReadUInt16( flags
).ReadUInt32( size
).ReadUInt32( dataSize
);
446 nRemainder
-= nRequiredHeaderSize
;
448 SAL_INFO ("vcl.emf", "\t\tEMF+ record type: " << std::hex
<< type
<< std::dec
);
451 if( type
== 16388 ) {
453 SAL_INFO ("vcl.emf", "\t\tEMF+ lock DC (device context)");
456 // Get the length of the remaining data of this record based
457 // on the alleged size
458 sal_uInt32 nRemainingRecordData
= size
>= nRequiredHeaderSize
?
459 size
-nRequiredHeaderSize
: 0;
460 // clip to available size
461 nRemainingRecordData
= std::min(nRemainingRecordData
, nRemainder
);
462 pWMF
->SeekRel(nRemainingRecordData
);
463 nRemainder
-= nRemainingRecordData
;
465 pWMF
->SeekRel(nRemainder
);
469 * Reads polygons from the stream.
470 * The \<class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
471 * The \<class Drawer> parameter is a boost binding for the method that will draw the polygon.
472 * skipFirst: if the first point read is the 0th point or the 1st point in the array.
474 template <class T
, class Drawer
>
475 void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer
, const bool skipFirst
)
477 sal_uInt32
nPoints(0), nStartIndex(0);
479 pWMF
->ReadUInt32( nPoints
);
486 Polygon aPolygon
= ReadPolygon
<T
>(nStartIndex
, nPoints
);
487 drawer(pOut
, aPolygon
, skipFirst
, bRecordPath
);
491 * Reads polygons from the stream.
492 * The \<class T> parameter is for the type of the points
493 * nStartIndex: which is the starting index in the polygon of the first point read
494 * nPoints: number of points
495 * pWMF: the stream containings the polygons
498 Polygon
EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex
, sal_uInt32 nPoints
)
500 bool bRecordOk
= nPoints
<= SAL_MAX_UINT16
;
501 SAL_WARN_IF(!bRecordOk
, "vcl.filter", "polygon record has more polygons than we can handle");
505 Polygon
aPolygon(nPoints
);
506 for (sal_uInt16 i
= nStartIndex
; i
< nPoints
&& pWMF
->good(); i
++ )
512 aPolygon
[ i
] = Point( nX
, nY
);
519 * Reads a polyline from the WMF file and draws it
520 * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
523 void EnhWMFReader::ReadAndDrawPolyLine()
526 sal_Int32 i
, nPoly(0), nGesPoints(0);
527 pWMF
->SeekRel( 0x10 );
528 // Number of Polygons:
529 pWMF
->ReadInt32( nPoly
).ReadInt32( nGesPoints
);
531 // taking the amount of points of each polygon, retrieving the total number of points
533 ( static_cast< sal_uInt32
>(nPoly
) < SAL_MAX_UINT32
/ sizeof(sal_uInt16
) ) &&
534 ( static_cast< sal_uInt32
>( nPoly
) * sizeof(sal_uInt16
) ) <= ( nEndPos
- pWMF
->Tell() )
537 boost::scoped_array
<sal_uInt16
> pnPoints(new sal_uInt16
[ nPoly
]);
538 for ( i
= 0; i
< nPoly
&& pWMF
->good(); i
++ )
540 pWMF
->ReadUInt32( nPoints
);
541 pnPoints
[ i
] = (sal_uInt16
)nPoints
;
543 // Get polygon points:
544 for ( i
= 0; ( i
< nPoly
) && pWMF
->good(); i
++ )
546 Polygon aPolygon
= ReadPolygon
<T
>(0, pnPoints
[i
]);
547 pOut
->DrawPolyLine( aPolygon
, false, bRecordPath
);
552 // these are referenced from inside the templates
554 SvStream
& operator>>(SvStream
& rStream
, sal_Int16
&n
)
556 return rStream
.ReadInt16(n
);
559 SvStream
& operator>>(SvStream
& rStream
, sal_Int32
&n
)
561 return rStream
.ReadInt32(n
);
565 * Reads a poly polygon from the WMF file and draws it.
566 * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
569 void EnhWMFReader::ReadAndDrawPolyPolygon()
571 sal_uInt32
nPoly(0), nGesPoints(0), nReadPoints(0);
572 pWMF
->SeekRel( 0x10 );
573 // Number of polygons
574 pWMF
->ReadUInt32( nPoly
).ReadUInt32( nGesPoints
);
576 ( nGesPoints
< SAL_MAX_UINT32
/ sizeof(Point
) ) && //check against numeric overflowing
577 ( nPoly
< SAL_MAX_UINT32
/ sizeof(sal_uInt16
) ) &&
578 ( ( nPoly
* sizeof( sal_uInt16
) ) <= ( nEndPos
- pWMF
->Tell() ) ))
580 // Get number of points in each polygon
581 boost::scoped_array
<sal_uInt16
> pnPoints(new sal_uInt16
[ nPoly
]);
582 for (sal_uInt32 i
= 0; i
< nPoly
&& pWMF
->good(); ++i
)
584 sal_uInt32
nPoints(0);
585 pWMF
->ReadUInt32( nPoints
);
586 pnPoints
[ i
] = (sal_uInt16
)nPoints
;
588 if ( pWMF
->good() && ( nGesPoints
* (sizeof(T
)+sizeof(T
)) ) <= ( nEndPos
- pWMF
->Tell() ) )
590 // Get polygon points
591 tools::PolyPolygon
aPolyPoly(nPoly
, nPoly
);
592 for (sal_uInt32 i
= 0; i
< nPoly
&& pWMF
->good(); ++i
)
594 const sal_uInt16
nPointCount(pnPoints
[i
]);
595 boost::scoped_array
<Point
> pPtAry(new Point
[nPointCount
]);
596 for (sal_uInt16 j
= 0; j
< nPointCount
&& pWMF
->good(); ++j
)
600 pPtAry
[ j
] = Point( nX
, nY
);
604 aPolyPoly
.Insert(Polygon(nPointCount
, pPtAry
.get()));
607 pOut
->DrawPolyPolygon( aPolyPoly
, bRecordPath
);
610 OSL_ENSURE(nReadPoints
== nGesPoints
, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
615 bool EnhWMFReader::ReadEnhWMF()
617 sal_uInt32 nStretchBltMode
= 0;
618 sal_uInt32
nNextPos(0),
619 nW(0), nH(0), nColor(0), nIndex(0),
620 nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
621 sal_Int32
nX32(0), nY32(0), nx32(0), ny32(0);
623 bool bStatus
= ReadHeader();
624 bool bHaveDC
= false;
626 static bool bEnableEMFPlus
= ( getenv( "EMF_PLUS_DISABLE" ) == NULL
);
628 while( bStatus
&& nRecordCount
-- && pWMF
->good())
630 sal_uInt32
nRecType(0), nRecSize(0);
631 pWMF
->ReadUInt32(nRecType
).ReadUInt32(nRecSize
);
633 if ( !pWMF
->good() || ( nRecSize
< 8 ) || ( nRecSize
& 3 ) ) // Parameters are always divisible by 4
639 auto nCurPos
= pWMF
->Tell();
641 if (nEndPos
< nCurPos
- 8)
647 const sal_uInt32 nMaxPossibleRecSize
= nEndPos
- (nCurPos
- 8);
648 if (nRecSize
> nMaxPossibleRecSize
)
654 nNextPos
= nCurPos
+ (nRecSize
- 8);
656 if( !aBmpSaveList
.empty()
657 && ( nRecType
!= EMR_STRETCHBLT
)
658 && ( nRecType
!= EMR_STRETCHDIBITS
)
660 pOut
->ResolveBitmapActions( aBmpSaveList
);
665 SAL_INFO ("vcl.emf", "0x" << std::hex
<< (nNextPos
- nRecSize
) << "-0x" << nNextPos
<< " " << record_type_name(nRecType
) << " size: " << nRecSize
<< std::dec
);
667 if( bEnableEMFPlus
&& nRecType
== EMR_GDICOMMENT
) {
670 pWMF
->ReadUInt32( length
);
672 SAL_INFO("vcl.emf", "\tGDI comment, length: " << length
);
674 if( pWMF
->good() && length
>= 4 && length
<= pWMF
->remainingSize() ) {
677 pWMF
->ReadUInt32( id
);
679 SAL_INFO ("vcl.emf", "\t\tbegin " << (char)(id
& 0xff) << (char)((id
& 0xff00) >> 8) << (char)((id
& 0xff0000) >> 16) << (char)((id
& 0xff000000) >> 24) << " id: 0x" << std::hex
<< id
<< std::dec
);
681 // EMF+ comment (FIXME: BE?)
682 if( id
== 0x2B464D45 && nRecSize
>= 12 )
683 // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields.
684 // We have already read 4-byte CommentIdentifier, so reduce length appropriately
685 ReadEMFPlusComment( length
-4, bHaveDC
);
686 // GDIC comment, doesn't do anything useful yet
687 else if( id
== 0x43494447 && nRecSize
>= 12 ) {
688 // TODO: ReadGDIComment()
690 SAL_INFO ("vcl.emf", "\t\tunknown id: 0x" << std::hex
<< id
<< std::dec
);
694 else if( !bEMFPlus
|| bHaveDC
|| nRecType
== EMR_EOF
)
698 case EMR_POLYBEZIERTO
:
699 ReadAndDrawPolygon
<sal_Int32
>(boost::bind(&WinMtfOutput::DrawPolyBezier
, _1
, _2
, _3
, _4
), true);
701 case EMR_POLYBEZIER
:
702 ReadAndDrawPolygon
<sal_Int32
>(boost::bind(&WinMtfOutput::DrawPolyBezier
, _1
, _2
, _3
, _4
), false);
706 ReadAndDrawPolygon
<sal_Int32
>(boost::bind(&WinMtfOutput::DrawPolygon
, _1
, _2
, _3
, _4
), false);
709 case EMR_POLYLINETO
:
710 ReadAndDrawPolygon
<sal_Int32
>(boost::bind(&WinMtfOutput::DrawPolyLine
, _1
, _2
, _3
, _4
), true);
713 ReadAndDrawPolygon
<sal_Int32
>(boost::bind(&WinMtfOutput::DrawPolyLine
, _1
, _2
, _3
, _4
), false);
716 case EMR_POLYPOLYLINE
:
717 ReadAndDrawPolyLine
<sal_Int32
>();
720 case EMR_POLYPOLYGON
:
721 ReadAndDrawPolyPolygon
<sal_Int32
>();
724 case EMR_SETWINDOWEXTEX
:
726 pWMF
->ReadUInt32( nW
).ReadUInt32( nH
);
727 pOut
->SetWinExt( Size( nW
, nH
), true);
731 case EMR_SETWINDOWORGEX
:
733 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
734 pOut
->SetWinOrg( Point( nX32
, nY32
), true);
738 case EMR_SCALEWINDOWEXTEX
:
740 pWMF
->ReadUInt32( nNom1
).ReadUInt32( nDen1
).ReadUInt32( nNom2
).ReadUInt32( nDen2
);
741 pOut
->ScaleWinExt( (double)nNom1
/ nDen1
, (double)nNom2
/ nDen2
);
745 case EMR_SETVIEWPORTORGEX
:
747 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
748 pOut
->SetDevOrg( Point( nX32
, nY32
) );
752 case EMR_SCALEVIEWPORTEXTEX
:
754 pWMF
->ReadUInt32( nNom1
).ReadUInt32( nDen1
).ReadUInt32( nNom2
).ReadUInt32( nDen2
);
755 pOut
->ScaleDevExt( (double)nNom1
/ nDen1
, (double)nNom2
/ nDen2
);
759 case EMR_SETVIEWPORTEXTEX
:
761 pWMF
->ReadUInt32( nW
).ReadUInt32( nH
);
762 pOut
->SetDevExt( Size( nW
, nH
) );
767 nRecordCount
= 0; // #76846#
772 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
773 pOut
->DrawPixel( Point( nX32
, nY32
), ReadColor() );
777 case EMR_SETMAPMODE
:
780 pWMF
->ReadUInt32( nMapMode
);
781 pOut
->SetMapMode( nMapMode
);
787 pWMF
->ReadUInt32( nDat32
);
788 pOut
->SetBkMode( static_cast<BkMode
>(nDat32
) );
792 case EMR_SETPOLYFILLMODE
:
797 pWMF
->ReadUInt32( nDat32
);
798 pOut
->SetRasterOp( nDat32
);
802 case EMR_SETSTRETCHBLTMODE
:
804 pWMF
->ReadUInt32( nStretchBltMode
);
808 case EMR_SETTEXTALIGN
:
810 pWMF
->ReadUInt32( nDat32
);
811 pOut
->SetTextAlign( nDat32
);
815 case EMR_SETTEXTCOLOR
:
817 pOut
->SetTextColor( ReadColor() );
821 case EMR_SETBKCOLOR
:
823 pOut
->SetBkColor( ReadColor() );
827 case EMR_OFFSETCLIPRGN
:
829 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
830 pOut
->MoveClipRegion( Size( nX32
, nY32
) );
836 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
837 pOut
->MoveTo( Point( nX32
, nY32
), bRecordPath
);
841 case EMR_INTERSECTCLIPRECT
:
843 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
844 pOut
->IntersectClipRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
860 case EMR_SETWORLDTRANSFORM
:
864 pOut
->SetWorldTransform( aTempXForm
);
868 case EMR_MODIFYWORLDTRANSFORM
:
873 pWMF
->ReadUInt32( nMode
);
874 pOut
->ModifyWorldTransform( aTempXForm
, nMode
);
878 case EMR_SELECTOBJECT
:
880 pWMF
->ReadUInt32( nIndex
);
881 pOut
->SelectObject( nIndex
);
887 pWMF
->ReadUInt32( nIndex
);
888 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
894 // #fdo39428 Remove SvStream operator>>(long&)
895 sal_Int32
nTmpW(0), nTmpH(0);
897 pWMF
->ReadUInt32( nStyle
).ReadInt32( nTmpW
).ReadInt32( nTmpH
);
898 aSize
.Width() = nTmpW
;
899 aSize
.Height() = nTmpH
;
902 aLineInfo
.SetWidth( aSize
.Width() );
904 bool bTransparent
= false;
905 switch( nStyle
& 0xFF )
908 aLineInfo
.SetStyle( LINE_DASH
);
909 aLineInfo
.SetDashCount( 1 );
910 aLineInfo
.SetDotCount( 2 );
911 aLineInfo
.SetDashLen( 150 );
912 aLineInfo
.SetDotLen( 30 );
913 aLineInfo
.SetDistance( 50 );
916 aLineInfo
.SetStyle( LINE_DASH
);
917 aLineInfo
.SetDashCount( 1 );
918 aLineInfo
.SetDotCount( 1 );
919 aLineInfo
.SetDashLen( 150 );
920 aLineInfo
.SetDotLen( 30 );
921 aLineInfo
.SetDistance( 90 );
924 aLineInfo
.SetStyle( LINE_DASH
);
925 aLineInfo
.SetDashCount( 0 );
926 aLineInfo
.SetDotCount( 1 );
927 aLineInfo
.SetDotLen( 30 );
928 aLineInfo
.SetDistance( 50 );
931 aLineInfo
.SetStyle( LINE_DASH
);
932 aLineInfo
.SetDashCount( 1 );
933 aLineInfo
.SetDotCount( 0 );
934 aLineInfo
.SetDashLen( 225 );
935 aLineInfo
.SetDistance( 100 );
939 aLineInfo
.SetStyle( LINE_NONE
);
941 case PS_INSIDEFRAME
:
944 aLineInfo
.SetStyle( LINE_SOLID
);
946 switch( nStyle
& 0xF00 )
948 case PS_ENDCAP_ROUND
:
951 aLineInfo
.SetLineCap( com::sun::star::drawing::LineCap_ROUND
);
954 case PS_ENDCAP_SQUARE
:
957 aLineInfo
.SetLineCap( com::sun::star::drawing::LineCap_SQUARE
);
960 case PS_ENDCAP_FLAT
:
962 aLineInfo
.SetLineCap( com::sun::star::drawing::LineCap_BUTT
);
964 switch( nStyle
& 0xF000 )
967 aLineInfo
.SetLineJoin ( basegfx::B2DLINEJOIN_ROUND
);
970 aLineInfo
.SetLineJoin ( basegfx::B2DLINEJOIN_MITER
);
973 aLineInfo
.SetLineJoin ( basegfx::B2DLINEJOIN_BEVEL
);
976 aLineInfo
.SetLineJoin ( basegfx::B2DLINEJOIN_NONE
);
978 pOut
->CreateObject( nIndex
, GDI_PEN
, new WinMtfLineStyle( ReadColor(), aLineInfo
, bTransparent
) );
983 case EMR_EXTCREATEPEN
:
986 sal_uInt32 offBmi
, cbBmi
, offBits
, cbBits
, nStyle
, nWidth
, nBrushStyle
, elpNumEntries
;
989 pWMF
->ReadUInt32( nIndex
);
990 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
992 pWMF
->ReadUInt32( offBmi
).ReadUInt32( cbBmi
).ReadUInt32( offBits
).ReadUInt32( cbBits
). ReadUInt32( nStyle
).ReadUInt32( nWidth
).ReadUInt32( nBrushStyle
);
993 aColorRef
= ReadColor();
994 pWMF
->ReadInt32( elpHatch
).ReadUInt32( elpNumEntries
);
998 aLineInfo
.SetWidth( nWidth
);
1000 bool bTransparent
= false;
1001 sal_uInt16 nDashCount
= 0;
1002 sal_uInt16 nDotCount
= 0;
1004 switch( nStyle
& PS_STYLE_MASK
)
1006 case PS_DASHDOTDOT
:
1017 bTransparent
= true;
1018 aLineInfo
.SetStyle( LINE_NONE
);
1021 case PS_INSIDEFRAME
:
1024 aLineInfo
.SetStyle( LINE_SOLID
);
1026 if ( nDashCount
| nDotCount
)
1028 aLineInfo
.SetStyle( LINE_DASH
);
1029 aLineInfo
.SetDashCount( nDashCount
);
1030 aLineInfo
.SetDotCount( nDotCount
);
1032 pOut
->CreateObject( nIndex
, GDI_PEN
, new WinMtfLineStyle( aColorRef
, aLineInfo
, bTransparent
) );
1037 case EMR_CREATEBRUSHINDIRECT
:
1040 pWMF
->ReadUInt32( nIndex
);
1041 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1043 pWMF
->ReadUInt32( nStyle
);
1044 pOut
->CreateObject( nIndex
, GDI_BRUSH
, new WinMtfFillStyle( ReadColor(), ( nStyle
== BS_HOLLOW
) ) );
1049 case EMR_DELETEOBJECT
:
1051 pWMF
->ReadUInt32( nIndex
);
1052 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1053 pOut
->DeleteObject( nIndex
);
1059 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
1060 pOut
->DrawEllipse( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
1064 case EMR_RECTANGLE
:
1066 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
1067 pOut
->DrawRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
1071 case EMR_ROUNDRECT
:
1073 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nW
).ReadUInt32( nH
);
1074 Size
aSize( Size( nW
, nH
) );
1075 pOut
->DrawRoundRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
), aSize
);
1081 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1082 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1083 pOut
->DrawArc( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1089 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1090 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1091 pOut
->DrawChord( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1097 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1098 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1099 const Rectangle
aRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
));
1101 // #i73608# OutputDevice deviates from WMF
1102 // semantics. start==end means full ellipse here.
1103 if( nStartX
== nEndX
&& nStartY
== nEndY
)
1104 pOut
->DrawEllipse( aRect
);
1106 pOut
->DrawPie( aRect
, Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1112 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
1113 pOut
->LineTo( Point( nX32
, nY32
), bRecordPath
);
1119 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1120 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1121 pOut
->DrawArc( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
), true );
1125 case EMR_BEGINPATH
:
1132 case EMR_ABORTPATH
:
1135 bRecordPath
= false;
1138 case EMR_CLOSEFIGURE
:
1143 pOut
->StrokeAndFillPath( false, true );
1146 case EMR_STROKEANDFILLPATH
:
1147 pOut
->StrokeAndFillPath( true, true );
1150 case EMR_STROKEPATH
:
1151 pOut
->StrokeAndFillPath( true, false );
1154 case EMR_SELECTCLIPPATH
:
1156 sal_Int32 nClippingMode
;
1157 pWMF
->ReadInt32(nClippingMode
);
1158 pOut
->SetClipPath(pOut
->GetPathObj(), nClippingMode
, true);
1162 case EMR_EXTSELECTCLIPRGN
:
1164 sal_Int32 nClippingMode
, cbRgnData
;
1165 pWMF
->ReadInt32(cbRgnData
);
1166 pWMF
->ReadInt32(nClippingMode
);
1168 // This record's region data should be ignored if mode
1169 // is RGN_COPY - see EMF spec section 2.3.2.2
1170 if (nClippingMode
== RGN_COPY
)
1172 pOut
->SetDefaultClipPath();
1176 tools::PolyPolygon aPolyPoly
;
1178 ImplReadRegion(aPolyPoly
, *pWMF
, nRecSize
);
1179 pOut
->SetClipPath(aPolyPoly
, nClippingMode
, false);
1185 case EMR_ALPHABLEND
:
1187 sal_Int32
xDest(0), yDest(0), cxDest(0), cyDest(0);
1189 BLENDFUNCTION aFunc
;
1190 sal_Int32
xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
1192 sal_uInt32
BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
1193 sal_uInt32
cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
1195 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1196 pWMF
->SeekRel( 0x10 );
1198 pWMF
->ReadInt32( xDest
).ReadInt32( yDest
).ReadInt32( cxDest
).ReadInt32( cyDest
);
1200 pWMF
->ReadInt32( xSrc
).ReadInt32( ySrc
);
1202 pWMF
->ReadUInt32( BkColorSrc
).ReadUInt32( iUsageSrc
).ReadUInt32( offBmiSrc
).ReadUInt32( cbBmiSrc
)
1203 .ReadUInt32( offBitsSrc
).ReadUInt32( cbBitsSrc
).ReadInt32( cxSrc
).ReadInt32( cySrc
) ;
1205 sal_uInt32 dwRop
= SRCAND
|SRCINVERT
;
1208 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
+1, cyDest
+1 ) );
1210 if ( (cbBitsSrc
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
) )
1214 sal_uInt32 nSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1215 if ( nSize
<= ( nEndPos
- nStartPos
) )
1217 char* pBuf
= new char[ nSize
];
1218 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1219 aTmp
.ObjectOwnsMemory( true );
1220 aTmp
.WriteUChar( 'B' )
1222 .WriteUInt32( cbBitsSrc
)
1225 .WriteUInt32( cbBmiSrc
+ 14 );
1226 pWMF
->Seek( nStart
+ offBmiSrc
);
1227 pWMF
->Read( pBuf
+ 14, cbBmiSrc
);
1228 pWMF
->Seek( nStart
+ offBitsSrc
);
1229 pWMF
->Read( pBuf
+ 14 + cbBmiSrc
, cbBitsSrc
);
1231 ReadDIB(aBitmap
, aTmp
, true);
1233 // test if it is sensible to crop
1234 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1235 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1236 ( xSrc
+ cxSrc
<= aBitmap
.GetSizePixel().Width() ) &&
1237 ( ySrc
+ cySrc
<= aBitmap
.GetSizePixel().Height() ) )
1239 Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1240 aBitmap
.Crop( aCropRect
);
1242 aBmpSaveList
.push_back( new BSaveStruct( aBitmap
, aRect
, dwRop
, pOut
->GetFillStyle () ) );
1248 case EMR_BITBLT
: // PASSTHROUGH INTENDED
1249 case EMR_STRETCHBLT
:
1251 sal_Int32 xDest
, yDest
, cxDest
, cyDest
, xSrc
, ySrc
, cxSrc
, cySrc
;
1252 sal_uInt32 dwRop
, iUsageSrc
, offBmiSrc
, cbBmiSrc
, offBitsSrc
, cbBitsSrc
;
1255 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1257 pWMF
->SeekRel( 0x10 );
1258 pWMF
->ReadInt32( xDest
).ReadInt32( yDest
).ReadInt32( cxDest
).ReadInt32( cyDest
).ReadUInt32( dwRop
).ReadInt32( xSrc
).ReadInt32( ySrc
)
1260 pWMF
->ReadUInt32( nColor
).ReadUInt32( iUsageSrc
).ReadUInt32( offBmiSrc
).ReadUInt32( cbBmiSrc
)
1261 .ReadUInt32( offBitsSrc
).ReadUInt32( cbBitsSrc
);
1263 if ( nRecType
== EMR_STRETCHBLT
)
1264 pWMF
->ReadInt32( cxSrc
).ReadInt32( cySrc
);
1269 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
, cyDest
) );
1271 cxDest
= abs( (int)cxDest
); // sj: i37894, size can be negative
1272 cyDest
= abs( (int)cyDest
); // and also 122889
1274 if ( (cbBitsSrc
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
) )
1278 sal_uInt32 nSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1279 if ( nSize
<= ( nEndPos
- nStartPos
) )
1281 char* pBuf
= new char[ nSize
];
1282 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1283 aTmp
.ObjectOwnsMemory( true );
1284 aTmp
.WriteUChar( 'B' )
1286 .WriteUInt32( cbBitsSrc
)
1289 .WriteUInt32( cbBmiSrc
+ 14 );
1290 pWMF
->Seek( nStart
+ offBmiSrc
);
1291 pWMF
->Read( pBuf
+ 14, cbBmiSrc
);
1292 pWMF
->Seek( nStart
+ offBitsSrc
);
1293 pWMF
->Read( pBuf
+ 14 + cbBmiSrc
, cbBitsSrc
);
1295 ReadDIB(aBitmap
, aTmp
, true);
1297 // test if it is sensible to crop
1298 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1299 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1300 ( xSrc
+ cxSrc
<= aBitmap
.GetSizePixel().Width() ) &&
1301 ( ySrc
+ cySrc
<= aBitmap
.GetSizePixel().Height() ) )
1303 Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1304 aBitmap
.Crop( aCropRect
);
1306 aBmpSaveList
.push_back( new BSaveStruct( aBitmap
, aRect
, dwRop
, pOut
->GetFillStyle () ) );
1312 case EMR_STRETCHDIBITS
:
1314 sal_Int32 xDest
, yDest
, xSrc
, ySrc
, cxSrc
, cySrc
, cxDest
, cyDest
;
1315 sal_uInt32 offBmiSrc
, cbBmiSrc
, offBitsSrc
, cbBitsSrc
, iUsageSrc
, dwRop
;
1316 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1318 pWMF
->SeekRel( 0x10 );
1319 pWMF
->ReadInt32( xDest
)
1325 .ReadUInt32( offBmiSrc
)
1326 .ReadUInt32( cbBmiSrc
)
1327 .ReadUInt32( offBitsSrc
)
1328 .ReadUInt32( cbBitsSrc
)
1329 .ReadUInt32( iUsageSrc
)
1330 .ReadUInt32( dwRop
)
1331 .ReadInt32( cxDest
)
1332 .ReadInt32( cyDest
);
1335 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
, cyDest
) );
1337 cxDest
= abs( (int)cxDest
); // sj: i37894, size can be negative
1338 cyDest
= abs( (int)cyDest
); // and also 122889
1340 if ( ((SAL_MAX_UINT32
- 14) < cbBitsSrc
)
1341 || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
)
1348 sal_uInt32 nSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1349 if ( nSize
<= ( nEndPos
- nStartPos
) )
1351 char* pBuf
= new char[ nSize
];
1352 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1353 aTmp
.ObjectOwnsMemory( true );
1354 aTmp
.WriteUChar( 'B' )
1356 .WriteUInt32( cbBitsSrc
)
1359 .WriteUInt32( cbBmiSrc
+ 14 );
1360 pWMF
->Seek( nStart
+ offBmiSrc
);
1361 pWMF
->Read( pBuf
+ 14, cbBmiSrc
);
1362 pWMF
->Seek( nStart
+ offBitsSrc
);
1363 pWMF
->Read( pBuf
+ 14 + cbBmiSrc
, cbBitsSrc
);
1365 ReadDIB(aBitmap
, aTmp
, true);
1367 // test if it is sensible to crop
1368 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1369 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1370 ( xSrc
+ cxSrc
<= aBitmap
.GetSizePixel().Width() ) &&
1371 ( ySrc
+ cySrc
<= aBitmap
.GetSizePixel().Height() ) )
1373 Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1374 aBitmap
.Crop( aCropRect
);
1376 aBmpSaveList
.push_back( new BSaveStruct( aBitmap
, aRect
, dwRop
, pOut
->GetFillStyle () ) );
1382 case EMR_EXTCREATEFONTINDIRECTW
:
1384 pWMF
->ReadUInt32( nIndex
);
1385 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1388 pWMF
->ReadInt32( aLogFont
.lfHeight
)
1389 .ReadInt32( aLogFont
.lfWidth
)
1390 .ReadInt32( aLogFont
.lfEscapement
)
1391 .ReadInt32( aLogFont
.lfOrientation
)
1392 .ReadInt32( aLogFont
.lfWeight
)
1393 .ReadUChar( aLogFont
.lfItalic
)
1394 .ReadUChar( aLogFont
.lfUnderline
)
1395 .ReadUChar( aLogFont
.lfStrikeOut
)
1396 .ReadUChar( aLogFont
.lfCharSet
)
1397 .ReadUChar( aLogFont
.lfOutPrecision
)
1398 .ReadUChar( aLogFont
.lfClipPrecision
)
1399 .ReadUChar( aLogFont
.lfQuality
)
1400 .ReadUChar( aLogFont
.lfPitchAndFamily
);
1402 sal_Unicode lfFaceName
[LF_FACESIZE
+1];
1403 lfFaceName
[LF_FACESIZE
] = 0;
1404 for (int i
= 0; i
< LF_FACESIZE
; ++i
)
1406 sal_uInt16
nChar(0);
1407 pWMF
->ReadUInt16(nChar
);
1408 lfFaceName
[i
] = nChar
;
1410 aLogFont
.alfFaceName
= OUString( lfFaceName
);
1412 // #i123216# Not used in the test case of #121382# (always identity in XForm), also
1413 // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1414 // from #i123216# creates errors, so removing.
1416 // // #i121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1417 // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1418 // // constraints and dangers
1419 // const XForm& rXF = pOut->GetWorldTransform();
1420 // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1421 // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1422 // aLogFont.lfWidth = aTransVec.getX();
1423 // aLogFont.lfHeight = aTransVec.getY();
1425 pOut
->CreateObject( nIndex
, GDI_FONT
, new WinMtfFontStyle( aLogFont
) );
1430 case EMR_EXTTEXTOUTA
:
1432 case EMR_EXTTEXTOUTW
:
1434 sal_Int32 nLeft
, nTop
, nRight
, nBottom
, ptlReferenceX
, ptlReferenceY
, nGfxMode
, nXScale
, nYScale
;
1435 sal_uInt32 nOffString
, nOptions
, offDx
;
1437 std::vector
<long> aDX
;
1439 nCurPos
= pWMF
->Tell() - 8;
1441 pWMF
->ReadInt32( nLeft
).ReadInt32( nTop
).ReadInt32( nRight
).ReadInt32( nBottom
).ReadInt32( nGfxMode
).ReadInt32( nXScale
).ReadInt32( nYScale
)
1442 .ReadInt32( ptlReferenceX
).ReadInt32( ptlReferenceY
).ReadInt32( nLen
).ReadUInt32( nOffString
).ReadUInt32( nOptions
);
1444 pWMF
->SeekRel( 0x10 );
1445 pWMF
->ReadUInt32( offDx
);
1447 ComplexTextLayoutMode nTextLayoutMode
= TEXT_LAYOUT_DEFAULT
;
1448 if ( nOptions
& ETO_RTLREADING
)
1449 nTextLayoutMode
= TEXT_LAYOUT_BIDI_RTL
| TEXT_LAYOUT_TEXTORIGIN_LEFT
;
1450 pOut
->SetTextLayoutMode( nTextLayoutMode
);
1451 DBG_ASSERT( ( nOptions
& ( ETO_PDY
| ETO_GLYPH_INDEX
) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1453 Point
aPos( ptlReferenceX
, ptlReferenceY
);
1454 bool bLenSane
= nLen
> 0 && nLen
< static_cast<sal_Int32
>( SAL_MAX_UINT32
/ sizeof(sal_Int32
) );
1455 bool bOffStringSane
= nOffString
<= nEndPos
- nCurPos
;
1456 if (bLenSane
&& bOffStringSane
)
1458 if ( offDx
&& (( nCurPos
+ offDx
+ nLen
* 4 ) <= nNextPos
) )
1460 pWMF
->Seek( nCurPos
+ offDx
);
1461 if ( ( nLen
* sizeof(sal_uInt32
) ) <= ( nEndPos
- pWMF
->Tell() ) )
1464 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1467 pWMF
->ReadInt32(val
);
1472 pWMF
->Seek( nCurPos
+ nOffString
);
1476 if ( nLen
<= static_cast<sal_Int32
>( nEndPos
- pWMF
->Tell() ) )
1478 boost::scoped_array
<sal_Char
> pBuf(new sal_Char
[ nLen
]);
1479 pWMF
->Read( pBuf
.get(), nLen
);
1480 aText
= OUString(pBuf
.get(), nLen
, pOut
->GetCharSet());
1483 if ( aText
.getLength() != nLen
)
1485 std::vector
<long> aOldDX(aText
.getLength());
1487 sal_Int32 nDXLen
= std::min
<sal_Int32
>(nLen
, aOldDX
.size());
1488 for (sal_Int32 i
= 0, j
= 0; i
< aText
.getLength(); ++i
)
1490 sal_Unicode cUniChar
= aText
[i
];
1491 OString
aCharacter(&cUniChar
, 1, pOut
->GetCharSet());
1493 for (sal_Int32 k
= 0; ( k
< aCharacter
.getLength() ) && ( j
< nDXLen
) && ( i
< aText
.getLength() ); ++k
)
1494 aDX
[ i
] += aOldDX
[j
++];
1501 if ( ( nLen
* sizeof(sal_Unicode
) ) <= ( nEndPos
- pWMF
->Tell() ) )
1503 boost::scoped_array
<sal_Unicode
> pBuf(new sal_Unicode
[ nLen
]);
1504 pWMF
->Read( pBuf
.get(), nLen
<< 1 );
1505 #ifdef OSL_BIGENDIAN
1506 sal_Char nTmp
, *pTmp
= (sal_Char
*)( pBuf
.get() + nLen
);
1507 while ( pTmp
-- != (sal_Char
*)pBuf
.get() )
1514 aText
= OUString(pBuf
.get(), nLen
);
1517 pOut
->DrawText(aPos
, aText
, aDX
.data(), bRecordPath
, nGfxMode
);
1522 case EMR_POLYBEZIERTO16
:
1523 ReadAndDrawPolygon
<sal_Int16
>(boost::bind(&WinMtfOutput::DrawPolyBezier
, _1
, _2
, _3
, _4
), true);
1525 case EMR_POLYBEZIER16
:
1526 ReadAndDrawPolygon
<sal_Int16
>(boost::bind(&WinMtfOutput::DrawPolyBezier
, _1
, _2
, _3
, _4
), false);
1529 case EMR_POLYGON16
:
1530 ReadAndDrawPolygon
<sal_Int16
>(boost::bind(&WinMtfOutput::DrawPolygon
, _1
, _2
, _3
, _4
), false);
1533 case EMR_POLYLINETO16
:
1534 ReadAndDrawPolygon
<sal_Int16
>(boost::bind(&WinMtfOutput::DrawPolyLine
, _1
, _2
, _3
, _4
), true);
1536 case EMR_POLYLINE16
:
1537 ReadAndDrawPolygon
<sal_Int16
>(boost::bind(&WinMtfOutput::DrawPolyLine
, _1
, _2
, _3
, _4
), false);
1540 case EMR_POLYPOLYLINE16
:
1541 ReadAndDrawPolyLine
<sal_Int16
>();
1544 case EMR_POLYPOLYGON16
:
1545 ReadAndDrawPolyPolygon
<sal_Int16
>();
1551 tools::PolyPolygon aPolyPoly
;
1552 pWMF
->SeekRel( 0x10 );
1553 pWMF
->ReadUInt32( nLen
).ReadUInt32( nIndex
);
1555 if ( ImplReadRegion( aPolyPoly
, *pWMF
, nRecSize
) )
1558 pOut
->SelectObject( nIndex
);
1559 pOut
->DrawPolyPolygon( aPolyPoly
, false );
1565 case EMR_CREATEDIBPATTERNBRUSHPT
:
1567 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1570 pWMF
->ReadUInt32( nIndex
);
1572 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1574 sal_uInt32 usage
, offBmi
, cbBmi
, offBits
, cbBits
;
1576 pWMF
->ReadUInt32( usage
);
1577 pWMF
->ReadUInt32( offBmi
);
1578 pWMF
->ReadUInt32( cbBmi
);
1579 pWMF
->ReadUInt32( offBits
);
1580 pWMF
->ReadUInt32( cbBits
);
1582 if ( (cbBits
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBits
< cbBmi
) )
1586 sal_uInt32 nSize
= cbBmi
+ cbBits
+ 14;
1587 if ( nSize
<= ( nEndPos
- nStartPos
) )
1589 char* pBuf
= new char[ nSize
];
1591 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1592 aTmp
.ObjectOwnsMemory( true );
1593 aTmp
.WriteUChar( 'B' )
1595 .WriteUInt32( cbBits
)
1598 .WriteUInt32( cbBmi
+ 14 );
1599 pWMF
->Seek( nStart
+ offBmi
);
1600 pWMF
->Read( pBuf
+ 14, cbBmi
);
1601 pWMF
->Seek( nStart
+ offBits
);
1602 pWMF
->Read( pBuf
+ 14 + cbBmi
, cbBits
);
1604 ReadDIB(aBitmap
, aTmp
, true);
1609 pOut
->CreateObject( nIndex
, GDI_BRUSH
, new WinMtfFillStyle( aBitmap
) );
1613 case EMR_MASKBLT
: SAL_INFO("vcl.emf", "not implemented 'MaskBlt'"); break;
1614 case EMR_PLGBLT
: SAL_INFO("vcl.emf", "not implemented 'PlgBlt'"); break;
1615 case EMR_SETDIBITSTODEVICE
: SAL_INFO("vcl.emf", "not implemented 'SetDIBitsToDevice'"); break;
1616 case EMR_FRAMERGN
: SAL_INFO("vcl.emf", "not implemented 'FrameRgn'"); break;
1617 case EMR_INVERTRGN
: SAL_INFO("vcl.emf", "not implemented 'InvertRgn'"); break;
1618 case EMR_PAINTRGN
: SAL_INFO("vcl.emf", "not implemented 'PaintRgn'"); break;
1619 case EMR_FLATTENPATH
: SAL_INFO("vcl.emf", "not implemented 'FlattenPath'"); break;
1620 case EMR_WIDENPATH
: SAL_INFO("vcl.emf", "not implemented 'WidenPath'"); break;
1621 case EMR_POLYDRAW
: SAL_INFO("vcl.emf", "not implemented 'Polydraw'"); break;
1622 case EMR_SETARCDIRECTION
: SAL_INFO("vcl.emf", "not implemented 'SetArcDirection'"); break;
1623 case EMR_SETPALETTEENTRIES
: SAL_INFO("vcl.emf", "not implemented 'SetPaletteEntries'"); break;
1624 case EMR_RESIZEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'ResizePalette'"); break;
1625 case EMR_EXTFLOODFILL
: SAL_INFO("vcl.emf", "not implemented 'ExtFloodFill'"); break;
1626 case EMR_ANGLEARC
: SAL_INFO("vcl.emf", "not implemented 'AngleArc'"); break;
1627 case EMR_SETCOLORADJUSTMENT
: SAL_INFO("vcl.emf", "not implemented 'SetColorAdjustment'"); break;
1628 case EMR_POLYDRAW16
: SAL_INFO("vcl.emf", "not implemented 'PolyDraw16'"); break;
1629 case EMR_POLYTEXTOUTA
: SAL_INFO("vcl.emf", "not implemented 'PolyTextOutA'"); break;
1630 case EMR_POLYTEXTOUTW
: SAL_INFO("vcl.emf", "not implemented 'PolyTextOutW'"); break;
1631 case EMR_CREATECOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'CreateColorSpace'"); break;
1632 case EMR_SETCOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'SetColorSpace'"); break;
1633 case EMR_DELETECOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'DeleteColorSpace'"); break;
1634 case EMR_GLSRECORD
: SAL_INFO("vcl.emf", "not implemented 'GlsRecord'"); break;
1635 case EMR_GLSBOUNDEDRECORD
: SAL_INFO("vcl.emf", "not implemented 'GlsBoundRecord'"); break;
1636 case EMR_PIXELFORMAT
: SAL_INFO("vcl.emf", "not implemented 'PixelFormat'"); break;
1637 case EMR_DRAWESCAPE
: SAL_INFO("vcl.emf", "not implemented 'DrawEscape'"); break;
1638 case EMR_EXTESCAPE
: SAL_INFO("vcl.emf", "not implemented 'ExtEscape'"); break;
1639 case EMR_STARTDOC
: SAL_INFO("vcl.emf", "not implemented 'StartDoc'"); break;
1640 case EMR_SMALLTEXTOUT
: SAL_INFO("vcl.emf", "not implemented 'SmallTextOut'"); break;
1641 case EMR_FORCEUFIMAPPING
: SAL_INFO("vcl.emf", "not implemented 'ForceUFIMapping'"); break;
1642 case EMR_NAMEDESCAPE
: SAL_INFO("vcl.emf", "not implemented 'NamedEscape'"); break;
1643 case EMR_COLORCORRECTPALETTE
: SAL_INFO("vcl.emf", "not implemented 'ColorCorrectPalette'"); break;
1644 case EMR_SETICMPROFILEA
: SAL_INFO("vcl.emf", "not implemented 'SetICMProfileA'"); break;
1645 case EMR_SETICMPROFILEW
: SAL_INFO("vcl.emf", "not implemented 'SetICMProfileW'"); break;
1646 case EMR_TRANSPARENTBLT
: SAL_INFO("vcl.emf", "not implemented 'TransparenBlt'"); break;
1647 case EMR_TRANSPARENTDIB
: SAL_INFO("vcl.emf", "not implemented 'TransparenDib'"); break;
1648 case EMR_GRADIENTFILL
: SAL_INFO("vcl.emf", "not implemented 'GradientFill'"); break;
1649 case EMR_SETLINKEDUFIS
: SAL_INFO("vcl.emf", "not implemented 'SetLinkedUFIS'"); break;
1651 case EMR_SETMAPPERFLAGS
: SAL_INFO("vcl.emf", "not implemented 'SetMapperFlags'"); break;
1652 case EMR_SETICMMODE
: SAL_INFO("vcl.emf", "not implemented 'SetICMMode'"); break;
1653 case EMR_CREATEMONOBRUSH
: SAL_INFO("vcl.emf", "not implemented 'CreateMonoBrush'"); break;
1654 case EMR_SETBRUSHORGEX
: SAL_INFO("vcl.emf", "not implemented 'SetBrushOrgEx'"); break;
1655 case EMR_SETMETARGN
: SAL_INFO("vcl.emf", "not implemented 'SetMetArgn'"); break;
1656 case EMR_SETMITERLIMIT
: SAL_INFO("vcl.emf", "not implemented 'SetMiterLimit'"); break;
1657 case EMR_EXCLUDECLIPRECT
: SAL_INFO("vcl.emf", "not implemented 'ExcludeClipRect'"); break;
1658 case EMR_REALIZEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'RealizePalette'"); break;
1659 case EMR_SELECTPALETTE
: SAL_INFO("vcl.emf", "not implemented 'SelectPalette'"); break;
1660 case EMR_CREATEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'CreatePalette'"); break;
1661 case EMR_ALPHADIBBLEND
: SAL_INFO("vcl.emf", "not implemented 'AlphaDibBlend'"); break;
1662 case EMR_SETTEXTJUSTIFICATION
: SAL_INFO("vcl.emf", "not implemented 'SetTextJustification'"); break;
1664 case EMR_GDICOMMENT
:
1665 case EMR_HEADER
: // has already been read at ReadHeader()
1668 default : SAL_INFO("vcl.emf", "Unknown Meta Action"); break;
1671 pWMF
->Seek( nNextPos
);
1673 if( !aBmpSaveList
.empty() )
1674 pOut
->ResolveBitmapActions( aBmpSaveList
);
1677 pWMF
->Seek(nEndPos
);
1682 bool EnhWMFReader::ReadHeader()
1684 sal_uInt32 nType
, nSignature
, nVersion
;
1685 sal_uInt32 nHeaderSize
, nPalEntries
;
1687 // Spare me the METAFILEHEADER here
1688 // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
1689 pWMF
->ReadUInt32( nType
).ReadUInt32( nHeaderSize
);
1690 if (nType
!= 0x00000001)
1692 // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
1693 SAL_WARN("vcl.emf", "EMF header type is not set to 0x00000001 - possibly corrupted file?");
1697 // Start reading the EMR_HEADER Header object
1699 // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
1700 Rectangle rclBounds
= ReadRectangle(); // rectangle in logical units
1702 // picture frame size (RectL object)
1703 Rectangle rclFrame
= ReadRectangle(); // rectangle in device units 1/100th mm
1705 pWMF
->ReadUInt32( nSignature
);
1707 // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
1708 // and 2.1.14 FormatSignature Enumeration
1709 if (nSignature
!= 0x464d4520)
1711 SAL_WARN("vcl.emf", "EMF\t\tSignature is not 0x464d4520 (\"FME\") - possibly corrupted file?");
1715 pWMF
->ReadUInt32(nVersion
); // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
1716 // Microsoft note that not even Windows checks this...
1717 if (nVersion
!= 0x00010000)
1719 SAL_WARN("vcl.emf", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
1722 pWMF
->ReadUInt32(nEndPos
); // size of metafile
1723 nEndPos
+= nStartPos
;
1725 sal_uInt32 nStrmPos
= pWMF
->Tell(); // checking if nEndPos is valid
1726 pWMF
->Seek(STREAM_SEEK_TO_END
);
1727 sal_uInt32 nActualFileSize
= pWMF
->Tell();
1729 if ( nActualFileSize
< nEndPos
)
1731 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object records number of bytes as " << nEndPos
1732 << ", however the file size is actually " << nActualFileSize
1733 << " bytes. Possible file corruption?");
1734 nEndPos
= nActualFileSize
;
1736 pWMF
->Seek(nStrmPos
);
1738 pWMF
->ReadInt32(nRecordCount
);
1740 if (nRecordCount
<= 0)
1742 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object shows record counter as <= 0! This shouldn't "
1743 "be possible... indicator of possible file corruption?");
1747 // the number of "handles", or graphics objects used in the metafile
1749 sal_uInt16 nHandlesCount
;
1750 pWMF
->ReadUInt16(nHandlesCount
);
1752 // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
1753 // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
1754 // value is actually pretty useful in checking if there is possible corruption
1756 sal_uInt16 nReserved
;
1757 pWMF
->ReadUInt16(nReserved
);
1759 if ( nReserved
!= 0x0000 )
1761 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object's reserved field is NOT 0x0000... possible "
1765 // The next 4 bytes specifies the number of characters in the metafile description.
1766 // The 4 bytes after that specific the offset from this record that contains the
1767 // metafile description... zero means no description string.
1768 // For now, we ignore it.
1772 sal_Int32 nPixX
, nPixY
, nMillX
, nMillY
;
1773 pWMF
->ReadUInt32(nPalEntries
);
1774 pWMF
->ReadInt32(nPixX
);
1775 pWMF
->ReadInt32(nPixY
);
1776 pWMF
->ReadInt32(nMillX
);
1777 pWMF
->ReadInt32(nMillY
);
1779 pOut
->SetrclFrame(rclFrame
);
1780 pOut
->SetrclBounds(rclBounds
);
1781 pOut
->SetRefPix(Size( nPixX
, nPixY
) );
1782 pOut
->SetRefMill(Size( nMillX
, nMillY
) );
1784 pWMF
->Seek(nStartPos
+ nHeaderSize
);
1788 Rectangle
EnhWMFReader::ReadRectangle()
1790 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
1791 pWMF
->ReadInt32(nLeft
);
1792 pWMF
->ReadInt32(nTop
);
1793 pWMF
->ReadInt32(nRight
);
1794 pWMF
->ReadInt32(nBottom
);
1795 return Rectangle(nLeft
, nTop
, nRight
, nBottom
);
1798 Rectangle
EnhWMFReader::ReadRectangle( sal_Int32 x1
, sal_Int32 y1
, sal_Int32 x2
, sal_Int32 y2
)
1800 Point
aTL ( Point( x1
, y1
) );
1801 Point
aBR( Point( --x2
, --y2
) );
1802 return Rectangle( aTL
, aBR
);
1805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */