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 <osl/endian.h>
21 #include <basegfx/matrix/b2dhommatrix.hxx>
22 #include <vcl/dibtools.hxx>
23 #include <o3tl/make_unique.hxx>
30 #include <tools/stream.hxx>
31 #include <vcl/pngwrite.hxx>
39 #define EMR_POLYBEZIER 2
41 #define EMR_POLYLINE 4
42 #define EMR_POLYBEZIERTO 5
43 #define EMR_POLYLINETO 6
44 #define EMR_POLYPOLYLINE 7
45 #define EMR_POLYPOLYGON 8
46 #define EMR_SETWINDOWEXTEX 9
47 #define EMR_SETWINDOWORGEX 10
48 #define EMR_SETVIEWPORTEXTEX 11
49 #define EMR_SETVIEWPORTORGEX 12
50 #define EMR_SETBRUSHORGEX 13
52 #define EMR_SETPIXELV 15
53 #define EMR_SETMAPPERFLAGS 16
54 #define EMR_SETMAPMODE 17
55 #define EMR_SETBKMODE 18
56 #define EMR_SETPOLYFILLMODE 19
57 #define EMR_SETROP2 20
58 #define EMR_SETSTRETCHBLTMODE 21
59 #define EMR_SETTEXTALIGN 22
60 #define EMR_SETCOLORADJUSTMENT 23
61 #define EMR_SETTEXTCOLOR 24
62 #define EMR_SETBKCOLOR 25
63 #define EMR_OFFSETCLIPRGN 26
64 #define EMR_MOVETOEX 27
65 #define EMR_SETMETARGN 28
66 #define EMR_EXCLUDECLIPRECT 29
67 #define EMR_INTERSECTCLIPRECT 30
68 #define EMR_SCALEVIEWPORTEXTEX 31
69 #define EMR_SCALEWINDOWEXTEX 32
71 #define EMR_RESTOREDC 34
72 #define EMR_SETWORLDTRANSFORM 35
73 #define EMR_MODIFYWORLDTRANSFORM 36
74 #define EMR_SELECTOBJECT 37
75 #define EMR_CREATEPEN 38
76 #define EMR_CREATEBRUSHINDIRECT 39
77 #define EMR_DELETEOBJECT 40
78 #define EMR_ANGLEARC 41
79 #define EMR_ELLIPSE 42
80 #define EMR_RECTANGLE 43
81 #define EMR_ROUNDRECT 44
85 #define EMR_SELECTPALETTE 48
86 #define EMR_CREATEPALETTE 49
87 #define EMR_SETPALETTEENTRIES 50
88 #define EMR_RESIZEPALETTE 51
89 #define EMR_REALIZEPALETTE 52
90 #define EMR_EXTFLOODFILL 53
93 #define EMR_POLYDRAW 56
94 #define EMR_SETARCDIRECTION 57
95 #define EMR_SETMITERLIMIT 58
96 #define EMR_BEGINPATH 59
97 #define EMR_ENDPATH 60
98 #define EMR_CLOSEFIGURE 61
99 #define EMR_FILLPATH 62
100 #define EMR_STROKEANDFILLPATH 63
101 #define EMR_STROKEPATH 64
102 #define EMR_FLATTENPATH 65
103 #define EMR_WIDENPATH 66
104 #define EMR_SELECTCLIPPATH 67
105 #define EMR_ABORTPATH 68
107 #define EMR_GDICOMMENT 70
108 #define EMR_FILLRGN 71
109 #define EMR_FRAMERGN 72
110 #define EMR_INVERTRGN 73
111 #define EMR_PAINTRGN 74
112 #define EMR_EXTSELECTCLIPRGN 75
113 #define EMR_BITBLT 76
114 #define EMR_STRETCHBLT 77
115 #define EMR_MASKBLT 78
116 #define EMR_PLGBLT 79
117 #define EMR_SETDIBITSTODEVICE 80
118 #define EMR_STRETCHDIBITS 81
119 #define EMR_EXTCREATEFONTINDIRECTW 82
120 #define EMR_EXTTEXTOUTA 83
121 #define EMR_EXTTEXTOUTW 84
122 #define EMR_POLYBEZIER16 85
123 #define EMR_POLYGON16 86
124 #define EMR_POLYLINE16 87
125 #define EMR_POLYBEZIERTO16 88
126 #define EMR_POLYLINETO16 89
127 #define EMR_POLYPOLYLINE16 90
128 #define EMR_POLYPOLYGON16 91
129 #define EMR_POLYDRAW16 92
130 #define EMR_CREATEMONOBRUSH 93
131 #define EMR_CREATEDIBPATTERNBRUSHPT 94
132 #define EMR_EXTCREATEPEN 95
133 #define EMR_POLYTEXTOUTA 96
134 #define EMR_POLYTEXTOUTW 97
136 // WINDOWS VERSION >= 0x400
137 #define EMR_SETICMMODE 98
138 #define EMR_CREATECOLORSPACE 99
139 #define EMR_SETCOLORSPACE 100
140 #define EMR_DELETECOLORSPACE 101
141 #define EMR_GLSRECORD 102
142 #define EMR_GLSBOUNDEDRECORD 103
143 #define EMR_PIXELFORMAT 104
145 // WINDOWS VERSION >= 0x500
146 #define EMR_DRAWESCAPE 105
147 #define EMR_EXTESCAPE 106
148 #define EMR_STARTDOC 107
149 #define EMR_SMALLTEXTOUT 108
150 #define EMR_FORCEUFIMAPPING 109
151 #define EMR_NAMEDESCAPE 110
152 #define EMR_COLORCORRECTPALETTE 111
153 #define EMR_SETICMPROFILEA 112
154 #define EMR_SETICMPROFILEW 113
155 #define EMR_ALPHABLEND 114
156 #define EMR_ALPHADIBBLEND 115
157 #define EMR_TRANSPARENTBLT 116
158 #define EMR_TRANSPARENTDIB 117
159 #define EMR_GRADIENTFILL 118
160 #define EMR_SETLINKEDUFIS 119
161 #define EMR_SETTEXTJUSTIFICATION 120
167 record_type_name(sal_uInt32 nRecType
)
175 case EMR_HEADER
: return "HEADER";
176 case EMR_POLYBEZIER
: return "POLYBEZIER";
177 case EMR_POLYGON
: return "POLYGON";
178 case EMR_POLYLINE
: return "POLYLINE";
179 case EMR_POLYBEZIERTO
: return "POLYBEZIERTO";
180 case EMR_POLYLINETO
: return "POLYLINETO";
181 case EMR_POLYPOLYLINE
: return "POLYPOLYLINE";
182 case EMR_POLYPOLYGON
: return "POLYPOLYGON";
183 case EMR_SETWINDOWEXTEX
: return "SETWINDOWEXTEX";
184 case EMR_SETWINDOWORGEX
: return "SETWINDOWORGEX";
185 case EMR_SETVIEWPORTEXTEX
: return "SETVIEWPORTEXTEX";
186 case EMR_SETVIEWPORTORGEX
: return "SETVIEWPORTORGEX";
187 case EMR_SETBRUSHORGEX
: return "SETBRUSHORGEX";
188 case EMR_EOF
: return "EOF";
189 case EMR_SETPIXELV
: return "SETPIXELV";
190 case EMR_SETMAPPERFLAGS
: return "SETMAPPERFLAGS";
191 case EMR_SETMAPMODE
: return "SETMAPMODE";
192 case EMR_SETBKMODE
: return "SETBKMODE";
193 case EMR_SETPOLYFILLMODE
: return "SETPOLYFILLMODE";
194 case EMR_SETROP2
: return "SETROP2";
195 case EMR_SETSTRETCHBLTMODE
: return "SETSTRETCHBLTMODE";
196 case EMR_SETTEXTALIGN
: return "SETTEXTALIGN";
197 case EMR_SETCOLORADJUSTMENT
: return "SETCOLORADJUSTMENT";
198 case EMR_SETTEXTCOLOR
: return "SETTEXTCOLOR";
199 case EMR_SETBKCOLOR
: return "SETBKCOLOR";
200 case EMR_OFFSETCLIPRGN
: return "OFFSETCLIPRGN";
201 case EMR_MOVETOEX
: return "MOVETOEX";
202 case EMR_SETMETARGN
: return "SETMETARGN";
203 case EMR_EXCLUDECLIPRECT
: return "EXCLUDECLIPRECT";
204 case EMR_INTERSECTCLIPRECT
: return "INTERSECTCLIPRECT";
205 case EMR_SCALEVIEWPORTEXTEX
: return "SCALEVIEWPORTEXTEX";
206 case EMR_SCALEWINDOWEXTEX
: return "SCALEWINDOWEXTEX";
207 case EMR_SAVEDC
: return "SAVEDC";
208 case EMR_RESTOREDC
: return "RESTOREDC";
209 case EMR_SETWORLDTRANSFORM
: return "SETWORLDTRANSFORM";
210 case EMR_MODIFYWORLDTRANSFORM
: return "MODIFYWORLDTRANSFORM";
211 case EMR_SELECTOBJECT
: return "SELECTOBJECT";
212 case EMR_CREATEPEN
: return "CREATEPEN";
213 case EMR_CREATEBRUSHINDIRECT
: return "CREATEBRUSHINDIRECT";
214 case EMR_DELETEOBJECT
: return "DELETEOBJECT";
215 case EMR_ANGLEARC
: return "ANGLEARC";
216 case EMR_ELLIPSE
: return "ELLIPSE";
217 case EMR_RECTANGLE
: return "RECTANGLE";
218 case EMR_ROUNDRECT
: return "ROUNDRECT";
219 case EMR_ARC
: return "ARC";
220 case EMR_CHORD
: return "CHORD";
221 case EMR_PIE
: return "PIE";
222 case EMR_SELECTPALETTE
: return "SELECTPALETTE";
223 case EMR_CREATEPALETTE
: return "CREATEPALETTE";
224 case EMR_SETPALETTEENTRIES
: return "SETPALETTEENTRIES";
225 case EMR_RESIZEPALETTE
: return "RESIZEPALETTE";
226 case EMR_REALIZEPALETTE
: return "REALIZEPALETTE";
227 case EMR_EXTFLOODFILL
: return "EXTFLOODFILL";
228 case EMR_LINETO
: return "LINETO";
229 case EMR_ARCTO
: return "ARCTO";
230 case EMR_POLYDRAW
: return "POLYDRAW";
231 case EMR_SETARCDIRECTION
: return "SETARCDIRECTION";
232 case EMR_SETMITERLIMIT
: return "SETMITERLIMIT";
233 case EMR_BEGINPATH
: return "BEGINPATH";
234 case EMR_ENDPATH
: return "ENDPATH";
235 case EMR_CLOSEFIGURE
: return "CLOSEFIGURE";
236 case EMR_FILLPATH
: return "FILLPATH";
237 case EMR_STROKEANDFILLPATH
: return "STROKEANDFILLPATH";
238 case EMR_STROKEPATH
: return "STROKEPATH";
239 case EMR_FLATTENPATH
: return "FLATTENPATH";
240 case EMR_WIDENPATH
: return "WIDENPATH";
241 case EMR_SELECTCLIPPATH
: return "SELECTCLIPPATH";
242 case EMR_ABORTPATH
: return "ABORTPATH";
243 case EMR_GDICOMMENT
: return "GDICOMMENT";
244 case EMR_FILLRGN
: return "FILLRGN";
245 case EMR_FRAMERGN
: return "FRAMERGN";
246 case EMR_INVERTRGN
: return "INVERTRGN";
247 case EMR_PAINTRGN
: return "PAINTRGN";
248 case EMR_EXTSELECTCLIPRGN
: return "EXTSELECTCLIPRGN";
249 case EMR_BITBLT
: return "BITBLT";
250 case EMR_STRETCHBLT
: return "STRETCHBLT";
251 case EMR_MASKBLT
: return "MASKBLT";
252 case EMR_PLGBLT
: return "PLGBLT";
253 case EMR_SETDIBITSTODEVICE
: return "SETDIBITSTODEVICE";
254 case EMR_STRETCHDIBITS
: return "STRETCHDIBITS";
255 case EMR_EXTCREATEFONTINDIRECTW
: return "EXTCREATEFONTINDIRECTW";
256 case EMR_EXTTEXTOUTA
: return "EXTTEXTOUTA";
257 case EMR_EXTTEXTOUTW
: return "EXTTEXTOUTW";
258 case EMR_POLYBEZIER16
: return "POLYBEZIER16";
259 case EMR_POLYGON16
: return "POLYGON16";
260 case EMR_POLYLINE16
: return "POLYLINE16";
261 case EMR_POLYBEZIERTO16
: return "POLYBEZIERTO16";
262 case EMR_POLYLINETO16
: return "POLYLINETO16";
263 case EMR_POLYPOLYLINE16
: return "POLYPOLYLINE16";
264 case EMR_POLYPOLYGON16
: return "POLYPOLYGON16";
265 case EMR_POLYDRAW16
: return "POLYDRAW16";
266 case EMR_CREATEMONOBRUSH
: return "CREATEMONOBRUSH";
267 case EMR_CREATEDIBPATTERNBRUSHPT
: return "CREATEDIBPATTERNBRUSHPT";
268 case EMR_EXTCREATEPEN
: return "EXTCREATEPEN";
269 case EMR_POLYTEXTOUTA
: return "POLYTEXTOUTA";
270 case EMR_POLYTEXTOUTW
: return "POLYTEXTOUTW";
271 case EMR_SETICMMODE
: return "SETICMMODE";
272 case EMR_CREATECOLORSPACE
: return "CREATECOLORSPACE";
273 case EMR_SETCOLORSPACE
: return "SETCOLORSPACE";
274 case EMR_DELETECOLORSPACE
: return "DELETECOLORSPACE";
275 case EMR_GLSRECORD
: return "GLSRECORD";
276 case EMR_GLSBOUNDEDRECORD
: return "GLSBOUNDEDRECORD";
277 case EMR_PIXELFORMAT
: return "PIXELFORMAT";
278 case EMR_DRAWESCAPE
: return "DRAWESCAPE";
279 case EMR_EXTESCAPE
: return "EXTESCAPE";
280 case EMR_STARTDOC
: return "STARTDOC";
281 case EMR_SMALLTEXTOUT
: return "SMALLTEXTOUT";
282 case EMR_FORCEUFIMAPPING
: return "FORCEUFIMAPPING";
283 case EMR_NAMEDESCAPE
: return "NAMEDESCAPE";
284 case EMR_COLORCORRECTPALETTE
: return "COLORCORRECTPALETTE";
285 case EMR_SETICMPROFILEA
: return "SETICMPROFILEA";
286 case EMR_SETICMPROFILEW
: return "SETICMPROFILEW";
287 case EMR_ALPHABLEND
: return "ALPHABLEND";
288 case EMR_ALPHADIBBLEND
: return "ALPHADIBBLEND";
289 case EMR_TRANSPARENTBLT
: return "TRANSPARENTBLT";
290 case EMR_TRANSPARENTDIB
: return "TRANSPARENTDIB";
291 case EMR_GRADIENTFILL
: return "GRADIENTFILL";
292 case EMR_SETLINKEDUFIS
: return "SETLINKEDUFIS";
293 case EMR_SETTEXTJUSTIFICATION
: return "SETTEXTJUSTIFICATION";
295 // Yes, return a pointer to a static buffer. This is a very
296 // local debugging output function, so no big deal.
297 static char buffer
[11];
298 sprintf(buffer
, "0x%08" SAL_PRIxUINT32
, nRecType
);
305 // little endian <-> big endian switch
306 static float GetSwapFloat(SvStream
& rStream
)
309 sal_Int8
* pPtr
= (sal_Int8
*)&fTmp
;
310 rStream
.ReadSChar(pPtr
[3]);
311 rStream
.ReadSChar(pPtr
[2]);
312 rStream
.ReadSChar(pPtr
[1]);
313 rStream
.ReadSChar(pPtr
[0]);
320 unsigned char aBlendOperation
;
321 unsigned char aBlendFlags
;
322 unsigned char aSrcConstantAlpha
;
323 unsigned char aAlphaFormat
;
325 friend SvStream
& operator>>(SvStream
& rInStream
, BLENDFUNCTION
& rBlendFun
);
328 SvStream
& operator>>(SvStream
& rInStream
, BLENDFUNCTION
& rBlendFun
)
330 rInStream
.ReadUChar(rBlendFun
.aBlendOperation
);
331 rInStream
.ReadUChar(rBlendFun
.aBlendFlags
);
332 rInStream
.ReadUChar(rBlendFun
.aSrcConstantAlpha
);
333 rInStream
.ReadUChar(rBlendFun
.aAlphaFormat
);
337 SvStream
& operator>>(SvStream
& rInStream
, XForm
& rXForm
)
339 if (sizeof(float) != 4)
341 OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
347 rXForm
.eM11
= GetSwapFloat(rInStream
);
348 rXForm
.eM12
= GetSwapFloat(rInStream
);
349 rXForm
.eM21
= GetSwapFloat(rInStream
);
350 rXForm
.eM22
= GetSwapFloat(rInStream
);
351 rXForm
.eDx
= GetSwapFloat(rInStream
);
352 rXForm
.eDy
= GetSwapFloat(rInStream
);
354 rInStream
.ReadFloat(rXForm
.eM11
);
355 rInStream
.ReadFloat(rXForm
.eM12
);
356 rInStream
.ReadFloat(rXForm
.eM21
);
357 rInStream
.ReadFloat(rXForm
.eM22
);
358 rInStream
.ReadFloat(rXForm
.eDx
);
359 rInStream
.ReadFloat(rXForm
.eDy
);
365 bool ImplReadRegion( tools::PolyPolygon
& rPolyPoly
, SvStream
& rStream
, sal_uInt32 nLen
)
370 sal_uInt32 nHdSize
, nType
, nCount
, nRgnSize
, i
;
371 rStream
.ReadUInt32(nHdSize
);
372 rStream
.ReadUInt32(nType
);
373 rStream
.ReadUInt32(nCount
);
374 rStream
.ReadUInt32(nRgnSize
);
377 && nType
== RDH_RECTANGLES
378 && nLen
>= ((nCount
<< 4) + (nHdSize
- 16)))
380 sal_Int32 nx1
, ny1
, nx2
, ny2
;
382 for (i
= 0; i
< nCount
; i
++)
384 rStream
.ReadInt32(nx1
);
385 rStream
.ReadInt32(ny1
);
386 rStream
.ReadInt32(nx2
);
387 rStream
.ReadInt32(ny2
);
389 Rectangle
aRectangle(Point(nx1
, ny1
), Point(nx2
, ny2
));
391 tools::Polygon
aPolygon(aRectangle
);
392 tools::PolyPolygon
aPolyPolyOr1(aPolygon
);
393 tools::PolyPolygon
aPolyPolyOr2(rPolyPoly
);
394 rPolyPoly
.GetUnion(aPolyPolyOr1
, aPolyPolyOr2
);
395 rPolyPoly
= aPolyPolyOr2
;
402 } // anonymous namespace
404 EnhWMFReader::EnhWMFReader(SvStream
& rStream
,GDIMetaFile
& rGDIMetaFile
,FilterConfigItem
* pConfigItem
)
405 : WinMtf(rGDIMetaFile
, rStream
, pConfigItem
)
411 EnhWMFReader::~EnhWMFReader()
414 void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length
, bool& bHaveDC
)
417 pOut
->PassEMFPlusHeaderInfo();
419 #if OSL_DEBUG_LEVEL > 1
420 // debug code - write the stream to debug file /tmp/emf-stream.emf
421 sal_uInt64
const pos
= pWMF
->Tell();
423 SvFileStream
file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE
| StreamMode::TRUNC
);
425 pWMF
->WriteStream(file
);
435 sal_uInt64
const pos
= pWMF
->Tell();
436 void *buffer
= malloc( length
);
437 pOut
->PassEMFPlus( buffer
, pWMF
->ReadBytes(buffer
, length
) );
443 // skip in SeekRel if impossibly unavailable
444 sal_uInt32 nRemainder
= length
;
446 const size_t nRequiredHeaderSize
= 12;
447 while (nRemainder
>= nRequiredHeaderSize
)
449 sal_uInt16
type(0), flags(0);
450 sal_uInt32
size(0), dataSize(0);
452 pWMF
->ReadUInt16( type
).ReadUInt16( flags
).ReadUInt32( size
).ReadUInt32( dataSize
);
453 nRemainder
-= nRequiredHeaderSize
;
455 SAL_INFO ("vcl.emf", "\t\tEMF+ record type: " << std::hex
<< type
<< std::dec
);
458 if( type
== 16388 ) {
460 SAL_INFO ("vcl.emf", "\t\tEMF+ lock DC (device context)");
463 // Get the length of the remaining data of this record based
464 // on the alleged size
465 sal_uInt32 nRemainingRecordData
= size
>= nRequiredHeaderSize
?
466 size
-nRequiredHeaderSize
: 0;
467 // clip to available size
468 nRemainingRecordData
= std::min(nRemainingRecordData
, nRemainder
);
469 pWMF
->SeekRel(nRemainingRecordData
);
470 nRemainder
-= nRemainingRecordData
;
472 pWMF
->SeekRel(nRemainder
);
476 * Reads polygons from the stream.
477 * The \<class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
478 * The \<class Drawer> parameter is a c++11 lambda for the method that will draw the polygon.
479 * skipFirst: if the first point read is the 0th point or the 1st point in the array.
481 template <class T
, class Drawer
>
482 void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer
, const bool skipFirst
)
484 sal_uInt32
nPoints(0), nStartIndex(0);
486 pWMF
->ReadUInt32( nPoints
);
493 tools::Polygon aPolygon
= ReadPolygon
<T
>(nStartIndex
, nPoints
);
494 drawer(pOut
, aPolygon
, skipFirst
, bRecordPath
);
498 * Reads polygons from the stream.
499 * The \<class T> parameter is for the type of the points
500 * nStartIndex: which is the starting index in the polygon of the first point read
501 * nPoints: number of points
502 * pWMF: the stream containing the polygons
505 tools::Polygon
EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex
, sal_uInt32 nPoints
)
507 bool bRecordOk
= nPoints
<= SAL_MAX_UINT16
;
508 SAL_WARN_IF(!bRecordOk
, "vcl.filter", "polygon record has more polygons than we can handle");
510 return tools::Polygon();
512 tools::Polygon
aPolygon(nPoints
);
513 for (sal_uInt16 i
= nStartIndex
; i
< nPoints
&& pWMF
->good(); i
++ )
519 aPolygon
[ i
] = Point( nX
, nY
);
526 * Reads a polyline from the WMF file and draws it
527 * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
530 void EnhWMFReader::ReadAndDrawPolyLine()
533 sal_Int32 i
, nPoly(0), nGesPoints(0);
534 pWMF
->SeekRel( 0x10 );
535 // Number of Polygons:
536 pWMF
->ReadInt32( nPoly
).ReadInt32( nGesPoints
);
538 // taking the amount of points of each polygon, retrieving the total number of points
540 ( static_cast< sal_uInt32
>(nPoly
) < SAL_MAX_UINT32
/ sizeof(sal_uInt16
) ) &&
541 ( static_cast< sal_uInt32
>( nPoly
) * sizeof(sal_uInt16
) ) <= ( nEndPos
- pWMF
->Tell() )
544 std::unique_ptr
<sal_uInt16
[]> pnPoints(new sal_uInt16
[ nPoly
]);
545 for ( i
= 0; i
< nPoly
&& pWMF
->good(); i
++ )
547 pWMF
->ReadUInt32( nPoints
);
548 pnPoints
[ i
] = (sal_uInt16
)nPoints
;
550 // Get polygon points:
551 for ( i
= 0; ( i
< nPoly
) && pWMF
->good(); i
++ )
553 tools::Polygon aPolygon
= ReadPolygon
<T
>(0, pnPoints
[i
]);
554 pOut
->DrawPolyLine( aPolygon
, false, bRecordPath
);
559 // these are referenced from inside the templates
561 SvStream
& operator>>(SvStream
& rStream
, sal_Int16
&n
)
563 return rStream
.ReadInt16(n
);
566 SvStream
& operator>>(SvStream
& rStream
, sal_Int32
&n
)
568 return rStream
.ReadInt32(n
);
572 * Reads a poly polygon from the WMF file and draws it.
573 * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
576 void EnhWMFReader::ReadAndDrawPolyPolygon()
578 sal_uInt32
nPoly(0), nGesPoints(0), nReadPoints(0);
579 pWMF
->SeekRel( 0x10 );
580 // Number of polygons
581 pWMF
->ReadUInt32( nPoly
).ReadUInt32( nGesPoints
);
583 ( nGesPoints
< SAL_MAX_UINT32
/ sizeof(Point
) ) && //check against numeric overflowing
584 ( nPoly
< SAL_MAX_UINT32
/ sizeof(sal_uInt16
) ) &&
585 ( ( nPoly
* sizeof( sal_uInt16
) ) <= ( nEndPos
- pWMF
->Tell() ) ))
587 // Get number of points in each polygon
588 std::unique_ptr
<sal_uInt16
[]> pnPoints(new sal_uInt16
[ nPoly
]);
589 for (sal_uInt32 i
= 0; i
< nPoly
&& pWMF
->good(); ++i
)
591 sal_uInt32
nPoints(0);
592 pWMF
->ReadUInt32( nPoints
);
593 pnPoints
[ i
] = (sal_uInt16
)nPoints
;
595 if ( pWMF
->good() && ( nGesPoints
* (sizeof(T
)+sizeof(T
)) ) <= ( nEndPos
- pWMF
->Tell() ) )
597 // Get polygon points
598 tools::PolyPolygon
aPolyPoly(nPoly
, nPoly
);
599 for (sal_uInt32 i
= 0; i
< nPoly
&& pWMF
->good(); ++i
)
601 const sal_uInt16
nPointCount(pnPoints
[i
]);
602 std::unique_ptr
<Point
[]> pPtAry(new Point
[nPointCount
]);
603 for (sal_uInt16 j
= 0; j
< nPointCount
&& pWMF
->good(); ++j
)
607 pPtAry
[ j
] = Point( nX
, nY
);
611 aPolyPoly
.Insert( tools::Polygon(nPointCount
, pPtAry
.get()) );
614 pOut
->DrawPolyPolygon( aPolyPoly
, bRecordPath
);
617 OSL_ENSURE(nReadPoints
== nGesPoints
, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
622 bool EnhWMFReader::ReadEnhWMF()
624 sal_uInt32 nStretchBltMode
= 0;
625 sal_uInt32
nNextPos(0),
626 nW(0), nH(0), nColor(0), nIndex(0),
627 nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
628 sal_Int32
nX32(0), nY32(0), nx32(0), ny32(0);
630 bool bStatus
= ReadHeader();
631 bool bHaveDC
= false;
633 static bool bEnableEMFPlus
= ( getenv( "EMF_PLUS_DISABLE" ) == nullptr );
635 while( bStatus
&& nRecordCount
-- && pWMF
->good())
637 sal_uInt32
nRecType(0), nRecSize(0);
638 pWMF
->ReadUInt32(nRecType
).ReadUInt32(nRecSize
);
640 if ( !pWMF
->good() || ( nRecSize
< 8 ) || ( nRecSize
& 3 ) ) // Parameters are always divisible by 4
646 auto nCurPos
= pWMF
->Tell();
648 if (nEndPos
< nCurPos
- 8)
654 const sal_uInt32 nMaxPossibleRecSize
= nEndPos
- (nCurPos
- 8);
655 if (nRecSize
> nMaxPossibleRecSize
)
661 nNextPos
= nCurPos
+ (nRecSize
- 8);
663 if( !aBmpSaveList
.empty()
664 && ( nRecType
!= EMR_STRETCHBLT
)
665 && ( nRecType
!= EMR_STRETCHDIBITS
)
667 pOut
->ResolveBitmapActions( aBmpSaveList
);
672 SAL_INFO ("vcl.emf", "0x" << std::hex
<< (nNextPos
- nRecSize
) << "-0x" << nNextPos
<< " " << record_type_name(nRecType
) << " size: " << nRecSize
<< std::dec
);
674 if( bEnableEMFPlus
&& nRecType
== EMR_GDICOMMENT
) {
677 pWMF
->ReadUInt32( length
);
679 SAL_INFO("vcl.emf", "\tGDI comment, length: " << length
);
681 if( pWMF
->good() && length
>= 4 && length
<= pWMF
->remainingSize() ) {
684 pWMF
->ReadUInt32( id
);
686 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
);
688 // EMF+ comment (FIXME: BE?)
689 if( id
== 0x2B464D45 && nRecSize
>= 12 )
690 // [MS-EMF] 2.3.3: DataSize includes both CommentIdentifier and CommentRecordParm fields.
691 // We have already read 4-byte CommentIdentifier, so reduce length appropriately
692 ReadEMFPlusComment( length
-4, bHaveDC
);
693 // GDIC comment, doesn't do anything useful yet
694 else if( id
== 0x43494447 && nRecSize
>= 12 ) {
695 // TODO: ReadGDIComment()
697 SAL_INFO ("vcl.emf", "\t\tunknown id: 0x" << std::hex
<< id
<< std::dec
);
701 else if( !bEMFPlus
|| bHaveDC
|| nRecType
== EMR_EOF
)
705 case EMR_POLYBEZIERTO
:
706 ReadAndDrawPolygon
<sal_Int32
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
707 { pWinMtfOutput
->DrawPolyBezier( rPolygon
, aTo
, aRecordPath
); }, true );
709 case EMR_POLYBEZIER
:
710 ReadAndDrawPolygon
<sal_Int32
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
711 { pWinMtfOutput
->DrawPolyBezier( rPolygon
, aTo
, aRecordPath
); }, false );
715 ReadAndDrawPolygon
<sal_Int32
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
716 { pWinMtfOutput
->DrawPolygon( rPolygon
, aTo
, aRecordPath
); }, false );
719 case EMR_POLYLINETO
:
720 ReadAndDrawPolygon
<sal_Int32
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
721 { pWinMtfOutput
->DrawPolyLine( rPolygon
, aTo
, aRecordPath
); }, true );
725 ReadAndDrawPolygon
<sal_Int32
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
726 { pWinMtfOutput
->DrawPolyLine( rPolygon
, aTo
, aRecordPath
); }, false );
729 case EMR_POLYPOLYLINE
:
730 ReadAndDrawPolyLine
<sal_Int32
>();
733 case EMR_POLYPOLYGON
:
734 ReadAndDrawPolyPolygon
<sal_Int32
>();
737 case EMR_SETWINDOWEXTEX
:
739 pWMF
->ReadUInt32( nW
).ReadUInt32( nH
);
740 pOut
->SetWinExt( Size( nW
, nH
), true);
744 case EMR_SETWINDOWORGEX
:
746 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
747 pOut
->SetWinOrg( Point( nX32
, nY32
), true);
751 case EMR_SCALEWINDOWEXTEX
:
753 pWMF
->ReadUInt32( nNom1
).ReadUInt32( nDen1
).ReadUInt32( nNom2
).ReadUInt32( nDen2
);
754 pOut
->ScaleWinExt( (double)nNom1
/ nDen1
, (double)nNom2
/ nDen2
);
758 case EMR_SETVIEWPORTORGEX
:
760 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
761 pOut
->SetDevOrg( Point( nX32
, nY32
) );
765 case EMR_SCALEVIEWPORTEXTEX
:
767 pWMF
->ReadUInt32( nNom1
).ReadUInt32( nDen1
).ReadUInt32( nNom2
).ReadUInt32( nDen2
);
768 pOut
->ScaleDevExt( (double)nNom1
/ nDen1
, (double)nNom2
/ nDen2
);
772 case EMR_SETVIEWPORTEXTEX
:
774 pWMF
->ReadUInt32( nW
).ReadUInt32( nH
);
775 pOut
->SetDevExt( Size( nW
, nH
) );
785 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
786 pOut
->DrawPixel( Point( nX32
, nY32
), ReadColor() );
790 case EMR_SETMAPMODE
:
793 pWMF
->ReadUInt32( nMapMode
);
794 pOut
->SetMapMode( nMapMode
);
800 pWMF
->ReadUInt32( nDat32
);
801 pOut
->SetBkMode( static_cast<BkMode
>(nDat32
) );
805 case EMR_SETPOLYFILLMODE
:
810 pWMF
->ReadUInt32( nDat32
);
811 pOut
->SetRasterOp( (WMFRasterOp
)nDat32
);
815 case EMR_SETSTRETCHBLTMODE
:
817 pWMF
->ReadUInt32( nStretchBltMode
);
821 case EMR_SETTEXTALIGN
:
823 pWMF
->ReadUInt32( nDat32
);
824 pOut
->SetTextAlign( nDat32
);
828 case EMR_SETTEXTCOLOR
:
830 pOut
->SetTextColor( ReadColor() );
834 case EMR_SETBKCOLOR
:
836 pOut
->SetBkColor( ReadColor() );
840 case EMR_OFFSETCLIPRGN
:
842 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
843 pOut
->MoveClipRegion( Size( nX32
, nY32
) );
849 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
850 pOut
->MoveTo( Point( nX32
, nY32
), bRecordPath
);
854 case EMR_INTERSECTCLIPRECT
:
856 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
857 pOut
->IntersectClipRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
873 case EMR_SETWORLDTRANSFORM
:
877 pOut
->SetWorldTransform( aTempXForm
);
881 case EMR_MODIFYWORLDTRANSFORM
:
886 pWMF
->ReadUInt32( nMode
);
887 pOut
->ModifyWorldTransform( aTempXForm
, nMode
);
891 case EMR_SELECTOBJECT
:
893 pWMF
->ReadUInt32( nIndex
);
894 pOut
->SelectObject( nIndex
);
900 pWMF
->ReadUInt32( nIndex
);
901 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
907 // #fdo39428 Remove SvStream operator>>(long&)
908 sal_Int32
nTmpW(0), nTmpH(0);
910 pWMF
->ReadUInt32( nStyle
).ReadInt32( nTmpW
).ReadInt32( nTmpH
);
911 aSize
.Width() = nTmpW
;
912 aSize
.Height() = nTmpH
;
915 aLineInfo
.SetWidth( aSize
.Width() );
917 bool bTransparent
= false;
918 switch( nStyle
& PS_STYLE_MASK
)
921 aLineInfo
.SetStyle( LineStyle::Dash
);
922 aLineInfo
.SetDashCount( 1 );
923 aLineInfo
.SetDotCount( 2 );
926 aLineInfo
.SetStyle( LineStyle::Dash
);
927 aLineInfo
.SetDashCount( 1 );
928 aLineInfo
.SetDotCount( 1 );
931 aLineInfo
.SetStyle( LineStyle::Dash
);
932 aLineInfo
.SetDashCount( 0 );
933 aLineInfo
.SetDotCount( 1 );
936 aLineInfo
.SetStyle( LineStyle::Dash
);
937 aLineInfo
.SetDashCount( 1 );
938 aLineInfo
.SetDotCount( 0 );
942 aLineInfo
.SetStyle( LineStyle::NONE
);
944 case PS_INSIDEFRAME
:
947 aLineInfo
.SetStyle( LineStyle::Solid
);
949 switch( nStyle
& PS_ENDCAP_STYLE_MASK
)
951 case PS_ENDCAP_ROUND
:
954 aLineInfo
.SetLineCap( css::drawing::LineCap_ROUND
);
958 case PS_ENDCAP_SQUARE
:
961 aLineInfo
.SetLineCap( css::drawing::LineCap_SQUARE
);
965 case PS_ENDCAP_FLAT
:
967 aLineInfo
.SetLineCap( css::drawing::LineCap_BUTT
);
969 switch( nStyle
& PS_JOIN_STYLE_MASK
)
972 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Round
);
975 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Miter
);
978 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Bevel
);
981 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::NONE
);
983 pOut
->CreateObjectIndexed(nIndex
, o3tl::make_unique
<WinMtfLineStyle
>( ReadColor(), aLineInfo
, bTransparent
));
988 case EMR_EXTCREATEPEN
:
991 sal_uInt32 offBmi
, cbBmi
, offBits
, cbBits
, nStyle
, nWidth
, nBrushStyle
, elpNumEntries
;
994 pWMF
->ReadUInt32( nIndex
);
995 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
997 pWMF
->ReadUInt32( offBmi
).ReadUInt32( cbBmi
).ReadUInt32( offBits
).ReadUInt32( cbBits
). ReadUInt32( nStyle
).ReadUInt32( nWidth
).ReadUInt32( nBrushStyle
);
998 aColorRef
= ReadColor();
999 pWMF
->ReadInt32( elpHatch
).ReadUInt32( elpNumEntries
);
1003 aLineInfo
.SetWidth( nWidth
);
1005 bool bTransparent
= false;
1007 switch( nStyle
& PS_STYLE_MASK
)
1009 case PS_DASHDOTDOT
:
1010 aLineInfo
.SetStyle( LineStyle::Dash
);
1011 aLineInfo
.SetDashCount( 1 );
1012 aLineInfo
.SetDotCount( 2 );
1015 aLineInfo
.SetStyle( LineStyle::Dash
);
1016 aLineInfo
.SetDashCount( 1 );
1017 aLineInfo
.SetDotCount( 1 );
1020 aLineInfo
.SetStyle( LineStyle::Dash
);
1021 aLineInfo
.SetDashCount( 0 );
1022 aLineInfo
.SetDotCount( 1 );
1025 aLineInfo
.SetStyle( LineStyle::Dash
);
1026 aLineInfo
.SetDashCount( 1 );
1027 aLineInfo
.SetDotCount( 0 );
1030 bTransparent
= true;
1031 aLineInfo
.SetStyle( LineStyle::NONE
);
1034 case PS_INSIDEFRAME
:
1037 aLineInfo
.SetStyle( LineStyle::Solid
);
1039 switch( nStyle
& PS_ENDCAP_STYLE_MASK
)
1041 case PS_ENDCAP_ROUND
:
1042 if ( aLineInfo
.GetWidth() )
1044 aLineInfo
.SetLineCap( css::drawing::LineCap_ROUND
);
1048 case PS_ENDCAP_SQUARE
:
1049 if ( aLineInfo
.GetWidth() )
1051 aLineInfo
.SetLineCap( css::drawing::LineCap_SQUARE
);
1055 case PS_ENDCAP_FLAT
:
1057 aLineInfo
.SetLineCap( css::drawing::LineCap_BUTT
);
1059 switch( nStyle
& PS_JOIN_STYLE_MASK
)
1061 case PS_JOIN_ROUND
:
1062 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Round
);
1064 case PS_JOIN_MITER
:
1065 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Miter
);
1067 case PS_JOIN_BEVEL
:
1068 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::Bevel
);
1071 aLineInfo
.SetLineJoin ( basegfx::B2DLineJoin::NONE
);
1073 pOut
->CreateObjectIndexed(nIndex
, o3tl::make_unique
<WinMtfLineStyle
>( aColorRef
, aLineInfo
, bTransparent
));
1078 case EMR_CREATEBRUSHINDIRECT
:
1081 pWMF
->ReadUInt32( nIndex
);
1082 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1084 pWMF
->ReadUInt32( nStyle
);
1085 pOut
->CreateObjectIndexed(nIndex
, o3tl::make_unique
<WinMtfFillStyle
>( ReadColor(), ( nStyle
== BS_HOLLOW
) ));
1090 case EMR_DELETEOBJECT
:
1092 pWMF
->ReadUInt32( nIndex
);
1093 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1094 pOut
->DeleteObject( nIndex
);
1100 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
1101 pOut
->DrawEllipse( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
1105 case EMR_RECTANGLE
:
1107 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
);
1108 pOut
->DrawRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
) );
1112 case EMR_ROUNDRECT
:
1114 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nW
).ReadUInt32( nH
);
1115 Size
aSize( Size( nW
, nH
) );
1116 pOut
->DrawRoundRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
), aSize
);
1122 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1123 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1124 pOut
->DrawArc( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1130 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1131 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1132 pOut
->DrawChord( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1138 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1139 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1140 const Rectangle
aRect( ReadRectangle( nX32
, nY32
, nx32
, ny32
));
1142 // #i73608# OutputDevice deviates from WMF
1143 // semantics. start==end means full ellipse here.
1144 if( nStartX
== nEndX
&& nStartY
== nEndY
)
1145 pOut
->DrawEllipse( aRect
);
1147 pOut
->DrawPie( aRect
, Point( nStartX
, nStartY
), Point( nEndX
, nEndY
) );
1153 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
);
1154 pOut
->LineTo( Point( nX32
, nY32
), bRecordPath
);
1160 sal_uInt32 nStartX
, nStartY
, nEndX
, nEndY
;
1161 pWMF
->ReadInt32( nX32
).ReadInt32( nY32
).ReadInt32( nx32
).ReadInt32( ny32
).ReadUInt32( nStartX
).ReadUInt32( nStartY
).ReadUInt32( nEndX
).ReadUInt32( nEndY
);
1162 pOut
->DrawArc( ReadRectangle( nX32
, nY32
, nx32
, ny32
), Point( nStartX
, nStartY
), Point( nEndX
, nEndY
), true );
1166 case EMR_BEGINPATH
:
1173 case EMR_ABORTPATH
:
1177 bRecordPath
= false;
1180 case EMR_CLOSEFIGURE
:
1185 pOut
->StrokeAndFillPath( false, true );
1188 case EMR_STROKEANDFILLPATH
:
1189 pOut
->StrokeAndFillPath( true, true );
1192 case EMR_STROKEPATH
:
1193 pOut
->StrokeAndFillPath( true, false );
1196 case EMR_SELECTCLIPPATH
:
1198 sal_Int32 nClippingMode
;
1199 pWMF
->ReadInt32(nClippingMode
);
1200 pOut
->SetClipPath(pOut
->GetPathObj(), nClippingMode
, true);
1204 case EMR_EXTSELECTCLIPRGN
:
1206 sal_Int32 nClippingMode
, cbRgnData
;
1207 pWMF
->ReadInt32(cbRgnData
);
1208 pWMF
->ReadInt32(nClippingMode
);
1210 // This record's region data should be ignored if mode
1211 // is RGN_COPY - see EMF spec section 2.3.2.2
1212 if (nClippingMode
== RGN_COPY
)
1214 pOut
->SetDefaultClipPath();
1218 tools::PolyPolygon aPolyPoly
;
1220 ImplReadRegion(aPolyPoly
, *pWMF
, nRecSize
);
1221 pOut
->SetClipPath(aPolyPoly
, nClippingMode
, false);
1227 case EMR_ALPHABLEND
:
1229 sal_Int32
xDest(0), yDest(0), cxDest(0), cyDest(0);
1231 BLENDFUNCTION aFunc
;
1232 sal_Int32
xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
1234 sal_uInt32
BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
1235 sal_uInt32
cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
1237 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1238 pWMF
->SeekRel( 0x10 );
1240 pWMF
->ReadInt32( xDest
).ReadInt32( yDest
).ReadInt32( cxDest
).ReadInt32( cyDest
);
1242 pWMF
->ReadInt32( xSrc
).ReadInt32( ySrc
);
1244 pWMF
->ReadUInt32( BkColorSrc
).ReadUInt32( iUsageSrc
).ReadUInt32( offBmiSrc
).ReadUInt32( cbBmiSrc
)
1245 .ReadUInt32( offBitsSrc
).ReadUInt32( cbBitsSrc
).ReadInt32( cxSrc
).ReadInt32( cySrc
) ;
1247 sal_uInt32 dwRop
= SRCAND
|SRCINVERT
;
1248 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
+1, cyDest
+1 ) );
1250 if ( (cbBitsSrc
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
) )
1254 const sal_uInt32 nSourceSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1255 bool bSafeRead
= nSourceSize
<= (nEndPos
- nStartPos
);
1256 sal_uInt32
nDeltaToDIB5HeaderSize(0);
1257 const bool bReadAlpha(0x01 == aFunc
.aAlphaFormat
);
1258 if (bSafeRead
&& bReadAlpha
)
1260 // we need to read alpha channel data if AlphaFormat of BLENDFUNCTION is
1261 // AC_SRC_ALPHA (==0x01). To read it, create a temp DIB-File which is ready
1263 const sal_uInt32 nHeaderSize
= getDIBV5HeaderSize();
1264 if (cbBmiSrc
> nHeaderSize
)
1267 nDeltaToDIB5HeaderSize
= nHeaderSize
- cbBmiSrc
;
1271 const sal_uInt32
nTargetSize(cbBmiSrc
+ nDeltaToDIB5HeaderSize
+ cbBitsSrc
+ 14);
1272 char* pBuf
= new char[ nTargetSize
];
1273 SvMemoryStream
aTmp( pBuf
, nTargetSize
, StreamMode::READ
| StreamMode::WRITE
);
1275 aTmp
.ObjectOwnsMemory( true );
1277 // write BM-Header (14 bytes)
1278 aTmp
.WriteUChar( 'B' )
1280 .WriteUInt32( cbBitsSrc
)
1283 .WriteUInt32( cbBmiSrc
+ nDeltaToDIB5HeaderSize
+ 14 );
1285 // copy DIBInfoHeader from source (cbBmiSrc bytes)
1286 pWMF
->Seek( nStart
+ offBmiSrc
);
1287 pWMF
->ReadBytes(pBuf
+ 14, cbBmiSrc
);
1291 // need to add values for all stuff that DIBV5Header is bigger
1292 // than DIBInfoHeader, all values are correctly initialized to zero,
1293 // so we can use memset here
1294 memset(pBuf
+ cbBmiSrc
+ 14, 0, nDeltaToDIB5HeaderSize
);
1297 // copy bitmap data from source (offBitsSrc bytes)
1298 pWMF
->Seek( nStart
+ offBitsSrc
);
1299 pWMF
->ReadBytes(pBuf
+ 14 + nDeltaToDIB5HeaderSize
+ cbBmiSrc
, cbBitsSrc
);
1302 // prepare to read and fill BitmapEx
1310 if(ReadDIBV5(aBitmap
, aAlpha
, aTmp
))
1312 aBitmapEx
= BitmapEx(aBitmap
, aAlpha
);
1319 if(ReadDIB(aBitmap
, aTmp
, true))
1321 if(0xff != aFunc
.aSrcConstantAlpha
)
1323 // add const alpha channel
1324 aBitmapEx
= BitmapEx(
1326 AlphaMask(aBitmap
.GetSizePixel(), &aFunc
.aSrcConstantAlpha
));
1331 aBitmapEx
= BitmapEx(aBitmap
);
1336 if(!aBitmapEx
.IsEmpty())
1338 // test if it is sensible to crop
1339 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1340 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1341 ( xSrc
+ cxSrc
< aBitmapEx
.GetSizePixel().Width() ) &&
1342 ( ySrc
+ cySrc
< aBitmapEx
.GetSizePixel().Height() ) )
1344 const Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1346 aBitmapEx
.Crop( aCropRect
);
1350 static bool bDoSaveForVisualControl(false);
1352 if(bDoSaveForVisualControl
)
1354 SvFileStream
aNew(OUString("c:\\metafile_content.png"), StreamMode::WRITE
|StreamMode::TRUNC
);
1355 vcl::PNGWriter
aPNGWriter(aBitmapEx
);
1356 aPNGWriter
.Write(aNew
);
1359 aBmpSaveList
.emplace_back(new BSaveStruct(aBitmapEx
, aRect
, dwRop
));
1366 case EMR_BITBLT
: // PASSTHROUGH INTENDED
1367 case EMR_STRETCHBLT
:
1369 sal_Int32 xDest
, yDest
, cxDest
, cyDest
, xSrc
, ySrc
, cxSrc
, cySrc
;
1370 sal_uInt32 dwRop
, iUsageSrc
, offBmiSrc
, cbBmiSrc
, offBitsSrc
, cbBitsSrc
;
1373 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1375 pWMF
->SeekRel( 0x10 );
1376 pWMF
->ReadInt32( xDest
).ReadInt32( yDest
).ReadInt32( cxDest
).ReadInt32( cyDest
).ReadUInt32( dwRop
).ReadInt32( xSrc
).ReadInt32( ySrc
)
1378 pWMF
->ReadUInt32( nColor
).ReadUInt32( iUsageSrc
).ReadUInt32( offBmiSrc
).ReadUInt32( cbBmiSrc
)
1379 .ReadUInt32( offBitsSrc
).ReadUInt32( cbBitsSrc
);
1381 if ( nRecType
== EMR_STRETCHBLT
)
1382 pWMF
->ReadInt32( cxSrc
).ReadInt32( cySrc
);
1387 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
, cyDest
) );
1389 if ( (cbBitsSrc
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
) )
1393 sal_uInt32 nSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1394 if ( nSize
<= ( nEndPos
- nStartPos
) )
1396 char* pBuf
= new char[ nSize
];
1397 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1398 aTmp
.ObjectOwnsMemory( true );
1399 aTmp
.WriteUChar( 'B' )
1401 .WriteUInt32( cbBitsSrc
)
1404 .WriteUInt32( cbBmiSrc
+ 14 );
1405 pWMF
->Seek( nStart
+ offBmiSrc
);
1406 pWMF
->ReadBytes(pBuf
+ 14, cbBmiSrc
);
1407 pWMF
->Seek( nStart
+ offBitsSrc
);
1408 pWMF
->ReadBytes(pBuf
+ 14 + cbBmiSrc
, cbBitsSrc
);
1410 ReadDIB(aBitmap
, aTmp
, true);
1412 // test if it is sensible to crop
1413 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1414 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1415 ( xSrc
+ cxSrc
<= aBitmap
.GetSizePixel().Width() ) &&
1416 ( ySrc
+ cySrc
<= aBitmap
.GetSizePixel().Height() ) )
1418 Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1419 aBitmap
.Crop( aCropRect
);
1421 aBmpSaveList
.emplace_back(new BSaveStruct(aBitmap
, aRect
, dwRop
));
1427 case EMR_STRETCHDIBITS
:
1429 sal_Int32 xDest
, yDest
, xSrc
, ySrc
, cxSrc
, cySrc
, cxDest
, cyDest
;
1430 sal_uInt32 offBmiSrc
, cbBmiSrc
, offBitsSrc
, cbBitsSrc
, iUsageSrc
, dwRop
;
1431 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1433 pWMF
->SeekRel( 0x10 );
1434 pWMF
->ReadInt32( xDest
)
1440 .ReadUInt32( offBmiSrc
)
1441 .ReadUInt32( cbBmiSrc
)
1442 .ReadUInt32( offBitsSrc
)
1443 .ReadUInt32( cbBitsSrc
)
1444 .ReadUInt32( iUsageSrc
)
1445 .ReadUInt32( dwRop
)
1446 .ReadInt32( cxDest
)
1447 .ReadInt32( cyDest
);
1450 Rectangle
aRect( Point( xDest
, yDest
), Size( cxDest
, cyDest
) );
1452 if ( ((SAL_MAX_UINT32
- 14) < cbBitsSrc
)
1453 || ((SAL_MAX_UINT32
- 14) - cbBitsSrc
< cbBmiSrc
)
1460 sal_uInt32 nSize
= cbBmiSrc
+ cbBitsSrc
+ 14;
1461 if ( nSize
<= ( nEndPos
- nStartPos
) )
1463 char* pBuf
= new char[ nSize
];
1464 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1465 aTmp
.ObjectOwnsMemory( true );
1466 aTmp
.WriteUChar( 'B' )
1468 .WriteUInt32( cbBitsSrc
)
1471 .WriteUInt32( cbBmiSrc
+ 14 );
1472 pWMF
->Seek( nStart
+ offBmiSrc
);
1473 pWMF
->ReadBytes(pBuf
+ 14, cbBmiSrc
);
1474 pWMF
->Seek( nStart
+ offBitsSrc
);
1475 pWMF
->ReadBytes(pBuf
+ 14 + cbBmiSrc
, cbBitsSrc
);
1477 ReadDIB(aBitmap
, aTmp
, true);
1479 // test if it is sensible to crop
1480 if ( ( cxSrc
> 0 ) && ( cySrc
> 0 ) &&
1481 ( xSrc
>= 0 ) && ( ySrc
>= 0 ) &&
1482 ( xSrc
+ cxSrc
<= aBitmap
.GetSizePixel().Width() ) &&
1483 ( ySrc
+ cySrc
<= aBitmap
.GetSizePixel().Height() ) )
1485 Rectangle
aCropRect( Point( xSrc
, ySrc
), Size( cxSrc
, cySrc
) );
1486 aBitmap
.Crop( aCropRect
);
1488 aBmpSaveList
.emplace_back(new BSaveStruct(aBitmap
, aRect
, dwRop
));
1494 case EMR_EXTCREATEFONTINDIRECTW
:
1496 pWMF
->ReadUInt32( nIndex
);
1497 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1500 pWMF
->ReadInt32( aLogFont
.lfHeight
)
1501 .ReadInt32( aLogFont
.lfWidth
)
1502 .ReadInt32( aLogFont
.lfEscapement
)
1503 .ReadInt32( aLogFont
.lfOrientation
)
1504 .ReadInt32( aLogFont
.lfWeight
)
1505 .ReadUChar( aLogFont
.lfItalic
)
1506 .ReadUChar( aLogFont
.lfUnderline
)
1507 .ReadUChar( aLogFont
.lfStrikeOut
)
1508 .ReadUChar( aLogFont
.lfCharSet
)
1509 .ReadUChar( aLogFont
.lfOutPrecision
)
1510 .ReadUChar( aLogFont
.lfClipPrecision
)
1511 .ReadUChar( aLogFont
.lfQuality
)
1512 .ReadUChar( aLogFont
.lfPitchAndFamily
);
1514 sal_Unicode lfFaceName
[LF_FACESIZE
+1];
1515 lfFaceName
[LF_FACESIZE
] = 0;
1516 for (int i
= 0; i
< LF_FACESIZE
; ++i
)
1518 sal_uInt16
nChar(0);
1519 pWMF
->ReadUInt16(nChar
);
1520 lfFaceName
[i
] = nChar
;
1522 aLogFont
.alfFaceName
= OUString( lfFaceName
);
1524 // #i123216# Not used in the test case of #121382# (always identity in XForm), also
1525 // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1526 // from #i123216# creates errors, so removing.
1528 // // #i121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1529 // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1530 // // constraints and dangers
1531 // const XForm& rXF = pOut->GetWorldTransform();
1532 // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1533 // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1534 // aLogFont.lfWidth = aTransVec.getX();
1535 // aLogFont.lfHeight = aTransVec.getY();
1537 pOut
->CreateObjectIndexed(nIndex
, o3tl::make_unique
<WinMtfFontStyle
>( aLogFont
));
1542 case EMR_EXTTEXTOUTA
:
1545 case EMR_EXTTEXTOUTW
:
1547 sal_Int32 nLeft
, nTop
, nRight
, nBottom
, ptlReferenceX
, ptlReferenceY
, nGfxMode
, nXScale
, nYScale
;
1548 sal_uInt32 nOffString
, nOptions
, offDx
;
1550 std::vector
<long> aDX
;
1552 nCurPos
= pWMF
->Tell() - 8;
1554 pWMF
->ReadInt32( nLeft
).ReadInt32( nTop
).ReadInt32( nRight
).ReadInt32( nBottom
).ReadInt32( nGfxMode
).ReadInt32( nXScale
).ReadInt32( nYScale
)
1555 .ReadInt32( ptlReferenceX
).ReadInt32( ptlReferenceY
).ReadInt32( nLen
).ReadUInt32( nOffString
).ReadUInt32( nOptions
);
1557 pWMF
->SeekRel( 0x10 );
1558 pWMF
->ReadUInt32( offDx
);
1560 ComplexTextLayoutFlags nTextLayoutMode
= ComplexTextLayoutFlags::Default
;
1561 if ( nOptions
& ETO_RTLREADING
)
1562 nTextLayoutMode
= ComplexTextLayoutFlags::BiDiRtl
| ComplexTextLayoutFlags::TextOriginLeft
;
1563 pOut
->SetTextLayoutMode( nTextLayoutMode
);
1564 SAL_WARN_IF( ( nOptions
& ( ETO_PDY
| ETO_GLYPH_INDEX
) ) != 0, "vcl", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1566 Point
aPos( ptlReferenceX
, ptlReferenceY
);
1567 bool bLenSane
= nLen
> 0 && nLen
< static_cast<sal_Int32
>( SAL_MAX_UINT32
/ sizeof(sal_Int32
) );
1568 bool bOffStringSane
= nOffString
<= nEndPos
- nCurPos
;
1569 if (bLenSane
&& bOffStringSane
)
1571 if ( offDx
&& (( nCurPos
+ offDx
+ nLen
* 4 ) <= nNextPos
) )
1573 pWMF
->Seek( nCurPos
+ offDx
);
1574 if ( ( nLen
* sizeof(sal_uInt32
) ) <= ( nEndPos
- pWMF
->Tell() ) )
1577 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
1580 pWMF
->ReadInt32(val
);
1585 pWMF
->Seek( nCurPos
+ nOffString
);
1589 if ( nLen
<= static_cast<sal_Int32
>( nEndPos
- pWMF
->Tell() ) )
1591 std::unique_ptr
<sal_Char
[]> pBuf(new sal_Char
[ nLen
]);
1592 pWMF
->ReadBytes(pBuf
.get(), nLen
);
1593 aText
= OUString(pBuf
.get(), nLen
, pOut
->GetCharSet());
1596 if ( aText
.getLength() != nLen
)
1598 std::vector
<long> aOldDX(aText
.getLength());
1600 sal_Int32 nDXLen
= std::min
<sal_Int32
>(nLen
, aOldDX
.size());
1601 for (sal_Int32 i
= 0, j
= 0; i
< aText
.getLength(); ++i
)
1603 sal_Unicode cUniChar
= aText
[i
];
1604 OString
aCharacter(&cUniChar
, 1, pOut
->GetCharSet());
1606 for (sal_Int32 k
= 0; ( k
< aCharacter
.getLength() ) && ( j
< nDXLen
) && ( i
< aText
.getLength() ); ++k
)
1607 aDX
[ i
] += aOldDX
[j
++];
1614 if ( ( nLen
* sizeof(sal_Unicode
) ) <= ( nEndPos
- pWMF
->Tell() ) )
1616 std::unique_ptr
<sal_Unicode
[]> pBuf(new sal_Unicode
[ nLen
]);
1617 pWMF
->ReadBytes(pBuf
.get(), nLen
<< 1);
1618 #ifdef OSL_BIGENDIAN
1619 sal_Char nTmp
, *pTmp
= (sal_Char
*)( pBuf
.get() + nLen
);
1620 while ( pTmp
-- != (sal_Char
*)pBuf
.get() )
1627 aText
= OUString(pBuf
.get(), nLen
);
1630 pOut
->DrawText(aPos
, aText
, aDX
.data(), bRecordPath
, nGfxMode
);
1635 case EMR_POLYBEZIERTO16
:
1636 ReadAndDrawPolygon
<sal_Int16
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
1637 { pWinMtfOutput
->DrawPolyBezier( rPolygon
, aTo
, aRecordPath
); }, true );
1640 case EMR_POLYBEZIER16
:
1641 ReadAndDrawPolygon
<sal_Int16
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
1642 { pWinMtfOutput
->DrawPolyBezier( rPolygon
, aTo
, aRecordPath
); }, false );
1645 case EMR_POLYGON16
:
1646 ReadAndDrawPolygon
<sal_Int16
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
1647 { pWinMtfOutput
->DrawPolygon( rPolygon
, aTo
, aRecordPath
); }, false );
1650 case EMR_POLYLINETO16
:
1651 ReadAndDrawPolygon
<sal_Int16
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
1652 { pWinMtfOutput
->DrawPolyLine( rPolygon
, aTo
, aRecordPath
); }, true );
1655 case EMR_POLYLINE16
:
1656 ReadAndDrawPolygon
<sal_Int16
>( [] ( std::unique_ptr
<WinMtfOutput
> &pWinMtfOutput
, tools::Polygon
& rPolygon
, bool aTo
, bool aRecordPath
)
1657 { pWinMtfOutput
->DrawPolyLine( rPolygon
, aTo
, aRecordPath
); }, false );
1660 case EMR_POLYPOLYLINE16
:
1661 ReadAndDrawPolyLine
<sal_Int16
>();
1664 case EMR_POLYPOLYGON16
:
1665 ReadAndDrawPolyPolygon
<sal_Int16
>();
1671 tools::PolyPolygon aPolyPoly
;
1672 pWMF
->SeekRel( 0x10 );
1673 pWMF
->ReadUInt32( nLen
).ReadUInt32( nIndex
);
1675 if ( ImplReadRegion( aPolyPoly
, *pWMF
, nRecSize
) )
1678 pOut
->SelectObject( nIndex
);
1679 pOut
->DrawPolyPolygon( aPolyPoly
);
1685 case EMR_CREATEDIBPATTERNBRUSHPT
:
1687 sal_uInt32 nStart
= pWMF
->Tell() - 8;
1690 pWMF
->ReadUInt32( nIndex
);
1692 if ( ( nIndex
& ENHMETA_STOCK_OBJECT
) == 0 )
1694 sal_uInt32 usage
, offBmi
, cbBmi
, offBits
, cbBits
;
1696 pWMF
->ReadUInt32( usage
);
1697 pWMF
->ReadUInt32( offBmi
);
1698 pWMF
->ReadUInt32( cbBmi
);
1699 pWMF
->ReadUInt32( offBits
);
1700 pWMF
->ReadUInt32( cbBits
);
1702 if ( (cbBits
> (SAL_MAX_UINT32
- 14)) || ((SAL_MAX_UINT32
- 14) - cbBits
< cbBmi
) )
1706 sal_uInt32 nSize
= cbBmi
+ cbBits
+ 14;
1707 if ( nSize
<= ( nEndPos
- nStartPos
) )
1709 char* pBuf
= new char[ nSize
];
1711 SvMemoryStream
aTmp( pBuf
, nSize
, StreamMode::READ
| StreamMode::WRITE
);
1712 aTmp
.ObjectOwnsMemory( true );
1713 aTmp
.WriteUChar( 'B' )
1715 .WriteUInt32( cbBits
)
1718 .WriteUInt32( cbBmi
+ 14 );
1719 pWMF
->Seek( nStart
+ offBmi
);
1720 pWMF
->ReadBytes(pBuf
+ 14, cbBmi
);
1721 pWMF
->Seek( nStart
+ offBits
);
1722 pWMF
->ReadBytes(pBuf
+ 14 + cbBmi
, cbBits
);
1724 ReadDIB(aBitmap
, aTmp
, true);
1729 pOut
->CreateObjectIndexed(nIndex
, o3tl::make_unique
<WinMtfFillStyle
>( aBitmap
));
1733 case EMR_MASKBLT
: SAL_INFO("vcl.emf", "not implemented 'MaskBlt'"); break;
1734 case EMR_PLGBLT
: SAL_INFO("vcl.emf", "not implemented 'PlgBlt'"); break;
1735 case EMR_SETDIBITSTODEVICE
: SAL_INFO("vcl.emf", "not implemented 'SetDIBitsToDevice'"); break;
1736 case EMR_FRAMERGN
: SAL_INFO("vcl.emf", "not implemented 'FrameRgn'"); break;
1737 case EMR_INVERTRGN
: SAL_INFO("vcl.emf", "not implemented 'InvertRgn'"); break;
1738 case EMR_PAINTRGN
: SAL_INFO("vcl.emf", "not implemented 'PaintRgn'"); break;
1739 case EMR_FLATTENPATH
: SAL_INFO("vcl.emf", "not implemented 'FlattenPath'"); break;
1740 case EMR_WIDENPATH
: SAL_INFO("vcl.emf", "not implemented 'WidenPath'"); break;
1741 case EMR_POLYDRAW
: SAL_INFO("vcl.emf", "not implemented 'Polydraw'"); break;
1742 case EMR_SETARCDIRECTION
: SAL_INFO("vcl.emf", "not implemented 'SetArcDirection'"); break;
1743 case EMR_SETPALETTEENTRIES
: SAL_INFO("vcl.emf", "not implemented 'SetPaletteEntries'"); break;
1744 case EMR_RESIZEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'ResizePalette'"); break;
1745 case EMR_EXTFLOODFILL
: SAL_INFO("vcl.emf", "not implemented 'ExtFloodFill'"); break;
1746 case EMR_ANGLEARC
: SAL_INFO("vcl.emf", "not implemented 'AngleArc'"); break;
1747 case EMR_SETCOLORADJUSTMENT
: SAL_INFO("vcl.emf", "not implemented 'SetColorAdjustment'"); break;
1748 case EMR_POLYDRAW16
: SAL_INFO("vcl.emf", "not implemented 'PolyDraw16'"); break;
1749 case EMR_POLYTEXTOUTA
: SAL_INFO("vcl.emf", "not implemented 'PolyTextOutA'"); break;
1750 case EMR_POLYTEXTOUTW
: SAL_INFO("vcl.emf", "not implemented 'PolyTextOutW'"); break;
1751 case EMR_CREATECOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'CreateColorSpace'"); break;
1752 case EMR_SETCOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'SetColorSpace'"); break;
1753 case EMR_DELETECOLORSPACE
: SAL_INFO("vcl.emf", "not implemented 'DeleteColorSpace'"); break;
1754 case EMR_GLSRECORD
: SAL_INFO("vcl.emf", "not implemented 'GlsRecord'"); break;
1755 case EMR_GLSBOUNDEDRECORD
: SAL_INFO("vcl.emf", "not implemented 'GlsBoundRecord'"); break;
1756 case EMR_PIXELFORMAT
: SAL_INFO("vcl.emf", "not implemented 'PixelFormat'"); break;
1757 case EMR_DRAWESCAPE
: SAL_INFO("vcl.emf", "not implemented 'DrawEscape'"); break;
1758 case EMR_EXTESCAPE
: SAL_INFO("vcl.emf", "not implemented 'ExtEscape'"); break;
1759 case EMR_STARTDOC
: SAL_INFO("vcl.emf", "not implemented 'StartDoc'"); break;
1760 case EMR_SMALLTEXTOUT
: SAL_INFO("vcl.emf", "not implemented 'SmallTextOut'"); break;
1761 case EMR_FORCEUFIMAPPING
: SAL_INFO("vcl.emf", "not implemented 'ForceUFIMapping'"); break;
1762 case EMR_NAMEDESCAPE
: SAL_INFO("vcl.emf", "not implemented 'NamedEscape'"); break;
1763 case EMR_COLORCORRECTPALETTE
: SAL_INFO("vcl.emf", "not implemented 'ColorCorrectPalette'"); break;
1764 case EMR_SETICMPROFILEA
: SAL_INFO("vcl.emf", "not implemented 'SetICMProfileA'"); break;
1765 case EMR_SETICMPROFILEW
: SAL_INFO("vcl.emf", "not implemented 'SetICMProfileW'"); break;
1766 case EMR_TRANSPARENTBLT
: SAL_INFO("vcl.emf", "not implemented 'TransparenBlt'"); break;
1767 case EMR_TRANSPARENTDIB
: SAL_INFO("vcl.emf", "not implemented 'TransparenDib'"); break;
1768 case EMR_GRADIENTFILL
: SAL_INFO("vcl.emf", "not implemented 'GradientFill'"); break;
1769 case EMR_SETLINKEDUFIS
: SAL_INFO("vcl.emf", "not implemented 'SetLinkedUFIS'"); break;
1771 case EMR_SETMAPPERFLAGS
: SAL_INFO("vcl.emf", "not implemented 'SetMapperFlags'"); break;
1772 case EMR_SETICMMODE
: SAL_INFO("vcl.emf", "not implemented 'SetICMMode'"); break;
1773 case EMR_CREATEMONOBRUSH
: SAL_INFO("vcl.emf", "not implemented 'CreateMonoBrush'"); break;
1774 case EMR_SETBRUSHORGEX
: SAL_INFO("vcl.emf", "not implemented 'SetBrushOrgEx'"); break;
1775 case EMR_SETMETARGN
: SAL_INFO("vcl.emf", "not implemented 'SetMetArgn'"); break;
1776 case EMR_SETMITERLIMIT
: SAL_INFO("vcl.emf", "not implemented 'SetMiterLimit'"); break;
1777 case EMR_EXCLUDECLIPRECT
: SAL_INFO("vcl.emf", "not implemented 'ExcludeClipRect'"); break;
1778 case EMR_REALIZEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'RealizePalette'"); break;
1779 case EMR_SELECTPALETTE
: SAL_INFO("vcl.emf", "not implemented 'SelectPalette'"); break;
1780 case EMR_CREATEPALETTE
: SAL_INFO("vcl.emf", "not implemented 'CreatePalette'"); break;
1781 case EMR_ALPHADIBBLEND
: SAL_INFO("vcl.emf", "not implemented 'AlphaDibBlend'"); break;
1782 case EMR_SETTEXTJUSTIFICATION
: SAL_INFO("vcl.emf", "not implemented 'SetTextJustification'"); break;
1784 case EMR_GDICOMMENT
:
1785 case EMR_HEADER
: // has already been read at ReadHeader()
1788 default : SAL_INFO("vcl.emf", "Unknown Meta Action"); break;
1791 pWMF
->Seek( nNextPos
);
1793 if( !aBmpSaveList
.empty() )
1794 pOut
->ResolveBitmapActions( aBmpSaveList
);
1797 pWMF
->Seek(nEndPos
);
1802 bool EnhWMFReader::ReadHeader()
1804 sal_uInt32 nType
, nSignature
, nVersion
;
1805 sal_uInt32 nHeaderSize
, nPalEntries
;
1807 // Spare me the METAFILEHEADER here
1808 // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
1809 pWMF
->ReadUInt32( nType
).ReadUInt32( nHeaderSize
);
1810 if (nType
!= 0x00000001)
1812 // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
1813 SAL_WARN("vcl.emf", "EMF header type is not set to 0x00000001 - possibly corrupted file?");
1817 // Start reading the EMR_HEADER Header object
1819 // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
1820 Rectangle rclBounds
= ReadRectangle(); // rectangle in logical units
1822 // picture frame size (RectL object)
1823 Rectangle rclFrame
= ReadRectangle(); // rectangle in device units 1/100th mm
1825 pWMF
->ReadUInt32( nSignature
);
1827 // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
1828 // and 2.1.14 FormatSignature Enumeration
1829 if (nSignature
!= 0x464d4520)
1831 SAL_WARN("vcl.emf", "EMF\t\tSignature is not 0x464d4520 (\"FME\") - possibly corrupted file?");
1835 pWMF
->ReadUInt32(nVersion
); // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
1836 // Microsoft note that not even Windows checks this...
1837 if (nVersion
!= 0x00010000)
1839 SAL_WARN("vcl.emf", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
1842 pWMF
->ReadUInt32(nEndPos
); // size of metafile
1843 nEndPos
+= nStartPos
;
1845 sal_uInt32 nStrmPos
= pWMF
->Tell(); // checking if nEndPos is valid
1846 pWMF
->Seek(STREAM_SEEK_TO_END
);
1847 sal_uInt32 nActualFileSize
= pWMF
->Tell();
1849 if ( nActualFileSize
< nEndPos
)
1851 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object records number of bytes as " << nEndPos
1852 << ", however the file size is actually " << nActualFileSize
1853 << " bytes. Possible file corruption?");
1854 nEndPos
= nActualFileSize
;
1856 pWMF
->Seek(nStrmPos
);
1858 pWMF
->ReadInt32(nRecordCount
);
1860 if (nRecordCount
<= 0)
1862 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object shows record counter as <= 0! This shouldn't "
1863 "be possible... indicator of possible file corruption?");
1867 // the number of "handles", or graphics objects used in the metafile
1869 sal_uInt16 nHandlesCount
;
1870 pWMF
->ReadUInt16(nHandlesCount
);
1872 // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
1873 // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
1874 // value is actually pretty useful in checking if there is possible corruption
1876 sal_uInt16 nReserved
;
1877 pWMF
->ReadUInt16(nReserved
);
1879 if ( nReserved
!= 0x0000 )
1881 SAL_WARN("vcl.emf", "EMF\t\tEMF Header object's reserved field is NOT 0x0000... possible "
1885 // The next 4 bytes specifies the number of characters in the metafile description.
1886 // The 4 bytes after that specific the offset from this record that contains the
1887 // metafile description... zero means no description string.
1888 // For now, we ignore it.
1892 sal_Int32 nPixX
, nPixY
, nMillX
, nMillY
;
1893 pWMF
->ReadUInt32(nPalEntries
);
1894 pWMF
->ReadInt32(nPixX
);
1895 pWMF
->ReadInt32(nPixY
);
1896 pWMF
->ReadInt32(nMillX
);
1897 pWMF
->ReadInt32(nMillY
);
1899 pOut
->SetrclFrame(rclFrame
);
1900 pOut
->SetrclBounds(rclBounds
);
1901 pOut
->SetRefPix(Size( nPixX
, nPixY
) );
1902 pOut
->SetRefMill(Size( nMillX
, nMillY
) );
1904 pWMF
->Seek(nStartPos
+ nHeaderSize
);
1908 Rectangle
EnhWMFReader::ReadRectangle()
1910 sal_Int32 nLeft
, nTop
, nRight
, nBottom
;
1911 pWMF
->ReadInt32(nLeft
);
1912 pWMF
->ReadInt32(nTop
);
1913 pWMF
->ReadInt32(nRight
);
1914 pWMF
->ReadInt32(nBottom
);
1915 return Rectangle(nLeft
, nTop
, nRight
, nBottom
);
1918 Rectangle
EnhWMFReader::ReadRectangle( sal_Int32 x1
, sal_Int32 y1
, sal_Int32 x2
, sal_Int32 y2
)
1920 Point
aTL ( Point( x1
, y1
) );
1921 Point
aBR( Point( --x2
, --y2
) );
1922 return Rectangle( aTL
, aBR
);
1925 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */