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