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