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