Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "winmtf.hxx"
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>
26 :
27 : using namespace std;
28 :
29 : // GDI-Array
30 :
31 : #define EMR_HEADER 1
32 : #define EMR_POLYBEZIER 2
33 : #define EMR_POLYGON 3
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
44 : #define EMR_EOF 14
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
63 : #define EMR_SAVEDC 33
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
75 : #define EMR_ARC 45
76 : #define EMR_CHORD 46
77 : #define EMR_PIE 47
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
84 : #define EMR_LINETO 54
85 : #define EMR_ARCTO 55
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
99 :
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
128 :
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
137 :
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
155 :
156 : namespace
157 : {
158 :
159 : const char *
160 0 : record_type_name(sal_uInt32 nRecType)
161 : {
162 : #ifndef SAL_LOG_INFO
163 : (void) nRecType;
164 0 : return "";
165 : #else
166 : switch( nRecType )
167 : {
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";
287 : default:
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);
292 : return buffer;
293 : }
294 : #endif
295 : }
296 :
297 : #ifdef OSL_BIGENDIAN
298 : // little endian <-> big endian switch
299 : static float GetSwapFloat(SvStream& rStream)
300 : {
301 : float fTmp;
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]);
307 : return fTmp;
308 : }
309 : #endif
310 :
311 : struct BLENDFUNCTION
312 : {
313 : unsigned char aBlendOperation;
314 : unsigned char aBlendFlags;
315 : unsigned char aSrcConstantAlpha;
316 : unsigned char aAlphaFormat;
317 :
318 : friend SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun);
319 : };
320 :
321 5 : SvStream& operator>>(SvStream& rInStream, BLENDFUNCTION& rBlendFun)
322 : {
323 5 : rInStream.ReadUChar(rBlendFun.aBlendOperation);
324 5 : rInStream.ReadUChar(rBlendFun.aBlendFlags);
325 5 : rInStream.ReadUChar(rBlendFun.aSrcConstantAlpha);
326 5 : rInStream.ReadUChar(rBlendFun.aAlphaFormat);
327 5 : return rInStream;
328 : }
329 :
330 1240 : SvStream& operator>>(SvStream& rInStream, XForm& rXForm)
331 : {
332 : if (sizeof(float) != 4)
333 : {
334 : OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
335 : rXForm = XForm();
336 : }
337 : else
338 : {
339 : #ifdef OSL_BIGENDIAN
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);
346 : #else
347 1240 : rInStream.ReadFloat(rXForm.eM11);
348 1240 : rInStream.ReadFloat(rXForm.eM12);
349 1240 : rInStream.ReadFloat(rXForm.eM21);
350 1240 : rInStream.ReadFloat(rXForm.eM22);
351 1240 : rInStream.ReadFloat(rXForm.eDx);
352 1240 : rInStream.ReadFloat(rXForm.eDy);
353 : #endif
354 : }
355 1240 : return rInStream;
356 : }
357 :
358 0 : static bool ImplReadRegion( tools::PolyPolygon& rPolyPoly, SvStream& rStream, sal_uInt32 nLen )
359 : {
360 0 : if (nLen == 0)
361 0 : return false;
362 :
363 : sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
364 0 : rStream.ReadUInt32(nHdSize);
365 0 : rStream.ReadUInt32(nType);
366 0 : rStream.ReadUInt32(nCount);
367 0 : rStream.ReadUInt32(nRgnSize);
368 :
369 0 : if ( nCount > 0
370 0 : && nType == RDH_RECTANGLES
371 0 : && nLen >= ((nCount << 4) + (nHdSize - 16)))
372 : {
373 : sal_Int32 nx1, ny1, nx2, ny2;
374 :
375 0 : for (i = 0; i < nCount; i++)
376 : {
377 0 : rStream.ReadInt32(nx1);
378 0 : rStream.ReadInt32(ny1);
379 0 : rStream.ReadInt32(nx2);
380 0 : rStream.ReadInt32(ny2);
381 :
382 0 : Rectangle aRectangle(Point(nx1, ny1), Point(nx2, ny2));
383 :
384 0 : Polygon aPolygon(aRectangle);
385 0 : tools::PolyPolygon aPolyPolyOr1(aPolygon);
386 0 : tools::PolyPolygon aPolyPolyOr2(rPolyPoly);
387 0 : rPolyPoly.GetUnion(aPolyPolyOr1, aPolyPolyOr2);
388 0 : rPolyPoly = aPolyPolyOr2;
389 0 : }
390 0 : return true;
391 : }
392 0 : return false;
393 : }
394 :
395 : } // anonymous namespace
396 :
397 131 : EnhWMFReader::EnhWMFReader(SvStream& rStream,GDIMetaFile& rGDIMetaFile,FilterConfigItem* pConfigItem)
398 131 : : WinMtf(new WinMtfOutput(rGDIMetaFile), rStream , pConfigItem)
399 : , bRecordPath(false)
400 : , nRecordCount(0)
401 262 : , bEMFPlus(false)
402 131 : {}
403 :
404 131 : EnhWMFReader::~EnhWMFReader()
405 131 : {}
406 :
407 517 : void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC)
408 : {
409 517 : if (!bEMFPlus) {
410 80 : pOut->PassEMFPlusHeaderInfo();
411 :
412 : #if OSL_DEBUG_LEVEL > 1
413 : // debug code - write the stream to debug file /tmp/emf-stream.emf
414 : int pos = pWMF->Tell();
415 : pWMF->Seek(0);
416 : SvFileStream file( OUString( "/tmp/emf-stream.emf" ), StreamMode::WRITE | StreamMode::TRUNC );
417 :
418 : pWMF->WriteStream(file);
419 : file.Flush();
420 : file.Close();
421 :
422 : pWMF->Seek( pos );
423 : #endif
424 :
425 : }
426 517 : bEMFPlus = true;
427 :
428 517 : sal_Size pos = pWMF->Tell();
429 517 : void *buffer = malloc( length );
430 517 : pOut->PassEMFPlus( buffer, pWMF->Read( buffer, length ) );
431 517 : free( buffer );
432 517 : pWMF->Seek( pos );
433 :
434 517 : bHaveDC = false;
435 :
436 : OSL_ASSERT(length >= 4);
437 : // reduce by 32bit length itself, skip in SeekRel if
438 : // impossibly unavailable
439 517 : sal_uInt32 nRemainder = length >= 4 ? length-4 : length;
440 :
441 517 : const size_t nRequiredHeaderSize = 12;
442 3945 : while (nRemainder >= nRequiredHeaderSize)
443 : {
444 2911 : sal_uInt16 type(0), flags(0);
445 2911 : sal_uInt32 size(0), dataSize(0);
446 :
447 2911 : pWMF->ReadUInt16( type ).ReadUInt16( flags ).ReadUInt32( size ).ReadUInt32( dataSize );
448 2911 : nRemainder -= nRequiredHeaderSize;
449 :
450 : SAL_INFO ("vcl.emf", "\t\tEMF+ record type: " << std::hex << type << std::dec);
451 :
452 : // GetDC
453 2911 : if( type == 16388 ) {
454 206 : bHaveDC = true;
455 : SAL_INFO ("vcl.emf", "\t\tEMF+ lock DC (device context)");
456 : }
457 :
458 : // Get the length of the remaining data of this record based
459 : // on the alleged size
460 2911 : sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
461 2911 : size-nRequiredHeaderSize : 0;
462 : // clip to available size
463 2911 : nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
464 2911 : pWMF->SeekRel(nRemainingRecordData);
465 2911 : nRemainder -= nRemainingRecordData;
466 : }
467 517 : pWMF->SeekRel(nRemainder);
468 517 : }
469 :
470 : /**
471 : * Reads polygons from the stream.
472 : * The \<class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
473 : * The \<class Drawer> parameter is a boost binding for the method that will draw the polygon.
474 : * skipFirst: if the first point read is the 0th point or the 1st point in the array.
475 : * */
476 : template <class T, class Drawer>
477 447 : void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer, const bool skipFirst)
478 : {
479 447 : sal_uInt32 nPoints(0), nStartIndex(0);
480 447 : pWMF->SeekRel( 16 );
481 447 : pWMF->ReadUInt32( nPoints );
482 447 : if (skipFirst)
483 : {
484 54 : nPoints ++;
485 54 : nStartIndex ++;
486 : }
487 :
488 447 : Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
489 447 : drawer(pOut, aPolygon, skipFirst, bRecordPath);
490 447 : }
491 :
492 : /**
493 : * Reads polygons from the stream.
494 : * The \<class T> parameter is for the type of the points
495 : * nStartIndex: which is the starting index in the polygon of the first point read
496 : * nPoints: number of points
497 : * pWMF: the stream containings the polygons
498 : * */
499 : template <class T>
500 456 : Polygon EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
501 : {
502 456 : bool bRecordOk = nPoints <= SAL_MAX_UINT16;
503 : SAL_WARN_IF(!bRecordOk, "vcl.filter", "polygon record has more polygons than we can handle");
504 456 : if (!bRecordOk)
505 1 : return Polygon();
506 :
507 455 : Polygon aPolygon(nPoints);
508 4127 : for (sal_uInt16 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
509 : {
510 : T nX, nY;
511 3672 : *pWMF >> nX >> nY;
512 3672 : if (!pWMF->good())
513 0 : break;
514 3672 : aPolygon[ i ] = Point( nX, nY );
515 : }
516 :
517 455 : return aPolygon;
518 : }
519 :
520 : /**
521 : * Reads a polyline from the WMF file and draws it
522 : * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
523 : * */
524 : template <class T>
525 9 : void EnhWMFReader::ReadAndDrawPolyLine()
526 : {
527 : sal_uInt32 nPoints;
528 9 : sal_Int32 i, nPoly(0), nGesPoints(0);
529 9 : pWMF->SeekRel( 0x10 );
530 : // Number of Polygons:
531 9 : pWMF->ReadInt32( nPoly ).ReadInt32( nGesPoints );
532 :
533 : // taking the amount of points of each polygon, retrieving the total number of points
534 18 : if ( pWMF->good() &&
535 : ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
536 9 : ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() )
537 : )
538 : {
539 9 : boost::scoped_array<sal_uInt16> pnPoints(new sal_uInt16[ nPoly ]);
540 18 : for ( i = 0; i < nPoly && pWMF->good(); i++ )
541 : {
542 9 : pWMF->ReadUInt32( nPoints );
543 9 : pnPoints[ i ] = (sal_uInt16)nPoints;
544 : }
545 : // Get polygon points:
546 18 : for ( i = 0; ( i < nPoly ) && pWMF->good(); i++ )
547 : {
548 9 : Polygon aPolygon = ReadPolygon<T>(0, pnPoints[i]);
549 9 : pOut->DrawPolyLine( aPolygon, false, bRecordPath );
550 9 : }
551 : }
552 9 : }
553 :
554 : // these are referenced from inside the templates
555 :
556 9354 : SvStream& operator>>(SvStream& rStream, sal_Int16 &n)
557 : {
558 9354 : return rStream.ReadInt16(n);
559 : }
560 :
561 2306 : SvStream& operator>>(SvStream& rStream, sal_Int32 &n)
562 : {
563 2306 : return rStream.ReadInt32(n);
564 : }
565 :
566 : /**
567 : * Reads a poly polygon from the WMF file and draws it.
568 : * The \<class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
569 : * */
570 : template <class T>
571 42 : void EnhWMFReader::ReadAndDrawPolyPolygon()
572 : {
573 42 : sal_uInt32 nPoly(0), nGesPoints(0), nReadPoints(0);
574 42 : pWMF->SeekRel( 0x10 );
575 : // Number of polygons
576 42 : pWMF->ReadUInt32( nPoly ).ReadUInt32( nGesPoints );
577 84 : if ( pWMF->good() &&
578 : ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && //check against numeric overflowing
579 : ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
580 42 : ( ( nPoly * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) ))
581 : {
582 : // Get number of points in each polygon
583 42 : boost::scoped_array<sal_uInt16> pnPoints(new sal_uInt16[ nPoly ]);
584 116 : for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
585 : {
586 74 : sal_uInt32 nPoints(0);
587 74 : pWMF->ReadUInt32( nPoints );
588 74 : pnPoints[ i ] = (sal_uInt16)nPoints;
589 : }
590 42 : if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
591 : {
592 : // Get polygon points
593 42 : tools::PolyPolygon aPolyPoly(nPoly, nPoly);
594 116 : for (sal_uInt32 i = 0; i < nPoly && pWMF->good(); ++i)
595 : {
596 74 : const sal_uInt16 nPointCount(pnPoints[i]);
597 74 : boost::scoped_array<Point> pPtAry(new Point[nPointCount]);
598 2232 : for (sal_uInt16 j = 0; j < nPointCount && pWMF->good(); ++j)
599 : {
600 2158 : T nX(0), nY(0);
601 2158 : *pWMF >> nX >> nY;
602 2158 : pPtAry[ j ] = Point( nX, nY );
603 2158 : ++nReadPoints;
604 : }
605 :
606 74 : aPolyPoly.Insert(Polygon(nPointCount, pPtAry.get()));
607 : }
608 :
609 42 : pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
610 : }
611 :
612 42 : OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
613 :
614 : }
615 42 : }
616 :
617 131 : bool EnhWMFReader::ReadEnhWMF()
618 : {
619 131 : sal_uInt32 nStretchBltMode = 0;
620 131 : sal_uInt32 nRecType(0), nRecSize(0), nNextPos(0),
621 131 : nW(0), nH(0), nColor(0), nIndex(0),
622 131 : nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
623 131 : sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
624 :
625 131 : bool bStatus = ReadHeader();
626 131 : bool bHaveDC = false;
627 :
628 131 : static bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == NULL );
629 :
630 23986 : while( bStatus && nRecordCount-- && pWMF->good())
631 : {
632 23728 : pWMF->ReadUInt32( nRecType ).ReadUInt32( nRecSize );
633 :
634 23728 : if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
635 : {
636 3 : bStatus = false;
637 3 : break;
638 : }
639 :
640 23725 : nNextPos = pWMF->Tell() + ( nRecSize - 8 );
641 :
642 23725 : if ( !pWMF->good() || nNextPos > nEndPos )
643 : {
644 1 : bStatus = false;
645 1 : break;
646 : }
647 :
648 47448 : if( !aBmpSaveList.empty()
649 1200 : && ( nRecType != EMR_STRETCHBLT )
650 24911 : && ( nRecType != EMR_STRETCHDIBITS )
651 : ) {
652 1178 : pOut->ResolveBitmapActions( aBmpSaveList );
653 : }
654 :
655 23724 : bool bFlag = false;
656 :
657 : SAL_INFO ("vcl.emf", "0x" << std::hex << (nNextPos - nRecSize) << "-0x" << nNextPos << " " << record_type_name(nRecType) << " size: " << nRecSize << std::dec);
658 :
659 23724 : if( bEnableEMFPlus && nRecType == EMR_GDICOMMENT ) {
660 : sal_uInt32 length;
661 :
662 580 : pWMF->ReadUInt32( length );
663 :
664 : SAL_INFO("vcl.emf", "\tGDI comment, length: " << length);
665 :
666 580 : if( pWMF->good() && length >= 4 ) {
667 : sal_uInt32 id;
668 :
669 580 : pWMF->ReadUInt32( id );
670 :
671 : 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);
672 :
673 : // EMF+ comment (FIXME: BE?)
674 580 : if( id == 0x2B464D45 && nRecSize >= 12 )
675 517 : ReadEMFPlusComment( length, bHaveDC );
676 : // GDIC comment, doesn't do anything useful yet
677 63 : else if( id == 0x43494447 && nRecSize >= 12 ) {
678 : // TODO: ReadGDIComment()
679 : } else {
680 : SAL_INFO ("vcl.emf", "\t\tunknown id: 0x" << std::hex << id << std::dec);
681 : }
682 580 : }
683 : }
684 23144 : else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
685 : {
686 21556 : switch( nRecType )
687 : {
688 : case EMR_POLYBEZIERTO :
689 0 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), true);
690 0 : break;
691 : case EMR_POLYBEZIER :
692 0 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), false);
693 0 : break;
694 :
695 : case EMR_POLYGON :
696 92 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), false);
697 92 : break;
698 :
699 : case EMR_POLYLINETO :
700 13 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), true);
701 13 : break;
702 : case EMR_POLYLINE :
703 226 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), false);
704 226 : break;
705 :
706 : case EMR_POLYPOLYLINE :
707 0 : ReadAndDrawPolyLine<sal_Int32>();
708 0 : break;
709 :
710 : case EMR_POLYPOLYGON :
711 0 : ReadAndDrawPolyPolygon<sal_Int32>();
712 0 : break;
713 :
714 : case EMR_SETWINDOWEXTEX :
715 : { // #75383#
716 157 : pWMF->ReadUInt32( nW ).ReadUInt32( nH );
717 157 : pOut->SetWinExt( Size( nW, nH ), true);
718 : }
719 157 : break;
720 :
721 : case EMR_SETWINDOWORGEX :
722 : {
723 194 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
724 194 : pOut->SetWinOrg( Point( nX32, nY32 ), true);
725 : }
726 194 : break;
727 :
728 : case EMR_SCALEWINDOWEXTEX :
729 : {
730 0 : pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
731 0 : pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
732 : }
733 0 : break;
734 :
735 : case EMR_SETVIEWPORTORGEX :
736 : {
737 120 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
738 120 : pOut->SetDevOrg( Point( nX32, nY32 ) );
739 : }
740 120 : break;
741 :
742 : case EMR_SCALEVIEWPORTEXTEX :
743 : {
744 3 : pWMF->ReadUInt32( nNom1 ).ReadUInt32( nDen1 ).ReadUInt32( nNom2 ).ReadUInt32( nDen2 );
745 3 : pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
746 : }
747 3 : break;
748 :
749 : case EMR_SETVIEWPORTEXTEX :
750 : {
751 77 : pWMF->ReadUInt32( nW ).ReadUInt32( nH );
752 77 : pOut->SetDevExt( Size( nW, nH ) );
753 : }
754 77 : break;
755 :
756 : case EMR_EOF :
757 127 : nRecordCount = 0; // #76846#
758 127 : break;
759 :
760 : case EMR_SETPIXELV :
761 : {
762 158 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
763 158 : pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
764 : }
765 158 : break;
766 :
767 : case EMR_SETMAPMODE :
768 : {
769 : sal_uInt32 nMapMode;
770 83 : pWMF->ReadUInt32( nMapMode );
771 83 : pOut->SetMapMode( nMapMode );
772 : }
773 83 : break;
774 :
775 : case EMR_SETBKMODE :
776 : {
777 323 : pWMF->ReadUInt32( nDat32 );
778 323 : pOut->SetBkMode( static_cast<BkMode>(nDat32) );
779 : }
780 323 : break;
781 :
782 : case EMR_SETPOLYFILLMODE :
783 102 : break;
784 :
785 : case EMR_SETROP2 :
786 : {
787 697 : pWMF->ReadUInt32( nDat32 );
788 697 : pOut->SetRasterOp( nDat32 );
789 : }
790 697 : break;
791 :
792 : case EMR_SETSTRETCHBLTMODE :
793 : {
794 0 : pWMF->ReadUInt32( nStretchBltMode );
795 : }
796 0 : break;
797 :
798 : case EMR_SETTEXTALIGN :
799 : {
800 284 : pWMF->ReadUInt32( nDat32 );
801 284 : pOut->SetTextAlign( nDat32 );
802 : }
803 284 : break;
804 :
805 : case EMR_SETTEXTCOLOR :
806 : {
807 837 : pOut->SetTextColor( ReadColor() );
808 : }
809 837 : break;
810 :
811 : case EMR_SETBKCOLOR :
812 : {
813 570 : pOut->SetBkColor( ReadColor() );
814 : }
815 570 : break;
816 :
817 : case EMR_OFFSETCLIPRGN :
818 : {
819 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
820 0 : pOut->MoveClipRegion( Size( nX32, nY32 ) );
821 : }
822 0 : break;
823 :
824 : case EMR_MOVETOEX :
825 : {
826 912 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
827 912 : pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
828 : }
829 912 : break;
830 :
831 : case EMR_INTERSECTCLIPRECT :
832 : {
833 304 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
834 304 : pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
835 : }
836 304 : break;
837 :
838 : case EMR_SAVEDC :
839 : {
840 690 : pOut->Push();
841 : }
842 690 : break;
843 :
844 : case EMR_RESTOREDC :
845 : {
846 647 : pOut->Pop();
847 : }
848 647 : break;
849 :
850 : case EMR_SETWORLDTRANSFORM :
851 : {
852 13 : XForm aTempXForm;
853 13 : *pWMF >> aTempXForm;
854 13 : pOut->SetWorldTransform( aTempXForm );
855 : }
856 13 : break;
857 :
858 : case EMR_MODIFYWORLDTRANSFORM :
859 : {
860 : sal_uInt32 nMode;
861 64 : XForm aTempXForm;
862 64 : *pWMF >> aTempXForm;
863 64 : pWMF->ReadUInt32( nMode );
864 64 : pOut->ModifyWorldTransform( aTempXForm, nMode );
865 : }
866 64 : break;
867 :
868 : case EMR_SELECTOBJECT :
869 : {
870 7583 : pWMF->ReadUInt32( nIndex );
871 7583 : pOut->SelectObject( nIndex );
872 : }
873 7583 : break;
874 :
875 : case EMR_CREATEPEN :
876 : {
877 623 : pWMF->ReadUInt32( nIndex );
878 623 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
879 : {
880 :
881 623 : LineInfo aLineInfo;
882 : sal_uInt32 nStyle;
883 623 : Size aSize;
884 : // #fdo39428 Remove SvStream operator>>(long&)
885 623 : sal_Int32 nTmpW(0), nTmpH(0);
886 :
887 623 : pWMF->ReadUInt32( nStyle ).ReadInt32( nTmpW ).ReadInt32( nTmpH );
888 623 : aSize.Width() = nTmpW;
889 623 : aSize.Height() = nTmpH;
890 :
891 623 : if ( aSize.Width() )
892 24 : aLineInfo.SetWidth( aSize.Width() );
893 :
894 623 : bool bTransparent = false;
895 623 : switch( nStyle & 0xFF )
896 : {
897 : case PS_DASHDOTDOT :
898 0 : aLineInfo.SetStyle( LINE_DASH );
899 0 : aLineInfo.SetDashCount( 1 );
900 0 : aLineInfo.SetDotCount( 2 );
901 0 : aLineInfo.SetDashLen( 150 );
902 0 : aLineInfo.SetDotLen( 30 );
903 0 : aLineInfo.SetDistance( 50 );
904 0 : break;
905 : case PS_DASHDOT :
906 0 : aLineInfo.SetStyle( LINE_DASH );
907 0 : aLineInfo.SetDashCount( 1 );
908 0 : aLineInfo.SetDotCount( 1 );
909 0 : aLineInfo.SetDashLen( 150 );
910 0 : aLineInfo.SetDotLen( 30 );
911 0 : aLineInfo.SetDistance( 90 );
912 0 : break;
913 : case PS_DOT :
914 0 : aLineInfo.SetStyle( LINE_DASH );
915 0 : aLineInfo.SetDashCount( 0 );
916 0 : aLineInfo.SetDotCount( 1 );
917 0 : aLineInfo.SetDotLen( 30 );
918 0 : aLineInfo.SetDistance( 50 );
919 0 : break;
920 : case PS_DASH :
921 0 : aLineInfo.SetStyle( LINE_DASH );
922 0 : aLineInfo.SetDashCount( 1 );
923 0 : aLineInfo.SetDotCount( 0 );
924 0 : aLineInfo.SetDashLen( 225 );
925 0 : aLineInfo.SetDistance( 100 );
926 0 : break;
927 : case PS_NULL :
928 203 : bTransparent = true;
929 203 : aLineInfo.SetStyle( LINE_NONE );
930 203 : break;
931 : case PS_INSIDEFRAME :
932 : case PS_SOLID :
933 : default :
934 420 : aLineInfo.SetStyle( LINE_SOLID );
935 : }
936 623 : switch( nStyle & 0xF00 )
937 : {
938 : case PS_ENDCAP_ROUND :
939 623 : if ( aSize.Width() )
940 : {
941 24 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_ROUND );
942 24 : break;
943 : }
944 : case PS_ENDCAP_SQUARE :
945 599 : if ( aSize.Width() )
946 : {
947 0 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_SQUARE );
948 0 : break;
949 : }
950 : case PS_ENDCAP_FLAT :
951 : default :
952 599 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_BUTT );
953 : }
954 623 : switch( nStyle & 0xF000 )
955 : {
956 : case PS_JOIN_ROUND :
957 623 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
958 623 : break;
959 : case PS_JOIN_MITER :
960 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
961 0 : break;
962 : case PS_JOIN_BEVEL :
963 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
964 0 : break;
965 : default :
966 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
967 : }
968 623 : pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
969 : }
970 : }
971 623 : break;
972 :
973 : case EMR_EXTCREATEPEN :
974 : {
975 : sal_Int32 elpHatch;
976 : sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
977 25 : Color aColorRef;
978 :
979 25 : pWMF->ReadUInt32( nIndex );
980 25 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
981 : {
982 25 : pWMF->ReadUInt32( offBmi ).ReadUInt32( cbBmi ).ReadUInt32( offBits ).ReadUInt32( cbBits ). ReadUInt32( nStyle ).ReadUInt32( nWidth ).ReadUInt32( nBrushStyle );
983 25 : aColorRef = ReadColor();
984 25 : pWMF->ReadInt32( elpHatch ).ReadUInt32( elpNumEntries );
985 :
986 25 : LineInfo aLineInfo;
987 25 : if ( nWidth )
988 19 : aLineInfo.SetWidth( nWidth );
989 :
990 25 : bool bTransparent = false;
991 25 : sal_uInt16 nDashCount = 0;
992 25 : sal_uInt16 nDotCount = 0;
993 :
994 25 : switch( nStyle & PS_STYLE_MASK )
995 : {
996 : case PS_DASHDOTDOT :
997 0 : nDotCount++;
998 : case PS_DASHDOT :
999 0 : nDashCount++;
1000 : case PS_DOT :
1001 0 : nDotCount++;
1002 0 : break;
1003 : case PS_DASH :
1004 0 : nDashCount++;
1005 0 : break;
1006 : case PS_NULL :
1007 6 : bTransparent = true;
1008 6 : aLineInfo.SetStyle( LINE_NONE );
1009 6 : break;
1010 :
1011 : case PS_INSIDEFRAME :
1012 : case PS_SOLID :
1013 : default :
1014 19 : aLineInfo.SetStyle( LINE_SOLID );
1015 : }
1016 25 : if ( nDashCount | nDotCount )
1017 : {
1018 0 : aLineInfo.SetStyle( LINE_DASH );
1019 0 : aLineInfo.SetDashCount( nDashCount );
1020 0 : aLineInfo.SetDotCount( nDotCount );
1021 : }
1022 25 : pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( aColorRef, aLineInfo, bTransparent ) );
1023 : }
1024 : }
1025 25 : break;
1026 :
1027 : case EMR_CREATEBRUSHINDIRECT :
1028 : {
1029 : sal_uInt32 nStyle;
1030 613 : pWMF->ReadUInt32( nIndex );
1031 613 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1032 : {
1033 613 : pWMF->ReadUInt32( nStyle );
1034 613 : pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ) );
1035 : }
1036 : }
1037 613 : break;
1038 :
1039 : case EMR_DELETEOBJECT :
1040 : {
1041 1489 : pWMF->ReadUInt32( nIndex );
1042 1489 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1043 1489 : pOut->DeleteObject( nIndex );
1044 : }
1045 1489 : break;
1046 :
1047 : case EMR_ELLIPSE :
1048 : {
1049 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
1050 0 : pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
1051 : }
1052 0 : break;
1053 :
1054 : case EMR_RECTANGLE :
1055 : {
1056 125 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 );
1057 125 : pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
1058 : }
1059 125 : break;
1060 :
1061 : case EMR_ROUNDRECT :
1062 : {
1063 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nW ).ReadUInt32( nH );
1064 0 : Size aSize( Size( nW, nH ) );
1065 0 : pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
1066 : }
1067 0 : break;
1068 :
1069 : case EMR_ARC :
1070 : {
1071 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
1072 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
1073 0 : pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
1074 : }
1075 0 : break;
1076 :
1077 : case EMR_CHORD :
1078 : {
1079 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
1080 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
1081 0 : pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
1082 : }
1083 0 : break;
1084 :
1085 : case EMR_PIE :
1086 : {
1087 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
1088 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
1089 0 : const Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
1090 :
1091 : // #i73608# OutputDevice deviates from WMF
1092 : // semantics. start==end means full ellipse here.
1093 0 : if( nStartX == nEndX && nStartY == nEndY )
1094 0 : pOut->DrawEllipse( aRect );
1095 : else
1096 0 : pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
1097 : }
1098 0 : break;
1099 :
1100 : case EMR_LINETO :
1101 : {
1102 854 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 );
1103 854 : pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
1104 : }
1105 854 : break;
1106 :
1107 : case EMR_ARCTO :
1108 : {
1109 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
1110 0 : pWMF->ReadInt32( nX32 ).ReadInt32( nY32 ).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nStartX ).ReadUInt32( nStartY ).ReadUInt32( nEndX ).ReadUInt32( nEndY );
1111 0 : pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), true );
1112 : }
1113 0 : break;
1114 :
1115 : case EMR_BEGINPATH :
1116 : {
1117 41 : pOut->ClearPath();
1118 41 : bRecordPath = true;
1119 : }
1120 41 : break;
1121 :
1122 : case EMR_ABORTPATH :
1123 0 : pOut->ClearPath();
1124 : case EMR_ENDPATH :
1125 41 : bRecordPath = false;
1126 41 : break;
1127 :
1128 : case EMR_CLOSEFIGURE :
1129 30 : pOut->ClosePath();
1130 30 : break;
1131 :
1132 : case EMR_FILLPATH :
1133 13 : pOut->StrokeAndFillPath( false, true );
1134 13 : break;
1135 :
1136 : case EMR_STROKEANDFILLPATH :
1137 1 : pOut->StrokeAndFillPath( true, true );
1138 1 : break;
1139 :
1140 : case EMR_STROKEPATH :
1141 10 : pOut->StrokeAndFillPath( true, false );
1142 10 : break;
1143 :
1144 : case EMR_SELECTCLIPPATH :
1145 : {
1146 : sal_Int32 nClippingMode;
1147 17 : pWMF->ReadInt32(nClippingMode);
1148 17 : pOut->SetClipPath(pOut->GetPathObj(), nClippingMode, true);
1149 : }
1150 17 : break;
1151 :
1152 : case EMR_EXTSELECTCLIPRGN :
1153 : {
1154 : sal_Int32 nClippingMode, cbRgnData;
1155 130 : pWMF->ReadInt32(cbRgnData);
1156 130 : pWMF->ReadInt32(nClippingMode);
1157 :
1158 : // This record's region data should be ignored if mode
1159 : // is RGN_COPY - see EMF spec section 2.3.2.2
1160 130 : if (nClippingMode == RGN_COPY)
1161 : {
1162 130 : pOut->SetDefaultClipPath();
1163 : }
1164 : else
1165 : {
1166 0 : tools::PolyPolygon aPolyPoly;
1167 0 : if (cbRgnData)
1168 0 : ImplReadRegion(aPolyPoly, *pWMF, nRecSize);
1169 0 : pOut->SetClipPath(aPolyPoly, nClippingMode, false);
1170 : }
1171 :
1172 : }
1173 130 : break;
1174 :
1175 : case EMR_ALPHABLEND:
1176 : {
1177 5 : sal_Int32 xDest(0), yDest(0), cxDest(0), cyDest(0);
1178 :
1179 : BLENDFUNCTION aFunc;
1180 5 : sal_Int32 xSrc(0), ySrc(0), cxSrc(0), cySrc(0);
1181 5 : XForm xformSrc;
1182 5 : sal_uInt32 BkColorSrc(0), iUsageSrc(0), offBmiSrc(0);
1183 5 : sal_uInt32 cbBmiSrc(0), offBitsSrc(0), cbBitsSrc(0);
1184 :
1185 5 : sal_uInt32 nStart = pWMF->Tell() - 8;
1186 5 : pWMF->SeekRel( 0x10 );
1187 :
1188 5 : pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest );
1189 5 : *pWMF >> aFunc;
1190 5 : pWMF->ReadInt32( xSrc ).ReadInt32( ySrc );
1191 5 : *pWMF >> xformSrc;
1192 5 : pWMF->ReadUInt32( BkColorSrc ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
1193 5 : .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc ).ReadInt32( cxSrc ).ReadInt32( cySrc ) ;
1194 :
1195 5 : sal_uInt32 dwRop = SRCAND|SRCINVERT;
1196 :
1197 5 : Bitmap aBitmap;
1198 5 : Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
1199 :
1200 5 : if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
1201 0 : bStatus = false;
1202 : else
1203 : {
1204 5 : sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1205 5 : if ( nSize <= ( nEndPos - nStartPos ) )
1206 : {
1207 5 : char* pBuf = new char[ nSize ];
1208 5 : SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1209 5 : aTmp.ObjectOwnsMemory( true );
1210 5 : aTmp.WriteUChar( 'B' )
1211 5 : .WriteUChar( 'M' )
1212 5 : .WriteUInt32( cbBitsSrc )
1213 10 : .WriteUInt16( 0 )
1214 5 : .WriteUInt16( 0 )
1215 10 : .WriteUInt32( cbBmiSrc + 14 );
1216 5 : pWMF->Seek( nStart + offBmiSrc );
1217 5 : pWMF->Read( pBuf + 14, cbBmiSrc );
1218 5 : pWMF->Seek( nStart + offBitsSrc );
1219 5 : pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
1220 5 : aTmp.Seek( 0 );
1221 5 : ReadDIB(aBitmap, aTmp, true);
1222 :
1223 : // test if it is sensible to crop
1224 25 : if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
1225 20 : ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
1226 40 : ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
1227 15 : ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
1228 : {
1229 5 : Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1230 5 : aBitmap.Crop( aCropRect );
1231 : }
1232 5 : aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
1233 : }
1234 5 : }
1235 : }
1236 5 : break;
1237 :
1238 : case EMR_BITBLT : // PASSTHROUGH INTENDED
1239 : case EMR_STRETCHBLT :
1240 : {
1241 : sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
1242 : sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
1243 1158 : XForm xformSrc;
1244 :
1245 1158 : sal_uInt32 nStart = pWMF->Tell() - 8;
1246 :
1247 1158 : pWMF->SeekRel( 0x10 );
1248 1158 : pWMF->ReadInt32( xDest ).ReadInt32( yDest ).ReadInt32( cxDest ).ReadInt32( cyDest ).ReadUInt32( dwRop ).ReadInt32( xSrc ).ReadInt32( ySrc )
1249 1158 : >> xformSrc;
1250 1158 : pWMF->ReadUInt32( nColor ).ReadUInt32( iUsageSrc ).ReadUInt32( offBmiSrc ).ReadUInt32( cbBmiSrc )
1251 1158 : .ReadUInt32( offBitsSrc ).ReadUInt32( cbBitsSrc );
1252 :
1253 1158 : if ( nRecType == EMR_STRETCHBLT )
1254 32 : pWMF->ReadInt32( cxSrc ).ReadInt32( cySrc );
1255 : else
1256 1126 : cxSrc = cySrc = 0;
1257 :
1258 1158 : Bitmap aBitmap;
1259 1158 : Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
1260 :
1261 1158 : cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
1262 1158 : cyDest = abs( (int)cyDest ); // and also 122889
1263 :
1264 1158 : if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
1265 0 : bStatus = false;
1266 : else
1267 : {
1268 1158 : sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1269 1158 : if ( nSize <= ( nEndPos - nStartPos ) )
1270 : {
1271 1158 : char* pBuf = new char[ nSize ];
1272 1158 : SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1273 1158 : aTmp.ObjectOwnsMemory( true );
1274 1158 : aTmp.WriteUChar( 'B' )
1275 1158 : .WriteUChar( 'M' )
1276 1158 : .WriteUInt32( cbBitsSrc )
1277 2316 : .WriteUInt16( 0 )
1278 1158 : .WriteUInt16( 0 )
1279 2316 : .WriteUInt32( cbBmiSrc + 14 );
1280 1158 : pWMF->Seek( nStart + offBmiSrc );
1281 1158 : pWMF->Read( pBuf + 14, cbBmiSrc );
1282 1158 : pWMF->Seek( nStart + offBitsSrc );
1283 1158 : pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
1284 1158 : aTmp.Seek( 0 );
1285 1158 : ReadDIB(aBitmap, aTmp, true);
1286 :
1287 : // test if it is sensible to crop
1288 4634 : if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
1289 8 : ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
1290 3484 : ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
1291 1162 : ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
1292 : {
1293 2 : Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1294 2 : aBitmap.Crop( aCropRect );
1295 : }
1296 1158 : aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
1297 : }
1298 1158 : }
1299 : }
1300 1158 : break;
1301 :
1302 : case EMR_STRETCHDIBITS :
1303 : {
1304 : sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
1305 : sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
1306 37 : sal_uInt32 nStart = pWMF->Tell() - 8;
1307 :
1308 37 : pWMF->SeekRel( 0x10 );
1309 37 : pWMF->ReadInt32( xDest )
1310 37 : .ReadInt32( yDest )
1311 37 : .ReadInt32( xSrc )
1312 37 : .ReadInt32( ySrc )
1313 37 : .ReadInt32( cxSrc )
1314 37 : .ReadInt32( cySrc )
1315 37 : .ReadUInt32( offBmiSrc )
1316 37 : .ReadUInt32( cbBmiSrc )
1317 37 : .ReadUInt32( offBitsSrc )
1318 37 : .ReadUInt32( cbBitsSrc )
1319 37 : .ReadUInt32( iUsageSrc )
1320 37 : .ReadUInt32( dwRop )
1321 37 : .ReadInt32( cxDest )
1322 37 : .ReadInt32( cyDest );
1323 :
1324 37 : Bitmap aBitmap;
1325 37 : Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
1326 :
1327 37 : cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
1328 37 : cyDest = abs( (int)cyDest ); // and also 122889
1329 :
1330 37 : if ( ((SAL_MAX_UINT32 - 14) < cbBitsSrc)
1331 37 : || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc )
1332 : )
1333 : {
1334 0 : bStatus = false;
1335 : }
1336 : else
1337 : {
1338 37 : sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1339 37 : if ( nSize <= ( nEndPos - nStartPos ) )
1340 : {
1341 37 : char* pBuf = new char[ nSize ];
1342 37 : SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1343 37 : aTmp.ObjectOwnsMemory( true );
1344 37 : aTmp.WriteUChar( 'B' )
1345 37 : .WriteUChar( 'M' )
1346 37 : .WriteUInt32( cbBitsSrc )
1347 74 : .WriteUInt16( 0 )
1348 37 : .WriteUInt16( 0 )
1349 74 : .WriteUInt32( cbBmiSrc + 14 );
1350 37 : pWMF->Seek( nStart + offBmiSrc );
1351 37 : pWMF->Read( pBuf + 14, cbBmiSrc );
1352 37 : pWMF->Seek( nStart + offBitsSrc );
1353 37 : pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
1354 37 : aTmp.Seek( 0 );
1355 37 : ReadDIB(aBitmap, aTmp, true);
1356 :
1357 : // test if it is sensible to crop
1358 185 : if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
1359 148 : ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
1360 296 : ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
1361 111 : ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
1362 : {
1363 37 : Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1364 37 : aBitmap.Crop( aCropRect );
1365 : }
1366 37 : aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
1367 : }
1368 37 : }
1369 : }
1370 37 : break;
1371 :
1372 : case EMR_EXTCREATEFONTINDIRECTW :
1373 : {
1374 393 : pWMF->ReadUInt32( nIndex );
1375 393 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1376 : {
1377 393 : LOGFONTW aLogFont;
1378 393 : pWMF->ReadInt32( aLogFont.lfHeight )
1379 393 : .ReadInt32( aLogFont.lfWidth )
1380 393 : .ReadInt32( aLogFont.lfEscapement )
1381 393 : .ReadInt32( aLogFont.lfOrientation )
1382 393 : .ReadInt32( aLogFont.lfWeight )
1383 393 : .ReadUChar( aLogFont.lfItalic )
1384 393 : .ReadUChar( aLogFont.lfUnderline )
1385 393 : .ReadUChar( aLogFont.lfStrikeOut )
1386 393 : .ReadUChar( aLogFont.lfCharSet )
1387 393 : .ReadUChar( aLogFont.lfOutPrecision )
1388 393 : .ReadUChar( aLogFont.lfClipPrecision )
1389 393 : .ReadUChar( aLogFont.lfQuality )
1390 393 : .ReadUChar( aLogFont.lfPitchAndFamily );
1391 :
1392 : sal_Unicode lfFaceName[LF_FACESIZE+1];
1393 393 : lfFaceName[LF_FACESIZE] = 0;
1394 12969 : for (int i = 0; i < LF_FACESIZE; ++i)
1395 : {
1396 12576 : sal_uInt16 nChar(0);
1397 12576 : pWMF->ReadUInt16(nChar);
1398 12576 : lfFaceName[i] = nChar;
1399 : }
1400 393 : aLogFont.alfFaceName = OUString( lfFaceName );
1401 :
1402 : // #i123216# Not used in the test case of #121382# (always identity in XForm), also
1403 : // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1404 : // from #i123216# creates errors, so removing.
1405 :
1406 : // // #i121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1407 : // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1408 : // // constraints and dangers
1409 : // const XForm& rXF = pOut->GetWorldTransform();
1410 : // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1411 : // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1412 : // aLogFont.lfWidth = aTransVec.getX();
1413 : // aLogFont.lfHeight = aTransVec.getY();
1414 :
1415 393 : pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
1416 : }
1417 : }
1418 393 : break;
1419 :
1420 : case EMR_EXTTEXTOUTA :
1421 0 : bFlag = true;
1422 : case EMR_EXTTEXTOUTW :
1423 : {
1424 : sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
1425 : sal_uInt32 nCurPos, nOffString, nOptions, offDx;
1426 : sal_Int32 nLen;
1427 1401 : long* pDX = NULL;
1428 :
1429 1401 : nCurPos = pWMF->Tell() - 8;
1430 :
1431 1401 : pWMF->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom ).ReadInt32( nGfxMode ).ReadInt32( nXScale ).ReadInt32( nYScale )
1432 1401 : .ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
1433 :
1434 1401 : pWMF->SeekRel( 0x10 );
1435 1401 : pWMF->ReadUInt32( offDx );
1436 :
1437 1401 : ComplexTextLayoutMode nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
1438 1401 : if ( nOptions & ETO_RTLREADING )
1439 0 : nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
1440 1401 : pOut->SetTextLayoutMode( nTextLayoutMode );
1441 : DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1442 :
1443 1401 : Point aPos( ptlReferenceX, ptlReferenceY );
1444 1401 : if ( nLen && nLen < static_cast<sal_Int32>( SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
1445 : {
1446 1397 : if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
1447 : {
1448 1397 : pWMF->Seek( nCurPos + offDx );
1449 1397 : if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
1450 : {
1451 1397 : pDX = new long[ nLen ];
1452 : sal_Int32 i;
1453 : sal_Int32 val;
1454 8865 : for ( i = 0; i < nLen; i++ )
1455 : {
1456 7468 : pWMF->ReadInt32( val );
1457 7468 : pDX[ i ] = val;
1458 : }
1459 : }
1460 : }
1461 1397 : pWMF->Seek( nCurPos + nOffString );
1462 1397 : OUString aText;
1463 1397 : if ( bFlag )
1464 : {
1465 0 : if ( nLen <= static_cast<sal_Int32>( nEndPos - pWMF->Tell() ) )
1466 : {
1467 0 : boost::scoped_array<sal_Char> pBuf(new sal_Char[ nLen ]);
1468 0 : pWMF->Read( pBuf.get(), nLen );
1469 0 : aText = OUString( pBuf.get(), (sal_uInt16)nLen, pOut->GetCharSet() );
1470 0 : pBuf.reset();
1471 :
1472 0 : if ( aText.getLength() != nLen )
1473 : {
1474 : sal_uInt16 i, j;
1475 0 : long* pOldDx = pDX;
1476 0 : pDX = new long[ aText.getLength() ];
1477 0 : for ( i = 0, j = 0; i < aText.getLength(); i++ )
1478 : {
1479 0 : sal_Unicode cUniChar = aText[i];
1480 0 : OString aCharacter(&cUniChar, 1, pOut->GetCharSet());
1481 0 : pDX[ i ] = 0;
1482 0 : for (sal_Int32 k = 0; ( k < aCharacter.getLength() ) && ( j < nLen ) && ( i < aText.getLength() ); ++k)
1483 0 : pDX[ i ] += pOldDx[ j++ ];
1484 0 : }
1485 0 : delete[] pOldDx;
1486 0 : }
1487 : }
1488 : }
1489 : else
1490 : {
1491 1397 : if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
1492 : {
1493 1397 : boost::scoped_array<sal_Unicode> pBuf(new sal_Unicode[ nLen ]);
1494 1397 : pWMF->Read( pBuf.get(), nLen << 1 );
1495 : #ifdef OSL_BIGENDIAN
1496 : sal_Char nTmp, *pTmp = (sal_Char*)( pBuf.get() + nLen );
1497 : while ( pTmp-- != (sal_Char*)pBuf.get() )
1498 : {
1499 : nTmp = *pTmp--;
1500 : pTmp[ 1 ] = *pTmp;
1501 : *pTmp = nTmp;
1502 : }
1503 : #endif
1504 1397 : aText = OUString(pBuf.get(), nLen);
1505 : }
1506 : }
1507 1397 : pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
1508 : }
1509 1401 : delete[] pDX;
1510 : }
1511 1401 : break;
1512 :
1513 : case EMR_POLYBEZIERTO16 :
1514 41 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), true);
1515 41 : break;
1516 : case EMR_POLYBEZIER16 :
1517 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), false);
1518 0 : break;
1519 :
1520 : case EMR_POLYGON16 :
1521 73 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), false);
1522 73 : break;
1523 :
1524 : case EMR_POLYLINETO16 :
1525 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), true);
1526 0 : break;
1527 : case EMR_POLYLINE16 :
1528 2 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), false);
1529 2 : break;
1530 :
1531 : case EMR_POLYPOLYLINE16 :
1532 9 : ReadAndDrawPolyLine<sal_Int16>();
1533 9 : break;
1534 :
1535 : case EMR_POLYPOLYGON16 :
1536 42 : ReadAndDrawPolyPolygon<sal_Int16>();
1537 42 : break;
1538 :
1539 : case EMR_FILLRGN :
1540 : {
1541 : sal_uInt32 nLen;
1542 0 : tools::PolyPolygon aPolyPoly;
1543 0 : pWMF->SeekRel( 0x10 );
1544 0 : pWMF->ReadUInt32( nLen ).ReadUInt32( nIndex );
1545 :
1546 0 : if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
1547 : {
1548 0 : pOut->Push();
1549 0 : pOut->SelectObject( nIndex );
1550 0 : pOut->DrawPolyPolygon( aPolyPoly, false );
1551 0 : pOut->Pop();
1552 0 : }
1553 : }
1554 0 : break;
1555 :
1556 : case EMR_CREATEDIBPATTERNBRUSHPT :
1557 : {
1558 1 : sal_uInt32 nStart = pWMF->Tell() - 8;
1559 1 : Bitmap aBitmap;
1560 :
1561 1 : pWMF->ReadUInt32( nIndex );
1562 :
1563 1 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1564 : {
1565 : sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
1566 :
1567 1 : pWMF->ReadUInt32( usage );
1568 1 : pWMF->ReadUInt32( offBmi );
1569 1 : pWMF->ReadUInt32( cbBmi );
1570 1 : pWMF->ReadUInt32( offBits );
1571 1 : pWMF->ReadUInt32( cbBits );
1572 :
1573 1 : if ( (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
1574 0 : bStatus = false;
1575 1 : else if ( offBmi )
1576 : {
1577 1 : sal_uInt32 nSize = cbBmi + cbBits + 14;
1578 1 : if ( nSize <= ( nEndPos - nStartPos ) )
1579 : {
1580 1 : char* pBuf = new char[ nSize ];
1581 :
1582 1 : SvMemoryStream aTmp( pBuf, nSize, StreamMode::READ | StreamMode::WRITE );
1583 1 : aTmp.ObjectOwnsMemory( true );
1584 1 : aTmp.WriteUChar( 'B' )
1585 1 : .WriteUChar( 'M' )
1586 1 : .WriteUInt32( cbBits )
1587 2 : .WriteUInt16( 0 )
1588 1 : .WriteUInt16( 0 )
1589 2 : .WriteUInt32( cbBmi + 14 );
1590 1 : pWMF->Seek( nStart + offBmi );
1591 1 : pWMF->Read( pBuf + 14, cbBmi );
1592 1 : pWMF->Seek( nStart + offBits );
1593 1 : pWMF->Read( pBuf + 14 + cbBmi, cbBits );
1594 1 : aTmp.Seek( 0 );
1595 1 : ReadDIB(aBitmap, aTmp, true);
1596 : }
1597 : }
1598 : }
1599 :
1600 1 : pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aBitmap ) );
1601 : }
1602 1 : break;
1603 :
1604 0 : case EMR_MASKBLT : SAL_INFO("vcl.emf", "not implemented 'MaskBlt'"); break;
1605 0 : case EMR_PLGBLT : SAL_INFO("vcl.emf", "not implemented 'PlgBlt'"); break;
1606 0 : case EMR_SETDIBITSTODEVICE : SAL_INFO("vcl.emf", "not implemented 'SetDIBitsToDevice'"); break;
1607 0 : case EMR_FRAMERGN : SAL_INFO("vcl.emf", "not implemented 'FrameRgn'"); break;
1608 0 : case EMR_INVERTRGN : SAL_INFO("vcl.emf", "not implemented 'InvertRgn'"); break;
1609 0 : case EMR_PAINTRGN : SAL_INFO("vcl.emf", "not implemented 'PaintRgn'"); break;
1610 0 : case EMR_FLATTENPATH : SAL_INFO("vcl.emf", "not implemented 'FlattenPath'"); break;
1611 0 : case EMR_WIDENPATH : SAL_INFO("vcl.emf", "not implemented 'WidenPath'"); break;
1612 0 : case EMR_POLYDRAW : SAL_INFO("vcl.emf", "not implemented 'Polydraw'"); break;
1613 0 : case EMR_SETARCDIRECTION : SAL_INFO("vcl.emf", "not implemented 'SetArcDirection'"); break;
1614 0 : case EMR_SETPALETTEENTRIES : SAL_INFO("vcl.emf", "not implemented 'SetPaletteEntries'"); break;
1615 0 : case EMR_RESIZEPALETTE : SAL_INFO("vcl.emf", "not implemented 'ResizePalette'"); break;
1616 0 : case EMR_EXTFLOODFILL : SAL_INFO("vcl.emf", "not implemented 'ExtFloodFill'"); break;
1617 0 : case EMR_ANGLEARC : SAL_INFO("vcl.emf", "not implemented 'AngleArc'"); break;
1618 1 : case EMR_SETCOLORADJUSTMENT : SAL_INFO("vcl.emf", "not implemented 'SetColorAdjustment'"); break;
1619 0 : case EMR_POLYDRAW16 : SAL_INFO("vcl.emf", "not implemented 'PolyDraw16'"); break;
1620 0 : case EMR_POLYTEXTOUTA : SAL_INFO("vcl.emf", "not implemented 'PolyTextOutA'"); break;
1621 0 : case EMR_POLYTEXTOUTW : SAL_INFO("vcl.emf", "not implemented 'PolyTextOutW'"); break;
1622 0 : case EMR_CREATECOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'CreateColorSpace'"); break;
1623 0 : case EMR_SETCOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'SetColorSpace'"); break;
1624 0 : case EMR_DELETECOLORSPACE : SAL_INFO("vcl.emf", "not implemented 'DeleteColorSpace'"); break;
1625 0 : case EMR_GLSRECORD : SAL_INFO("vcl.emf", "not implemented 'GlsRecord'"); break;
1626 0 : case EMR_GLSBOUNDEDRECORD : SAL_INFO("vcl.emf", "not implemented 'GlsBoundRecord'"); break;
1627 0 : case EMR_PIXELFORMAT : SAL_INFO("vcl.emf", "not implemented 'PixelFormat'"); break;
1628 0 : case EMR_DRAWESCAPE : SAL_INFO("vcl.emf", "not implemented 'DrawEscape'"); break;
1629 0 : case EMR_EXTESCAPE : SAL_INFO("vcl.emf", "not implemented 'ExtEscape'"); break;
1630 0 : case EMR_STARTDOC : SAL_INFO("vcl.emf", "not implemented 'StartDoc'"); break;
1631 0 : case EMR_SMALLTEXTOUT : SAL_INFO("vcl.emf", "not implemented 'SmallTextOut'"); break;
1632 0 : case EMR_FORCEUFIMAPPING : SAL_INFO("vcl.emf", "not implemented 'ForceUFIMapping'"); break;
1633 0 : case EMR_NAMEDESCAPE : SAL_INFO("vcl.emf", "not implemented 'NamedEscape'"); break;
1634 0 : case EMR_COLORCORRECTPALETTE : SAL_INFO("vcl.emf", "not implemented 'ColorCorrectPalette'"); break;
1635 1 : case EMR_SETICMPROFILEA : SAL_INFO("vcl.emf", "not implemented 'SetICMProfileA'"); break;
1636 0 : case EMR_SETICMPROFILEW : SAL_INFO("vcl.emf", "not implemented 'SetICMProfileW'"); break;
1637 0 : case EMR_TRANSPARENTBLT : SAL_INFO("vcl.emf", "not implemented 'TransparenBlt'"); break;
1638 0 : case EMR_TRANSPARENTDIB : SAL_INFO("vcl.emf", "not implemented 'TransparenDib'"); break;
1639 0 : case EMR_GRADIENTFILL : SAL_INFO("vcl.emf", "not implemented 'GradientFill'"); break;
1640 0 : case EMR_SETLINKEDUFIS : SAL_INFO("vcl.emf", "not implemented 'SetLinkedUFIS'"); break;
1641 :
1642 0 : case EMR_SETMAPPERFLAGS : SAL_INFO("vcl.emf", "not implemented 'SetMapperFlags'"); break;
1643 0 : case EMR_SETICMMODE : SAL_INFO("vcl.emf", "not implemented 'SetICMMode'"); break;
1644 0 : case EMR_CREATEMONOBRUSH : SAL_INFO("vcl.emf", "not implemented 'CreateMonoBrush'"); break;
1645 1 : case EMR_SETBRUSHORGEX : SAL_INFO("vcl.emf", "not implemented 'SetBrushOrgEx'"); break;
1646 51 : case EMR_SETMETARGN : SAL_INFO("vcl.emf", "not implemented 'SetMetArgn'"); break;
1647 14 : case EMR_SETMITERLIMIT : SAL_INFO("vcl.emf", "not implemented 'SetMiterLimit'"); break;
1648 2 : case EMR_EXCLUDECLIPRECT : SAL_INFO("vcl.emf", "not implemented 'ExcludeClipRect'"); break;
1649 1 : case EMR_REALIZEPALETTE : SAL_INFO("vcl.emf", "not implemented 'RealizePalette'"); break;
1650 26 : case EMR_SELECTPALETTE : SAL_INFO("vcl.emf", "not implemented 'SelectPalette'"); break;
1651 1 : case EMR_CREATEPALETTE : SAL_INFO("vcl.emf", "not implemented 'CreatePalette'"); break;
1652 0 : case EMR_ALPHADIBBLEND : SAL_INFO("vcl.emf", "not implemented 'AlphaDibBlend'"); break;
1653 0 : case EMR_SETTEXTJUSTIFICATION : SAL_INFO("vcl.emf", "not implemented 'SetTextJustification'"); break;
1654 :
1655 : case EMR_GDICOMMENT :
1656 : case EMR_HEADER : // has already been read at ReadHeader()
1657 0 : break;
1658 :
1659 8 : default : SAL_INFO("vcl.emf", "Unknown Meta Action"); break;
1660 : }
1661 : }
1662 23724 : pWMF->Seek( nNextPos );
1663 : }
1664 131 : if( !aBmpSaveList.empty() )
1665 0 : pOut->ResolveBitmapActions( aBmpSaveList );
1666 :
1667 131 : if ( bStatus )
1668 127 : pWMF->Seek(nEndPos);
1669 :
1670 131 : return bStatus;
1671 : };
1672 :
1673 131 : bool EnhWMFReader::ReadHeader()
1674 : {
1675 : sal_uInt32 nType, nSignature, nVersion;
1676 : sal_uInt32 nHeaderSize, nPalEntries;
1677 :
1678 : // Spare me the METAFILEHEADER here
1679 : // Reading the METAHEADER - EMR_HEADER ([MS-EMF] section 2.3.4.2 EMR_HEADER Record Types)
1680 131 : pWMF->ReadUInt32( nType ).ReadUInt32( nHeaderSize );
1681 131 : if (nType != 0x00000001)
1682 : {
1683 : // per [MS-EMF] 2.3.4.2 EMF Header Record Types, type MUST be 0x00000001
1684 : SAL_WARN("vcl.emf", "EMF header type is not set to 0x00000001 - possibly corrupted file?");
1685 0 : return false;
1686 : }
1687 :
1688 : // Start reading the EMR_HEADER Header object
1689 :
1690 : // bound size (RectL object, see [MS-WMF] section 2.2.2.19)
1691 131 : Rectangle rclBounds = ReadRectangle(); // rectangle in logical units
1692 :
1693 : // picture frame size (RectL object)
1694 131 : Rectangle rclFrame = ReadRectangle(); // rectangle in device units 1/100th mm
1695 :
1696 131 : pWMF->ReadUInt32( nSignature );
1697 :
1698 : // nSignature MUST be the ASCII characters "FME", see [WS-EMF] 2.2.9 Header Object
1699 : // and 2.1.14 FormatSignature Enumeration
1700 131 : if (nSignature != 0x464d4520)
1701 : {
1702 : SAL_WARN("vcl.emf", "EMF\t\tSignature is not 0x464d4520 (\"FME\") - possibly corrupted file?");
1703 0 : return false;
1704 : }
1705 :
1706 131 : pWMF->ReadUInt32(nVersion); // according to [WS-EMF] 2.2.9, this SHOULD be 0x0001000, however
1707 : // Microsoft note that not even Windows checks this...
1708 131 : if (nVersion != 0x00010000)
1709 : {
1710 : SAL_WARN("vcl.emf", "EMF\t\tThis really should be 0x00010000, though not absolutely essential...");
1711 : }
1712 :
1713 131 : pWMF->ReadUInt32(nEndPos); // size of metafile
1714 131 : nEndPos += nStartPos;
1715 :
1716 131 : sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
1717 131 : pWMF->Seek(STREAM_SEEK_TO_END);
1718 131 : sal_uInt32 nActualFileSize = pWMF->Tell();
1719 :
1720 131 : if ( nActualFileSize < nEndPos )
1721 : {
1722 : SAL_WARN("vcl.emf", "EMF\t\tEMF Header object records number of bytes as " << nEndPos
1723 : << ", however the file size is actually " << nActualFileSize
1724 : << " bytes. Possible file corruption?");
1725 1 : nEndPos = nActualFileSize;
1726 : }
1727 131 : pWMF->Seek(nStrmPos);
1728 :
1729 131 : pWMF->ReadInt32(nRecordCount);
1730 :
1731 131 : if (nRecordCount == 0)
1732 : {
1733 : SAL_WARN("vcl.emf", "EMF\t\tEMF Header object shows record counter as 0! This shouldn't "
1734 : "be possible... indicator of possible file corruption?");
1735 0 : return false;
1736 : }
1737 :
1738 : // the number of "handles", or graphics objects used in the metafile
1739 :
1740 : sal_uInt16 nHandlesCount;
1741 131 : pWMF->ReadUInt16(nHandlesCount);
1742 :
1743 : // the next 2 bytes are reserved, but according to [MS-EMF] section 2.2.9
1744 : // it MUST be 0x000 and MUST be ignored... the thing is, having such a specific
1745 : // value is actually pretty useful in checking if there is possible corruption
1746 :
1747 : sal_uInt16 nReserved;
1748 131 : pWMF->ReadUInt16(nReserved);
1749 :
1750 131 : if ( nReserved != 0x0000 )
1751 : {
1752 : SAL_WARN("vcl.emf", "EMF\t\tEMF Header object's reserved field is NOT 0x0000... possible "
1753 : "corruption?");
1754 : }
1755 :
1756 : // The next 4 bytes specifies the number of characters in the metafile description.
1757 : // The 4 bytes after that specific the offset from this record that contains the
1758 : // metafile description... zero means no description string.
1759 : // For now, we ignore it.
1760 :
1761 131 : pWMF->SeekRel(0x8);
1762 :
1763 : sal_Int32 nPixX, nPixY, nMillX, nMillY;
1764 131 : pWMF->ReadUInt32(nPalEntries);
1765 131 : pWMF->ReadInt32(nPixX);
1766 131 : pWMF->ReadInt32(nPixY);
1767 131 : pWMF->ReadInt32(nMillX);
1768 131 : pWMF->ReadInt32(nMillY);
1769 :
1770 131 : pOut->SetrclFrame(rclFrame);
1771 131 : pOut->SetrclBounds(rclBounds);
1772 131 : pOut->SetRefPix(Size( nPixX, nPixY ) );
1773 131 : pOut->SetRefMill(Size( nMillX, nMillY ) );
1774 :
1775 131 : pWMF->Seek(nStartPos + nHeaderSize);
1776 131 : return true;
1777 : }
1778 :
1779 262 : Rectangle EnhWMFReader::ReadRectangle()
1780 : {
1781 : sal_Int32 nLeft, nTop, nRight, nBottom;
1782 262 : pWMF->ReadInt32(nLeft);
1783 262 : pWMF->ReadInt32(nTop);
1784 262 : pWMF->ReadInt32(nRight);
1785 262 : pWMF->ReadInt32(nBottom);
1786 262 : return Rectangle(nLeft, nTop, nRight, nBottom);
1787 : }
1788 :
1789 429 : Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
1790 : {
1791 429 : Point aTL ( Point( x1, y1 ) );
1792 429 : Point aBR( Point( --x2, --y2 ) );
1793 429 : return Rectangle( aTL, aBR );
1794 801 : }
1795 :
1796 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|