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