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 :
21 : #include "winmtf.hxx"
22 : #include <osl/endian.h>
23 : #include <boost/bind.hpp>
24 :
25 : using namespace std;
26 : //=========================== GDI-Array ===================================
27 :
28 : #define EMR_HEADER 1
29 : #define EMR_POLYBEZIER 2
30 : #define EMR_POLYGON 3
31 : #define EMR_POLYLINE 4
32 : #define EMR_POLYBEZIERTO 5
33 : #define EMR_POLYLINETO 6
34 : #define EMR_POLYPOLYLINE 7
35 : #define EMR_POLYPOLYGON 8
36 : #define EMR_SETWINDOWEXTEX 9
37 : #define EMR_SETWINDOWORGEX 10
38 : #define EMR_SETVIEWPORTEXTEX 11
39 : #define EMR_SETVIEWPORTORGEX 12
40 : #define EMR_SETBRUSHORGEX 13
41 : #define EMR_EOF 14
42 : #define EMR_SETPIXELV 15
43 : #define EMR_SETMAPPERFLAGS 16
44 : #define EMR_SETMAPMODE 17
45 : #define EMR_SETBKMODE 18
46 : #define EMR_SETPOLYFILLMODE 19
47 : #define EMR_SETROP2 20
48 : #define EMR_SETSTRETCHBLTMODE 21
49 : #define EMR_SETTEXTALIGN 22
50 : #define EMR_SETCOLORADJUSTMENT 23
51 : #define EMR_SETTEXTCOLOR 24
52 : #define EMR_SETBKCOLOR 25
53 : #define EMR_OFFSETCLIPRGN 26
54 : #define EMR_MOVETOEX 27
55 : #define EMR_SETMETARGN 28
56 : #define EMR_EXCLUDECLIPRECT 29
57 : #define EMR_INTERSECTCLIPRECT 30
58 : #define EMR_SCALEVIEWPORTEXTEX 31
59 : #define EMR_SCALEWINDOWEXTEX 32
60 : #define EMR_SAVEDC 33
61 : #define EMR_RESTOREDC 34
62 : #define EMR_SETWORLDTRANSFORM 35
63 : #define EMR_MODIFYWORLDTRANSFORM 36
64 : #define EMR_SELECTOBJECT 37
65 : #define EMR_CREATEPEN 38
66 : #define EMR_CREATEBRUSHINDIRECT 39
67 : #define EMR_DELETEOBJECT 40
68 : #define EMR_ANGLEARC 41
69 : #define EMR_ELLIPSE 42
70 : #define EMR_RECTANGLE 43
71 : #define EMR_ROUNDRECT 44
72 : #define EMR_ARC 45
73 : #define EMR_CHORD 46
74 : #define EMR_PIE 47
75 : #define EMR_SELECTPALETTE 48
76 : #define EMR_CREATEPALETTE 49
77 : #define EMR_SETPALETTEENTRIES 50
78 : #define EMR_RESIZEPALETTE 51
79 : #define EMR_REALIZEPALETTE 52
80 : #define EMR_EXTFLOODFILL 53
81 : #define EMR_LINETO 54
82 : #define EMR_ARCTO 55
83 : #define EMR_POLYDRAW 56
84 : #define EMR_SETARCDIRECTION 57
85 : #define EMR_SETMITERLIMIT 58
86 : #define EMR_BEGINPATH 59
87 : #define EMR_ENDPATH 60
88 : #define EMR_CLOSEFIGURE 61
89 : #define EMR_FILLPATH 62
90 : #define EMR_STROKEANDFILLPATH 63
91 : #define EMR_STROKEPATH 64
92 : #define EMR_FLATTENPATH 65
93 : #define EMR_WIDENPATH 66
94 : #define EMR_SELECTCLIPPATH 67
95 : #define EMR_ABORTPATH 68
96 :
97 : #define EMR_GDICOMMENT 70
98 : #define EMR_FILLRGN 71
99 : #define EMR_FRAMERGN 72
100 : #define EMR_INVERTRGN 73
101 : #define EMR_PAINTRGN 74
102 : #define EMR_EXTSELECTCLIPRGN 75
103 : #define EMR_BITBLT 76
104 : #define EMR_STRETCHBLT 77
105 : #define EMR_MASKBLT 78
106 : #define EMR_PLGBLT 79
107 : #define EMR_SETDIBITSTODEVICE 80
108 : #define EMR_STRETCHDIBITS 81
109 : #define EMR_EXTCREATEFONTINDIRECTW 82
110 : #define EMR_EXTTEXTOUTA 83
111 : #define EMR_EXTTEXTOUTW 84
112 : #define EMR_POLYBEZIER16 85
113 : #define EMR_POLYGON16 86
114 : #define EMR_POLYLINE16 87
115 : #define EMR_POLYBEZIERTO16 88
116 : #define EMR_POLYLINETO16 89
117 : #define EMR_POLYPOLYLINE16 90
118 : #define EMR_POLYPOLYGON16 91
119 : #define EMR_POLYDRAW16 92
120 : #define EMR_CREATEMONOBRUSH 93
121 : #define EMR_CREATEDIBPATTERNBRUSHPT 94
122 : #define EMR_EXTCREATEPEN 95
123 : #define EMR_POLYTEXTOUTA 96
124 : #define EMR_POLYTEXTOUTW 97
125 :
126 : // WINDOWS VERSION >= 0x400
127 : #define EMR_SETICMMODE 98
128 : #define EMR_CREATECOLORSPACE 99
129 : #define EMR_SETCOLORSPACE 100
130 : #define EMR_DELETECOLORSPACE 101
131 : #define EMR_GLSRECORD 102
132 : #define EMR_GLSBOUNDEDRECORD 103
133 : #define EMR_PIXELFORMAT 104
134 :
135 : // WINDOWS VERSION >= 0x500
136 : #define EMR_DRAWESCAPE 105
137 : #define EMR_EXTESCAPE 106
138 : #define EMR_STARTDOC 107
139 : #define EMR_SMALLTEXTOUT 108
140 : #define EMR_FORCEUFIMAPPING 109
141 : #define EMR_NAMEDESCAPE 110
142 : #define EMR_COLORCORRECTPALETTE 111
143 : #define EMR_SETICMPROFILEA 112
144 : #define EMR_SETICMPROFILEW 113
145 : #define EMR_ALPHABLEND 114
146 : #define EMR_ALPHADIBBLEND 115
147 : #define EMR_TRANSPARENTBLT 116
148 : #define EMR_TRANSPARENTDIB 117
149 : #define EMR_GRADIENTFILL 118
150 : #define EMR_SETLINKEDUFIS 119
151 : #define EMR_SETTEXTJUSTIFICATION 120
152 :
153 : #if OSL_DEBUG_LEVEL > 1
154 : #define EMFP_DEBUG(x) x
155 : #else
156 : #define EMFP_DEBUG(x)
157 : #endif
158 :
159 : //-----------------------------------------------------------------------------------
160 :
161 : #ifdef OSL_BIGENDIAN
162 : // currently unused
163 : static float GetSwapFloat( SvStream& rSt )
164 : {
165 : float fTmp;
166 : sal_Int8* pPtr = (sal_Int8*)&fTmp;
167 : rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
168 : return fTmp;
169 : }
170 : #endif
171 :
172 32 : SvStream& operator>>( SvStream& rIn, XForm& rXForm )
173 : {
174 : if ( sizeof( float ) != 4 )
175 : {
176 : OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
177 : rXForm = XForm();
178 : }
179 : else
180 : {
181 : #ifdef OSL_BIGENDIAN
182 : rXForm.eM11 = GetSwapFloat( rIn );
183 : rXForm.eM12 = GetSwapFloat( rIn );
184 : rXForm.eM21 = GetSwapFloat( rIn );
185 : rXForm.eM22 = GetSwapFloat( rIn );
186 : rXForm.eDx = GetSwapFloat( rIn );
187 : rXForm.eDy = GetSwapFloat( rIn );
188 : #else
189 32 : rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
190 64 : >> rXForm.eDx >> rXForm.eDy;
191 : #endif
192 : }
193 32 : return rIn;
194 : }
195 :
196 0 : static sal_Bool ImplReadRegion( PolyPolygon& rPolyPoly, SvStream& rSt, sal_uInt32 nLen )
197 : {
198 0 : sal_Bool bOk = sal_False;
199 0 : if ( nLen )
200 : {
201 : sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
202 0 : rSt >> nHdSize
203 0 : >> nType
204 0 : >> nCount
205 0 : >> nRgnSize;
206 :
207 0 : if ( nCount && ( nType == RDH_RECTANGLES ) &&
208 : ( nLen >= ( ( nCount << 4 ) + ( nHdSize - 16 ) ) ) )
209 : {
210 : sal_Int32 nx1, ny1, nx2, ny2;
211 :
212 0 : for ( i = 0; i < nCount; i++ )
213 : {
214 0 : rSt >> nx1 >> ny1 >> nx2 >> ny2;
215 :
216 0 : Rectangle aRect( Point( nx1, ny1 ), Point( nx2, ny2 ) );
217 0 : Polygon aPolygon( aRect );
218 0 : PolyPolygon aPolyPolyOr1( aPolygon );
219 0 : PolyPolygon aPolyPolyOr2( rPolyPoly );
220 0 : rPolyPoly.GetUnion( aPolyPolyOr1, aPolyPolyOr2 );
221 0 : rPolyPoly = aPolyPolyOr2;
222 0 : }
223 0 : bOk = sal_True;
224 : }
225 : }
226 0 : return bOk;
227 : }
228 :
229 : EMFP_DEBUG(void dumpWords( SvStream& s, int i )
230 : {
231 : sal_uInt32 pos = s.Tell();
232 : sal_Int16 data;
233 : for( ; i > 0; i -- ) {
234 : s >> data;
235 : EMFP_DEBUG(printf ("\t\t\tdata: %04hx\n", data));
236 : }
237 : s.Seek (pos);
238 : });
239 :
240 70 : void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length, sal_Bool& bHaveDC)
241 : {
242 70 : if (!bEMFPlus) {
243 4 : pOut->PassEMFPlusHeaderInfo();
244 :
245 : // debug code - write the stream to debug file /tmp/emf-stream.emf
246 : EMFP_DEBUG(int pos = pWMF->Tell();
247 : pWMF->Seek(0);
248 : SvFileStream file( rtl::OUString( "/tmp/emf-stream.emf" ), STREAM_WRITE | STREAM_TRUNC );
249 :
250 : *pWMF >> file;
251 : file.Flush();
252 : file.Close();
253 :
254 : pWMF->Seek( pos );)
255 : }
256 70 : bEMFPlus = true;
257 :
258 70 : sal_Size pos = pWMF->Tell();
259 70 : void *buffer = malloc( length );
260 70 : pOut->PassEMFPlus( buffer, pWMF->Read( buffer, length ) );
261 70 : free( buffer );
262 70 : pWMF->Seek( pos );
263 :
264 70 : bHaveDC = false;
265 :
266 : OSL_ASSERT(length >= 4);
267 : //reduce by 32bit length itself, skip in SeekRel if
268 : //impossibly unavailble
269 70 : sal_uInt32 nRemainder = length >= 4 ? length-4 : length;
270 :
271 70 : const size_t nRequiredHeaderSize = 12;
272 313 : while (nRemainder >= nRequiredHeaderSize)
273 : {
274 173 : sal_uInt16 type(0), flags(0);
275 173 : sal_uInt32 size(0), dataSize(0);
276 :
277 173 : *pWMF >> type >> flags >> size >> dataSize;
278 173 : nRemainder -= nRequiredHeaderSize;
279 :
280 : EMFP_DEBUG(printf ("\t\tEMF+ record type: %d\n", type));
281 :
282 : // GetDC
283 173 : if( type == 16388 ) {
284 19 : bHaveDC = true;
285 : EMFP_DEBUG(printf ("\t\tEMF+ lock DC (device context)\n"));
286 : }
287 :
288 : //Get the length of the remaining data of this record based
289 : //on the alleged size
290 : sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
291 173 : size-nRequiredHeaderSize : 0;
292 : //clip to available size
293 173 : nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
294 173 : pWMF->SeekRel(nRemainingRecordData);
295 173 : nRemainder -= nRemainingRecordData;
296 : }
297 70 : pWMF->SeekRel(nRemainder);
298 70 : }
299 :
300 : /**
301 : * Reads polygons from the stream.
302 : * The <class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
303 : * The <class Drawer> parameter is a boost binding for the method that will draw the polygon.
304 : * skipFirst: if the first point read is the 0th point or the 1st point in the array.
305 : * */
306 : template <class T, class Drawer>
307 207 : void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer, const sal_Bool skipFirst)
308 : {
309 207 : sal_uInt32 nPoints(0), nStartIndex(0);
310 207 : pWMF->SeekRel( 16 );
311 207 : *pWMF >> nPoints;
312 207 : if (skipFirst)
313 : {
314 21 : nPoints ++;
315 21 : nStartIndex ++;
316 : }
317 :
318 207 : Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
319 207 : drawer(pOut, aPolygon, skipFirst, bRecordPath);
320 207 : }
321 :
322 :
323 : /**
324 : * Reads polygons from the stream.
325 : * The <class T> parameter is for the type of the points
326 : * nStartIndex: which is the starting index in the polygon of the first point read
327 : * nPoints: number of points
328 : * pWMF: the stream containings the polygons
329 : * */
330 : template <class T>
331 207 : Polygon EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
332 : {
333 207 : Polygon aPolygon(nPoints);
334 1403 : for (sal_uInt16 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
335 : {
336 : T nX, nY;
337 1196 : *pWMF >> nX >> nY;
338 1196 : if (!pWMF->good())
339 : break;
340 1196 : aPolygon[ i ] = Point( nX, nY );
341 : }
342 :
343 207 : return aPolygon;
344 : }
345 :
346 : /**
347 : * Reads a polyline from the WMF file and draws it
348 : * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
349 : * */
350 : template <class T>
351 0 : void EnhWMFReader::ReadAndDrawPolyLine()
352 : {
353 : sal_uInt32 nPoints;
354 0 : sal_Int32 i, nPoly(0), nGesPoints(0);
355 0 : pWMF->SeekRel( 0x10 );
356 : // Number of Polygons:
357 0 : *pWMF >> nPoly >> nGesPoints;
358 :
359 : // taking the amount of points of each polygon, retrieving the total number of points
360 0 : if ( pWMF->good() &&
361 : ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
362 : ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() )
363 : )
364 : {
365 0 : sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
366 0 : for ( i = 0; i < nPoly && pWMF->good(); i++ )
367 : {
368 0 : *pWMF >> nPoints;
369 0 : pnPoints[ i ] = (sal_uInt16)nPoints;
370 : }
371 : // Get polygon points:
372 0 : for ( i = 0; ( i < nPoly ) && pWMF->good(); i++ )
373 : {
374 0 : Polygon aPolygon = ReadPolygon<T>(0, pnPoints[i]);
375 0 : pOut->DrawPolyLine( aPolygon, sal_False, bRecordPath );
376 : }
377 0 : delete[] pnPoints;
378 : }
379 0 : }
380 :
381 : /**
382 : * Reads a poly polygon from the WMF file and draws it.
383 : * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
384 : * */
385 : template <class T>
386 6 : void EnhWMFReader::ReadAndDrawPolyPolygon()
387 : {
388 : sal_uInt32 i, nPoly, nGesPoints, nPoints;
389 6 : pWMF->SeekRel( 0x10 );
390 : // Number of polygons
391 6 : *pWMF >> nPoly >> nGesPoints;
392 6 : if ( pWMF->good() &&
393 : ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && //check against numeric overflowing
394 : ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
395 : ( ( nPoly * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) ))
396 : {
397 : //Get number of points in each polygon
398 6 : sal_uInt16 * pnPoints = new sal_uInt16[ nPoly ];
399 12 : for ( i = 0; i < nPoly && pWMF->good(); i++ )
400 : {
401 6 : *pWMF >> nPoints;
402 6 : pnPoints[ i ] = (sal_uInt16)nPoints;
403 : } //end for
404 6 : if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
405 : {
406 : // Get polygon points
407 6 : Point * pPtAry = new Point[ nGesPoints ];
408 49 : for ( i = 0; i < nGesPoints && pWMF->good(); i++ )
409 : {
410 : T nX, nY;
411 43 : *pWMF >> nX >> nY;
412 43 : pPtAry[ i ] = Point( nX, nY );
413 : } //end for
414 : // Create PolyPolygon Actions
415 6 : PolyPolygon aPolyPoly( (sal_uInt16)nPoly, pnPoints, pPtAry );
416 6 : pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
417 6 : delete[] pPtAry;
418 : } //end if
419 6 : delete[] pnPoints;
420 : } //end if
421 6 : }
422 :
423 15 : sal_Bool EnhWMFReader::ReadEnhWMF()
424 : {
425 15 : sal_uInt32 nStretchBltMode = 0;
426 15 : sal_uInt32 nRecType(0), nRecSize(0), nNextPos(0),
427 15 : nW(0), nH(0), nColor(0), nIndex(0),
428 15 : nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
429 15 : sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
430 :
431 15 : sal_Bool bFlag(sal_False), bStatus = ReadHeader();
432 15 : sal_Bool bHaveDC = false;
433 :
434 15 : static sal_Bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == NULL );
435 :
436 3269 : while( bStatus && nRecordCount-- && pWMF->good())
437 : {
438 3242 : *pWMF >> nRecType >> nRecSize;
439 :
440 3242 : if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
441 : {
442 2 : bStatus = sal_False;
443 2 : break;
444 : }
445 :
446 3240 : nNextPos = pWMF->Tell() + ( nRecSize - 8 );
447 :
448 3240 : if ( !pWMF->good() || nNextPos > nEndPos )
449 : {
450 1 : bStatus = sal_False;
451 1 : break;
452 : }
453 :
454 3239 : if( !aBmpSaveList.empty()
455 : && ( nRecType != EMR_STRETCHBLT )
456 : && ( nRecType != EMR_STRETCHDIBITS )
457 : )
458 19 : pOut->ResolveBitmapActions( aBmpSaveList );
459 :
460 3239 : bFlag = sal_False;
461 :
462 : EMFP_DEBUG(printf ("0x%04x-0x%04x record type: %d size: %d\n",(unsigned int) (nNextPos - nRecSize),(unsigned int) nNextPos, (int)nRecType,(int) nRecSize));
463 :
464 3239 : if( bEnableEMFPlus && nRecType == EMR_GDICOMMENT ) {
465 : sal_uInt32 length;
466 :
467 73 : *pWMF >> length;
468 :
469 : EMFP_DEBUG(printf ("\tGDI comment\n\t\tlength: %d\n", (int)length));
470 :
471 73 : if( pWMF->good() && length >= 4 ) {
472 : sal_uInt32 id;
473 :
474 73 : *pWMF >> id;
475 :
476 : EMFP_DEBUG(printf ("\t\tbegin %c%c%c%c id: 0x%x\n", (char)(id & 0xff), (char)((id & 0xff00) >> 8), (char)((id & 0xff0000) >> 16), (char)((id & 0xff000000) >> 24), (unsigned int)id));
477 :
478 : // EMF+ comment (fixme: BE?)
479 73 : if( id == 0x2B464D45 && nRecSize >= 12 )
480 70 : ReadEMFPlusComment( length, bHaveDC );
481 : // GDIC comment, doesn't do anything useful yet
482 0 : else if( id == 0x43494447 && nRecSize >= 12 ) {
483 : //ToDo: ReadGDIComment()
484 : } else {
485 : EMFP_DEBUG(printf ("\t\tunknown id: 0x%x\n",(unsigned int) id));
486 : }
487 73 : }
488 3166 : } else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
489 :
490 2185 : switch( nRecType )
491 : {
492 : case EMR_POLYBEZIERTO :
493 0 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
494 0 : break;
495 : case EMR_POLYBEZIER :
496 0 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
497 0 : break;
498 :
499 : case EMR_POLYGON :
500 48 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
501 48 : break;
502 :
503 : case EMR_POLYLINETO :
504 5 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
505 5 : break;
506 : case EMR_POLYLINE :
507 138 : ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
508 138 : break;
509 :
510 : case EMR_POLYPOLYLINE :
511 0 : ReadAndDrawPolyLine<sal_Int32>();
512 0 : break;
513 :
514 : case EMR_POLYPOLYGON :
515 0 : ReadAndDrawPolyPolygon<sal_Int32>();
516 0 : break;
517 :
518 : case EMR_SETWINDOWEXTEX :
519 : { // #75383#
520 20 : *pWMF >> nW >> nH;
521 20 : pOut->SetWinExt( Size( nW, nH ) );
522 : }
523 20 : break;
524 :
525 : case EMR_SETWINDOWORGEX :
526 : {
527 17 : *pWMF >> nX32 >> nY32;
528 17 : pOut->SetWinOrg( Point( nX32, nY32 ) );
529 : }
530 17 : break;
531 :
532 : case EMR_SCALEWINDOWEXTEX :
533 : {
534 0 : *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
535 0 : pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
536 : }
537 0 : break;
538 :
539 : case EMR_SETVIEWPORTORGEX :
540 : {
541 11 : *pWMF >> nX32 >> nY32;
542 11 : pOut->SetDevOrg( Point( nX32, nY32 ) );
543 : }
544 11 : break;
545 :
546 : case EMR_SCALEVIEWPORTEXTEX :
547 : {
548 3 : *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
549 3 : pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
550 : }
551 3 : break;
552 :
553 : case EMR_SETVIEWPORTEXTEX :
554 : {
555 8 : *pWMF >> nW >> nH;
556 8 : pOut->SetDevExt( Size( nW, nH ) );
557 : }
558 8 : break;
559 :
560 : case EMR_EOF :
561 12 : nRecordCount = 0; // #76846#
562 12 : break;
563 :
564 : case EMR_SETPIXELV :
565 : {
566 0 : *pWMF >> nX32 >> nY32;
567 0 : pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
568 : }
569 0 : break;
570 :
571 : case EMR_SETMAPMODE :
572 : {
573 : sal_uInt32 nMapMode;
574 13 : *pWMF >> nMapMode;
575 13 : pOut->SetMapMode( nMapMode );
576 : }
577 13 : break;
578 :
579 : case EMR_SETBKMODE :
580 : {
581 11 : *pWMF >> nDat32;
582 11 : pOut->SetBkMode( nDat32 );
583 : }
584 11 : break;
585 :
586 : case EMR_SETPOLYFILLMODE :
587 22 : break;
588 :
589 : case EMR_SETROP2 :
590 : {
591 75 : *pWMF >> nDat32;
592 75 : pOut->SetRasterOp( nDat32 );
593 : }
594 75 : break;
595 :
596 : case EMR_SETSTRETCHBLTMODE :
597 : {
598 0 : *pWMF >> nStretchBltMode;
599 : }
600 0 : break;
601 :
602 : case EMR_SETTEXTALIGN :
603 : {
604 59 : *pWMF >> nDat32;
605 59 : pOut->SetTextAlign( nDat32 );
606 : }
607 59 : break;
608 :
609 : case EMR_SETTEXTCOLOR :
610 : {
611 62 : pOut->SetTextColor( ReadColor() );
612 : }
613 62 : break;
614 :
615 : case EMR_SETBKCOLOR :
616 : {
617 6 : pOut->SetBkColor( ReadColor() );
618 : }
619 6 : break;
620 :
621 : case EMR_OFFSETCLIPRGN :
622 : {
623 0 : *pWMF >> nX32 >> nY32;
624 0 : pOut->MoveClipRegion( Size( nX32, nY32 ) );
625 : }
626 0 : break;
627 :
628 : case EMR_MOVETOEX :
629 : {
630 21 : *pWMF >> nX32 >> nY32;
631 21 : pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
632 : }
633 21 : break;
634 :
635 : case EMR_INTERSECTCLIPRECT :
636 : {
637 3 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
638 3 : pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
639 : }
640 3 : break;
641 :
642 : case EMR_SAVEDC :
643 : {
644 91 : pOut->Push();
645 : }
646 91 : break;
647 :
648 : case EMR_RESTOREDC :
649 : {
650 79 : pOut->Pop();
651 : }
652 79 : break;
653 :
654 : case EMR_SETWORLDTRANSFORM :
655 : {
656 1 : XForm aTempXForm;
657 1 : *pWMF >> aTempXForm;
658 1 : pOut->SetWorldTransform( aTempXForm );
659 : }
660 1 : break;
661 :
662 : case EMR_MODIFYWORLDTRANSFORM :
663 : {
664 : sal_uInt32 nMode;
665 1 : XForm aTempXForm;
666 1 : *pWMF >> aTempXForm >> nMode;
667 1 : pOut->ModifyWorldTransform( aTempXForm, nMode );
668 : }
669 1 : break;
670 :
671 : case EMR_SELECTOBJECT :
672 : {
673 646 : *pWMF >> nIndex;
674 646 : pOut->SelectObject( nIndex );
675 : }
676 646 : break;
677 :
678 : case EMR_CREATEPEN :
679 : {
680 195 : *pWMF >> nIndex;
681 195 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
682 : {
683 :
684 195 : LineInfo aLineInfo;
685 : sal_uInt32 nStyle;
686 195 : Size aSize;
687 : //#fdo39428 Remove SvStream operator>>(long&)
688 195 : sal_Int32 nTmpW(0), nTmpH(0);
689 :
690 195 : *pWMF >> nStyle >> nTmpW >> nTmpH;
691 195 : aSize.Width() = nTmpW;
692 195 : aSize.Height() = nTmpH;
693 :
694 195 : if ( aSize.Width() )
695 0 : aLineInfo.SetWidth( aSize.Width() );
696 :
697 195 : sal_Bool bTransparent = sal_False;
698 195 : sal_uInt16 nDashCount = 0;
699 195 : sal_uInt16 nDotCount = 0;
700 195 : switch( nStyle )
701 : {
702 : case PS_DASHDOTDOT :
703 0 : nDotCount++;
704 : case PS_DASHDOT :
705 0 : nDashCount++;
706 : case PS_DOT :
707 0 : nDotCount++;
708 0 : break;
709 : case PS_DASH :
710 0 : nDashCount++;
711 0 : break;
712 : case PS_NULL :
713 48 : bTransparent = sal_True;
714 48 : aLineInfo.SetStyle( LINE_NONE );
715 48 : break;
716 : default :
717 : case PS_INSIDEFRAME :
718 : case PS_SOLID :
719 147 : aLineInfo.SetStyle( LINE_SOLID );
720 : }
721 195 : if ( nDashCount | nDotCount )
722 : {
723 0 : aLineInfo.SetStyle( LINE_DASH );
724 0 : aLineInfo.SetDashCount( nDashCount );
725 0 : aLineInfo.SetDotCount( nDotCount );
726 : }
727 195 : pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
728 : }
729 : }
730 195 : break;
731 :
732 : case EMR_EXTCREATEPEN :
733 : {
734 : sal_Int32 elpHatch;
735 : sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
736 3 : Color aColorRef;
737 :
738 3 : *pWMF >> nIndex;
739 3 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
740 : {
741 3 : *pWMF >> offBmi >> cbBmi >> offBits >> cbBits >> nStyle >> nWidth >> nBrushStyle;
742 3 : aColorRef = ReadColor();
743 3 : *pWMF >> elpHatch >> elpNumEntries;
744 :
745 3 : LineInfo aLineInfo;
746 3 : if ( nWidth )
747 0 : aLineInfo.SetWidth( nWidth );
748 :
749 3 : sal_Bool bTransparent = sal_False;
750 3 : sal_uInt16 nDashCount = 0;
751 3 : sal_uInt16 nDotCount = 0;
752 :
753 3 : switch( nStyle & PS_STYLE_MASK )
754 : {
755 : case PS_DASHDOTDOT :
756 0 : nDotCount++;
757 : case PS_DASHDOT :
758 0 : nDashCount++;
759 : case PS_DOT :
760 0 : nDotCount++;
761 0 : break;
762 : case PS_DASH :
763 0 : nDashCount++;
764 0 : break;
765 : case PS_NULL :
766 3 : bTransparent = sal_True;
767 3 : aLineInfo.SetStyle( LINE_NONE );
768 3 : break;
769 :
770 : default :
771 : case PS_INSIDEFRAME :
772 : case PS_SOLID :
773 0 : aLineInfo.SetStyle( LINE_SOLID );
774 : }
775 3 : if ( nDashCount | nDotCount )
776 : {
777 0 : aLineInfo.SetStyle( LINE_DASH );
778 0 : aLineInfo.SetDashCount( nDashCount );
779 0 : aLineInfo.SetDotCount( nDotCount );
780 : }
781 3 : pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( aColorRef, aLineInfo, bTransparent ) );
782 : }
783 : }
784 3 : break;
785 :
786 : case EMR_CREATEBRUSHINDIRECT :
787 : {
788 : sal_uInt32 nStyle;
789 64 : *pWMF >> nIndex;
790 64 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
791 : {
792 64 : *pWMF >> nStyle;
793 64 : pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
794 : }
795 : }
796 64 : break;
797 :
798 : case EMR_DELETEOBJECT :
799 : {
800 314 : *pWMF >> nIndex;
801 314 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
802 314 : pOut->DeleteObject( nIndex );
803 : }
804 314 : break;
805 :
806 : case EMR_ELLIPSE :
807 : {
808 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
809 0 : pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
810 : }
811 0 : break;
812 :
813 : case EMR_RECTANGLE :
814 : {
815 9 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
816 9 : pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
817 : }
818 9 : break;
819 :
820 : case EMR_ROUNDRECT :
821 : {
822 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nW >> nH;
823 0 : Size aSize( Size( nW, nH ) );
824 0 : pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
825 : }
826 0 : break;
827 :
828 : case EMR_ARC :
829 : {
830 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
831 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
832 0 : pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
833 : }
834 0 : break;
835 :
836 : case EMR_CHORD :
837 : {
838 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
839 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
840 0 : pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
841 : }
842 0 : break;
843 :
844 : case EMR_PIE :
845 : {
846 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
847 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
848 0 : const Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
849 :
850 : // #i73608# OutputDevice deviates from WMF
851 : // semantics. start==end means full ellipse here.
852 0 : if( nStartX == nEndX && nStartY == nEndY )
853 0 : pOut->DrawEllipse( aRect );
854 : else
855 0 : pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
856 : }
857 0 : break;
858 :
859 : case EMR_LINETO :
860 : {
861 0 : *pWMF >> nX32 >> nY32;
862 0 : pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
863 : }
864 0 : break;
865 :
866 : case EMR_ARCTO :
867 : {
868 : sal_uInt32 nStartX, nStartY, nEndX, nEndY;
869 0 : *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
870 0 : pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), sal_True );
871 : }
872 0 : break;
873 :
874 : case EMR_BEGINPATH :
875 : {
876 16 : pOut->ClearPath();
877 16 : bRecordPath = sal_True;
878 : }
879 16 : break;
880 :
881 : case EMR_ABORTPATH :
882 0 : pOut->ClearPath();
883 : case EMR_ENDPATH :
884 16 : bRecordPath = sal_False;
885 16 : break;
886 :
887 : case EMR_CLOSEFIGURE :
888 13 : pOut->ClosePath();
889 13 : break;
890 :
891 : case EMR_FILLPATH :
892 11 : pOut->StrokeAndFillPath( sal_False, sal_True );
893 11 : break;
894 :
895 : case EMR_STROKEANDFILLPATH :
896 0 : pOut->StrokeAndFillPath( sal_True, sal_True );
897 0 : break;
898 :
899 : case EMR_STROKEPATH :
900 0 : pOut->StrokeAndFillPath( sal_True, sal_False );
901 0 : break;
902 :
903 : case EMR_SELECTCLIPPATH :
904 : {
905 : sal_Int32 nClippingMode;
906 5 : *pWMF >> nClippingMode;
907 5 : pOut->SetClipPath( pOut->GetPathObj(), nClippingMode, sal_True );
908 : }
909 5 : break;
910 :
911 : case EMR_EXTSELECTCLIPRGN :
912 : {
913 : sal_Int32 iMode, cbRgnData;
914 3 : *pWMF >> cbRgnData
915 3 : >> iMode;
916 :
917 3 : PolyPolygon aPolyPoly;
918 3 : if ( cbRgnData )
919 0 : ImplReadRegion( aPolyPoly, *pWMF, nRecSize );
920 3 : pOut->SetClipPath( aPolyPoly, iMode, sal_False );
921 : }
922 3 : break;
923 :
924 : case EMR_BITBLT : // PASSTHROUGH INTENDED
925 : case EMR_STRETCHBLT :
926 : {
927 : sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
928 : sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
929 30 : XForm xformSrc;
930 :
931 30 : sal_uInt32 nStart = pWMF->Tell() - 8;
932 :
933 30 : pWMF->SeekRel( 0x10 );
934 30 : *pWMF >> xDest >> yDest >> cxDest >> cyDest >> dwRop >> xSrc >> ySrc
935 30 : >> xformSrc >> nColor >> iUsageSrc >> offBmiSrc >> cbBmiSrc
936 30 : >> offBitsSrc >> cbBitsSrc;
937 :
938 30 : if ( nRecType == EMR_STRETCHBLT )
939 30 : *pWMF >> cxSrc >> cySrc;
940 : else
941 0 : cxSrc = cySrc = 0;
942 :
943 30 : Bitmap aBitmap;
944 30 : Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
945 :
946 30 : cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
947 30 : cyDest = abs( (int)cyDest ); // and also 122889
948 :
949 30 : if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
950 0 : bStatus = sal_False;
951 : else
952 : {
953 30 : sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
954 30 : if ( nSize <= ( nEndPos - nStartPos ) )
955 : {
956 30 : char* pBuf = new char[ nSize ];
957 30 : SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
958 30 : aTmp.ObjectOwnsMemory( sal_True );
959 30 : aTmp << (sal_uInt8)'B'
960 30 : << (sal_uInt8)'M'
961 60 : << (sal_uInt32)cbBitsSrc
962 30 : << (sal_uInt16)0
963 30 : << (sal_uInt16)0
964 60 : << (sal_uInt32)cbBmiSrc + 14;
965 30 : pWMF->Seek( nStart + offBmiSrc );
966 30 : pWMF->Read( pBuf + 14, cbBmiSrc );
967 30 : pWMF->Seek( nStart + offBitsSrc );
968 30 : pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
969 30 : aTmp.Seek( 0 );
970 30 : aBitmap.Read( aTmp, sal_True );
971 :
972 : // test if it is sensible to crop
973 60 : if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
974 : ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
975 30 : ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
976 30 : ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
977 : {
978 0 : Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
979 0 : aBitmap.Crop( aCropRect );
980 : }
981 30 : aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
982 : }
983 30 : }
984 : }
985 30 : break;
986 :
987 : case EMR_STRETCHDIBITS :
988 : {
989 : sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
990 : sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
991 1 : sal_uInt32 nStart = pWMF->Tell() - 8;
992 :
993 1 : pWMF->SeekRel( 0x10 );
994 1 : *pWMF >> xDest
995 1 : >> yDest
996 1 : >> xSrc
997 1 : >> ySrc
998 1 : >> cxSrc
999 1 : >> cySrc
1000 1 : >> offBmiSrc
1001 1 : >> cbBmiSrc
1002 1 : >> offBitsSrc
1003 1 : >> cbBitsSrc
1004 1 : >> iUsageSrc
1005 1 : >> dwRop
1006 1 : >> cxDest
1007 1 : >> cyDest;
1008 :
1009 1 : Bitmap aBitmap;
1010 1 : Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
1011 :
1012 1 : cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
1013 1 : cyDest = abs( (int)cyDest ); // and also 122889
1014 :
1015 1 : if ( ((SAL_MAX_UINT32 - 14) < cbBitsSrc)
1016 : || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc )
1017 : )
1018 : {
1019 0 : bStatus = sal_False;
1020 : }
1021 : else
1022 : {
1023 1 : sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
1024 1 : if ( nSize <= ( nEndPos - nStartPos ) )
1025 : {
1026 1 : char* pBuf = new char[ nSize ];
1027 1 : SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
1028 1 : aTmp.ObjectOwnsMemory( sal_True );
1029 1 : aTmp << (sal_uInt8)'B'
1030 1 : << (sal_uInt8)'M'
1031 2 : << (sal_uInt32)cbBitsSrc
1032 1 : << (sal_uInt16)0
1033 1 : << (sal_uInt16)0
1034 2 : << (sal_uInt32)cbBmiSrc + 14;
1035 1 : pWMF->Seek( nStart + offBmiSrc );
1036 1 : pWMF->Read( pBuf + 14, cbBmiSrc );
1037 1 : pWMF->Seek( nStart + offBitsSrc );
1038 1 : pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
1039 1 : aTmp.Seek( 0 );
1040 1 : aBitmap.Read( aTmp, sal_True );
1041 :
1042 : // test if it is sensible to crop
1043 6 : if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
1044 : ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
1045 3 : ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
1046 3 : ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
1047 : {
1048 1 : Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
1049 1 : aBitmap.Crop( aCropRect );
1050 : }
1051 1 : aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
1052 : }
1053 1 : }
1054 : }
1055 1 : break;
1056 :
1057 : case EMR_EXTCREATEFONTINDIRECTW :
1058 : {
1059 63 : *pWMF >> nIndex;
1060 63 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1061 : {
1062 63 : LOGFONTW aLogFont;
1063 63 : *pWMF >> aLogFont.lfHeight
1064 63 : >> aLogFont.lfWidth
1065 63 : >> aLogFont.lfEscapement
1066 63 : >> aLogFont.lfOrientation
1067 63 : >> aLogFont.lfWeight
1068 63 : >> aLogFont.lfItalic
1069 63 : >> aLogFont.lfUnderline
1070 63 : >> aLogFont.lfStrikeOut
1071 63 : >> aLogFont.lfCharSet
1072 63 : >> aLogFont.lfOutPrecision
1073 63 : >> aLogFont.lfClipPrecision
1074 63 : >> aLogFont.lfQuality
1075 63 : >> aLogFont.lfPitchAndFamily;
1076 :
1077 : sal_Unicode lfFaceName[ LF_FACESIZE ];
1078 :
1079 2079 : for ( int i = 0; i < LF_FACESIZE; i++ )
1080 : {
1081 : sal_uInt16 nChar;
1082 2016 : *pWMF >> nChar;
1083 2016 : lfFaceName[ i ] = nChar;
1084 : }
1085 63 : aLogFont.alfFaceName = rtl::OUString( lfFaceName );
1086 63 : pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
1087 : }
1088 : }
1089 63 : break;
1090 :
1091 : case EMR_EXTTEXTOUTA :
1092 0 : bFlag = sal_True;
1093 : case EMR_EXTTEXTOUTW :
1094 : {
1095 : sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
1096 : sal_uInt32 nCurPos, nLen, nOffString, nOptions, offDx;
1097 65 : sal_Int32* pDX = NULL;
1098 :
1099 65 : nCurPos = pWMF->Tell() - 8;
1100 :
1101 65 : *pWMF >> nLeft >> nTop >> nRight >> nBottom >> nGfxMode >> nXScale >> nYScale
1102 65 : >> ptlReferenceX >> ptlReferenceY >> nLen >> nOffString >> nOptions;
1103 :
1104 65 : pWMF->SeekRel( 0x10 );
1105 65 : *pWMF >> offDx;
1106 :
1107 65 : sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
1108 65 : if ( nOptions & ETO_RTLREADING )
1109 0 : nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
1110 65 : pOut->SetTextLayoutMode( nTextLayoutMode );
1111 : DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1112 :
1113 65 : Point aPos( ptlReferenceX, ptlReferenceY );
1114 65 : if ( nLen && ( nLen < SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
1115 : {
1116 65 : if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
1117 : {
1118 65 : pWMF->Seek( nCurPos + offDx );
1119 65 : if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
1120 : {
1121 65 : pDX = new sal_Int32[ nLen ];
1122 : sal_uInt32 i;
1123 329 : for ( i = 0; i < nLen; i++ )
1124 264 : *pWMF >> pDX[ i ];
1125 : }
1126 : }
1127 65 : pWMF->Seek( nCurPos + nOffString );
1128 65 : String aText;
1129 65 : if ( bFlag )
1130 : {
1131 0 : if ( nLen <= ( nEndPos - pWMF->Tell() ) )
1132 : {
1133 0 : sal_Char* pBuf = new sal_Char[ nLen ];
1134 0 : pWMF->Read( pBuf, nLen );
1135 0 : aText = String( pBuf, (sal_uInt16)nLen, pOut->GetCharSet() );
1136 0 : delete[] pBuf;
1137 :
1138 0 : if ( aText.Len() != nLen )
1139 : {
1140 : sal_uInt16 i, j;
1141 0 : sal_Int32* pOldDx = pDX;
1142 0 : pDX = new sal_Int32[ aText.Len() ];
1143 0 : for ( i = 0, j = 0; i < aText.Len(); i++ )
1144 : {
1145 0 : sal_Unicode cUniChar = aText.GetChar(i);
1146 0 : rtl::OString aCharacter(&cUniChar, 1, pOut->GetCharSet());
1147 0 : pDX[ i ] = 0;
1148 0 : for (sal_Int32 k = 0; ( k < aCharacter.getLength() ) && ( j < nLen ) && ( i < aText.Len() ); ++k)
1149 0 : pDX[ i ] += pOldDx[ j++ ];
1150 0 : }
1151 0 : delete[] pOldDx;
1152 : }
1153 : }
1154 : }
1155 : else
1156 : {
1157 65 : if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
1158 : {
1159 65 : sal_Unicode* pBuf = new sal_Unicode[ nLen ];
1160 65 : pWMF->Read( pBuf, nLen << 1 );
1161 : #ifdef OSL_BIGENDIAN
1162 : sal_Char nTmp, *pTmp = (sal_Char*)( pBuf + nLen );
1163 : while ( pTmp-- != (sal_Char*)pBuf )
1164 : {
1165 : nTmp = *pTmp--;
1166 : pTmp[ 1 ] = *pTmp;
1167 : *pTmp = nTmp;
1168 : }
1169 : #endif
1170 65 : aText = rtl::OUString(pBuf, nLen);
1171 65 : delete[] pBuf;
1172 : }
1173 : }
1174 65 : pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
1175 : }
1176 65 : delete[] pDX;
1177 : }
1178 65 : break;
1179 :
1180 : case EMR_POLYBEZIERTO16 :
1181 16 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
1182 16 : break;
1183 : case EMR_POLYBEZIER16 :
1184 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
1185 0 : break;
1186 :
1187 : case EMR_POLYGON16 :
1188 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
1189 0 : break;
1190 :
1191 : case EMR_POLYLINETO16 :
1192 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
1193 0 : break;
1194 : case EMR_POLYLINE16 :
1195 0 : ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
1196 0 : break;
1197 :
1198 : case EMR_POLYPOLYLINE16 :
1199 0 : ReadAndDrawPolyLine<sal_Int16>();
1200 0 : break;
1201 :
1202 : case EMR_POLYPOLYGON16 :
1203 6 : ReadAndDrawPolyPolygon<sal_Int16>();
1204 6 : break;
1205 :
1206 : case EMR_FILLRGN :
1207 : {
1208 : sal_uInt32 nLen;
1209 0 : PolyPolygon aPolyPoly;
1210 0 : pWMF->SeekRel( 0x10 );
1211 0 : *pWMF >> nLen >> nIndex;
1212 :
1213 0 : if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
1214 : {
1215 0 : pOut->Push();
1216 0 : pOut->SelectObject( nIndex );
1217 0 : pOut->DrawPolyPolygon( aPolyPoly, sal_False );
1218 0 : pOut->Pop();
1219 0 : }
1220 : }
1221 0 : break;
1222 :
1223 : case EMR_CREATEDIBPATTERNBRUSHPT :
1224 : {
1225 1 : sal_uInt32 nStart = pWMF->Tell() - 8;
1226 1 : Bitmap aBitmap;
1227 :
1228 1 : *pWMF >> nIndex;
1229 :
1230 1 : if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1231 : {
1232 : sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
1233 :
1234 1 : *pWMF >> usage;
1235 1 : *pWMF >> offBmi;
1236 1 : *pWMF >> cbBmi;
1237 1 : *pWMF >> offBits;
1238 1 : *pWMF >> cbBits;
1239 :
1240 1 : if ( (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
1241 0 : bStatus = sal_False;
1242 1 : else if ( offBmi )
1243 : {
1244 1 : sal_uInt32 nSize = cbBmi + cbBits + 14;
1245 1 : if ( nSize <= ( nEndPos - nStartPos ) )
1246 : {
1247 1 : char* pBuf = new char[ nSize ];
1248 :
1249 1 : SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
1250 1 : aTmp.ObjectOwnsMemory( sal_True );
1251 1 : aTmp << (sal_uInt8)'B'
1252 1 : << (sal_uInt8)'M'
1253 2 : << (sal_uInt32)cbBits
1254 1 : << (sal_uInt16)0
1255 1 : << (sal_uInt16)0
1256 2 : << (sal_uInt32)cbBmi + 14;
1257 1 : pWMF->Seek( nStart + offBmi );
1258 1 : pWMF->Read( pBuf + 14, cbBmi );
1259 1 : pWMF->Seek( nStart + offBits );
1260 1 : pWMF->Read( pBuf + 14 + cbBmi, cbBits );
1261 1 : aTmp.Seek( 0 );
1262 1 : aBitmap.Read( aTmp, sal_True );
1263 : }
1264 : }
1265 : }
1266 :
1267 1 : pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aBitmap ) );
1268 : }
1269 1 : break;
1270 :
1271 : #ifdef WIN_MTF_ASSERT
1272 : default : WinMtfAssertHandler( "Unknown Meta Action" ); break;
1273 : case EMR_MASKBLT : WinMtfAssertHandler( "MaskBlt" ); break;
1274 : case EMR_PLGBLT : WinMtfAssertHandler( "PlgBlt" ); break;
1275 : case EMR_SETDIBITSTODEVICE : WinMtfAssertHandler( "SetDIBitsToDevice" ); break;
1276 : case EMR_FRAMERGN : WinMtfAssertHandler( "FrameRgn" ); break;
1277 : case EMR_INVERTRGN : WinMtfAssertHandler( "InvertRgn" ); break;
1278 : case EMR_PAINTRGN : WinMtfAssertHandler( "PaintRgn" ); break;
1279 : case EMR_FLATTENPATH : WinMtfAssertHandler( "FlattenPath" ); break;
1280 : case EMR_WIDENPATH : WinMtfAssertHandler( "WidenPath" ); break;
1281 : case EMR_POLYDRAW : WinMtfAssertHandler( "Polydraw" ); break;
1282 : case EMR_SETARCDIRECTION : WinMtfAssertHandler( "SetArcDirection" ); break;
1283 : case EMR_SETPALETTEENTRIES : WinMtfAssertHandler( "SetPaletteEntries" ); break;
1284 : case EMR_RESIZEPALETTE : WinMtfAssertHandler( "ResizePalette" ); break;
1285 : case EMR_EXTFLOODFILL : WinMtfAssertHandler( "ExtFloodFill" ); break;
1286 : case EMR_ANGLEARC : WinMtfAssertHandler( "AngleArc" ); break;
1287 : case EMR_SETCOLORADJUSTMENT : WinMtfAssertHandler( "SetColorAdjustment" ); break;
1288 : case EMR_POLYDRAW16 : WinMtfAssertHandler( "PolyDraw16" ); break;
1289 : case EMR_POLYTEXTOUTA : WinMtfAssertHandler( "PolyTextOutA" ); break;
1290 : case EMR_POLYTEXTOUTW : WinMtfAssertHandler( "PolyTextOutW" ); break;
1291 : case EMR_CREATECOLORSPACE : WinMtfAssertHandler( "CreateColorSpace" ); break;
1292 : case EMR_SETCOLORSPACE : WinMtfAssertHandler( "SetColorSpace" ); break;
1293 : case EMR_DELETECOLORSPACE : WinMtfAssertHandler( "DeleteColorSpace" ); break;
1294 : case EMR_GLSRECORD : WinMtfAssertHandler( "GlsRecord" ); break;
1295 : case EMR_GLSBOUNDEDRECORD : WinMtfAssertHandler( "GlsBoundRecord" ); break;
1296 : case EMR_PIXELFORMAT : WinMtfAssertHandler( "PixelFormat" ); break;
1297 : case EMR_DRAWESCAPE : WinMtfAssertHandler( "DrawEscape" ); break;
1298 : case EMR_EXTESCAPE : WinMtfAssertHandler( "ExtEscape" ); break;
1299 : case EMR_STARTDOC : WinMtfAssertHandler( "StartDoc" ); break;
1300 : case EMR_SMALLTEXTOUT : WinMtfAssertHandler( "SmallTextOut" ); break;
1301 : case EMR_FORCEUFIMAPPING : WinMtfAssertHandler( "ForceUFIMapping" ); break;
1302 : case EMR_NAMEDESCAPE : WinMtfAssertHandler( "NamedEscape" ); break;
1303 : case EMR_COLORCORRECTPALETTE : WinMtfAssertHandler( "ColorCorrectPalette" ); break;
1304 : case EMR_SETICMPROFILEA : WinMtfAssertHandler( "SetICMProfileA" ); break;
1305 : case EMR_SETICMPROFILEW : WinMtfAssertHandler( "SetICMProfileW" ); break;
1306 : case EMR_ALPHABLEND : WinMtfAssertHandler( "Alphablend" ); break;
1307 : case EMR_TRANSPARENTBLT : WinMtfAssertHandler( "TransparenBlt" ); break;
1308 : case EMR_TRANSPARENTDIB : WinMtfAssertHandler( "TransparenDib" ); break;
1309 : case EMR_GRADIENTFILL : WinMtfAssertHandler( "GradientFill" ); break;
1310 : case EMR_SETLINKEDUFIS : WinMtfAssertHandler( "SetLinkedUFIS" ); break;
1311 :
1312 : case EMR_SETMAPPERFLAGS : WinMtfAssertHandler( "SetMapperFlags", 0 ); break;
1313 : case EMR_SETICMMODE : WinMtfAssertHandler( "SetICMMode", 0 ); break;
1314 : case EMR_CREATEMONOBRUSH : WinMtfAssertHandler( "CreateMonoBrush", 0 ); break;
1315 : case EMR_SETBRUSHORGEX : WinMtfAssertHandler( "SetBrushOrgEx", 0 ); break;
1316 : case EMR_SETMETARGN : WinMtfAssertHandler( "SetMetArgn", 0 ); break;
1317 : case EMR_SETMITERLIMIT : WinMtfAssertHandler( "SetMiterLimit", 0 ); break;
1318 : case EMR_EXCLUDECLIPRECT : WinMtfAssertHandler( "ExcludeClipRect", 0 ); break;
1319 : case EMR_REALIZEPALETTE : WinMtfAssertHandler( "RealizePalette", 0 ); break;
1320 : case EMR_SELECTPALETTE : WinMtfAssertHandler( "SelectPalette", 0 ); break;
1321 : case EMR_CREATEPALETTE : WinMtfAssertHandler( "CreatePalette", 0 ); break;
1322 : case EMR_ALPHADIBBLEND : WinMtfAssertHandler( "AlphaDibBlend", 0 ); break;
1323 : case EMR_SETTEXTJUSTIFICATION : WinMtfAssertHandler( "SetTextJustification", 0 ); break;
1324 :
1325 : case EMR_GDICOMMENT :
1326 : case EMR_HEADER : // has already been read at ReadHeader()
1327 : break;
1328 : #endif
1329 : }
1330 3239 : pWMF->Seek( nNextPos );
1331 : }
1332 15 : if( !aBmpSaveList.empty() )
1333 0 : pOut->ResolveBitmapActions( aBmpSaveList );
1334 :
1335 15 : if ( bStatus )
1336 12 : pWMF->Seek(nEndPos);
1337 :
1338 15 : return bStatus;
1339 : };
1340 :
1341 : //-----------------------------------------------------------------------------------
1342 :
1343 15 : sal_Bool EnhWMFReader::ReadHeader()
1344 : {
1345 : sal_uInt32 nsal_uInt32, nHeaderSize, nPalEntries;
1346 : sal_Int32 nLeft, nTop, nRight, nBottom;
1347 :
1348 : // Spare me the METAFILEHEADER here
1349 : // Reading the METAHEADER
1350 15 : *pWMF >> nsal_uInt32 >> nHeaderSize;
1351 15 : if ( nsal_uInt32 != 1 ) // Type
1352 0 : return sal_False;
1353 :
1354 : // bound size
1355 15 : Rectangle rclBounds; // rectangle in logical units 1/100th mm
1356 15 : *pWMF >> nLeft >> nTop >> nRight >> nBottom;
1357 15 : rclBounds.Left() = nLeft;
1358 15 : rclBounds.Top() = nTop;
1359 15 : rclBounds.Right() = nRight;
1360 15 : rclBounds.Bottom() = nBottom;
1361 :
1362 : // picture frame size
1363 15 : Rectangle rclFrame; // rectangle in device units
1364 15 : *pWMF >> nLeft >> nTop >> nRight >> nBottom;
1365 15 : rclFrame.Left() = nLeft;
1366 15 : rclFrame.Top() = nTop;
1367 15 : rclFrame.Right() = nRight;
1368 15 : rclFrame.Bottom() = nBottom;
1369 :
1370 15 : *pWMF >> nsal_uInt32; // signature
1371 :
1372 15 : if ( nsal_uInt32 != 0x464d4520 )
1373 0 : return sal_False;
1374 :
1375 15 : *pWMF >> nsal_uInt32; // nVersion
1376 15 : *pWMF >> nEndPos; // size of metafile
1377 15 : nEndPos += nStartPos;
1378 :
1379 15 : sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
1380 15 : pWMF->Seek( STREAM_SEEK_TO_END );
1381 15 : if ( pWMF->Tell() < nEndPos )
1382 1 : nEndPos = pWMF->Tell();
1383 15 : pWMF->Seek( nStrmPos );
1384 :
1385 15 : *pWMF >> nRecordCount;
1386 :
1387 15 : if ( !nRecordCount )
1388 0 : return sal_False;
1389 :
1390 15 : pWMF->SeekRel( 0xc );
1391 :
1392 : sal_Int32 nPixX, nPixY, nMillX, nMillY;
1393 15 : *pWMF >> nPalEntries >> nPixX >> nPixY >> nMillX >> nMillY;
1394 :
1395 15 : pOut->SetrclFrame( rclFrame );
1396 15 : pOut->SetrclBounds( rclBounds );
1397 15 : pOut->SetRefPix( Size( nPixX, nPixY ) );
1398 15 : pOut->SetRefMill( Size( nMillX, nMillY ) );
1399 :
1400 15 : pWMF->Seek( nStartPos + nHeaderSize );
1401 15 : return sal_True;
1402 : }
1403 :
1404 : //-----------------------------------------------------------------------------------
1405 :
1406 12 : Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
1407 : {
1408 12 : Point aTL ( Point( x1, y1 ) );
1409 12 : Point aBR( Point( --x2, --y2 ) );
1410 12 : return Rectangle( aTL, aBR );
1411 : }
1412 :
1413 15 : EnhWMFReader::~EnhWMFReader()
1414 : {
1415 :
1416 123 : };
1417 :
1418 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|