xref: /AOO41X/main/svtools/source/filter/wmf/winwmf.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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 <vcl/gdimtf.hxx>
27 #include <rtl/crc.h>
28 #include <rtl/tencinfo.h>
29 #include <osl/endian.h>
30 #include <vcl/svapp.hxx>
31 #include <vcl/dibtools.hxx>
32 
33 //====================== MS-Windows-defines ===============================
34 
35 #define W_META_SETBKCOLOR           0x0201
36 #define W_META_SETBKMODE            0x0102
37 #define W_META_SETMAPMODE           0x0103
38 #define W_META_SETROP2              0x0104
39 #define W_META_SETRELABS            0x0105
40 #define W_META_SETPOLYFILLMODE      0x0106
41 #define W_META_SETSTRETCHBLTMODE    0x0107
42 #define W_META_SETTEXTCHAREXTRA     0x0108
43 #define W_META_SETTEXTCOLOR         0x0209
44 #define W_META_SETTEXTJUSTIFICATION 0x020A
45 #define W_META_SETWINDOWORG         0x020B
46 #define W_META_SETWINDOWEXT         0x020C
47 #define W_META_SETVIEWPORTORG       0x020D
48 #define W_META_SETVIEWPORTEXT       0x020E
49 #define W_META_OFFSETWINDOWORG      0x020F
50 #define W_META_SCALEWINDOWEXT       0x0410
51 #define W_META_OFFSETVIEWPORTORG    0x0211
52 #define W_META_SCALEVIEWPORTEXT     0x0412
53 #define W_META_LINETO               0x0213
54 #define W_META_MOVETO               0x0214
55 #define W_META_EXCLUDECLIPRECT      0x0415
56 #define W_META_INTERSECTCLIPRECT    0x0416
57 #define W_META_ARC                  0x0817
58 #define W_META_ELLIPSE              0x0418
59 #define W_META_FLOODFILL            0x0419
60 #define W_META_PIE                  0x081A
61 #define W_META_RECTANGLE            0x041B
62 #define W_META_ROUNDRECT            0x061C
63 #define W_META_PATBLT               0x061D
64 #define W_META_SAVEDC               0x001E
65 #define W_META_SETPIXEL             0x041F
66 #define W_META_OFFSETCLIPRGN        0x0220
67 #define W_META_TEXTOUT              0x0521
68 #define W_META_BITBLT               0x0922
69 #define W_META_STRETCHBLT           0x0B23
70 #define W_META_POLYGON              0x0324
71 #define W_META_POLYLINE             0x0325
72 #define W_META_ESCAPE               0x0626
73 #define W_META_RESTOREDC            0x0127
74 #define W_META_FILLREGION           0x0228
75 #define W_META_FRAMEREGION          0x0429
76 #define W_META_INVERTREGION         0x012A
77 #define W_META_PAINTREGION          0x012B
78 #define W_META_SELECTCLIPREGION     0x012C
79 #define W_META_SELECTOBJECT         0x012D
80 #define W_META_SETTEXTALIGN         0x012E
81 #define W_META_DRAWTEXT             0x062F
82 #define W_META_CHORD                0x0830
83 #define W_META_SETMAPPERFLAGS       0x0231
84 #define W_META_EXTTEXTOUT           0x0a32
85 #define W_META_SETDIBTODEV          0x0d33
86 #define W_META_SELECTPALETTE        0x0234
87 #define W_META_REALIZEPALETTE       0x0035
88 #define W_META_ANIMATEPALETTE       0x0436
89 #define W_META_SETPALENTRIES        0x0037
90 #define W_META_POLYPOLYGON          0x0538
91 #define W_META_RESIZEPALETTE        0x0139
92 #define W_META_DIBBITBLT            0x0940
93 #define W_META_DIBSTRETCHBLT        0x0b41
94 #define W_META_DIBCREATEPATTERNBRUSH 0x0142
95 #define W_META_STRETCHDIB           0x0f43
96 #define W_META_EXTFLOODFILL         0x0548
97 #define W_META_RESETDC              0x014C
98 #define W_META_STARTDOC             0x014D
99 #define W_META_STARTPAGE            0x004F
100 #define W_META_ENDPAGE              0x0050
101 #define W_META_ABORTDOC             0x0052
102 #define W_META_ENDDOC               0x005E
103 #define W_META_DELETEOBJECT         0x01f0
104 #define W_META_CREATEPALETTE        0x00f7
105 #define W_META_CREATEBRUSH          0x00F8
106 #define W_META_CREATEPATTERNBRUSH   0x01F9
107 #define W_META_CREATEPENINDIRECT    0x02FA
108 #define W_META_CREATEFONTINDIRECT   0x02FB
109 #define W_META_CREATEBRUSHINDIRECT  0x02FC
110 #define W_META_CREATEBITMAPINDIRECT 0x02FD
111 #define W_META_CREATEBITMAP         0x06FE
112 #define W_META_CREATEREGION         0x06FF
113 
114 //=================== Methoden von WMFReader ==============================
115 
ReadPoint()116 inline Point WMFReader::ReadPoint()
117 {
118     short nX, nY;
119     *pWMF >> nX >> nY;
120     return Point( nX, nY );
121 }
122 
123 // ------------------------------------------------------------------------
124 
ReadYX()125 inline Point WMFReader::ReadYX()
126 {
127     short nX, nY;
128     *pWMF >> nY >> nX;
129     return Point( nX, nY );
130 }
131 
132 // ------------------------------------------------------------------------
133 
ReadRectangle()134 Rectangle WMFReader::ReadRectangle()
135 {
136     Point aBR, aTL;
137     aBR = ReadYX();
138     aTL = ReadYX();
139     aBR.X()--;
140     aBR.Y()--;
141     return Rectangle( aTL, aBR );
142 }
143 
144 // ------------------------------------------------------------------------
145 
ReadYXExt()146 Size WMFReader::ReadYXExt()
147 {
148     short nW, nH;
149     *pWMF >> nH >> nW;
150     return Size( nW, nH );
151 }
152 
153 // ------------------------------------------------------------------------
154 
ReadRecordParams(sal_uInt16 nFunc)155 void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
156 {
157     switch( nFunc )
158     {
159         case W_META_SETBKCOLOR:
160         {
161             pOut->SetBkColor( ReadColor() );
162         }
163         break;
164 
165         case W_META_SETBKMODE:
166         {
167             sal_uInt16 nDat;
168             *pWMF >> nDat;
169             pOut->SetBkMode( nDat );
170         }
171         break;
172 
173         // !!!
174         case W_META_SETMAPMODE:
175         {
176             sal_Int16 nMapMode;
177             *pWMF >> nMapMode;
178             pOut->SetMapMode( nMapMode );
179         }
180         break;
181 
182         case W_META_SETROP2:
183         {
184             sal_uInt16 nROP2;
185             *pWMF >> nROP2;
186             pOut->SetRasterOp( nROP2 );
187         }
188         break;
189 
190         case W_META_SETTEXTCOLOR:
191         {
192             pOut->SetTextColor( ReadColor() );
193         }
194         break;
195 
196         case W_META_SETWINDOWORG:
197         {
198             pOut->SetWinOrg( ReadYX() );
199         }
200         break;
201 
202         case W_META_SETWINDOWEXT:
203         {
204             short nWidth, nHeight;
205             *pWMF >> nHeight >> nWidth;
206             pOut->SetWinExt( Size( nWidth, nHeight ) );
207         }
208         break;
209 
210         case W_META_OFFSETWINDOWORG:
211         {
212             short nXAdd, nYAdd;
213             *pWMF >> nYAdd >> nXAdd;
214             pOut->SetWinOrgOffset( nXAdd, nYAdd );
215         }
216         break;
217 
218         case W_META_SCALEWINDOWEXT:
219         {
220             short nXNum, nXDenom, nYNum, nYDenom;
221             *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
222             pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
223         }
224         break;
225 
226         case W_META_SETVIEWPORTORG:
227         case W_META_SETVIEWPORTEXT:
228         break;
229 
230         case W_META_OFFSETVIEWPORTORG:
231         {
232             short nXAdd, nYAdd;
233             *pWMF >> nYAdd >> nXAdd;
234             pOut->SetDevOrgOffset( nXAdd, nYAdd );
235         }
236         break;
237 
238         case W_META_SCALEVIEWPORTEXT:
239         {
240             short nXNum, nXDenom, nYNum, nYDenom;
241             *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
242             pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
243         }
244         break;
245 
246         case W_META_LINETO:
247         {
248             pOut->LineTo( ReadYX() );
249         }
250         break;
251 
252         case W_META_MOVETO:
253         {
254             pOut->MoveTo( ReadYX() );
255         }
256         break;
257 
258         case W_META_INTERSECTCLIPRECT:
259         {
260             pOut->IntersectClipRect( ReadRectangle() );
261         }
262         break;
263 
264         case W_META_RECTANGLE:
265         {
266             pOut->DrawRect( ReadRectangle() );
267         }
268         break;
269 
270         case W_META_ROUNDRECT:
271         {
272             Size aSize( ReadYXExt() );
273             pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
274         }
275         break;
276 
277         case W_META_ELLIPSE:
278         {
279             pOut->DrawEllipse( ReadRectangle() );
280         }
281         break;
282 
283         case W_META_ARC:
284         {
285             Point aEnd( ReadYX() );
286             Point aStart( ReadYX() );
287             Rectangle aRect( ReadRectangle() );
288             aRect.Justify();
289             pOut->DrawArc( aRect, aStart, aEnd );
290         }
291         break;
292 
293         case W_META_PIE:
294         {
295             Point     aEnd( ReadYX() );
296             Point     aStart( ReadYX() );
297             Rectangle aRect( ReadRectangle() );
298             aRect.Justify();
299 
300             // #i73608# OutputDevice deviates from WMF
301             // semantics. start==end means full ellipse here.
302             if( aStart == aEnd )
303                 pOut->DrawEllipse( aRect );
304             else
305                 pOut->DrawPie( aRect, aStart, aEnd );
306         }
307         break;
308 
309         case W_META_CHORD:
310         {
311             Point aEnd( ReadYX() );
312             Point aStart( ReadYX() );
313             Rectangle aRect( ReadRectangle() );
314             aRect.Justify();
315             pOut->DrawChord( aRect, aStart, aEnd );
316         }
317         break;
318 
319         case W_META_POLYGON:
320         {
321             sal_uInt16 i,nPoints;
322             *pWMF >> nPoints;
323             Polygon aPoly( nPoints );
324             for( i = 0; i < nPoints; i++ )
325                 aPoly[ i ] = ReadPoint();
326             pOut->DrawPolygon( aPoly );
327         }
328         break;
329 
330         case W_META_POLYPOLYGON:
331         {
332             sal_uInt16 nPolyCount(0);
333 
334             // get number of polygons
335             *pWMF >> nPolyCount;
336 
337             if(nPolyCount && !pWMF->IsEof())
338             {
339                 sal_uInt16* pnPoints = new sal_uInt16[nPolyCount];
340                 sal_uInt16 a(0);
341                 PolyPolygon aPolyPoly(nPolyCount, nPolyCount);
342 
343                 for(a = 0; a < nPolyCount && !pWMF->IsEof(); a++)
344                 {
345                     *pWMF >> pnPoints[a];
346                 }
347 
348                 for(a = 0; a < nPolyCount && !pWMF->IsEof(); a++)
349                 {
350                     const sal_uInt16 nPointCount(pnPoints[a]);
351                     Point* pPtAry = new Point[nPointCount];
352 
353                     for(sal_uInt16 b(0); b < nPointCount && !pWMF->IsEof(); b++)
354                     {
355                         pPtAry[b] = ReadPoint();
356                     }
357 
358                     aPolyPoly.Insert(Polygon(nPointCount, pPtAry));
359                     delete[] pPtAry;
360                 }
361 
362                 delete[] pnPoints;
363                 pOut->DrawPolyPolygon(aPolyPoly);
364             }
365         }
366         break;
367 
368         case W_META_POLYLINE:
369         {
370             sal_uInt16 i,nPoints;
371             *pWMF >> nPoints;
372             Polygon aPoly( nPoints );
373             for( i = 0; i < nPoints; i++ )
374                 aPoly[ i ] = ReadPoint();
375             pOut->DrawPolyLine( aPoly );
376         }
377         break;
378 
379         case W_META_SAVEDC:
380         {
381             pOut->Push();
382         }
383         break;
384 
385         case W_META_RESTOREDC:
386         {
387             pOut->Pop();
388         }
389         break;
390 
391         case W_META_SETPIXEL:
392         {
393             const Color aColor = ReadColor();
394             pOut->DrawPixel( ReadYX(), aColor );
395         }
396         break;
397 
398         case W_META_OFFSETCLIPRGN:
399         {
400             pOut->MoveClipRegion( ReadYXExt() );
401         }
402         break;
403 
404         case W_META_TEXTOUT:
405         {
406             sal_uInt16 nLength;
407             *pWMF >> nLength;
408             if ( nLength )
409             {
410                 char*   pChar = new char[ ( nLength + 1 ) &~ 1 ];
411                 pWMF->Read( pChar, ( nLength + 1 ) &~ 1 );
412                 String aText( pChar, nLength, pOut->GetCharSet() );
413                 delete[] pChar;
414                 Point aPosition( ReadYX() );
415                 pOut->DrawText( aPosition, aText );
416             }
417         }
418         break;
419 
420         case W_META_EXTTEXTOUT:
421         {
422             sal_Int16   nDx, nDxTmp;
423             sal_uInt16  i, nLen, nOptions;
424             sal_Int32   nRecordPos, nRecordSize, nOriginalTextLen, nNewTextLen;
425             Point       aPosition;
426             Rectangle   aRect;
427             sal_Int32*  pDXAry = NULL;
428 
429             pWMF->SeekRel(-6);
430             nRecordPos = pWMF->Tell();
431             *pWMF >> nRecordSize;
432             pWMF->SeekRel(2);
433             aPosition = ReadYX();
434             *pWMF >> nLen >> nOptions;
435 
436             sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
437             if ( nOptions & ETO_RTLREADING )
438                 nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
439             pOut->SetTextLayoutMode( nTextLayoutMode );
440             DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
441 
442             // Nur wenn der Text auch Zeichen enthaelt, macht die Ausgabe Sinn
443             if( nLen )
444             {
445                 nOriginalTextLen = nLen;
446                 if( nOptions & ETO_CLIPPED )
447                 {
448                     const Point aPt1( ReadPoint() );
449                     const Point aPt2( ReadPoint() );
450                     aRect = Rectangle( aPt1, aPt2 );
451                 }
452                 char* pChar = new char[ ( nOriginalTextLen + 1 ) &~ 1 ];
453                 pWMF->Read( pChar, ( nOriginalTextLen + 1 ) &~ 1 );
454                 String aText( pChar, (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
455                 nNewTextLen = aText.Len();                                              // less character (japanese version), so the
456                 delete[] pChar;                                                         // dxAry will not fit
457 
458                 if ( nNewTextLen )
459                 {
460                     sal_uInt32  nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
461                     sal_Int32   nDxArySize =  nMaxStreamPos - pWMF->Tell();
462                     sal_Int32   nDxAryEntries = nDxArySize >> 1;
463                     sal_Bool    bUseDXAry = sal_False;
464 
465                     if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
466                     {
467                         pDXAry = new sal_Int32[ nNewTextLen ];
468                         for ( i = 0; i < nNewTextLen; i++ )
469                         {
470                             if ( pWMF->Tell() >= nMaxStreamPos )
471                                 break;
472                             *pWMF >> nDx;
473                             if ( nNewTextLen != nOriginalTextLen )
474                             {
475                                 ByteString aTmp( aText.GetChar( i ), pOut->GetCharSet() );
476                                 if ( aTmp.Len() > 1 )
477                                 {
478                                     sal_Int32 nDxCount = aTmp.Len() - 1;
479                                     if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
480                                         break;
481                                     while ( nDxCount-- )
482                                     {
483                                         *pWMF >> nDxTmp;
484                                         nDx = nDx + nDxTmp;
485                                     }
486                                 }
487                             }
488                             pDXAry[ i ] = nDx;
489                         }
490                         if ( i == nNewTextLen )
491                             bUseDXAry = sal_True;
492                     }
493                     if ( pDXAry && bUseDXAry )
494                         pOut->DrawText( aPosition, aText, pDXAry );
495                     else
496                         pOut->DrawText( aPosition, aText );
497                 }
498             }
499             delete[] pDXAry;
500 
501         }
502         break;
503 
504         case W_META_SELECTOBJECT:
505         {
506             sal_Int16   nObjIndex;
507             *pWMF >> nObjIndex;
508             pOut->SelectObject( nObjIndex );
509         }
510         break;
511 
512         case W_META_SETTEXTALIGN:
513         {
514             sal_uInt16  nAlign;
515             *pWMF >> nAlign;
516             pOut->SetTextAlign( nAlign );
517         }
518         break;
519 
520         case W_META_BITBLT:
521         {
522             // 0-3   : nWinROP                      #93454#
523             // 4-5   : y offset of source bitmap
524             // 6-7   : x offset of source bitmap
525             // 8-9   : used height of source bitmap
526             // 10-11 : used width  of source bitmap
527             // 12-13 : destination position y (in pixel)
528             // 14-15 : destination position x (in pixel)
529             // 16-17 : dont know
530             // 18-19 : Width Bitmap in Pixel
531             // 20-21 : Height Bitmap in Pixel
532             // 22-23 : bytes per scanline
533             // 24    : planes
534             // 25    : bitcount
535 
536             sal_Int32   nWinROP;
537             sal_uInt16  nSx, nSy, nSxe, nSye, nDontKnow, nWidth, nHeight, nBytesPerScan;
538             sal_uInt8   nPlanes, nBitCount;
539 
540             *pWMF >> nWinROP
541                   >> nSy >> nSx >> nSye >> nSxe;
542             Point aPoint( ReadYX() );
543             *pWMF >> nDontKnow >> nWidth >> nHeight >> nBytesPerScan >> nPlanes >> nBitCount;
544 
545             if ( nWidth && nHeight && ( nPlanes == 1 ) && ( nBitCount == 1 ) )
546             {
547                 Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
548                 BitmapWriteAccess* pAcc;
549                 pAcc = aBmp.AcquireWriteAccess();
550                 if ( pAcc )
551                 {
552                     sal_uInt16 y, x, scan;
553                     sal_Int8 i, nEightPixels;
554                     for ( y = 0; y < nHeight; y++ )
555                     {
556                         x = 0;
557                         for ( scan = 0; scan < nBytesPerScan; scan++ )
558                         {
559                             *pWMF >> nEightPixels;
560                             for ( i = 7; i >= 0; i-- )
561                             {
562                                 if ( x < nWidth )
563                                 {
564                                     pAcc->SetPixelIndex( y, x, (nEightPixels>>i)&1 );
565                                 }
566                                 x++;
567                             }
568                         }
569                     }
570                     aBmp.ReleaseAccess( pAcc );
571                     if ( nSye && nSxe &&
572                         ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
573                             ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
574                     {
575                         Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
576                         aBmp.Crop( aCropRect );
577                     }
578                     Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
579                     aBmpSaveList.Insert( new BSaveStruct( aBmp, aDestRect, nWinROP ), LIST_APPEND );
580                 }
581             }
582         }
583         break;
584 
585         case W_META_STRETCHBLT:
586         case W_META_DIBBITBLT:
587         case W_META_DIBSTRETCHBLT:
588         case W_META_STRETCHDIB:
589         {
590             sal_Int32   nWinROP;
591             sal_uInt16  nSx, nSy, nSxe, nSye, nUsage;
592             Bitmap      aBmp;
593 
594             *pWMF >> nWinROP;
595 
596             if( nFunc == W_META_STRETCHDIB )
597                 *pWMF >> nUsage;
598 
599             // nSye and nSxe is the number of pixels that has to been used
600             if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
601                 *pWMF >> nSye >> nSxe;
602             else
603                 nSye = nSxe = 0;    // set this to zero as indicator not to scale the bitmap later
604 
605             // nSy and nx is the offset of the first pixel
606             *pWMF >> nSy >> nSx;
607 
608             if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
609             {
610                 if ( nWinROP == PATCOPY )
611                     *pWMF >> nUsage;    // i don't know anything of this parameter, so its called nUsage
612                                         // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
613 
614                 Size aDestSize( ReadYXExt() );
615                 if ( aDestSize.Width() && aDestSize.Height() )  // #92623# do not try to read buggy bitmaps
616                 {
617                     Rectangle aDestRect( ReadYX(), aDestSize );
618                     if ( nWinROP != PATCOPY )
619                         ReadDIB(aBmp, *pWMF, false);
620 
621                     // test if it is sensible to crop
622                     if ( nSye && nSxe &&
623                         ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
624                             ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
625                     {
626                         Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
627                         aBmp.Crop( aCropRect );
628                     }
629                     aBmpSaveList.Insert( new BSaveStruct( aBmp, aDestRect, nWinROP ), LIST_APPEND );
630                 }
631             }
632         }
633         break;
634 
635         case W_META_DIBCREATEPATTERNBRUSH:
636         {
637             Bitmap  aBmp;
638             BitmapReadAccess* pBmp;
639             sal_uInt32  nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
640             sal_uInt16  nFunction;
641 
642             *pWMF >> nFunction >> nFunction;
643 
644             ReadDIB(aBmp, *pWMF, false);
645             pBmp = aBmp.AcquireReadAccess();
646             if ( pBmp )
647             {
648                 for ( sal_Int32 y = 0; y < pBmp->Height(); y++ )
649                 {
650                     for ( sal_Int32 x = 0; x < pBmp->Width(); x++ )
651                     {
652                         const BitmapColor aColor( pBmp->GetColor( y, x ) );
653 
654                         nRed += aColor.GetRed();
655                         nGreen += aColor.GetGreen();
656                         nBlue += aColor.GetBlue();
657                     }
658                 }
659                 nCount = pBmp->Height() * pBmp->Width();
660                 if ( !nCount )
661                     nCount++;
662                 aBmp.ReleaseAccess( pBmp );
663             }
664             Color aColor( (sal_uInt8)( nRed / nCount ), (sal_uInt8)( nGreen / nCount ), (sal_uInt8)( nBlue / nCount ) );
665             pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( aColor, sal_False ) );
666         }
667         break;
668 
669         case W_META_DELETEOBJECT:
670         {
671             sal_Int16 nIndex;
672             *pWMF >> nIndex;
673             pOut->DeleteObject( nIndex );
674         }
675         break;
676 
677         case W_META_CREATEPALETTE:
678         {
679             pOut->CreateObject( GDI_DUMMY );
680         }
681         break;
682 
683         case W_META_CREATEBRUSH:
684         {
685             pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
686         }
687         break;
688 
689         case W_META_CREATEPATTERNBRUSH:
690         {
691             pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
692         }
693         break;
694 
695         case W_META_CREATEPENINDIRECT:
696         {
697             LineInfo    aLineInfo;
698             sal_uInt16      nStyle, nWidth, nHeight;
699 
700             *pWMF >> nStyle >> nWidth >> nHeight;
701 
702             if ( nWidth )
703                 aLineInfo.SetWidth( nWidth );
704 
705             sal_Bool bTransparent = sal_False;
706             sal_uInt16 nDashCount = 0;
707             sal_uInt16 nDotCount = 0;
708             switch( nStyle )
709             {
710                 case PS_DASHDOTDOT :
711                     nDotCount++;
712                 case PS_DASHDOT :
713                     nDashCount++;
714                 case PS_DOT :
715                     nDotCount++;
716                 break;
717                 case PS_DASH :
718                     nDashCount++;
719                 break;
720                 case PS_NULL :
721                     bTransparent = sal_True;
722                     aLineInfo.SetStyle( LINE_NONE );
723                 break;
724                 default :
725                 case PS_INSIDEFRAME :
726                 case PS_SOLID :
727                     aLineInfo.SetStyle( LINE_SOLID );
728             }
729             if ( nDashCount | nDotCount )
730             {
731                 aLineInfo.SetStyle( LINE_DASH );
732                 aLineInfo.SetDashCount( nDashCount );
733                 aLineInfo.SetDotCount( nDotCount );
734             }
735             pOut->CreateObject( GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
736         }
737         break;
738 
739         case W_META_CREATEBRUSHINDIRECT:
740         {
741             sal_uInt16  nStyle;
742             *pWMF >> nStyle;
743             pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
744         }
745         break;
746 
747         case W_META_CREATEFONTINDIRECT:
748         {
749             Size    aFontSize;
750             char    lfFaceName[ LF_FACESIZE ];
751             sal_Int16   lfEscapement, lfOrientation, lfWeight;  // ( ehemals sal_uInt16 )
752 
753             LOGFONTW aLogFont;
754             aFontSize = ReadYXExt();
755             *pWMF >> lfEscapement >> lfOrientation >> lfWeight
756                     >> aLogFont.lfItalic >> aLogFont.lfUnderline >> aLogFont.lfStrikeOut >> aLogFont.lfCharSet >> aLogFont.lfOutPrecision
757                         >> aLogFont.lfClipPrecision >> aLogFont.lfQuality >> aLogFont.lfPitchAndFamily;
758             pWMF->Read( lfFaceName, LF_FACESIZE );
759             aLogFont.lfWidth = aFontSize.Width();
760             aLogFont.lfHeight = aFontSize.Height();
761             aLogFont.lfEscapement = lfEscapement;
762             aLogFont.lfOrientation = lfOrientation;
763             aLogFont.lfWeight = lfWeight;
764 
765             CharSet eCharSet;
766             if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
767                 eCharSet = gsl_getSystemTextEncoding();
768             else
769                 eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
770             if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
771                 eCharSet = gsl_getSystemTextEncoding();
772             if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
773                 eCharSet = RTL_TEXTENCODING_MS_1252;
774             aLogFont.alfFaceName = UniString( lfFaceName, eCharSet );
775 
776             pOut->CreateObject( GDI_FONT, new WinMtfFontStyle( aLogFont ) );
777         }
778         break;
779 
780         case W_META_CREATEBITMAPINDIRECT:
781         {
782             pOut->CreateObject( GDI_DUMMY );
783         }
784         break;
785 
786         case W_META_CREATEBITMAP:
787         {
788             pOut->CreateObject( GDI_DUMMY );
789         }
790         break;
791 
792         case W_META_CREATEREGION:
793         {
794             pOut->CreateObject( GDI_DUMMY );
795         }
796         break;
797 
798         case W_META_EXCLUDECLIPRECT :
799         {
800             pOut->ExcludeClipRect( ReadRectangle() );
801         }
802         break;
803 
804         case W_META_PATBLT:
805         {
806             sal_uInt32 nROP, nOldROP;
807             *pWMF >> nROP;
808             Size aSize = ReadYXExt();
809             nOldROP = pOut->SetRasterOp( nROP );
810             pOut->DrawRect( Rectangle( ReadYX(), aSize ), sal_False );
811             pOut->SetRasterOp( nOldROP );
812         }
813         break;
814 
815         case W_META_SELECTCLIPREGION:
816         {
817             sal_Int16 nObjIndex;
818             *pWMF >> nObjIndex;
819             if ( !nObjIndex )
820             {
821                 PolyPolygon aEmptyPolyPoly;
822                 pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, sal_True );
823             }
824         }
825         break;
826 
827         case W_META_ESCAPE :
828         {
829             // nRecSize has been checked previously to be greater than 3
830             sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
831             sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
832 
833             // taking care that nRecSize does not exceed the maximal stream position
834             if ( nMetaRecEndPos > nEndPos )
835             {
836                 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
837                 break;
838             }
839             if ( nRecSize >= 4 )    // minimal escape lenght
840             {
841                 sal_uInt16  nMode, nLen;
842                 *pWMF >> nMode
843                       >> nLen;
844                 if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 4 ) )
845                 {
846                     sal_uInt32 nNewMagic; // we have to read int32 for
847                     *pWMF >> nNewMagic;   // META_ESCAPE_ENHANCED_METAFILE CommentIdentifier
848 
849                     if( nNewMagic == 0x2c2a4f4f &&  nLen >= 14 )
850                     {
851                         sal_uInt16 nMagic2;
852                         *pWMF >> nMagic2;
853                         if( nMagic2 == 0x0a ) // 2nd half of magic
854                         {                     // continue with private escape
855                             sal_uInt32 nCheck, nEsc;
856                             *pWMF >> nCheck
857                                   >> nEsc;
858 
859                             sal_uInt32 nEscLen = nLen - 14;
860                             if ( nEscLen <= ( nRecSize * 2 ) )
861                             {
862 #ifdef OSL_BIGENDIAN
863                                 sal_uInt32 nTmp = SWAPLONG( nEsc );
864                                 sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
865 #else
866                                 sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
867 #endif
868                                 sal_Int8* pData = NULL;
869 
870                                 if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
871                                 {
872                                     pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
873                                     break;
874                                 }
875                                 if ( nEscLen > 0 )
876                                 {
877                                     pData = new sal_Int8[ nEscLen ];
878                                     pWMF->Read( pData, nEscLen );
879                                     nCheckSum = rtl_crc32( nCheckSum, pData, nEscLen );
880                                 }
881                                 if ( nCheck == nCheckSum )
882                                 {
883                                     switch( nEsc )
884                                     {
885                                         case PRIVATE_ESCAPE_UNICODE :
886                                         {
887                                             // we will use text instead of polygons only if we have the correct font
888                                             if ( Application::GetDefaultDevice()->IsFontAvailable( pOut->GetFont().GetName() ) )
889                                             {
890                                                 Point  aPt;
891                                                 String aString;
892                                                 sal_uInt32  i, nStringLen, nDXCount;
893                                                 sal_Int32* pDXAry = NULL;
894                                                 SvMemoryStream aMemoryStream( nEscLen );
895                                                 aMemoryStream.Write( pData, nEscLen );
896                                                 aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
897                                                 aMemoryStream >> aPt.X()
898                                                               >> aPt.Y()
899                                                               >> nStringLen;
900 
901                                                 if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
902                                                 {
903                                                     sal_Unicode* pBuf = aString.AllocBuffer( (xub_StrLen)nStringLen );
904                                                     for ( i = 0; i < nStringLen; i++ )
905                                                         aMemoryStream >> pBuf[ i ];
906                                                     aMemoryStream >> nDXCount;
907                                                     if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
908                                                         nDXCount = 0;
909                                                     if ( nDXCount )
910                                                         pDXAry = new sal_Int32[ nDXCount ];
911                                                     for  ( i = 0; i < nDXCount; i++ )
912                                                         aMemoryStream >> pDXAry[ i ];
913                                                     aMemoryStream >> nSkipActions;
914                                                     pOut->DrawText( aPt, aString, pDXAry );
915                                                     delete[] pDXAry;
916                                                 }
917                                             }
918                                         }
919                                         break;
920                                     }
921                                 }
922                                 delete[] pData;
923                             }
924                         }
925                     }
926                     else if ( (nNewMagic == static_cast< sal_uInt32 >(0x43464D57)) && (nLen >= 34) && ( (sal_Int32)(nLen + 10) <= (sal_Int32)(nRecSize * 2) ))
927                     {
928                         sal_uInt32 nComType, nVersion, nFlags, nComRecCount,
929                                    nCurRecSize, nRemainingSize, nEMFTotalSize;
930                         sal_uInt16 nCheck;
931 
932                         *pWMF >> nComType >> nVersion >> nCheck >> nFlags
933                               >> nComRecCount >> nCurRecSize
934                               >> nRemainingSize >> nEMFTotalSize; // the nRemainingSize is not mentioned in MSDN documentation
935                                                                   // but it seems to be required to read in data produced by OLE
936 
937                         if( nComType == 0x01 && nVersion == 0x10000 && nComRecCount )
938                         {
939                             if( !nEMFRec )
940                             {   // first EMF comment
941                                 nEMFRecCount    = nComRecCount;
942                                 nEMFSize        = nEMFTotalSize;
943                                 pEMFStream = new SvMemoryStream( nEMFSize );
944                             }
945                             else if( ( nEMFRecCount != nComRecCount ) || ( nEMFSize != nEMFTotalSize ) ) // add additional checks here
946                             {
947                                 // total records should be the same as in previous comments
948                                 nEMFRecCount = 0xFFFFFFFF;
949                                 delete pEMFStream;
950                                 pEMFStream = NULL;
951                             }
952                             nEMFRec++;
953 
954                             if( pEMFStream && nCurRecSize + 34 > nLen )
955                             {
956                                 nEMFRecCount = 0xFFFFFFFF;
957                                 delete pEMFStream;
958                                 pEMFStream = NULL;
959                             }
960 
961                             if( pEMFStream )
962                             {
963                                 sal_Int8* pBuf = new sal_Int8[ nCurRecSize ];
964                                 sal_uInt32 nCount = pWMF->Read( pBuf, nCurRecSize );
965                                 if( nCount == nCurRecSize )
966                                     pEMFStream->Write( pBuf, nCount );
967                                 delete[] pBuf;
968                             }
969                         }
970                     }
971                 }
972             }
973         }
974         break;
975 
976         case W_META_SETRELABS:
977         case W_META_SETPOLYFILLMODE:
978         case W_META_SETSTRETCHBLTMODE:
979         case W_META_SETTEXTCHAREXTRA:
980         case W_META_SETTEXTJUSTIFICATION:
981         case W_META_FLOODFILL :
982         case W_META_FILLREGION:
983         case W_META_FRAMEREGION:
984         case W_META_INVERTREGION:
985         case W_META_PAINTREGION:
986         case W_META_DRAWTEXT:
987         case W_META_SETMAPPERFLAGS:
988         case W_META_SETDIBTODEV:
989         case W_META_SELECTPALETTE:
990         case W_META_REALIZEPALETTE:
991         case W_META_ANIMATEPALETTE:
992         case W_META_SETPALENTRIES:
993         case W_META_RESIZEPALETTE:
994         case W_META_EXTFLOODFILL:
995         case W_META_RESETDC:
996         case W_META_STARTDOC:
997         case W_META_STARTPAGE:
998         case W_META_ENDPAGE:
999         case W_META_ABORTDOC:
1000         case W_META_ENDDOC:
1001         break;
1002     }
1003 }
1004 
1005 // ------------------------------------------------------------------------
1006 
ReadHeader()1007 sal_Bool WMFReader::ReadHeader()
1008 {
1009     Rectangle   aPlaceableBound;
1010     sal_uInt32  nl, nStrmPos = pWMF->Tell();
1011 
1012     // Einlesen des METAFILEHEADER, falls vorhanden
1013     *pWMF >> nl;
1014 
1015     Size aWMFSize;
1016     if ( nl == 0x9ac6cdd7L )
1017     {
1018         sal_Int16 nVal;
1019 
1020         // hmf (Unused) ueberlesen wir
1021         pWMF->SeekRel(2);
1022 
1023         // BoundRect
1024         *pWMF >> nVal; aPlaceableBound.Left() = nVal;
1025         *pWMF >> nVal; aPlaceableBound.Top() = nVal;
1026         *pWMF >> nVal; aPlaceableBound.Right() = nVal;
1027         *pWMF >> nVal; aPlaceableBound.Bottom() = nVal;
1028 
1029         // inch
1030         *pWMF >> nUnitsPerInch;
1031 
1032         // reserved
1033         pWMF->SeekRel( 4 );
1034 
1035         // checksum  pruefen wir lieber nicht
1036         pWMF->SeekRel( 2 );
1037     }
1038     else
1039     {
1040         nUnitsPerInch = 96;
1041         pWMF->Seek( nStrmPos + 18 );    // set the streampos to the start of the the metaactions
1042         GetPlaceableBound( aPlaceableBound, pWMF );
1043         pWMF->Seek( nStrmPos );
1044     }
1045 
1046     pOut->SetWinOrg( aPlaceableBound.TopLeft() );
1047     aWMFSize = Size( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
1048     pOut->SetWinExt( aWMFSize );
1049 
1050     Size aDevExt( 10000, 10000 );
1051     if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
1052     {
1053         const Fraction  aFrac( 1, nUnitsPerInch );
1054         MapMode         aWMFMap( MAP_INCH, Point(), aFrac, aFrac );
1055         Size            aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MAP_100TH_MM ) );
1056         aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
1057     }
1058     pOut->SetDevExt( aDevExt );
1059 
1060     // Einlesen des METAHEADER
1061     *pWMF >> nl; // Typ und Headergroesse
1062 
1063     if( nl != 0x00090001 )
1064     {
1065         pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1066         return sal_False;
1067     }
1068 
1069     pWMF->SeekRel( 2 ); // Version (von Windows)
1070     pWMF->SeekRel( 4 ); // Size (der Datei in Words)
1071     pWMF->SeekRel( 2 ); // NoObjects (Maximale Anzahl der gleichzeitigen Objekte)
1072     pWMF->SeekRel( 4 ); // MaxRecord (Groesse des groessten Records in Words)
1073     pWMF->SeekRel( 2 ); // NoParameters (Unused
1074 
1075     return sal_True;
1076 }
1077 
ReadWMF()1078 void WMFReader::ReadWMF()
1079 {
1080     sal_uInt16  nFunction;
1081     sal_uLong   nPos, nPercent, nLastPercent;
1082 
1083     nSkipActions = 0;
1084     nCurrentAction = 0;
1085     nUnicodeEscapeAction = 0;
1086 
1087     pEMFStream      = NULL;
1088     nEMFRecCount    = 0;
1089     nEMFRec         = 0;
1090     nEMFSize        = 0;
1091 
1092     sal_Bool bEMFAvailable = sal_False;
1093 
1094     pOut->SetMapMode( MM_ANISOTROPIC );
1095     pOut->SetWinOrg( Point() );
1096     pOut->SetWinExt( Size( 1, 1 ) );
1097     pOut->SetDevExt( Size( 10000, 10000 ) );
1098 
1099     nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
1100     pWMF->Seek( nStartPos );
1101     Callback( (sal_uInt16) ( nLastPercent = 0 ) );
1102 
1103     if ( ReadHeader() )
1104     {
1105 
1106         nPos = pWMF->Tell();
1107 
1108         if( nEndPos - nStartPos )
1109         {
1110             while( sal_True )
1111             {
1112                 nCurrentAction++;
1113                 nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
1114 
1115                 if( nLastPercent + 4 <= nPercent )
1116                 {
1117                     Callback( (sal_uInt16) nPercent );
1118                     nLastPercent = nPercent;
1119                 }
1120                 *pWMF >> nRecSize >> nFunction;
1121 
1122                 if( pWMF->GetError() || ( nRecSize < 3 ) || ( nRecSize==3 && nFunction==0 ) || pWMF->IsEof() )
1123                 {
1124 
1125                     if( pWMF->IsEof() )
1126                         pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1127 
1128                     break;
1129                 }
1130                 if ( !bEMFAvailable )
1131                 {
1132                     if( aBmpSaveList.Count() &&
1133                         ( nFunction != W_META_STRETCHDIB ) &&
1134                         ( nFunction != W_META_DIBBITBLT ) &&
1135                         ( nFunction != W_META_DIBSTRETCHBLT ) )
1136                     {
1137                         pOut->ResolveBitmapActions( aBmpSaveList );
1138                     }
1139                     if ( !nSkipActions )
1140                         ReadRecordParams( nFunction );
1141                     else
1142                         nSkipActions--;
1143 
1144                     if( pEMFStream && nEMFRecCount == nEMFRec )
1145                     {
1146                         GDIMetaFile aMeta;
1147                         pEMFStream->Seek( 0 );
1148                         EnhWMFReader* pEMFReader = new EnhWMFReader ( *pEMFStream, aMeta );
1149                         bEMFAvailable = pEMFReader->ReadEnhWMF();
1150                         delete pEMFReader; // destroy first!!!
1151 
1152                         if( bEMFAvailable )
1153                         {
1154                             pOut->AddFromGDIMetaFile( aMeta );
1155                             pOut->SetrclFrame( Rectangle(0, 0, aMeta.GetPrefSize().Width(), aMeta.GetPrefSize().Height() ));
1156 
1157                             // the stream needs to be set to the wmf end position,
1158                             // otherwise the GfxLink that is created will be incorrect
1159                             // (leading to graphic loss after swapout/swapin).
1160                             // so we will proceed normally, but are ignoring further wmf
1161                             // records
1162                         }
1163                         else
1164                         {
1165                             // something went wrong
1166                             // continue with WMF, don't try this again
1167                             delete pEMFStream;
1168                             pEMFStream = NULL;
1169                         }
1170                     }
1171                 }
1172                 nPos += nRecSize * 2;
1173                 if ( nPos <= nEndPos )
1174                     pWMF->Seek( nPos  );
1175                 else
1176                     pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1177             }
1178         }
1179         else
1180             pWMF->SetError( SVSTREAM_GENERALERROR );
1181 
1182         if( !pWMF->GetError() && aBmpSaveList.Count() )
1183             pOut->ResolveBitmapActions( aBmpSaveList );
1184     }
1185     if ( pWMF->GetError() )
1186         pWMF->Seek( nStartPos );
1187 }
1188 
1189 // ------------------------------------------------------------------------
1190 
GetWinExtMax(const Point & rSource,Rectangle & rPlaceableBound,const sal_Int16 nMapMode)1191 static void GetWinExtMax( const Point& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
1192 {
1193     Point aSource( rSource );
1194     if ( nMapMode == MM_HIMETRIC )
1195         aSource.Y() = -rSource.Y();
1196     if ( aSource.X() < rPlaceableBound.Left() )
1197         rPlaceableBound.Left() = aSource.X();
1198     if ( aSource.X() > rPlaceableBound.Right() )
1199         rPlaceableBound.Right() = aSource.X();
1200     if ( aSource.Y() < rPlaceableBound.Top() )
1201         rPlaceableBound.Top() = aSource.Y();
1202     if ( aSource.Y() > rPlaceableBound.Bottom() )
1203         rPlaceableBound.Bottom() = aSource.Y();
1204 }
1205 
GetWinExtMax(const Rectangle & rSource,Rectangle & rPlaceableBound,const sal_Int16 nMapMode)1206 static void GetWinExtMax( const Rectangle& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
1207 {
1208     GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
1209     GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
1210 }
1211 
GetPlaceableBound(Rectangle & rPlaceableBound,SvStream * pStm)1212 sal_Bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm )
1213 {
1214     sal_Bool bRet = sal_True;
1215 
1216     rPlaceableBound.Left()   = (sal_Int32)0x7fffffff;
1217     rPlaceableBound.Top()    = (sal_Int32)0x7fffffff;
1218     rPlaceableBound.Right()  = (sal_Int32)0x80000000;
1219     rPlaceableBound.Bottom() = (sal_Int32)0x80000000;
1220 
1221     sal_Int16 nMapMode = MM_ANISOTROPIC;
1222 
1223     sal_uInt16 nFunction;
1224     sal_uInt32 nRSize;
1225     sal_uInt32 nPos = pStm->Tell();
1226     sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
1227 
1228     pStm->Seek( nPos );
1229 
1230     if( nEnd - nPos )
1231     {
1232         while( bRet )
1233         {
1234             *pStm >> nRSize >> nFunction;
1235 
1236             if( pStm->GetError() || ( nRSize < 3 ) || ( nRSize==3 && nFunction==0 ) || pStm->IsEof() )
1237             {
1238                 if( pStm->IsEof() )
1239                 {
1240                     pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1241                     bRet = sal_False;
1242                 }
1243                 break;
1244             }
1245             switch( nFunction )
1246             {
1247                 case W_META_SETWINDOWORG:
1248                 {
1249                     Point aWinOrg;
1250                     aWinOrg = ReadYX();
1251                     rPlaceableBound.SetPos( aWinOrg );
1252                 }
1253                 break;
1254 
1255                 case W_META_SETWINDOWEXT:
1256                 {
1257                     Point aPos0( 0, 0 );
1258                     sal_Int16 nWidth, nHeight;
1259                     *pStm >> nHeight >> nWidth;
1260                     rPlaceableBound.SetSize( Size( nWidth, nHeight ) );
1261                 }
1262                 break;
1263 
1264                 case W_META_SETMAPMODE :
1265                     *pStm >> nMapMode;
1266                 break;
1267 
1268                 case W_META_MOVETO:
1269                 case W_META_LINETO:
1270                     GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1271                 break;
1272 
1273                 case W_META_RECTANGLE:
1274                 case W_META_INTERSECTCLIPRECT:
1275                 case W_META_EXCLUDECLIPRECT :
1276                 case W_META_ELLIPSE:
1277                     GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1278                 break;
1279 
1280                 case W_META_ROUNDRECT:
1281                 {
1282                     Size aSize( ReadYXExt() );
1283                     GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1284                 }
1285                 break;
1286 
1287                 case W_META_ARC:
1288                 case W_META_PIE:
1289                 case W_META_CHORD:
1290                 {
1291                     Point aEnd( ReadYX() );
1292                     Point aStart( ReadYX() );
1293                     GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1294                 }
1295                 break;
1296 
1297                 case W_META_POLYGON:
1298                 {
1299                     sal_uInt16 i,nPoints;
1300                     *pStm >> nPoints;
1301                     for( i = 0; i < nPoints; i++ )
1302                         GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1303                 }
1304                 break;
1305 
1306                 case W_META_POLYPOLYGON:
1307                 {
1308                     sal_uInt16  i, nPoly, nPoints = 0;
1309                     *pStm >> nPoly;
1310                     for( i = 0; i < nPoly; i++ )
1311                     {
1312                         sal_uInt16 nP;
1313                         *pStm >> nP;
1314                         nPoints = nPoints + nP;
1315                     }
1316                     for ( i = 0; i < nPoints; i++ )
1317                         GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1318                 }
1319                 break;
1320 
1321                 case W_META_POLYLINE:
1322                 {
1323                     sal_uInt16 i,nPoints;
1324                     *pStm >> nPoints;
1325                     for( i = 0; i < nPoints; i++ )
1326                         GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1327                 }
1328                 break;
1329 
1330                 case W_META_SETPIXEL:
1331                 {
1332                     const Color aColor = ReadColor();
1333                     GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1334                 }
1335                 break;
1336 
1337                 case W_META_TEXTOUT:
1338                 {
1339                     sal_uInt16 nLength;
1340                     *pStm >> nLength;
1341                     // todo: we also have to take care of the text width
1342                     if ( nLength )
1343                     {
1344                         pStm->SeekRel( ( nLength + 1 ) &~ 1 );
1345                         GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1346                     }
1347                 }
1348                 break;
1349 
1350                 case W_META_EXTTEXTOUT:
1351                 {
1352                     sal_uInt16  nLen, nOptions;
1353                     sal_Int32   nRecordPos, nRecordSize;
1354                     Point       aPosition;
1355                     Rectangle   aRect;
1356 
1357                     pStm->SeekRel(-6);
1358                     nRecordPos = pStm->Tell();
1359                     *pStm >> nRecordSize;
1360                     pStm->SeekRel(2);
1361                     aPosition = ReadYX();
1362                     *pStm >> nLen >> nOptions;
1363                     // todo: we also have to take care of the text width
1364                     if( nLen )
1365                         GetWinExtMax( aPosition, rPlaceableBound, nMapMode );
1366                 }
1367                 break;
1368                 case W_META_BITBLT:
1369                 case W_META_STRETCHBLT:
1370                 case W_META_DIBBITBLT:
1371                 case W_META_DIBSTRETCHBLT:
1372                 case W_META_STRETCHDIB:
1373                 {
1374                     sal_Int32   nWinROP;
1375                     sal_uInt16  nSx, nSy, nSxe, nSye, nUsage;
1376                     *pStm >> nWinROP;
1377 
1378                     if( nFunction == W_META_STRETCHDIB )
1379                         *pStm >> nUsage;
1380 
1381                     // nSye and nSxe is the number of pixels that has to been used
1382                     if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
1383                         *pStm >> nSye >> nSxe;
1384                     else
1385                         nSye = nSxe = 0;    // set this to zero as indicator not to scale the bitmap later
1386 
1387                     // nSy and nx is the offset of the first pixel
1388                     *pStm >> nSy >> nSx;
1389 
1390                     if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
1391                     {
1392                         if ( nWinROP == PATCOPY )
1393                             *pStm >> nUsage;    // i don't know anything of this parameter, so its called nUsage
1394                                                 // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
1395 
1396                         Size aDestSize( ReadYXExt() );
1397                         if ( aDestSize.Width() && aDestSize.Height() )  // #92623# do not try to read buggy bitmaps
1398                         {
1399                             Rectangle aDestRect( ReadYX(), aDestSize );
1400                             GetWinExtMax( aDestRect, rPlaceableBound, nMapMode );
1401                         }
1402                     }
1403                 }
1404                 break;
1405 
1406                 case W_META_PATBLT:
1407                 {
1408                     sal_uInt32 nROP;
1409                     *pStm >> nROP;
1410                     Size aSize = ReadYXExt();
1411                     GetWinExtMax( Rectangle( ReadYX(), aSize ), rPlaceableBound, nMapMode );
1412                 }
1413                 break;
1414             }
1415             nPos += nRSize * 2;
1416             if ( nPos <= nEnd )
1417                 pStm->Seek( nPos );
1418             else
1419             {
1420                 pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1421                 bRet = sal_False;
1422             }
1423 
1424         }
1425     }
1426     else
1427     {
1428         pStm->SetError( SVSTREAM_GENERALERROR );
1429         bRet = sal_False;
1430     }
1431     return bRet;
1432 }
1433 
~WMFReader()1434 WMFReader::~WMFReader()
1435 {
1436     if( pEMFStream )
1437         delete pEMFStream;
1438 }
1439