update dev300-m58
[ooovba.git] / svtools / source / filter.vcl / wmf / winwmf.cxx
blobb0c673fe175b67b46d0af3ef03894438644470d7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: winwmf.cxx,v $
10 * $Revision: 1.36.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include "winmtf.hxx"
35 #include <svtools/wmf.hxx>
36 #include <rtl/crc.h>
37 #include <rtl/tencinfo.h>
38 #include <osl/endian.h>
40 //====================== MS-Windows-defines ===============================
42 #define W_META_SETBKCOLOR 0x0201
43 #define W_META_SETBKMODE 0x0102
44 #define W_META_SETMAPMODE 0x0103
45 #define W_META_SETROP2 0x0104
46 #define W_META_SETRELABS 0x0105
47 #define W_META_SETPOLYFILLMODE 0x0106
48 #define W_META_SETSTRETCHBLTMODE 0x0107
49 #define W_META_SETTEXTCHAREXTRA 0x0108
50 #define W_META_SETTEXTCOLOR 0x0209
51 #define W_META_SETTEXTJUSTIFICATION 0x020A
52 #define W_META_SETWINDOWORG 0x020B
53 #define W_META_SETWINDOWEXT 0x020C
54 #define W_META_SETVIEWPORTORG 0x020D
55 #define W_META_SETVIEWPORTEXT 0x020E
56 #define W_META_OFFSETWINDOWORG 0x020F
57 #define W_META_SCALEWINDOWEXT 0x0410
58 #define W_META_OFFSETVIEWPORTORG 0x0211
59 #define W_META_SCALEVIEWPORTEXT 0x0412
60 #define W_META_LINETO 0x0213
61 #define W_META_MOVETO 0x0214
62 #define W_META_EXCLUDECLIPRECT 0x0415
63 #define W_META_INTERSECTCLIPRECT 0x0416
64 #define W_META_ARC 0x0817
65 #define W_META_ELLIPSE 0x0418
66 #define W_META_FLOODFILL 0x0419
67 #define W_META_PIE 0x081A
68 #define W_META_RECTANGLE 0x041B
69 #define W_META_ROUNDRECT 0x061C
70 #define W_META_PATBLT 0x061D
71 #define W_META_SAVEDC 0x001E
72 #define W_META_SETPIXEL 0x041F
73 #define W_META_OFFSETCLIPRGN 0x0220
74 #define W_META_TEXTOUT 0x0521
75 #define W_META_BITBLT 0x0922
76 #define W_META_STRETCHBLT 0x0B23
77 #define W_META_POLYGON 0x0324
78 #define W_META_POLYLINE 0x0325
79 #define W_META_ESCAPE 0x0626
80 #define W_META_RESTOREDC 0x0127
81 #define W_META_FILLREGION 0x0228
82 #define W_META_FRAMEREGION 0x0429
83 #define W_META_INVERTREGION 0x012A
84 #define W_META_PAINTREGION 0x012B
85 #define W_META_SELECTCLIPREGION 0x012C
86 #define W_META_SELECTOBJECT 0x012D
87 #define W_META_SETTEXTALIGN 0x012E
88 #define W_META_DRAWTEXT 0x062F
89 #define W_META_CHORD 0x0830
90 #define W_META_SETMAPPERFLAGS 0x0231
91 #define W_META_EXTTEXTOUT 0x0a32
92 #define W_META_SETDIBTODEV 0x0d33
93 #define W_META_SELECTPALETTE 0x0234
94 #define W_META_REALIZEPALETTE 0x0035
95 #define W_META_ANIMATEPALETTE 0x0436
96 #define W_META_SETPALENTRIES 0x0037
97 #define W_META_POLYPOLYGON 0x0538
98 #define W_META_RESIZEPALETTE 0x0139
99 #define W_META_DIBBITBLT 0x0940
100 #define W_META_DIBSTRETCHBLT 0x0b41
101 #define W_META_DIBCREATEPATTERNBRUSH 0x0142
102 #define W_META_STRETCHDIB 0x0f43
103 #define W_META_EXTFLOODFILL 0x0548
104 #define W_META_RESETDC 0x014C
105 #define W_META_STARTDOC 0x014D
106 #define W_META_STARTPAGE 0x004F
107 #define W_META_ENDPAGE 0x0050
108 #define W_META_ABORTDOC 0x0052
109 #define W_META_ENDDOC 0x005E
110 #define W_META_DELETEOBJECT 0x01f0
111 #define W_META_CREATEPALETTE 0x00f7
112 #define W_META_CREATEBRUSH 0x00F8
113 #define W_META_CREATEPATTERNBRUSH 0x01F9
114 #define W_META_CREATEPENINDIRECT 0x02FA
115 #define W_META_CREATEFONTINDIRECT 0x02FB
116 #define W_META_CREATEBRUSHINDIRECT 0x02FC
117 #define W_META_CREATEBITMAPINDIRECT 0x02FD
118 #define W_META_CREATEBITMAP 0x06FE
119 #define W_META_CREATEREGION 0x06FF
121 //=================== Methoden von WMFReader ==============================
123 inline Point WMFReader::ReadPoint()
125 short nX, nY;
126 *pWMF >> nX >> nY;
127 return Point( nX, nY );
130 // ------------------------------------------------------------------------
132 inline Point WMFReader::ReadYX()
134 short nX, nY;
135 *pWMF >> nY >> nX;
136 return Point( nX, nY );
139 // ------------------------------------------------------------------------
141 Rectangle WMFReader::ReadRectangle()
143 Point aBR, aTL;
144 aBR = ReadYX();
145 aTL = ReadYX();
146 aBR.X()--;
147 aBR.Y()--;
148 return Rectangle( aTL, aBR );
151 // ------------------------------------------------------------------------
153 Size WMFReader::ReadYXExt()
155 short nW, nH;
156 *pWMF >> nH >> nW;
157 return Size( nW, nH );
160 // ------------------------------------------------------------------------
162 void WMFReader::ReadRecordParams( USHORT nFunc )
164 switch( nFunc )
166 case W_META_SETBKCOLOR:
168 pOut->SetBkColor( ReadColor() );
170 break;
172 case W_META_SETBKMODE:
174 USHORT nDat;
175 *pWMF >> nDat;
176 pOut->SetBkMode( nDat );
178 break;
180 // !!!
181 case W_META_SETMAPMODE:
183 sal_Int16 nMapMode;
184 *pWMF >> nMapMode;
185 pOut->SetMapMode( nMapMode );
187 break;
189 case W_META_SETROP2:
191 UINT16 nROP2;
192 *pWMF >> nROP2;
193 pOut->SetRasterOp( nROP2 );
195 break;
197 case W_META_SETTEXTCOLOR:
199 pOut->SetTextColor( ReadColor() );
201 break;
203 case W_META_SETWINDOWORG:
205 pOut->SetWinOrg( ReadYX() );
207 break;
209 case W_META_SETWINDOWEXT:
211 short nWidth, nHeight;
212 *pWMF >> nHeight >> nWidth;
213 pOut->SetWinExt( Size( nWidth, nHeight ) );
215 break;
217 case W_META_OFFSETWINDOWORG:
219 short nXAdd, nYAdd;
220 *pWMF >> nYAdd >> nXAdd;
221 pOut->SetWinOrgOffset( nXAdd, nYAdd );
223 break;
225 case W_META_SCALEWINDOWEXT:
227 short nXNum, nXDenom, nYNum, nYDenom;
228 *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
229 pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
231 break;
233 case W_META_SETVIEWPORTORG:
234 case W_META_SETVIEWPORTEXT:
235 break;
237 case W_META_OFFSETVIEWPORTORG:
239 short nXAdd, nYAdd;
240 *pWMF >> nYAdd >> nXAdd;
241 pOut->SetDevOrgOffset( nXAdd, nYAdd );
243 break;
245 case W_META_SCALEVIEWPORTEXT:
247 short nXNum, nXDenom, nYNum, nYDenom;
248 *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
249 pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
251 break;
253 case W_META_LINETO:
255 pOut->LineTo( ReadYX() );
257 break;
259 case W_META_MOVETO:
261 pOut->MoveTo( ReadYX() );
263 break;
265 case W_META_INTERSECTCLIPRECT:
267 pOut->IntersectClipRect( ReadRectangle() );
269 break;
271 case W_META_RECTANGLE:
273 pOut->DrawRect( ReadRectangle() );
275 break;
277 case W_META_ROUNDRECT:
279 Size aSize( ReadYXExt() );
280 pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
282 break;
284 case W_META_ELLIPSE:
286 pOut->DrawEllipse( ReadRectangle() );
288 break;
290 case W_META_ARC:
292 Point aEnd( ReadYX() );
293 Point aStart( ReadYX() );
294 Rectangle aRect( ReadRectangle() );
295 aRect.Justify();
296 pOut->DrawArc( aRect, aStart, aEnd );
298 break;
300 case W_META_PIE:
302 Point aEnd( ReadYX() );
303 Point aStart( ReadYX() );
304 Rectangle aRect( ReadRectangle() );
305 aRect.Justify();
307 // #i73608# OutputDevice deviates from WMF
308 // semantics. start==end means full ellipse here.
309 if( aStart == aEnd )
310 pOut->DrawEllipse( aRect );
311 else
312 pOut->DrawPie( aRect, aStart, aEnd );
314 break;
316 case W_META_CHORD:
318 Point aEnd( ReadYX() );
319 Point aStart( ReadYX() );
320 Rectangle aRect( ReadRectangle() );
321 aRect.Justify();
322 pOut->DrawChord( aRect, aStart, aEnd );
324 break;
326 case W_META_POLYGON:
328 USHORT i,nPoints;
329 *pWMF >> nPoints;
330 Polygon aPoly( nPoints );
331 for( i = 0; i < nPoints; i++ )
332 aPoly[ i ] = ReadPoint();
333 pOut->DrawPolygon( aPoly );
335 break;
337 case W_META_POLYPOLYGON:
339 USHORT i, nPoly, nPoints;
340 USHORT* pnPoints;
341 Point* pPtAry;
342 // Anzahl der Polygone:
343 *pWMF >> nPoly;
344 // Anzahl der Punkte eines jeden Polygons holen, Gesammtzahl der Punkte ermitteln:
345 pnPoints = new USHORT[ nPoly ];
346 nPoints = 0;
347 for( i = 0; i < nPoly; i++ )
349 *pWMF >> pnPoints[i];
350 nPoints = nPoints + pnPoints[i];
352 // Polygonpunkte holen:
353 pPtAry = (Point*) new char[ nPoints * sizeof(Point) ];
354 for ( i = 0; i < nPoints; i++ )
355 pPtAry[ i ] = ReadPoint();
356 // PolyPolygon Actions erzeugen
357 PolyPolygon aPolyPoly( nPoly, pnPoints, pPtAry );
358 pOut->DrawPolyPolygon( aPolyPoly );
359 delete[] (char*) pPtAry;
360 delete[] pnPoints;
362 break;
364 case W_META_POLYLINE:
366 USHORT i,nPoints;
367 *pWMF >> nPoints;
368 Polygon aPoly( nPoints );
369 for( i = 0; i < nPoints; i++ )
370 aPoly[ i ] = ReadPoint();
371 pOut->DrawPolyLine( aPoly );
373 break;
375 case W_META_SAVEDC:
377 pOut->Push();
379 break;
381 case W_META_RESTOREDC:
383 pOut->Pop();
385 break;
387 case W_META_SETPIXEL:
389 const Color aColor = ReadColor();
390 pOut->DrawPixel( ReadYX(), aColor );
392 break;
394 case W_META_OFFSETCLIPRGN:
396 pOut->MoveClipRegion( ReadYXExt() );
398 break;
400 case W_META_TEXTOUT:
402 USHORT nLength;
403 *pWMF >> nLength;
404 if ( nLength )
406 char* pChar = new char[ ( nLength + 1 ) &~ 1 ];
407 pWMF->Read( pChar, ( nLength + 1 ) &~ 1 );
408 String aText( pChar, nLength, pOut->GetCharSet() );
409 delete[] pChar;
410 Point aPosition( ReadYX() );
411 pOut->DrawText( aPosition, aText );
414 break;
416 case W_META_EXTTEXTOUT:
418 sal_Int16 nDx, nDxTmp;
419 sal_uInt16 i, nLen, nOptions;
420 sal_Int32 nRecordPos, nRecordSize, nOriginalTextLen, nNewTextLen;
421 Point aPosition;
422 Rectangle aRect;
423 sal_Int32* pDXAry = NULL;
425 pWMF->SeekRel(-6);
426 nRecordPos = pWMF->Tell();
427 *pWMF >> nRecordSize;
428 pWMF->SeekRel(2);
429 aPosition = ReadYX();
430 *pWMF >> nLen >> nOptions;
432 sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
433 if ( nOptions & ETO_RTLREADING )
434 nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
435 pOut->SetTextLayoutMode( nTextLayoutMode );
436 DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
438 // Nur wenn der Text auch Zeichen enthaelt, macht die Ausgabe Sinn
439 if( nLen )
441 nOriginalTextLen = nLen;
442 if( nOptions & ETO_CLIPPED )
444 const Point aPt1( ReadPoint() );
445 const Point aPt2( ReadPoint() );
446 aRect = Rectangle( aPt1, aPt2 );
448 char* pChar = new char[ ( nOriginalTextLen + 1 ) &~ 1 ];
449 pWMF->Read( pChar, ( nOriginalTextLen + 1 ) &~ 1 );
450 String aText( pChar, (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
451 nNewTextLen = aText.Len(); // less character (japanese version), so the
452 delete[] pChar; // dxAry will not fit
454 if ( nNewTextLen )
456 sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
457 sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
458 sal_Int32 nDxAryEntries = nDxArySize >> 1;
459 sal_Bool bUseDXAry = FALSE;
461 if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
463 pDXAry = new sal_Int32[ nNewTextLen ];
464 for ( i = 0; i < nNewTextLen; i++ )
466 if ( pWMF->Tell() >= nMaxStreamPos )
467 break;
468 *pWMF >> nDx;
469 if ( nNewTextLen != nOriginalTextLen )
471 ByteString aTmp( aText.GetChar( i ), pOut->GetCharSet() );
472 if ( aTmp.Len() > 1 )
474 sal_Int32 nDxCount = aTmp.Len() - 1;
475 if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
476 break;
477 while ( nDxCount-- )
479 *pWMF >> nDxTmp;
480 nDx = nDx + nDxTmp;
484 pDXAry[ i ] = nDx;
486 if ( i == nNewTextLen )
487 bUseDXAry = TRUE;
489 if ( pDXAry && bUseDXAry )
490 pOut->DrawText( aPosition, aText, pDXAry );
491 else
492 pOut->DrawText( aPosition, aText );
495 delete[] pDXAry;
498 break;
500 case W_META_SELECTOBJECT:
502 INT16 nObjIndex;
503 *pWMF >> nObjIndex;
504 pOut->SelectObject( nObjIndex );
506 break;
508 case W_META_SETTEXTALIGN:
510 UINT16 nAlign;
511 *pWMF >> nAlign;
512 pOut->SetTextAlign( nAlign );
514 break;
516 case W_META_BITBLT:
518 // 0-3 : nWinROP #93454#
519 // 4-5 : y offset of source bitmap
520 // 6-7 : x offset of source bitmap
521 // 8-9 : used height of source bitmap
522 // 10-11 : used width of source bitmap
523 // 12-13 : destination position y (in pixel)
524 // 14-15 : destination position x (in pixel)
525 // 16-17 : dont know
526 // 18-19 : Width Bitmap in Pixel
527 // 20-21 : Height Bitmap in Pixel
528 // 22-23 : bytes per scanline
529 // 24 : planes
530 // 25 : bitcount
532 sal_Int32 nWinROP;
533 sal_uInt16 nSx, nSy, nSxe, nSye, nDontKnow, nWidth, nHeight, nBytesPerScan;
534 sal_uInt8 nPlanes, nBitCount;
536 *pWMF >> nWinROP
537 >> nSy >> nSx >> nSye >> nSxe;
538 Point aPoint( ReadYX() );
539 *pWMF >> nDontKnow >> nWidth >> nHeight >> nBytesPerScan >> nPlanes >> nBitCount;
541 if ( nWidth && nHeight && ( nPlanes == 1 ) && ( nBitCount == 1 ) )
543 Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
544 BitmapWriteAccess* pAcc;
545 pAcc = aBmp.AcquireWriteAccess();
546 if ( pAcc )
548 sal_uInt16 y, x, scan;
549 sal_Int8 i, nEightPixels;
550 for ( y = 0; y < nHeight; y++ )
552 x = 0;
553 for ( scan = 0; scan < nBytesPerScan; scan++ )
555 *pWMF >> nEightPixels;
556 for ( i = 7; i >= 0; i-- )
558 if ( x < nWidth )
560 pAcc->SetPixel( y, x, (nEightPixels>>i)&1 );
562 x++;
566 aBmp.ReleaseAccess( pAcc );
567 if ( nSye && nSxe &&
568 ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
569 ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
571 Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
572 aBmp.Crop( aCropRect );
574 Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
575 aBmpSaveList.Insert( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ), LIST_APPEND );
579 break;
581 case W_META_STRETCHBLT:
582 case W_META_DIBBITBLT:
583 case W_META_DIBSTRETCHBLT:
584 case W_META_STRETCHDIB:
586 sal_Int32 nWinROP;
587 sal_uInt16 nSx, nSy, nSxe, nSye, nUsage;
588 Bitmap aBmp;
590 *pWMF >> nWinROP;
592 if( nFunc == W_META_STRETCHDIB )
593 *pWMF >> nUsage;
595 // nSye and nSxe is the number of pixels that has to been used
596 if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
597 *pWMF >> nSye >> nSxe;
598 else
599 nSye = nSxe = 0; // set this to zero as indicator not to scale the bitmap later
601 // nSy and nx is the offset of the first pixel
602 *pWMF >> nSy >> nSx;
604 if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
606 if ( nWinROP == PATCOPY )
607 *pWMF >> nUsage; // i don't know anything of this parameter, so its called nUsage
608 // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), FALSE );
610 Size aDestSize( ReadYXExt() );
611 if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
613 Rectangle aDestRect( ReadYX(), aDestSize );
614 if ( nWinROP != PATCOPY )
615 aBmp.Read( *pWMF, FALSE );
617 // test if it is sensible to crop
618 if ( nSye && nSxe &&
619 ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
620 ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
622 Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
623 aBmp.Crop( aCropRect );
625 aBmpSaveList.Insert( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ), LIST_APPEND );
629 break;
631 case W_META_DIBCREATEPATTERNBRUSH:
633 Bitmap aBmp;
634 BitmapReadAccess* pBmp;
635 UINT32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
636 UINT16 nFunction;
638 *pWMF >> nFunction >> nFunction;
640 aBmp.Read( *pWMF, FALSE );
641 pBmp = aBmp.AcquireReadAccess();
642 if ( pBmp )
644 for ( INT32 y = 0; y < pBmp->Height(); y++ )
646 for ( INT32 x = 0; x < pBmp->Width(); x++ )
648 const BitmapColor aColor( pBmp->GetColor( y, x ) );
650 nRed += aColor.GetRed();
651 nGreen += aColor.GetGreen();
652 nBlue += aColor.GetBlue();
655 nCount = pBmp->Height() * pBmp->Width();
656 if ( !nCount )
657 nCount++;
658 aBmp.ReleaseAccess( pBmp );
660 Color aColor( (BYTE)( nRed / nCount ), (BYTE)( nGreen / nCount ), (BYTE)( nBlue / nCount ) );
661 pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( aColor, FALSE ) );
663 break;
665 case W_META_DELETEOBJECT:
667 INT16 nIndex;
668 *pWMF >> nIndex;
669 pOut->DeleteObject( nIndex );
671 break;
673 case W_META_CREATEPALETTE:
675 pOut->CreateObject( GDI_DUMMY );
677 break;
679 case W_META_CREATEBRUSH:
681 pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), FALSE ) );
683 break;
685 case W_META_CREATEPATTERNBRUSH:
687 pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), FALSE ) );
689 break;
691 case W_META_CREATEPENINDIRECT:
693 LineInfo aLineInfo;
694 USHORT nStyle, nWidth, nHeight;
696 *pWMF >> nStyle >> nWidth >> nHeight;
698 if ( nWidth )
699 aLineInfo.SetWidth( nWidth );
701 BOOL bTransparent = FALSE;
702 UINT16 nDashCount = 0;
703 UINT16 nDotCount = 0;
704 switch( nStyle )
706 case PS_DASHDOTDOT :
707 nDotCount++;
708 case PS_DASHDOT :
709 nDashCount++;
710 case PS_DOT :
711 nDotCount++;
712 break;
713 case PS_DASH :
714 nDashCount++;
715 break;
716 case PS_NULL :
717 bTransparent = TRUE;
718 aLineInfo.SetStyle( LINE_NONE );
719 break;
720 default :
721 case PS_INSIDEFRAME :
722 case PS_SOLID :
723 aLineInfo.SetStyle( LINE_SOLID );
725 if ( nDashCount | nDotCount )
727 aLineInfo.SetStyle( LINE_DASH );
728 aLineInfo.SetDashCount( nDashCount );
729 aLineInfo.SetDotCount( nDotCount );
731 pOut->CreateObject( GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
733 break;
735 case W_META_CREATEBRUSHINDIRECT:
737 USHORT nStyle;
738 *pWMF >> nStyle;
739 pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? TRUE : FALSE ) );
741 break;
743 case W_META_CREATEFONTINDIRECT:
745 Size aFontSize;
746 char lfFaceName[ LF_FACESIZE ];
747 INT16 lfEscapement, lfOrientation, lfWeight; // ( ehemals USHORT )
749 LOGFONTW aLogFont;
750 aFontSize = ReadYXExt();
751 *pWMF >> lfEscapement >> lfOrientation >> lfWeight
752 >> aLogFont.lfItalic >> aLogFont.lfUnderline >> aLogFont.lfStrikeOut >> aLogFont.lfCharSet >> aLogFont.lfOutPrecision
753 >> aLogFont.lfClipPrecision >> aLogFont.lfQuality >> aLogFont.lfPitchAndFamily;
754 pWMF->Read( lfFaceName, LF_FACESIZE );
755 aLogFont.lfWidth = aFontSize.Width();
756 aLogFont.lfHeight = aFontSize.Height();
757 aLogFont.lfEscapement = lfEscapement;
758 aLogFont.lfOrientation = lfOrientation;
759 aLogFont.lfWeight = lfWeight;
761 CharSet eCharSet;
762 if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
763 eCharSet = gsl_getSystemTextEncoding();
764 else
765 eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
766 if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
767 eCharSet = gsl_getSystemTextEncoding();
768 if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
769 eCharSet = RTL_TEXTENCODING_MS_1252;
770 aLogFont.alfFaceName = UniString( lfFaceName, eCharSet );
772 pOut->CreateObject( GDI_FONT, new WinMtfFontStyle( aLogFont ) );
774 break;
776 case W_META_CREATEBITMAPINDIRECT:
778 pOut->CreateObject( GDI_DUMMY );
780 break;
782 case W_META_CREATEBITMAP:
784 pOut->CreateObject( GDI_DUMMY );
786 break;
788 case W_META_CREATEREGION:
790 pOut->CreateObject( GDI_DUMMY );
792 break;
794 case W_META_EXCLUDECLIPRECT :
796 pOut->ExcludeClipRect( ReadRectangle() );
798 break;
800 case W_META_PATBLT:
802 UINT32 nROP, nOldROP;
803 *pWMF >> nROP;
804 Size aSize = ReadYXExt();
805 nOldROP = pOut->SetRasterOp( nROP );
806 pOut->DrawRect( Rectangle( ReadYX(), aSize ), FALSE );
807 pOut->SetRasterOp( nOldROP );
809 break;
811 case W_META_SELECTCLIPREGION:
813 sal_Int16 nObjIndex;
814 *pWMF >> nObjIndex;
815 if ( !nObjIndex )
817 PolyPolygon aEmptyPolyPoly;
818 pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, sal_True );
821 break;
823 case W_META_ESCAPE :
825 // nRecSize has been checked previously to be greater than 3
826 sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
827 sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
829 // taking care that nRecSize does not exceed the maximal stream position
830 if ( nMetaRecEndPos > nEndPos )
832 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
833 break;
835 if ( nRecSize >= 12 ) // minimal escape lenght
837 sal_uInt16 nMode, nLen, OO;
838 sal_uInt32 Magic, nCheck,nEsc;
839 *pWMF >> nMode
840 >> nLen
841 >> OO
842 >> Magic
843 >> nCheck
844 >> nEsc;
845 if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 14 ) && ( OO == 0x4f4f ) && ( Magic == 0xa2c2a ) )
847 sal_uInt32 nEscLen = nLen - 14;
848 if ( nEscLen <= ( nRecSize * 2 ) )
850 #ifdef OSL_BIGENDIAN
851 sal_uInt32 nTmp = SWAPLONG( nEsc );
852 sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
853 #else
854 sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
855 #endif
856 sal_Int8* pData = NULL;
858 if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
860 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
861 break;
863 if ( nEscLen > 0 )
865 pData = new sal_Int8[ nEscLen ];
866 pWMF->Read( pData, nEscLen );
867 nCheckSum = rtl_crc32( nCheckSum, pData, nEscLen );
869 if ( nCheck == nCheckSum )
871 switch( nEsc )
873 case PRIVATE_ESCAPE_UNICODE :
874 { // we will use text instead of polygons only if we have the correct font
875 if ( aVDev.IsFontAvailable( pOut->GetFont().GetName() ) )
877 Point aPt;
878 String aString;
879 sal_uInt32 i, nStringLen, nDXCount;
880 sal_Int32* pDXAry = NULL;
881 SvMemoryStream aMemoryStream( nEscLen );
882 aMemoryStream.Write( pData, nEscLen );
883 aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
884 aMemoryStream >> aPt.X()
885 >> aPt.Y()
886 >> nStringLen;
888 if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
890 sal_Unicode* pBuf = aString.AllocBuffer( (xub_StrLen)nStringLen );
891 for ( i = 0; i < nStringLen; i++ )
892 aMemoryStream >> pBuf[ i ];
893 aMemoryStream >> nDXCount;
894 if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
895 nDXCount = 0;
896 if ( nDXCount )
897 pDXAry = new sal_Int32[ nDXCount ];
898 for ( i = 0; i < nDXCount; i++ )
899 aMemoryStream >> pDXAry[ i ];
900 aMemoryStream >> nSkipActions;
901 pOut->DrawText( aPt, aString, pDXAry );
902 delete[] pDXAry;
906 break;
909 delete[] pData;
914 break;
916 case W_META_SETRELABS:
917 case W_META_SETPOLYFILLMODE:
918 case W_META_SETSTRETCHBLTMODE:
919 case W_META_SETTEXTCHAREXTRA:
920 case W_META_SETTEXTJUSTIFICATION:
921 case W_META_FLOODFILL :
922 case W_META_FILLREGION:
923 case W_META_FRAMEREGION:
924 case W_META_INVERTREGION:
925 case W_META_PAINTREGION:
926 case W_META_DRAWTEXT:
927 case W_META_SETMAPPERFLAGS:
928 case W_META_SETDIBTODEV:
929 case W_META_SELECTPALETTE:
930 case W_META_REALIZEPALETTE:
931 case W_META_ANIMATEPALETTE:
932 case W_META_SETPALENTRIES:
933 case W_META_RESIZEPALETTE:
934 case W_META_EXTFLOODFILL:
935 case W_META_RESETDC:
936 case W_META_STARTDOC:
937 case W_META_STARTPAGE:
938 case W_META_ENDPAGE:
939 case W_META_ABORTDOC:
940 case W_META_ENDDOC:
941 break;
945 // ------------------------------------------------------------------------
947 BOOL WMFReader::ReadHeader(WMF_APMFILEHEADER *pAPMHeader)
949 Rectangle aPlaceableBound;
950 sal_uInt32 nl, nStrmPos = pWMF->Tell();
952 // Einlesen des METAFILEHEADER, falls vorhanden
953 *pWMF >> nl;
955 Size aWMFSize;
956 if ( nl == 0x9ac6cdd7L )
958 INT16 nVal;
960 // hmf (Unused) ueberlesen wir
961 pWMF->SeekRel(2);
963 // BoundRect
964 *pWMF >> nVal; aPlaceableBound.Left() = nVal;
965 *pWMF >> nVal; aPlaceableBound.Top() = nVal;
966 *pWMF >> nVal; aPlaceableBound.Right() = nVal;
967 *pWMF >> nVal; aPlaceableBound.Bottom() = nVal;
969 // inch
970 *pWMF >> nUnitsPerInch;
972 // reserved
973 pWMF->SeekRel( 4 );
975 // checksum pruefen wir lieber nicht
976 pWMF->SeekRel( 2 );
978 else
980 nUnitsPerInch = (pAPMHeader!=NULL?pAPMHeader->inch:96);
981 pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the the metaactions
982 GetPlaceableBound( aPlaceableBound, pWMF );
983 pWMF->Seek( nStrmPos );
984 if (pAPMHeader!=NULL) {
985 // #n417818#: If we have an external header then overwrite the bounds!
986 aPlaceableBound=Rectangle(pAPMHeader->left*567*nUnitsPerInch/1440/1000,
987 pAPMHeader->top*567*nUnitsPerInch/1440/1000,
988 pAPMHeader->right*567*nUnitsPerInch/1440/1000,
989 pAPMHeader->bottom*567*nUnitsPerInch/1440/1000);
993 pOut->SetUnitsPerInch( nUnitsPerInch );
994 pOut->SetWinOrg( aPlaceableBound.TopLeft() );
995 aWMFSize = Size( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
996 pOut->SetWinExt( aWMFSize );
998 Size aDevExt( 10000, 10000 );
999 if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
1001 const Fraction aFrac( 1, nUnitsPerInch );
1002 MapMode aWMFMap( MAP_INCH, Point(), aFrac, aFrac );
1003 Size aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MAP_100TH_MM ) );
1004 aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
1006 pOut->SetDevExt( aDevExt );
1008 // Einlesen des METAHEADER
1009 *pWMF >> nl; // Typ und Headergroesse
1011 if( nl != 0x00090001 )
1013 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1014 return FALSE;
1017 pWMF->SeekRel( 2 ); // Version (von Windows)
1018 pWMF->SeekRel( 4 ); // Size (der Datei in Words)
1019 pWMF->SeekRel( 2 ); // NoObjects (Maximale Anzahl der gleichzeitigen Objekte)
1020 pWMF->SeekRel( 4 ); // MaxRecord (Groesse des groessten Records in Words)
1021 pWMF->SeekRel( 2 ); // NoParameters (Unused
1023 return TRUE;
1026 void WMFReader::ReadWMF(WMF_APMFILEHEADER *pAPMHeader)
1028 USHORT nFunction;
1029 ULONG nPos, nPercent, nLastPercent;
1031 nSkipActions = 0;
1032 nCurrentAction = 0;
1033 nUnicodeEscapeAction = 0;
1035 pOut->SetMapMode( MM_ANISOTROPIC );
1036 pOut->SetWinOrg( Point() );
1037 pOut->SetWinExt( Size( 1, 1 ) );
1038 pOut->SetDevExt( Size( 10000, 10000 ) );
1040 nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
1041 pWMF->Seek( nStartPos );
1042 Callback( (USHORT) ( nLastPercent = 0 ) );
1044 if ( ReadHeader( pAPMHeader ) )
1047 nPos = pWMF->Tell();
1049 if( nEndPos - nStartPos )
1051 while( TRUE )
1053 nCurrentAction++;
1054 nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
1056 if( nLastPercent + 4 <= nPercent )
1058 Callback( (USHORT) nPercent );
1059 nLastPercent = nPercent;
1061 *pWMF >> nRecSize >> nFunction;
1063 if( pWMF->GetError() || ( nRecSize < 3 ) || ( nRecSize==3 && nFunction==0 ) || pWMF->IsEof() )
1066 if( pWMF->IsEof() )
1067 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1069 break;
1071 if( aBmpSaveList.Count() &&
1072 ( nFunction != W_META_STRETCHDIB ) &&
1073 ( nFunction != W_META_DIBBITBLT ) &&
1074 ( nFunction != W_META_DIBSTRETCHBLT ) )
1076 pOut->ResolveBitmapActions( aBmpSaveList );
1078 if ( !nSkipActions )
1079 ReadRecordParams( nFunction );
1080 else
1081 nSkipActions--;
1082 nPos += nRecSize * 2;
1083 if ( nPos <= nEndPos )
1084 pWMF->Seek( nPos );
1085 else
1086 pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1090 else
1091 pWMF->SetError( SVSTREAM_GENERALERROR );
1093 if( !pWMF->GetError() && aBmpSaveList.Count() )
1094 pOut->ResolveBitmapActions( aBmpSaveList );
1096 if ( pWMF->GetError() )
1097 pWMF->Seek( nStartPos );
1100 // ------------------------------------------------------------------------
1102 static void GetWinExtMax( const Point& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
1104 Point aSource( rSource );
1105 if ( nMapMode == MM_HIMETRIC )
1106 aSource.Y() = -rSource.Y();
1107 if ( aSource.X() < rPlaceableBound.Left() )
1108 rPlaceableBound.Left() = aSource.X();
1109 if ( aSource.X() > rPlaceableBound.Right() )
1110 rPlaceableBound.Right() = aSource.X();
1111 if ( aSource.Y() < rPlaceableBound.Top() )
1112 rPlaceableBound.Top() = aSource.Y();
1113 if ( aSource.Y() > rPlaceableBound.Bottom() )
1114 rPlaceableBound.Bottom() = aSource.Y();
1117 static void GetWinExtMax( const Rectangle& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
1119 GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
1120 GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
1123 sal_Bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm )
1125 sal_Bool bRet = sal_True;
1127 rPlaceableBound.Left() = (sal_Int32)0x7fffffff;
1128 rPlaceableBound.Top() = (sal_Int32)0x7fffffff;
1129 rPlaceableBound.Right() = (sal_Int32)0x80000000;
1130 rPlaceableBound.Bottom() = (sal_Int32)0x80000000;
1132 sal_Int16 nMapMode = MM_ANISOTROPIC;
1134 sal_uInt16 nFunction;
1135 sal_uInt32 nRSize;
1136 sal_uInt32 nPos = pStm->Tell();
1137 sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
1139 pStm->Seek( nPos );
1141 if( nEnd - nPos )
1143 while( bRet )
1145 *pStm >> nRSize >> nFunction;
1147 if( pStm->GetError() || ( nRSize < 3 ) || ( nRSize==3 && nFunction==0 ) || pStm->IsEof() )
1149 if( pStm->IsEof() )
1151 pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1152 bRet = sal_False;
1154 break;
1156 switch( nFunction )
1158 case W_META_SETWINDOWORG:
1160 Point aWinOrg;
1161 aWinOrg = ReadYX();
1162 rPlaceableBound.SetPos( aWinOrg );
1164 break;
1166 case W_META_SETWINDOWEXT:
1168 Point aPos0( 0, 0 );
1169 sal_Int16 nWidth, nHeight;
1170 *pStm >> nHeight >> nWidth;
1171 rPlaceableBound.SetSize( Size( nWidth, nHeight ) );
1173 break;
1175 case W_META_SETMAPMODE :
1176 *pStm >> nMapMode;
1177 break;
1179 case W_META_MOVETO:
1180 case W_META_LINETO:
1181 GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1182 break;
1184 case W_META_RECTANGLE:
1185 case W_META_INTERSECTCLIPRECT:
1186 case W_META_EXCLUDECLIPRECT :
1187 case W_META_ELLIPSE:
1188 GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1189 break;
1191 case W_META_ROUNDRECT:
1193 Size aSize( ReadYXExt() );
1194 GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1196 break;
1198 case W_META_ARC:
1199 case W_META_PIE:
1200 case W_META_CHORD:
1202 Point aEnd( ReadYX() );
1203 Point aStart( ReadYX() );
1204 GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
1206 break;
1208 case W_META_POLYGON:
1210 USHORT i,nPoints;
1211 *pStm >> nPoints;
1212 for( i = 0; i < nPoints; i++ )
1213 GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1215 break;
1217 case W_META_POLYPOLYGON:
1219 USHORT i, nPoly, nPoints = 0;
1220 *pStm >> nPoly;
1221 for( i = 0; i < nPoly; i++ )
1223 sal_uInt16 nP;
1224 *pStm >> nP;
1225 nPoints = nPoints + nP;
1227 for ( i = 0; i < nPoints; i++ )
1228 GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1230 break;
1232 case W_META_POLYLINE:
1234 USHORT i,nPoints;
1235 *pStm >> nPoints;
1236 for( i = 0; i < nPoints; i++ )
1237 GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
1239 break;
1241 case W_META_SETPIXEL:
1243 const Color aColor = ReadColor();
1244 GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1246 break;
1248 case W_META_TEXTOUT:
1250 USHORT nLength;
1251 *pStm >> nLength;
1252 // todo: we also have to take care of the text width
1253 if ( nLength )
1255 pStm->SeekRel( ( nLength + 1 ) &~ 1 );
1256 GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
1259 break;
1261 case W_META_EXTTEXTOUT:
1263 sal_uInt16 nLen, nOptions;
1264 sal_Int32 nRecordPos, nRecordSize;
1265 Point aPosition;
1266 Rectangle aRect;
1268 pStm->SeekRel(-6);
1269 nRecordPos = pStm->Tell();
1270 *pStm >> nRecordSize;
1271 pStm->SeekRel(2);
1272 aPosition = ReadYX();
1273 *pStm >> nLen >> nOptions;
1274 // todo: we also have to take care of the text width
1275 if( nLen )
1276 GetWinExtMax( aPosition, rPlaceableBound, nMapMode );
1278 break;
1279 case W_META_BITBLT:
1280 case W_META_STRETCHBLT:
1281 case W_META_DIBBITBLT:
1282 case W_META_DIBSTRETCHBLT:
1283 case W_META_STRETCHDIB:
1285 sal_Int32 nWinROP;
1286 sal_uInt16 nSx, nSy, nSxe, nSye, nUsage;
1287 *pStm >> nWinROP;
1289 if( nFunction == W_META_STRETCHDIB )
1290 *pStm >> nUsage;
1292 // nSye and nSxe is the number of pixels that has to been used
1293 if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
1294 *pStm >> nSye >> nSxe;
1295 else
1296 nSye = nSxe = 0; // set this to zero as indicator not to scale the bitmap later
1298 // nSy and nx is the offset of the first pixel
1299 *pStm >> nSy >> nSx;
1301 if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
1303 if ( nWinROP == PATCOPY )
1304 *pStm >> nUsage; // i don't know anything of this parameter, so its called nUsage
1305 // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), FALSE );
1307 Size aDestSize( ReadYXExt() );
1308 if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
1310 Rectangle aDestRect( ReadYX(), aDestSize );
1311 GetWinExtMax( aDestRect, rPlaceableBound, nMapMode );
1315 break;
1317 case W_META_PATBLT:
1319 UINT32 nROP;
1320 *pStm >> nROP;
1321 Size aSize = ReadYXExt();
1322 GetWinExtMax( Rectangle( ReadYX(), aSize ), rPlaceableBound, nMapMode );
1324 break;
1326 nPos += nRSize * 2;
1327 if ( nPos <= nEnd )
1328 pStm->Seek( nPos );
1329 else
1331 pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1332 bRet = sal_False;
1337 else
1339 pStm->SetError( SVSTREAM_GENERALERROR );
1340 bRet = sal_False;
1342 return bRet;