xref: /aoo42x/main/svtools/source/filter/wmf/winwmf.cxx (revision fb0b81f5)
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 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