xref: /trunk/main/svtools/source/filter/wmf/enhwmf.cxx (revision 721f84f2)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svtools.hxx"
24 
25 #include "winmtf.hxx"
26 #include <osl/endian.h>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <vcl/dibtools.hxx>
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
GetSwapFloat(SvStream & rSt)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 
operator >>(SvStream & rIn,BLENDFUNCTION & rBlendFun)180 SvStream& operator>>( SvStream& rIn, BLENDFUNCTION& rBlendFun )
181 {
182 	rIn >> rBlendFun.aBlendOperation >> rBlendFun.aBlendFlags >>
183 		     rBlendFun.aSrcConstantAlpha >> rBlendFun.aAlphaFormat;
184     return rIn;
185 }
operator >>(SvStream & rIn,XForm & rXForm)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 
ImplReadRegion(PolyPolygon & rPolyPoly,SvStream & rSt,sal_uInt32 nLen)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 
ReadEnhWMF()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 						ReadDIB(aBitmap, aTmp, true);
874 
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 						ReadDIB(aBitmap, aTmp, 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 						ReadDIB(aBitmap, aTmp, 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                     // #123216# Not used in the test case of #121382# (always identity in XForm), also
1027                     // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1028                     // from #123216# creates errors, so removing.
1029                     //
1030                     // // #121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1031                     // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1032                     // // constraints and dangers
1033                     // const XForm& rXF = pOut->GetWorldTransform();
1034                     // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1035                     // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1036                     // aLogFont.lfWidth = aTransVec.getX();
1037                     // aLogFont.lfHeight = aTransVec.getY();
1038 
1039 					pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
1040 				}
1041 			}
1042 			break;
1043 
1044 			case EMR_EXTTEXTOUTA :
1045 				bFlag = sal_True;
1046 			case EMR_EXTTEXTOUTW :
1047 			{
1048 				sal_Int32	nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
1049 				sal_uInt32	nCurPos, nLen, nOffString, nOptions, offDx;
1050 				sal_Int32*	pDX = NULL;
1051 
1052 				nCurPos = pWMF->Tell() - 8;
1053 
1054 				*pWMF >> nLeft >> nTop >> nRight >> nBottom >> nGfxMode >> nXScale >> nYScale
1055 					>> ptlReferenceX >> ptlReferenceY >> nLen >> nOffString >> nOptions;
1056 
1057 				pWMF->SeekRel( 0x10 );
1058 				*pWMF >> offDx;
1059 
1060 				sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
1061 				if ( nOptions & ETO_RTLREADING )
1062 					nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
1063 				pOut->SetTextLayoutMode( nTextLayoutMode );
1064 				DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1065 
1066 				Point aPos( ptlReferenceX, ptlReferenceY );
1067 				if ( nLen && ( nLen < SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
1068 				{
1069 					if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
1070 					{
1071 						pWMF->Seek( nCurPos + offDx );
1072 						if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
1073 						{
1074 							pDX = new sal_Int32[ nLen ];
1075 							sal_uInt32 i;
1076 							for ( i = 0; i < nLen; i++ )
1077 								*pWMF >> pDX[ i ];
1078 						}
1079 					}
1080 					pWMF->Seek( nCurPos + nOffString );
1081 					String aText;
1082 					if ( bFlag )
1083 					{
1084 						if ( nLen <= ( nEndPos - pWMF->Tell() ) )
1085 						{
1086 							sal_Char* pBuf = new sal_Char[ nLen ];
1087 							pWMF->Read( pBuf, nLen );
1088 							aText = String( pBuf, (sal_uInt16)nLen, pOut->GetCharSet() );
1089 							delete[] pBuf;
1090 
1091 							if ( aText.Len() != nLen )
1092 							{
1093 								sal_uInt16 i, j, k;
1094 								sal_Int32* pOldDx = pDX;
1095 								pDX = new sal_Int32[ aText.Len() ];
1096 								for ( i = 0, j = 0; i < aText.Len(); i++ )
1097 								{
1098 									ByteString aCharacter( aText.GetChar( i ), pOut->GetCharSet() );
1099 									pDX[ i ] = 0;
1100 									for ( k = 0; ( k < aCharacter.Len() ) && ( j < nLen ) && ( i < aText.Len() ); k++ )
1101 										pDX[ i ] += pOldDx[ j++ ];
1102 								}
1103 								delete[] pOldDx;
1104 							}
1105 						}
1106 					}
1107 					else
1108 					{
1109 						if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
1110 						{
1111 							sal_Unicode* pBuf = new sal_Unicode[ nLen ];
1112 							pWMF->Read( pBuf, nLen << 1 );
1113 #ifdef OSL_BIGENDIAN
1114 							sal_Char nTmp, *pTmp = (sal_Char*)( pBuf + nLen );
1115 							while ( pTmp-- != (sal_Char*)pBuf )
1116 							{
1117 								nTmp = *pTmp--;
1118 								pTmp[ 1 ] = *pTmp;
1119 								*pTmp = nTmp;
1120 							}
1121 #endif
1122 							aText = String( pBuf, (xub_StrLen)nLen );
1123 							delete[] pBuf;
1124 						}
1125 					}
1126 					pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
1127 				}
1128 				delete[] pDX;
1129 			}
1130 			break;
1131 
1132 			case EMR_POLYBEZIERTO16 :
1133 				bFlag = sal_True;
1134 			case EMR_POLYBEZIER16 :
1135 			{
1136 				pWMF->SeekRel( 16 );
1137 				*pWMF >> nPoints;
1138 				sal_uInt16 i = 0;
1139 				if ( bFlag )
1140 				{
1141 					i++;
1142 					nPoints++;
1143 				}
1144 				Polygon aPoly( (sal_uInt16)nPoints );
1145 				for( ; i < (sal_uInt16)nPoints; i++ )
1146 				{
1147 					*pWMF >> nX16 >> nY16;
1148 					aPoly[ i ] = Point( nX16, nY16 );
1149 				}
1150 				pOut->DrawPolyBezier( aPoly, bFlag, bRecordPath );	// Line( aPoly, bFlag );
1151 			}
1152 			break;
1153 
1154 			case EMR_POLYGON16 :
1155 			{
1156 				pWMF->SeekRel( 16 );
1157 				*pWMF >> nPoints;
1158 				Polygon aPoly( (sal_uInt16)nPoints );
1159 				for( sal_uInt16 k = 0; k < (sal_uInt16)nPoints; k++ )
1160 				{
1161 					*pWMF >> nX16 >> nY16;
1162 					aPoly[ k ] = Point( nX16, nY16 );
1163 				}
1164 				pOut->DrawPolygon( aPoly, bRecordPath );
1165 			}
1166 			break;
1167 
1168 			case EMR_POLYLINETO16 :
1169 				bFlag = sal_True;
1170 			case EMR_POLYLINE16 :
1171 			{
1172 				pWMF->SeekRel( 16 );
1173 				*pWMF >> nPoints;
1174 				sal_uInt16 i = 0;
1175 				if ( bFlag )
1176 				{
1177 					i++;
1178 					nPoints++;
1179 				}
1180 
1181 				Polygon aPoly( (sal_uInt16)nPoints );
1182 				for( ; i < (sal_uInt16)nPoints; i++ )
1183 				{
1184 					*pWMF >> nX16 >> nY16;
1185 					aPoly[ i ] = Point( nX16, nY16 );
1186 				}
1187 				pOut->DrawPolyLine( aPoly, bFlag, bRecordPath );
1188 			}
1189 			break;
1190 
1191 			case EMR_POLYPOLYLINE16 :
1192 			{
1193 				sal_uInt16*	pnPoints;
1194 
1195 				sal_Int32	i, nPoly, nGesPoints;
1196 				pWMF->SeekRel( 0x10 );
1197 				// Anzahl der Polygone:
1198 				*pWMF >> nPoly >> nGesPoints;
1199 
1200 				// taking the amount of points of each polygon, retrieving the total number of points
1201 				if ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) )
1202 				{
1203 					if ( ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() ) )
1204 					{
1205 						pnPoints = new sal_uInt16[ nPoly ];
1206 						for ( i = 0; i < nPoly; i++ )
1207 						{
1208 							*pWMF >> nPoints;
1209 							pnPoints[ i ] = (sal_uInt16)nPoints;
1210 						}
1211 						// Polygonpunkte holen:
1212 						for ( i = 0; ( i < nPoly ) && !pWMF->IsEof(); i++ )
1213 						{
1214 							Polygon aPolygon( pnPoints[ i ] );
1215 							for ( sal_uInt16 k = 0; k < pnPoints[ i ]; k++ )
1216 							{
1217 								*pWMF >> nX16 >> nY16;
1218 								aPolygon[ k ] = Point( nX16, nY16 );
1219 							}
1220 							pOut->DrawPolyLine( aPolygon, sal_False, bRecordPath );
1221 						}
1222 						delete[] pnPoints;
1223 					}
1224 				}
1225 			}
1226 			break;
1227 
1228 			case EMR_POLYPOLYGON16 :
1229 			{
1230 				sal_uInt32 nPoly(0);
1231                 sal_uInt32 nGesPoints(0);
1232 				pWMF->SeekRel( 0x10 );
1233 				// Anzahl der Polygone:
1234 				*pWMF >> nPoly >> nGesPoints;
1235                 sal_uInt32 nReadPoints(0);
1236 
1237                 if ( ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) )  && !pWMF->IsEof() )
1238 				{
1239 					if ( ( static_cast< sal_uInt32 >( nPoly ) * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) )
1240 					{
1241                         sal_uInt32 i(0);
1242 						sal_uInt16*	pnPoints = new sal_uInt16[ nPoly ];
1243 
1244                         for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
1245 						{
1246 							*pWMF >> nPoints;
1247 							pnPoints[ i ] = (sal_uInt16)nPoints;
1248 						}
1249 
1250                         if ( ( nGesPoints * (sizeof(sal_uInt16)+sizeof(sal_uInt16)) ) <= ( nEndPos - pWMF->Tell() )  && !pWMF->IsEof() )
1251 						{
1252                             PolyPolygon aPolyPoly(nPoly, nPoly);
1253 
1254 						    for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
1255 						    {
1256                                 const sal_uInt16 nPointCount(pnPoints[i]);
1257                 				Point* pPtAry = new Point[nPointCount];
1258 
1259                                 for(sal_uInt16 b(0); b < nPointCount && !pWMF->IsEof(); b++)
1260                                 {
1261 								    *pWMF >> nX16 >> nY16;
1262 								    pPtAry[b] = Point( nX16, nY16 );
1263                                     nReadPoints++;
1264                                 }
1265 
1266                                 aPolyPoly.Insert(Polygon(nPointCount, pPtAry));
1267                                 delete[] pPtAry;
1268                             }
1269 
1270 							// create PolyPolygon actions
1271 							pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
1272 						}
1273 
1274                         delete[] pnPoints;
1275 					}
1276 				}
1277 
1278                 OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON16 is unequal imported number (!)");
1279 			}
1280 			break;
1281 
1282 			case EMR_FILLRGN :
1283             {
1284                 sal_uInt32 nLen;
1285                 PolyPolygon aPolyPoly;
1286                 pWMF->SeekRel( 0x10 );
1287                 *pWMF >> nLen >> nIndex;
1288 
1289                 if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
1290                 {
1291                     pOut->Push();
1292                     pOut->SelectObject( nIndex );
1293 				    pOut->DrawPolyPolygon( aPolyPoly, sal_False );
1294                     pOut->Pop();
1295                 }
1296             }
1297             break;
1298 			case EMR_CREATEDIBPATTERNBRUSHPT :
1299 			{
1300 				sal_uInt32	nTmp32;
1301 				sal_uInt32  nOffset;
1302 				*pWMF >> nIndex;
1303 				Bitmap	aBmp;
1304 				BitmapReadAccess* pBmp;
1305 				sal_uInt32	nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
1306 
1307 				*pWMF >> nTmp32;
1308 				*pWMF >> nOffset;
1309 				for ( sal_uInt32 i = 0; i < (nOffset - 20)/4; i ++ )
1310 				{
1311 					*pWMF >> nTmp32;
1312 				}
1313 
1314 				ReadDIB(aBmp, *pWMF, false);
1315 				pBmp = aBmp.AcquireReadAccess();
1316 				if ( pBmp )
1317 				{
1318 					for ( sal_Int32 y = 0; y < pBmp->Height(); y++ )
1319 					{
1320 						for ( sal_Int32 x = 0; x < pBmp->Width(); x++ )
1321 						{
1322 							const BitmapColor aColor( pBmp->GetColor( y, x ) );
1323 
1324 							nRed += aColor.GetRed();
1325 							nGreen += aColor.GetGreen();
1326 							nBlue += aColor.GetBlue();
1327 						}
1328 					}
1329 					nCount = pBmp->Height() * pBmp->Width();
1330 					if ( !nCount )
1331 						nCount++;
1332 					aBmp.ReleaseAccess( pBmp );
1333 				}
1334 				Color aColor( (sal_Char)( nRed / nCount ), (sal_Char)( nGreen / nCount ), (sal_Char)( nBlue / nCount ) );
1335 				pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aColor, sal_False ) );
1336 			}
1337 			break;
1338 
1339 #ifdef WIN_MTF_ASSERT
1340             default :                           WinMtfAssertHandler( "Unknown Meta Action" );       break;
1341 			case EMR_MASKBLT :                  WinMtfAssertHandler( "MaskBlt" );                   break;
1342 			case EMR_PLGBLT :                   WinMtfAssertHandler( "PlgBlt" );                    break;
1343 			case EMR_SETDIBITSTODEVICE :        WinMtfAssertHandler( "SetDIBitsToDevice" );         break;
1344 			case EMR_FRAMERGN :                 WinMtfAssertHandler( "FrameRgn" );                  break;
1345 			case EMR_INVERTRGN :                WinMtfAssertHandler( "InvertRgn" );                 break;
1346             case EMR_PAINTRGN :                 WinMtfAssertHandler( "PaintRgn" );                  break;
1347             case EMR_FLATTENPATH :		        WinMtfAssertHandler( "FlattenPath" );               break;
1348             case EMR_WIDENPATH :                WinMtfAssertHandler( "WidenPath" );                 break;
1349 			case EMR_POLYDRAW :			        WinMtfAssertHandler( "Polydraw" );                  break;
1350 			case EMR_SETARCDIRECTION :	        WinMtfAssertHandler( "SetArcDirection" );           break;
1351 			case EMR_SETPALETTEENTRIES :        WinMtfAssertHandler( "SetPaletteEntries" );         break;
1352 			case EMR_RESIZEPALETTE :	        WinMtfAssertHandler( "ResizePalette" );             break;
1353 			case EMR_EXTFLOODFILL :		        WinMtfAssertHandler( "ExtFloodFill" );              break;
1354 			case EMR_ANGLEARC :     	        WinMtfAssertHandler( "AngleArc" );                  break;
1355 			case EMR_SETCOLORADJUSTMENT :       WinMtfAssertHandler( "SetColorAdjustment" );	    break;
1356 			case EMR_POLYDRAW16 :		        WinMtfAssertHandler( "PolyDraw16" );                break;
1357 			case EMR_POLYTEXTOUTA : 		    WinMtfAssertHandler( "PolyTextOutA" );              break;
1358 			case EMR_POLYTEXTOUTW :			    WinMtfAssertHandler( "PolyTextOutW" );              break;
1359 			case EMR_CREATECOLORSPACE :         WinMtfAssertHandler( "CreateColorSpace" );	        break;
1360             case EMR_SETCOLORSPACE :		    WinMtfAssertHandler( "SetColorSpace" );             break;
1361 			case EMR_DELETECOLORSPACE :		    WinMtfAssertHandler( "DeleteColorSpace" );          break;
1362 			case EMR_GLSRECORD :    		    WinMtfAssertHandler( "GlsRecord" );                 break;
1363 			case EMR_GLSBOUNDEDRECORD :		    WinMtfAssertHandler( "GlsBoundRecord" );            break;
1364 			case EMR_PIXELFORMAT :  		    WinMtfAssertHandler( "PixelFormat" );               break;
1365             case EMR_DRAWESCAPE :               WinMtfAssertHandler( "DrawEscape" );                break;
1366             case EMR_EXTESCAPE :                WinMtfAssertHandler( "ExtEscape" );                 break;
1367             case EMR_STARTDOC :                 WinMtfAssertHandler( "StartDoc" );                  break;
1368             case EMR_SMALLTEXTOUT :             WinMtfAssertHandler( "SmallTextOut" );              break;
1369             case EMR_FORCEUFIMAPPING :          WinMtfAssertHandler( "ForceUFIMapping" );           break;
1370             case EMR_NAMEDESCAPE :              WinMtfAssertHandler( "NamedEscape" );               break;
1371             case EMR_COLORCORRECTPALETTE :      WinMtfAssertHandler( "ColorCorrectPalette" );       break;
1372             case EMR_SETICMPROFILEA :           WinMtfAssertHandler( "SetICMProfileA" );            break;
1373             case EMR_SETICMPROFILEW :           WinMtfAssertHandler( "SetICMProfileW" );            break;
1374             case EMR_TRANSPARENTBLT :           WinMtfAssertHandler( "TransparenBlt" );             break;
1375             case EMR_TRANSPARENTDIB :           WinMtfAssertHandler( "TransparenDib" );             break;
1376             case EMR_GRADIENTFILL :             WinMtfAssertHandler( "GradientFill" );              break;
1377             case EMR_SETLINKEDUFIS :            WinMtfAssertHandler( "SetLinkedUFIS" );             break;
1378 
1379 			case EMR_SETMAPPERFLAGS :	        WinMtfAssertHandler( "SetMapperFlags", 0 );         break;
1380 			case EMR_SETICMMODE :			    WinMtfAssertHandler( "SetICMMode", 0 );             break;
1381 			case EMR_CREATEMONOBRUSH :          WinMtfAssertHandler( "CreateMonoBrush", 0 );        break;
1382             case EMR_SETBRUSHORGEX :	        WinMtfAssertHandler( "SetBrushOrgEx", 0 );          break;
1383             case EMR_SETMETARGN :		        WinMtfAssertHandler( "SetMetArgn", 0 );             break;
1384 			case EMR_SETMITERLIMIT :	        WinMtfAssertHandler( "SetMiterLimit", 0 );          break;
1385 			case EMR_EXCLUDECLIPRECT :          WinMtfAssertHandler( "ExcludeClipRect", 0 );        break;
1386 			case EMR_REALIZEPALETTE :	        WinMtfAssertHandler( "RealizePalette", 0 );         break;
1387 			case EMR_SELECTPALETTE :	        WinMtfAssertHandler( "SelectPalette", 0 );          break;
1388 			case EMR_CREATEPALETTE :	        WinMtfAssertHandler( "CreatePalette", 0 );          break;
1389             case EMR_ALPHADIBBLEND :            WinMtfAssertHandler( "AlphaDibBlend", 0 );          break;
1390             case EMR_SETTEXTJUSTIFICATION :     WinMtfAssertHandler( "SetTextJustification", 0 );   break;
1391 
1392 			case EMR_GDICOMMENT :
1393 			case EMR_HEADER :	            // has already been read at ReadHeader()
1394             break;
1395 #endif
1396 		}
1397 		pWMF->Seek( nNextPos );
1398 	}
1399 	if( aBmpSaveList.Count() )
1400 		pOut->ResolveBitmapActions( aBmpSaveList );
1401 
1402 	if ( bStatus )
1403 		pWMF->Seek(nEndPos);
1404 
1405 	return bStatus;
1406 };
1407 
1408 //-----------------------------------------------------------------------------------
1409 
ReadHeader()1410 sal_Bool EnhWMFReader::ReadHeader()
1411 {
1412 	sal_uInt32		nsal_uInt32, nHeaderSize, nPalEntries;
1413 	sal_Int32		nLeft, nTop, nRight, nBottom;
1414 
1415 	// METAFILEHEADER SPARE ICH MIR HIER
1416 	// Einlesen des METAHEADER
1417 	*pWMF >> nsal_uInt32 >> nHeaderSize;
1418 	if ( nsal_uInt32 != 1 )			// Typ
1419 		return sal_False;
1420 
1421 	// bound size
1422 	Rectangle rclBounds;	// rectangle in logical units 1/100th mm
1423 	*pWMF >> nLeft >> nTop >> nRight >> nBottom;
1424 	rclBounds.Left() = nLeft;
1425 	rclBounds.Top() = nTop;
1426 	rclBounds.Right() = nRight;
1427 	rclBounds.Bottom() = nBottom;
1428 
1429 	// picture frame size
1430 	Rectangle rclFrame;		// rectangle in device units
1431 	*pWMF >> nLeft >> nTop >> nRight >> nBottom;
1432 	rclFrame.Left() = nLeft;
1433 	rclFrame.Top() = nTop;
1434 	rclFrame.Right() = nRight;
1435 	rclFrame.Bottom() = nBottom;
1436 
1437 	*pWMF >> nsal_uInt32;									// signature
1438 
1439 	if ( nsal_uInt32 != 0x464d4520 )
1440 		return sal_False;
1441 
1442 	*pWMF >> nsal_uInt32;									// nVersion
1443 	*pWMF >> nEndPos;									// size of metafile
1444 	nEndPos += nStartPos;
1445 
1446 	sal_uInt32 nStrmPos = pWMF->Tell();					// checking if nEndPos is valid
1447 	pWMF->Seek( STREAM_SEEK_TO_END );
1448 	if ( pWMF->Tell() < nEndPos )
1449 		nEndPos = pWMF->Tell();
1450 	pWMF->Seek( nStrmPos );
1451 
1452 	*pWMF >> nRecordCount;
1453 
1454 	if ( !nRecordCount )
1455 		return sal_False;
1456 
1457 	pWMF->SeekRel( 0xc );
1458 
1459 	sal_Int32 nPixX, nPixY, nMillX, nMillY;
1460 	*pWMF >> nPalEntries >> nPixX >> nPixY >> nMillX >> nMillY;
1461 
1462 	pOut->SetrclFrame( rclFrame );
1463 	pOut->SetrclBounds( rclBounds );
1464 	pOut->SetRefPix( Size( nPixX, nPixY ) );
1465 	pOut->SetRefMill( Size( nMillX, nMillY ) );
1466 
1467 	pWMF->Seek( nStartPos + nHeaderSize );
1468 	return sal_True;
1469 }
1470 
1471 //-----------------------------------------------------------------------------------
1472 
ReadRectangle(sal_Int32 x1,sal_Int32 y1,sal_Int32 x2,sal_Int32 y2)1473 Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
1474 {
1475 	Point aTL ( Point( x1, y1 ) );
1476 	Point aBR( Point( --x2, --y2 ) );
1477 	return Rectangle( aTL, aBR );
1478 }
1479 
~EnhWMFReader()1480 EnhWMFReader::~EnhWMFReader()
1481 {
1482 
1483 };
1484 
1485 /* vim: set noet sw=4 ts=4: */
1486