xref: /AOO41X/main/svtools/source/filter/wmf/enhwmf.cxx (revision 8e8ee8fefdac26d905672cc573c35fd0ae1f9356)
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                     // // chnaged 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