Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "winmtf.hxx"
21 :
22 : #include <boost/scoped_array.hpp>
23 : #include <boost/optional.hpp>
24 : #include <vcl/gdimtf.hxx>
25 : #include <vcl/wmf.hxx>
26 : #include <rtl/crc.h>
27 : #include <rtl/tencinfo.h>
28 : #include <osl/endian.h>
29 : #include <vcl/svapp.hxx>
30 : #include <vcl/dibtools.hxx>
31 : #include <tools/fract.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 9084 : static void GetWinExtMax( const Point& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
115 : {
116 9084 : Point aSource( rSource );
117 9084 : if ( nMapMode == MM_HIMETRIC )
118 0 : aSource.Y() = -rSource.Y();
119 9084 : if ( aSource.X() < rPlaceableBound.Left() )
120 88 : rPlaceableBound.Left() = aSource.X();
121 9084 : if ( aSource.X() > rPlaceableBound.Right() )
122 83 : rPlaceableBound.Right() = aSource.X();
123 9084 : if ( aSource.Y() < rPlaceableBound.Top() )
124 79 : rPlaceableBound.Top() = aSource.Y();
125 9084 : if ( aSource.Y() > rPlaceableBound.Bottom() )
126 83 : rPlaceableBound.Bottom() = aSource.Y();
127 9084 : }
128 :
129 119 : static void GetWinExtMax( const Rectangle& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
130 : {
131 119 : GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
132 119 : GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
133 119 : }
134 :
135 58516 : inline Point WMFReader::ReadPoint()
136 : {
137 58516 : short nX = 0, nY = 0;
138 58516 : pWMF->ReadInt16( nX ).ReadInt16( nY );
139 58516 : return Point( nX, nY );
140 : }
141 :
142 896 : inline Point WMFReader::ReadYX()
143 : {
144 896 : short nX = 0, nY = 0;
145 896 : pWMF->ReadInt16( nY ).ReadInt16( nX );
146 896 : return Point( nX, nY );
147 : }
148 :
149 106 : Rectangle WMFReader::ReadRectangle()
150 : {
151 106 : Point aBR, aTL;
152 106 : aBR = ReadYX();
153 106 : aTL = ReadYX();
154 106 : aBR.X()--;
155 106 : aBR.Y()--;
156 106 : return Rectangle( aTL, aBR );
157 : }
158 :
159 349 : Size WMFReader::ReadYXExt()
160 : {
161 349 : short nW=0, nH=0;
162 349 : pWMF->ReadInt16( nH ).ReadInt16( nW );
163 349 : return Size( nW, nH );
164 : }
165 :
166 6723 : void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
167 : {
168 6723 : switch( nFunc )
169 : {
170 : case W_META_SETBKCOLOR:
171 : {
172 63 : pOut->SetBkColor( ReadColor() );
173 : }
174 63 : break;
175 :
176 : case W_META_SETBKMODE:
177 : {
178 93 : sal_uInt16 nDat = 0;
179 93 : pWMF->ReadUInt16( nDat );
180 93 : pOut->SetBkMode( static_cast<BkMode>(nDat) );
181 : }
182 93 : break;
183 :
184 : // !!!
185 : case W_META_SETMAPMODE:
186 : {
187 57 : sal_Int16 nMapMode = 0;
188 57 : pWMF->ReadInt16( nMapMode );
189 57 : pOut->SetMapMode( nMapMode );
190 : }
191 57 : break;
192 :
193 : case W_META_SETROP2:
194 : {
195 13 : sal_uInt16 nROP2 = 0;
196 13 : pWMF->ReadUInt16( nROP2 );
197 13 : pOut->SetRasterOp( nROP2 );
198 : }
199 13 : break;
200 :
201 : case W_META_SETTEXTCOLOR:
202 : {
203 90 : pOut->SetTextColor( ReadColor() );
204 : }
205 90 : break;
206 :
207 : case W_META_SETWINDOWORG:
208 : {
209 141 : pOut->SetWinOrg( ReadYX() );
210 : }
211 141 : break;
212 :
213 : case W_META_SETWINDOWEXT:
214 : {
215 140 : short nWidth = 0, nHeight = 0;
216 140 : pWMF->ReadInt16( nHeight ).ReadInt16( nWidth );
217 140 : pOut->SetWinExt( Size( nWidth, nHeight ) );
218 : }
219 140 : break;
220 :
221 : case W_META_OFFSETWINDOWORG:
222 : {
223 0 : short nXAdd = 0, nYAdd = 0;
224 0 : pWMF->ReadInt16( nYAdd ).ReadInt16( nXAdd );
225 0 : pOut->SetWinOrgOffset( nXAdd, nYAdd );
226 : }
227 0 : break;
228 :
229 : case W_META_SCALEWINDOWEXT:
230 : {
231 0 : short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
232 0 : pWMF->ReadInt16( nYDenom ).ReadInt16( nYNum ).ReadInt16( nXDenom ).ReadInt16( nXNum );
233 0 : if (!nYDenom || !nXDenom)
234 : {
235 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
236 0 : break;
237 : }
238 0 : pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
239 : }
240 0 : break;
241 :
242 : case W_META_SETVIEWPORTORG:
243 : case W_META_SETVIEWPORTEXT:
244 0 : break;
245 :
246 : case W_META_OFFSETVIEWPORTORG:
247 : {
248 0 : short nXAdd = 0, nYAdd = 0;
249 0 : pWMF->ReadInt16( nYAdd ).ReadInt16( nXAdd );
250 0 : pOut->SetDevOrgOffset( nXAdd, nYAdd );
251 : }
252 0 : break;
253 :
254 : case W_META_SCALEVIEWPORTEXT:
255 : {
256 0 : short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
257 0 : pWMF->ReadInt16( nYDenom ).ReadInt16( nYNum ).ReadInt16( nXDenom ).ReadInt16( nXNum );
258 0 : if (!nYDenom || !nXDenom)
259 : {
260 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
261 0 : break;
262 : }
263 0 : pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
264 : }
265 0 : break;
266 :
267 : case W_META_LINETO:
268 : {
269 14 : pOut->LineTo( ReadYX() );
270 : }
271 14 : break;
272 :
273 : case W_META_MOVETO:
274 : {
275 29 : pOut->MoveTo( ReadYX() );
276 : }
277 29 : break;
278 :
279 : case W_META_INTERSECTCLIPRECT:
280 : {
281 3 : pOut->IntersectClipRect( ReadRectangle() );
282 : }
283 3 : break;
284 :
285 : case W_META_RECTANGLE:
286 : {
287 29 : pOut->DrawRect( ReadRectangle() );
288 : }
289 29 : break;
290 :
291 : case W_META_ROUNDRECT:
292 : {
293 0 : Size aSize( ReadYXExt() );
294 0 : pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
295 : }
296 0 : break;
297 :
298 : case W_META_ELLIPSE:
299 : {
300 1 : pOut->DrawEllipse( ReadRectangle() );
301 : }
302 1 : break;
303 :
304 : case W_META_ARC:
305 : {
306 0 : Point aEnd( ReadYX() );
307 0 : Point aStart( ReadYX() );
308 0 : Rectangle aRect( ReadRectangle() );
309 0 : aRect.Justify();
310 0 : pOut->DrawArc( aRect, aStart, aEnd );
311 : }
312 0 : break;
313 :
314 : case W_META_PIE:
315 : {
316 0 : Point aEnd( ReadYX() );
317 0 : Point aStart( ReadYX() );
318 0 : Rectangle aRect( ReadRectangle() );
319 0 : aRect.Justify();
320 :
321 : // #i73608# OutputDevice deviates from WMF
322 : // semantics. start==end means full ellipse here.
323 0 : if( aStart == aEnd )
324 0 : pOut->DrawEllipse( aRect );
325 : else
326 0 : pOut->DrawPie( aRect, aStart, aEnd );
327 : }
328 0 : break;
329 :
330 : case W_META_CHORD:
331 : {
332 0 : Point aEnd( ReadYX() );
333 0 : Point aStart( ReadYX() );
334 0 : Rectangle aRect( ReadRectangle() );
335 0 : aRect.Justify();
336 0 : pOut->DrawChord( aRect, aStart, aEnd );
337 : }
338 0 : break;
339 :
340 : case W_META_POLYGON:
341 : {
342 541 : bool bRecordOk = true;
343 :
344 541 : sal_uInt16 nPoints(0);
345 541 : pWMF->ReadUInt16(nPoints);
346 :
347 541 : if (nPoints > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
348 : {
349 1 : bRecordOk = false;
350 : }
351 : else
352 : {
353 540 : Polygon aPoly(nPoints);
354 39497 : for (sal_uInt16 i(0); i < nPoints && pWMF->good(); ++i)
355 38957 : aPoly[ i ] = ReadPoint();
356 540 : pOut->DrawPolygon(aPoly);
357 : }
358 :
359 : SAL_WARN_IF(!bRecordOk, "vcl.filter", "polygon record has more points than we can handle");
360 :
361 541 : bRecordOk &= pWMF->good();
362 :
363 541 : if (!bRecordOk)
364 : {
365 1 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
366 1 : break;
367 : }
368 : }
369 540 : break;
370 :
371 : case W_META_POLYPOLYGON:
372 : {
373 61 : bool bRecordOk = true;
374 61 : sal_uInt16 nPolyCount(0);
375 : // Number of polygons:
376 61 : pWMF->ReadUInt16( nPolyCount );
377 61 : if (nPolyCount && pWMF->good())
378 : {
379 61 : if (nPolyCount > pWMF->remainingSize() / sizeof(sal_uInt16))
380 : {
381 0 : bRecordOk = false;
382 0 : break;
383 : }
384 :
385 : // Number of points of each polygon. Determine total number of points
386 61 : boost::scoped_array<sal_uInt16> xPolygonPointCounts(new sal_uInt16[nPolyCount]);
387 61 : sal_uInt16* pnPoints = xPolygonPointCounts.get();
388 122 : tools::PolyPolygon aPolyPoly(nPolyCount, nPolyCount);
389 61 : sal_uInt16 nPoints = 0;
390 328 : for (sal_uInt16 a = 0; a < nPolyCount && pWMF->good(); ++a)
391 : {
392 267 : pWMF->ReadUInt16( pnPoints[a] );
393 :
394 267 : if (pnPoints[a] > SAL_MAX_UINT16 - nPoints)
395 : {
396 0 : bRecordOk = false;
397 0 : break;
398 : }
399 :
400 267 : nPoints += pnPoints[a];
401 : }
402 :
403 : SAL_WARN_IF(!bRecordOk, "vcl.filter", "polypolygon record has more polygons than we can handle");
404 :
405 61 : bRecordOk &= pWMF->good();
406 :
407 61 : if (!bRecordOk)
408 : {
409 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
410 0 : break;
411 : }
412 :
413 : // Polygon points are:
414 328 : for (sal_uInt16 a = 0; a < nPolyCount && pWMF->good(); ++a)
415 : {
416 267 : const sal_uInt16 nPointCount(pnPoints[a]);
417 :
418 267 : if (nPointCount > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
419 : {
420 0 : bRecordOk = false;
421 0 : break;
422 : }
423 :
424 267 : boost::scoped_array<Point> xPolygonPoints(new Point[nPointCount]);
425 267 : Point* pPtAry = xPolygonPoints.get();
426 :
427 10884 : for(sal_uInt16 b(0); b < nPointCount && pWMF->good(); ++b)
428 : {
429 10617 : pPtAry[b] = ReadPoint();
430 : }
431 :
432 267 : aPolyPoly.Insert(Polygon(nPointCount, pPtAry));
433 267 : }
434 :
435 61 : bRecordOk &= pWMF->good();
436 :
437 61 : if (!bRecordOk)
438 : {
439 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
440 0 : break;
441 : }
442 :
443 122 : pOut->DrawPolyPolygon( aPolyPoly );
444 : }
445 : }
446 61 : break;
447 :
448 : case W_META_POLYLINE:
449 : {
450 27 : bool bRecordOk = true;
451 :
452 27 : sal_uInt16 nPoints(0);
453 27 : pWMF->ReadUInt16(nPoints);
454 :
455 27 : if (nPoints > pWMF->remainingSize() / (2 * sizeof(sal_uInt16)))
456 : {
457 0 : bRecordOk = false;
458 : }
459 : else
460 : {
461 27 : Polygon aPoly(nPoints);
462 84 : for (sal_uInt16 i(0); i < nPoints && pWMF->good(); ++i)
463 57 : aPoly[ i ] = ReadPoint();
464 27 : pOut->DrawPolyLine( aPoly );
465 : }
466 :
467 : SAL_WARN_IF(!bRecordOk, "vcl.filter", "polyline record has more points than we can handle");
468 :
469 27 : bRecordOk &= pWMF->good();
470 :
471 27 : if (!bRecordOk)
472 : {
473 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
474 0 : break;
475 : }
476 : }
477 27 : break;
478 :
479 : case W_META_SAVEDC:
480 : {
481 51 : pOut->Push();
482 : }
483 51 : break;
484 :
485 : case W_META_RESTOREDC:
486 : {
487 51 : pOut->Pop();
488 : }
489 51 : break;
490 :
491 : case W_META_SETPIXEL:
492 : {
493 0 : const Color aColor = ReadColor();
494 0 : pOut->DrawPixel( ReadYX(), aColor );
495 : }
496 0 : break;
497 :
498 : case W_META_OFFSETCLIPRGN:
499 : {
500 0 : pOut->MoveClipRegion( ReadYXExt() );
501 : }
502 0 : break;
503 :
504 : case W_META_TEXTOUT:
505 : {
506 2 : sal_uInt16 nLength = 0;
507 2 : pWMF->ReadUInt16( nLength );
508 2 : if ( nLength )
509 : {
510 2 : boost::scoped_array<char> pChar(new char[ ( nLength + 1 ) &~ 1 ]);
511 2 : pWMF->Read( pChar.get(), ( nLength + 1 ) &~ 1 );
512 4 : OUString aText( pChar.get(), nLength, pOut->GetCharSet() );
513 2 : pChar.reset();
514 2 : Point aPosition( ReadYX() );
515 4 : pOut->DrawText( aPosition, aText );
516 : }
517 : }
518 2 : break;
519 :
520 : case W_META_EXTTEXTOUT:
521 : {
522 177 : sal_uInt16 nLen = 0, nOptions = 0;
523 177 : sal_Int32 nRecordPos, nRecordSize = 0, nOriginalTextLen, nNewTextLen;
524 177 : Point aPosition;
525 177 : Rectangle aRect;
526 177 : boost::scoped_array<long> pDXAry;
527 :
528 177 : pWMF->SeekRel(-6);
529 177 : nRecordPos = pWMF->Tell();
530 177 : pWMF->ReadInt32( nRecordSize );
531 177 : pWMF->SeekRel(2);
532 177 : aPosition = ReadYX();
533 177 : pWMF->ReadUInt16( nLen );
534 177 : pWMF->ReadUInt16( nOptions );
535 :
536 177 : ComplexTextLayoutMode nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
537 177 : if ( nOptions & ETO_RTLREADING )
538 0 : nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
539 177 : pOut->SetTextLayoutMode( nTextLayoutMode );
540 : DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
541 :
542 : // output only makes sense if the text contains characters
543 177 : if( nLen )
544 : {
545 177 : nOriginalTextLen = nLen;
546 177 : if( nOptions & ETO_CLIPPED )
547 : {
548 53 : const Point aPt1( ReadPoint() );
549 53 : const Point aPt2( ReadPoint() );
550 53 : aRect = Rectangle( aPt1, aPt2 );
551 : }
552 177 : boost::scoped_array<char> pChar(new char[ ( nOriginalTextLen + 1 ) &~ 1 ]);
553 177 : pWMF->Read( pChar.get(), ( nOriginalTextLen + 1 ) &~ 1 );
554 354 : OUString aText( pChar.get(), (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
555 177 : nNewTextLen = aText.getLength(); // less character (japanese version), so the
556 177 : pChar.reset(); // dxAry will not fit
557 :
558 177 : if ( nNewTextLen )
559 : {
560 177 : sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
561 177 : sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
562 177 : sal_Int32 nDxAryEntries = nDxArySize >> 1;
563 177 : bool bUseDXAry = false;
564 :
565 177 : if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
566 : {
567 177 : sal_Int16 nDx = 0, nDxTmp = 0;
568 : sal_uInt16 i; //needed just outside the for
569 177 : pDXAry.reset(new long[ nNewTextLen ]);
570 747 : for (i = 0; i < nNewTextLen; i++ )
571 : {
572 663 : if ( pWMF->Tell() >= nMaxStreamPos )
573 93 : break;
574 570 : pWMF->ReadInt16( nDx );
575 570 : if ( nNewTextLen != nOriginalTextLen )
576 : {
577 0 : sal_Unicode nUniChar = aText[i];
578 0 : OString aTmp(&nUniChar, 1, pOut->GetCharSet());
579 0 : if ( aTmp.getLength() > 1 )
580 : {
581 0 : sal_Int32 nDxCount = aTmp.getLength() - 1;
582 0 : if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
583 0 : break;
584 0 : while ( nDxCount-- )
585 : {
586 0 : pWMF->ReadInt16( nDxTmp );
587 0 : nDx = nDx + nDxTmp;
588 : }
589 0 : }
590 : }
591 570 : pDXAry[ i ] = nDx;
592 : }
593 177 : if ( i == nNewTextLen )
594 84 : bUseDXAry = true;
595 : }
596 177 : if ( pDXAry && bUseDXAry )
597 84 : pOut->DrawText( aPosition, aText, pDXAry.get() );
598 : else
599 93 : pOut->DrawText( aPosition, aText );
600 177 : }
601 177 : }
602 : }
603 177 : break;
604 :
605 : case W_META_SELECTOBJECT:
606 : {
607 2863 : sal_Int16 nObjIndex = 0;
608 2863 : pWMF->ReadInt16( nObjIndex );
609 2863 : pOut->SelectObject( nObjIndex );
610 : }
611 2863 : break;
612 :
613 : case W_META_SETTEXTALIGN:
614 : {
615 89 : sal_uInt16 nAlign = 0;
616 89 : pWMF->ReadUInt16( nAlign );
617 89 : pOut->SetTextAlign( nAlign );
618 : }
619 89 : break;
620 :
621 : case W_META_BITBLT:
622 : {
623 : // 0-3 : nWinROP #93454#
624 : // 4-5 : y offset of source bitmap
625 : // 6-7 : x offset of source bitmap
626 : // 8-9 : used height of source bitmap
627 : // 10-11 : used width of source bitmap
628 : // 12-13 : destination position y (in pixel)
629 : // 14-15 : destination position x (in pixel)
630 : // 16-17 : dont know
631 : // 18-19 : Width Bitmap in Pixel
632 : // 20-21 : Height Bitmap in Pixel
633 : // 22-23 : bytes per scanline
634 : // 24 : planes
635 : // 25 : bitcount
636 :
637 0 : sal_Int32 nWinROP = 0;
638 0 : sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nDontKnow = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
639 : sal_uInt8 nPlanes, nBitCount;
640 :
641 0 : pWMF->ReadInt32( nWinROP )
642 0 : .ReadUInt16( nSy ).ReadUInt16( nSx ).ReadUInt16( nSye ).ReadUInt16( nSxe );
643 0 : Point aPoint( ReadYX() );
644 0 : pWMF->ReadUInt16( nDontKnow ).ReadUInt16( nWidth ).ReadUInt16( nHeight ).ReadUInt16( nBytesPerScan ).ReadUChar( nPlanes ).ReadUChar( nBitCount );
645 :
646 0 : if ( nWidth && nHeight && ( nPlanes == 1 ) && ( nBitCount == 1 ) )
647 : {
648 0 : Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
649 : BitmapWriteAccess* pAcc;
650 0 : pAcc = aBmp.AcquireWriteAccess();
651 0 : if ( pAcc )
652 : {
653 0 : for (sal_uInt16 y = 0; y < nHeight; y++ )
654 : {
655 0 : sal_uInt16 x = 0;
656 0 : for (sal_uInt16 scan = 0; scan < nBytesPerScan; scan++ )
657 : {
658 0 : sal_Int8 nEightPixels = 0;
659 0 : pWMF->ReadSChar( nEightPixels );
660 0 : for (sal_Int8 i = 7; i >= 0; i-- )
661 : {
662 0 : if ( x < nWidth )
663 : {
664 0 : pAcc->SetPixelIndex( y, x, (nEightPixels>>i)&1 );
665 : }
666 0 : x++;
667 : }
668 : }
669 : }
670 0 : Bitmap::ReleaseAccess( pAcc );
671 0 : if ( nSye && nSxe &&
672 0 : ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
673 0 : ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
674 : {
675 0 : Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
676 0 : aBmp.Crop( aCropRect );
677 : }
678 0 : Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
679 0 : aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
680 0 : }
681 : }
682 : }
683 0 : break;
684 :
685 : case W_META_STRETCHBLT:
686 : case W_META_DIBBITBLT:
687 : case W_META_DIBSTRETCHBLT:
688 : case W_META_STRETCHDIB:
689 : {
690 56 : sal_Int32 nWinROP = 0;
691 56 : sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nUsage = 0;
692 56 : Bitmap aBmp;
693 :
694 56 : pWMF->ReadInt32( nWinROP );
695 :
696 56 : if( nFunc == W_META_STRETCHDIB )
697 4 : pWMF->ReadUInt16( nUsage );
698 :
699 : // nSye and nSxe is the number of pixels that has to been used
700 : // If they are set to zero, it is as indicator not to scale the bitmap later
701 :
702 56 : if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
703 9 : pWMF->ReadUInt16( nSye ).ReadUInt16( nSxe );
704 :
705 : // nSy and nx is the offset of the first pixel
706 56 : pWMF->ReadUInt16( nSy ).ReadUInt16( nSx );
707 :
708 56 : if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
709 : {
710 56 : if ( nWinROP == PATCOPY )
711 1 : pWMF->ReadUInt16( nUsage ); // i don't know anything of this parameter, so its called nUsage
712 : // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), false );
713 :
714 56 : Size aDestSize( ReadYXExt() );
715 56 : if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
716 : {
717 56 : Rectangle aDestRect( ReadYX(), aDestSize );
718 56 : if ( nWinROP != PATCOPY )
719 55 : ReadDIB(aBmp, *pWMF, false);
720 :
721 : // test if it is sensible to crop
722 186 : if ( nSye && nSxe &&
723 157 : ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
724 74 : ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
725 : {
726 9 : Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
727 9 : aBmp.Crop( aCropRect );
728 : }
729 56 : aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
730 : }
731 56 : }
732 : }
733 56 : break;
734 :
735 : case W_META_DIBCREATEPATTERNBRUSH:
736 : {
737 4 : Bitmap aBmp;
738 : BitmapReadAccess* pBmp;
739 4 : sal_uInt32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
740 4 : sal_uInt16 nFunction = 0;
741 :
742 4 : pWMF->ReadUInt16( nFunction ).ReadUInt16( nFunction );
743 :
744 4 : ReadDIB(aBmp, *pWMF, false);
745 4 : pBmp = aBmp.AcquireReadAccess();
746 4 : if ( pBmp )
747 : {
748 36 : for ( long y = 0; y < pBmp->Height(); y++ )
749 : {
750 288 : for ( long x = 0; x < pBmp->Width(); x++ )
751 : {
752 256 : const BitmapColor aColor( pBmp->GetColor( y, x ) );
753 :
754 256 : nRed += aColor.GetRed();
755 256 : nGreen += aColor.GetGreen();
756 256 : nBlue += aColor.GetBlue();
757 256 : }
758 : }
759 4 : nCount = pBmp->Height() * pBmp->Width();
760 4 : if ( !nCount )
761 0 : nCount++;
762 4 : Bitmap::ReleaseAccess( pBmp );
763 : }
764 4 : Color aColor( (sal_uInt8)( nRed / nCount ), (sal_uInt8)( nGreen / nCount ), (sal_uInt8)( nBlue / nCount ) );
765 4 : pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( aColor, false ) );
766 : }
767 4 : break;
768 :
769 : case W_META_DELETEOBJECT:
770 : {
771 576 : sal_Int16 nIndex = 0;
772 576 : pWMF->ReadInt16( nIndex );
773 576 : pOut->DeleteObject( nIndex );
774 : }
775 576 : break;
776 :
777 : case W_META_CREATEPALETTE:
778 : {
779 0 : pOut->CreateObject( GDI_DUMMY );
780 : }
781 0 : break;
782 :
783 : case W_META_CREATEBRUSH:
784 : {
785 0 : pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), false ) );
786 : }
787 0 : break;
788 :
789 : case W_META_CREATEPATTERNBRUSH:
790 : {
791 0 : pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), false ) );
792 : }
793 0 : break;
794 :
795 : case W_META_CREATEPENINDIRECT:
796 : {
797 96 : LineInfo aLineInfo;
798 96 : sal_uInt16 nStyle = 0;
799 96 : sal_uInt16 nWidth = 0;
800 96 : sal_uInt16 nHeight = 0;
801 :
802 96 : pWMF->ReadUInt16(nStyle);
803 96 : pWMF->ReadUInt16(nWidth);
804 96 : pWMF->ReadUInt16(nHeight);
805 :
806 96 : if (nWidth > 0)
807 57 : aLineInfo.SetWidth(nWidth);
808 :
809 96 : bool bTransparent = false;
810 96 : switch( nStyle & 0xFF )
811 : {
812 : case PS_DASHDOTDOT :
813 1 : aLineInfo.SetStyle( LINE_DASH );
814 1 : aLineInfo.SetDashCount( 1 );
815 1 : aLineInfo.SetDotCount( 2 );
816 1 : aLineInfo.SetDashLen( 150 );
817 1 : aLineInfo.SetDotLen( 30 );
818 1 : aLineInfo.SetDistance( 50 );
819 1 : break;
820 : case PS_DASHDOT :
821 1 : aLineInfo.SetStyle( LINE_DASH );
822 1 : aLineInfo.SetDashCount( 1 );
823 1 : aLineInfo.SetDotCount( 1 );
824 1 : aLineInfo.SetDashLen( 150 );
825 1 : aLineInfo.SetDotLen( 30 );
826 1 : aLineInfo.SetDistance( 90 );
827 1 : break;
828 : case PS_DOT :
829 1 : aLineInfo.SetStyle( LINE_DASH );
830 1 : aLineInfo.SetDashCount( 0 );
831 1 : aLineInfo.SetDotCount( 1 );
832 1 : aLineInfo.SetDotLen( 30 );
833 1 : aLineInfo.SetDistance( 50 );
834 1 : break;
835 : case PS_DASH :
836 1 : aLineInfo.SetStyle( LINE_DASH );
837 1 : aLineInfo.SetDashCount( 1 );
838 1 : aLineInfo.SetDotCount( 0 );
839 1 : aLineInfo.SetDashLen( 225 );
840 1 : aLineInfo.SetDistance( 100 );
841 1 : break;
842 : case PS_NULL :
843 20 : bTransparent = true;
844 20 : aLineInfo.SetStyle( LINE_NONE );
845 20 : break;
846 : default :
847 : case PS_INSIDEFRAME :
848 : case PS_SOLID :
849 72 : aLineInfo.SetStyle( LINE_SOLID );
850 : }
851 96 : switch( nStyle & 0xF00 )
852 : {
853 : case PS_ENDCAP_ROUND :
854 96 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_ROUND );
855 96 : break;
856 : case PS_ENDCAP_SQUARE :
857 0 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_SQUARE );
858 0 : break;
859 : case PS_ENDCAP_FLAT :
860 : default :
861 0 : aLineInfo.SetLineCap( com::sun::star::drawing::LineCap_BUTT );
862 : }
863 96 : switch( nStyle & 0xF000 )
864 : {
865 : case PS_JOIN_ROUND :
866 96 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Round );
867 96 : break;
868 : case PS_JOIN_MITER :
869 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Miter );
870 0 : break;
871 : case PS_JOIN_BEVEL :
872 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::Bevel );
873 0 : break;
874 : default :
875 0 : aLineInfo.SetLineJoin ( basegfx::B2DLineJoin::NONE );
876 : }
877 96 : pOut->CreateObject( GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
878 : }
879 96 : break;
880 :
881 : case W_META_CREATEBRUSHINDIRECT:
882 : {
883 530 : sal_uInt16 nStyle = 0;
884 530 : pWMF->ReadUInt16( nStyle );
885 530 : pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ) );
886 : }
887 530 : break;
888 :
889 : case W_META_CREATEFONTINDIRECT:
890 : {
891 159 : Size aFontSize;
892 : char lfFaceName[LF_FACESIZE];
893 159 : sal_Int16 lfEscapement = 0;
894 159 : sal_Int16 lfOrientation = 0;
895 159 : sal_Int16 lfWeight = 0;
896 :
897 159 : LOGFONTW aLogFont;
898 159 : aFontSize = ReadYXExt();
899 159 : pWMF->ReadInt16( lfEscapement );
900 159 : pWMF->ReadInt16( lfOrientation );
901 159 : pWMF->ReadInt16( lfWeight );
902 159 : pWMF->ReadUChar( aLogFont.lfItalic );
903 159 : pWMF->ReadUChar( aLogFont.lfUnderline );
904 159 : pWMF->ReadUChar( aLogFont.lfStrikeOut );
905 159 : pWMF->ReadUChar( aLogFont.lfCharSet );
906 159 : pWMF->ReadUChar( aLogFont.lfOutPrecision );
907 159 : pWMF->ReadUChar( aLogFont.lfClipPrecision );
908 159 : pWMF->ReadUChar( aLogFont.lfQuality );
909 159 : pWMF->ReadUChar( aLogFont.lfPitchAndFamily );
910 159 : pWMF->Read( lfFaceName, LF_FACESIZE );
911 159 : aLogFont.lfWidth = aFontSize.Width();
912 159 : aLogFont.lfHeight = aFontSize.Height();
913 159 : aLogFont.lfEscapement = lfEscapement;
914 159 : aLogFont.lfOrientation = lfOrientation;
915 159 : aLogFont.lfWeight = lfWeight;
916 :
917 : rtl_TextEncoding eCharSet;
918 159 : if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
919 5 : eCharSet = osl_getThreadTextEncoding();
920 : else
921 154 : eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
922 159 : if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
923 0 : eCharSet = osl_getThreadTextEncoding();
924 159 : if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
925 8 : eCharSet = RTL_TEXTENCODING_MS_1252;
926 159 : aLogFont.alfFaceName = OUString( lfFaceName, strlen(lfFaceName), eCharSet );
927 :
928 159 : pOut->CreateObject( GDI_FONT, new WinMtfFontStyle( aLogFont ) );
929 : }
930 159 : break;
931 :
932 : case W_META_CREATEBITMAPINDIRECT:
933 : {
934 0 : pOut->CreateObject( GDI_DUMMY );
935 : }
936 0 : break;
937 :
938 : case W_META_CREATEBITMAP:
939 : {
940 0 : pOut->CreateObject( GDI_DUMMY );
941 : }
942 0 : break;
943 :
944 : case W_META_CREATEREGION:
945 : {
946 0 : pOut->CreateObject( GDI_DUMMY );
947 : }
948 0 : break;
949 :
950 : case W_META_EXCLUDECLIPRECT :
951 : {
952 0 : pOut->ExcludeClipRect( ReadRectangle() );
953 : }
954 0 : break;
955 :
956 : case W_META_PATBLT:
957 : {
958 88 : sal_uInt32 nROP = 0, nOldROP = 0;
959 88 : pWMF->ReadUInt32( nROP );
960 88 : Size aSize = ReadYXExt();
961 88 : nOldROP = pOut->SetRasterOp( nROP );
962 88 : pOut->DrawRect( Rectangle( ReadYX(), aSize ), false );
963 88 : pOut->SetRasterOp( nOldROP );
964 : }
965 88 : break;
966 :
967 : case W_META_SELECTCLIPREGION:
968 : {
969 1 : sal_Int16 nObjIndex = 0;
970 1 : pWMF->ReadInt16( nObjIndex );
971 1 : if ( !nObjIndex )
972 : {
973 1 : tools::PolyPolygon aEmptyPolyPoly;
974 1 : pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, true );
975 : }
976 : }
977 1 : break;
978 :
979 : case W_META_ESCAPE :
980 : {
981 : // nRecSize has been checked previously to be greater than 3
982 65 : sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
983 65 : sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
984 :
985 : // taking care that nRecSize does not exceed the maximal stream position
986 65 : if ( nMetaRecEndPos > nEndPos )
987 : {
988 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
989 0 : break;
990 : }
991 65 : if ( nRecSize >= 4 ) // minimal escape length
992 : {
993 65 : sal_uInt16 nMode = 0, nLen = 0;
994 65 : pWMF->ReadUInt16( nMode )
995 65 : .ReadUInt16( nLen );
996 65 : if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 4 ) )
997 : {
998 65 : sal_uInt32 nNewMagic = 0; // we have to read int32 for
999 65 : pWMF->ReadUInt32( nNewMagic ); // META_ESCAPE_ENHANCED_METAFILE CommentIdentifier
1000 :
1001 65 : if( nNewMagic == 0x2c2a4f4f && nLen >= 14 )
1002 : {
1003 0 : sal_uInt16 nMagic2 = 0;
1004 0 : pWMF->ReadUInt16( nMagic2 );
1005 0 : if( nMagic2 == 0x0a ) // 2nd half of magic
1006 : { // continue with private escape
1007 0 : sal_uInt32 nCheck = 0, nEsc = 0;
1008 0 : pWMF->ReadUInt32( nCheck )
1009 0 : .ReadUInt32( nEsc );
1010 :
1011 0 : sal_uInt32 nEscLen = nLen - 14;
1012 0 : if ( nEscLen <= ( nRecSize * 2 ) )
1013 : {
1014 : #ifdef OSL_BIGENDIAN
1015 : sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
1016 : sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
1017 : #else
1018 0 : sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
1019 : #endif
1020 0 : boost::scoped_array<sal_Int8> pData;
1021 :
1022 0 : if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
1023 : {
1024 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1025 0 : break;
1026 : }
1027 0 : if ( nEscLen > 0 )
1028 : {
1029 0 : pData.reset(new sal_Int8[ nEscLen ]);
1030 0 : pWMF->Read( pData.get(), nEscLen );
1031 0 : nCheckSum = rtl_crc32( nCheckSum, pData.get(), nEscLen );
1032 : }
1033 0 : if ( nCheck == nCheckSum )
1034 : {
1035 0 : switch( nEsc )
1036 : {
1037 : case PRIVATE_ESCAPE_UNICODE :
1038 : {
1039 : // we will use text instead of polygons only if we have the correct font
1040 0 : if ( Application::GetDefaultDevice()->IsFontAvailable( pOut->GetFont().GetName() ) )
1041 : {
1042 0 : Point aPt;
1043 0 : OUString aString;
1044 : sal_uInt32 nStringLen, nDXCount;
1045 0 : boost::scoped_array<long> pDXAry;
1046 0 : SvMemoryStream aMemoryStream( nEscLen );
1047 0 : aMemoryStream.Write( pData.get(), nEscLen );
1048 0 : aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
1049 0 : sal_Int32 nTmpX(0), nTmpY(0);
1050 0 : aMemoryStream.ReadInt32( nTmpX )
1051 0 : .ReadInt32( nTmpY )
1052 0 : .ReadUInt32( nStringLen );
1053 0 : aPt.X() = nTmpX;
1054 0 : aPt.Y() = nTmpY;
1055 :
1056 0 : if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
1057 : {
1058 :
1059 0 : aString = read_uInt16s_ToOUString(aMemoryStream, nStringLen);
1060 0 : aMemoryStream.ReadUInt32( nDXCount );
1061 0 : if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
1062 0 : nDXCount = 0;
1063 0 : if ( nDXCount )
1064 0 : pDXAry.reset(new long[ nDXCount ]);
1065 0 : for (sal_uInt32 i = 0; i < nDXCount; i++ )
1066 : {
1067 : sal_Int32 val;
1068 0 : aMemoryStream.ReadInt32( val);
1069 0 : pDXAry[ i ] = val;
1070 : }
1071 0 : aMemoryStream.ReadUInt32( nSkipActions );
1072 0 : pOut->DrawText( aPt, aString, pDXAry.get() );
1073 0 : }
1074 : }
1075 : }
1076 0 : break;
1077 : }
1078 0 : }
1079 : }
1080 0 : }
1081 : }
1082 65 : else if ( (nNewMagic == static_cast< sal_uInt32 >(0x43464D57)) && (nLen >= 34) && ( (sal_Int32)(nLen + 10) <= (sal_Int32)(nRecSize * 2) ))
1083 : {
1084 10 : sal_uInt32 nComType = 0, nVersion = 0, nFlags = 0, nComRecCount = 0,
1085 10 : nCurRecSize = 0, nRemainingSize = 0, nEMFTotalSize = 0;
1086 10 : sal_uInt16 nCheck = 0;
1087 :
1088 10 : pWMF->ReadUInt32( nComType ).ReadUInt32( nVersion ).ReadUInt16( nCheck ).ReadUInt32( nFlags )
1089 10 : .ReadUInt32( nComRecCount ).ReadUInt32( nCurRecSize )
1090 10 : .ReadUInt32( nRemainingSize ).ReadUInt32( nEMFTotalSize ); // the nRemainingSize is not mentioned in MSDN documentation
1091 : // but it seems to be required to read in data produced by OLE
1092 :
1093 10 : if( nComType == 0x01 && nVersion == 0x10000 && nComRecCount )
1094 : {
1095 10 : if( !nEMFRec )
1096 : { // first EMF comment
1097 8 : nEMFRecCount = nComRecCount;
1098 8 : nEMFSize = nEMFTotalSize;
1099 8 : pEMFStream = new SvMemoryStream( nEMFSize );
1100 : }
1101 2 : else if( ( nEMFRecCount != nComRecCount ) || ( nEMFSize != nEMFTotalSize ) ) // add additional checks here
1102 : {
1103 : // total records should be the same as in previous comments
1104 0 : nEMFRecCount = 0xFFFFFFFF;
1105 0 : delete pEMFStream;
1106 0 : pEMFStream = NULL;
1107 : }
1108 10 : nEMFRec++;
1109 :
1110 10 : if( pEMFStream && nCurRecSize + 34 > nLen )
1111 : {
1112 0 : nEMFRecCount = 0xFFFFFFFF;
1113 0 : delete pEMFStream;
1114 0 : pEMFStream = NULL;
1115 : }
1116 :
1117 10 : if( pEMFStream )
1118 : {
1119 10 : boost::scoped_array<sal_Int8> pBuf(new sal_Int8[ nCurRecSize ]);
1120 10 : sal_uInt32 nCount = pWMF->Read( pBuf.get(), nCurRecSize );
1121 10 : if( nCount == nCurRecSize )
1122 10 : pEMFStream->Write( pBuf.get(), nCount );
1123 : }
1124 : }
1125 : }
1126 : }
1127 : }
1128 : }
1129 65 : break;
1130 :
1131 : case W_META_SETRELABS:
1132 : case W_META_SETPOLYFILLMODE:
1133 : case W_META_SETSTRETCHBLTMODE:
1134 : case W_META_SETTEXTCHAREXTRA:
1135 : case W_META_SETTEXTJUSTIFICATION:
1136 : case W_META_FLOODFILL :
1137 : case W_META_FILLREGION:
1138 : case W_META_FRAMEREGION:
1139 : case W_META_INVERTREGION:
1140 : case W_META_PAINTREGION:
1141 : case W_META_DRAWTEXT:
1142 : case W_META_SETMAPPERFLAGS:
1143 : case W_META_SETDIBTODEV:
1144 : case W_META_SELECTPALETTE:
1145 : case W_META_REALIZEPALETTE:
1146 : case W_META_ANIMATEPALETTE:
1147 : case W_META_SETPALENTRIES:
1148 : case W_META_RESIZEPALETTE:
1149 : case W_META_EXTFLOODFILL:
1150 : case W_META_RESETDC:
1151 : case W_META_STARTDOC:
1152 : case W_META_STARTPAGE:
1153 : case W_META_ENDPAGE:
1154 : case W_META_ABORTDOC:
1155 : case W_META_ENDDOC:
1156 610 : break;
1157 : }
1158 6723 : }
1159 :
1160 : static const long aMaxWidth = 1024;
1161 :
1162 105 : bool WMFReader::ReadHeader()
1163 : {
1164 105 : sal_Size nStrmPos = pWMF->Tell();
1165 :
1166 105 : sal_uInt32 nPlaceableMetaKey(0);
1167 : // if available read the METAFILEHEADER
1168 105 : pWMF->ReadUInt32( nPlaceableMetaKey );
1169 105 : if (!pWMF->good())
1170 0 : return false;
1171 :
1172 105 : Rectangle aPlaceableBound;
1173 :
1174 105 : bool bPlaceable = nPlaceableMetaKey == 0x9ac6cdd7L;
1175 :
1176 : SAL_INFO("vcl.wmf", "Placeable: \"" << (bPlaceable ? "yes" : "no") << "\"");
1177 :
1178 105 : if (bPlaceable)
1179 : {
1180 : //TODO do some real error handling here
1181 : sal_Int16 nVal;
1182 :
1183 : // Skip reserved bytes
1184 57 : pWMF->SeekRel(2);
1185 :
1186 : // BoundRect
1187 57 : pWMF->ReadInt16( nVal );
1188 57 : aPlaceableBound.Left() = nVal;
1189 57 : pWMF->ReadInt16( nVal );
1190 57 : aPlaceableBound.Top() = nVal;
1191 57 : pWMF->ReadInt16( nVal );
1192 57 : aPlaceableBound.Right() = nVal;
1193 57 : pWMF->ReadInt16( nVal );
1194 57 : aPlaceableBound.Bottom() = nVal;
1195 :
1196 : // inch
1197 57 : pWMF->ReadUInt16( nUnitsPerInch );
1198 :
1199 : // reserved
1200 57 : pWMF->SeekRel( 4 );
1201 :
1202 : // Skip and don't check the checksum
1203 57 : pWMF->SeekRel( 2 );
1204 : }
1205 : else
1206 : {
1207 48 : nUnitsPerInch = 96;
1208 :
1209 :
1210 48 : if ( pExternalHeader != NULL
1211 4 : && pExternalHeader->xExt > 0
1212 4 : && pExternalHeader->yExt > 0
1213 4 : && (pExternalHeader->mapMode == MM_ISOTROPIC || pExternalHeader->mapMode == MM_ANISOTROPIC))
1214 : {
1215 : // #n417818#: If we have an external header then overwrite the bounds!
1216 : Rectangle aExtRect(0, 0,
1217 4 : (double) pExternalHeader->xExt * 567 * nUnitsPerInch / 1440000,
1218 8 : (double) pExternalHeader->yExt * 567 * nUnitsPerInch / 1440000);
1219 4 : aPlaceableBound = aExtRect;
1220 :
1221 : SAL_INFO("vcl.wmf", "External header size "
1222 : " t: " << aPlaceableBound.Left() << " l: " << aPlaceableBound.Top()
1223 : << " b: " << aPlaceableBound.Right() << " r: " << aPlaceableBound.Bottom());
1224 :
1225 4 : pOut->SetMapMode( pExternalHeader->mapMode );
1226 : }
1227 : else
1228 : {
1229 44 : pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the metaactions
1230 44 : GetPlaceableBound( aPlaceableBound, pWMF );
1231 :
1232 : // The image size is not known so normalize the calculated bounds so that the
1233 : // resulting image is not too big
1234 44 : const double fMaxWidth = static_cast<double>(aMaxWidth);
1235 44 : if (aPlaceableBound.GetWidth() > aMaxWidth)
1236 : {
1237 5 : double fRatio = aPlaceableBound.GetWidth() / fMaxWidth;
1238 :
1239 : aPlaceableBound = Rectangle(
1240 5 : aPlaceableBound.Left() / fRatio,
1241 5 : aPlaceableBound.Top() / fRatio,
1242 5 : aPlaceableBound.Right() / fRatio,
1243 20 : aPlaceableBound.Bottom() / fRatio);
1244 :
1245 : SAL_INFO("vcl.wmf", "Placeable bounds "
1246 : " t: " << aPlaceableBound.Left() << " l: " << aPlaceableBound.Top()
1247 : << " b: " << aPlaceableBound.Right() << " r: " << aPlaceableBound.Bottom());
1248 : }
1249 : }
1250 :
1251 48 : pWMF->Seek( nStrmPos );
1252 : }
1253 :
1254 105 : pOut->SetWinOrg( aPlaceableBound.TopLeft() );
1255 105 : Size aWMFSize( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
1256 105 : pOut->SetWinExt( aWMFSize );
1257 :
1258 : SAL_INFO("vcl.wmf", "WMF size w: " << aWMFSize.Width() << " h: " << aWMFSize.Height());
1259 :
1260 105 : Size aDevExt( 10000, 10000 );
1261 105 : if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
1262 : {
1263 96 : const Fraction aFrac( 1, nUnitsPerInch );
1264 192 : MapMode aWMFMap( MAP_INCH, Point(), aFrac, aFrac );
1265 96 : Size aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MAP_100TH_MM ) );
1266 192 : aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
1267 : }
1268 105 : pOut->SetDevExt( aDevExt );
1269 :
1270 : SAL_INFO("vcl.wmf", "Dev size w: " << aDevExt.Width() << " h: " << aDevExt.Height());
1271 :
1272 : // read the METAHEADER
1273 105 : sal_uInt32 nMetaKey(0);
1274 105 : pWMF->ReadUInt32( nMetaKey ); // type and headersize
1275 105 : if (!pWMF->good())
1276 9 : return false;
1277 96 : if (nMetaKey != 0x00090001)
1278 : {
1279 0 : sal_uInt16 aNextWord(0);
1280 0 : pWMF->ReadUInt16( aNextWord );
1281 0 : if (nMetaKey != 0x10000 || aNextWord != 0x09)
1282 : {
1283 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1284 0 : return false;
1285 : }
1286 : }
1287 :
1288 96 : pWMF->SeekRel( 2 ); // Version (of Windows)
1289 96 : pWMF->SeekRel( 4 ); // Size (of file in words)
1290 96 : pWMF->SeekRel( 2 ); // NoObjects (maximum number of simultaneous objects)
1291 96 : pWMF->SeekRel( 4 ); // MaxRecord (size of largets record in words)
1292 96 : pWMF->SeekRel( 2 ); // NoParameters (Unused
1293 :
1294 96 : return pWMF->good();
1295 : }
1296 :
1297 105 : void WMFReader::ReadWMF()
1298 : {
1299 : sal_uInt16 nFunction;
1300 : sal_uLong nPos, nPercent, nLastPercent;
1301 :
1302 105 : nSkipActions = 0;
1303 105 : nCurrentAction = 0;
1304 105 : nUnicodeEscapeAction = 0;
1305 :
1306 105 : pEMFStream = NULL;
1307 105 : nEMFRecCount = 0;
1308 105 : nEMFRec = 0;
1309 105 : nEMFSize = 0;
1310 :
1311 105 : pOut->SetMapMode( MM_ANISOTROPIC );
1312 105 : pOut->SetWinOrg( Point() );
1313 105 : pOut->SetWinExt( Size( 1, 1 ) );
1314 105 : pOut->SetDevExt( Size( 10000, 10000 ) );
1315 :
1316 105 : nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
1317 105 : pWMF->Seek( nStartPos );
1318 105 : Callback( (sal_uInt16) ( nLastPercent = 0 ) );
1319 :
1320 105 : if ( ReadHeader( ) )
1321 : {
1322 96 : bool bEMFAvailable = false;
1323 :
1324 96 : nPos = pWMF->Tell();
1325 :
1326 96 : if( nEndPos - nStartPos )
1327 : {
1328 : while( true )
1329 : {
1330 7093 : nCurrentAction++;
1331 7093 : nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
1332 :
1333 7093 : if( nLastPercent + 4 <= nPercent )
1334 : {
1335 964 : Callback( (sal_uInt16) nPercent );
1336 964 : nLastPercent = nPercent;
1337 : }
1338 7093 : pWMF->ReadUInt32( nRecSize ).ReadUInt16( nFunction );
1339 :
1340 14186 : if( pWMF->GetError()
1341 7092 : || ( nRecSize < 3 )
1342 7091 : || ( nRecSize == 3
1343 150 : && nFunction == 0
1344 : )
1345 14090 : || pWMF->IsEof()
1346 : )
1347 : {
1348 96 : if( pWMF->IsEof() )
1349 1 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1350 :
1351 96 : break;
1352 : }
1353 6997 : if ( !bEMFAvailable )
1354 : {
1355 13446 : if( !aBmpSaveList.empty()
1356 56 : && ( nFunction != W_META_STRETCHDIB )
1357 56 : && ( nFunction != W_META_DIBBITBLT )
1358 6777 : && ( nFunction != W_META_DIBSTRETCHBLT )
1359 : )
1360 : {
1361 52 : pOut->ResolveBitmapActions( aBmpSaveList );
1362 : }
1363 :
1364 6723 : if ( !nSkipActions )
1365 6723 : ReadRecordParams( nFunction );
1366 : else
1367 0 : nSkipActions--;
1368 :
1369 6723 : if( pEMFStream && nEMFRecCount == nEMFRec )
1370 : {
1371 8 : GDIMetaFile aMeta;
1372 8 : pEMFStream->Seek( 0 );
1373 8 : EnhWMFReader* pEMFReader = new EnhWMFReader ( *pEMFStream, aMeta );
1374 8 : bEMFAvailable = pEMFReader->ReadEnhWMF();
1375 8 : delete pEMFReader; // destroy first!!!
1376 :
1377 8 : if( bEMFAvailable )
1378 : {
1379 8 : pOut->AddFromGDIMetaFile( aMeta );
1380 8 : pOut->SetrclFrame( Rectangle( Point(0, 0), aMeta.GetPrefSize()));
1381 :
1382 : // the stream needs to be set to the wmf end position,
1383 : // otherwise the GfxLink that is created will be incorrect
1384 : // (leading to graphic loss after swapout/swapin).
1385 : // so we will proceed normally, but are ignoring further wmf
1386 : // records
1387 : }
1388 : else
1389 : {
1390 : // something went wrong
1391 : // continue with WMF, don't try this again
1392 0 : delete pEMFStream;
1393 0 : pEMFStream = NULL;
1394 8 : }
1395 : }
1396 : }
1397 6997 : nPos += nRecSize * 2;
1398 6997 : if ( nPos <= nEndPos )
1399 6997 : pWMF->Seek( nPos );
1400 : else
1401 0 : pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
1402 6997 : }
1403 : }
1404 : else
1405 0 : pWMF->SetError( SVSTREAM_GENERALERROR );
1406 :
1407 96 : if( !pWMF->GetError() && !aBmpSaveList.empty() )
1408 0 : pOut->ResolveBitmapActions( aBmpSaveList );
1409 : }
1410 105 : if ( pWMF->GetError() )
1411 11 : pWMF->Seek( nStartPos );
1412 105 : }
1413 :
1414 44 : bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm )
1415 : {
1416 44 : bool bRet = true;
1417 :
1418 44 : Rectangle aBound;
1419 44 : aBound.Left() = RECT_MAX;
1420 44 : aBound.Top() = RECT_MAX;
1421 44 : aBound.Right() = RECT_MIN;
1422 44 : aBound.Bottom() = RECT_MIN;
1423 44 : bool bBoundsDetermined = false;
1424 :
1425 44 : sal_uInt32 nPos = pStm->Tell();
1426 44 : sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
1427 :
1428 44 : pStm->Seek( nPos );
1429 :
1430 44 : Point aWinOrg(0,0);
1431 44 : boost::optional<Size> aWinExt;
1432 :
1433 44 : Point aViewportOrg(0,0);
1434 88 : boost::optional<Size> aViewportExt;
1435 :
1436 44 : if( nEnd - nPos )
1437 : {
1438 44 : sal_Int16 nMapMode = MM_ANISOTROPIC;
1439 : sal_uInt16 nFunction;
1440 : sal_uInt32 nRSize;
1441 :
1442 3807 : while( bRet )
1443 : {
1444 3756 : pStm->ReadUInt32( nRSize ).ReadUInt16( nFunction );
1445 :
1446 3756 : if( pStm->GetError() )
1447 : {
1448 0 : bRet = false;
1449 0 : break;
1450 : }
1451 3756 : else if ( nRSize==3 && nFunction==0 )
1452 : {
1453 : break;
1454 : }
1455 3721 : else if ( nRSize < 3 || pStm->IsEof() )
1456 : {
1457 2 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1458 2 : bRet = false;
1459 2 : break;
1460 : }
1461 3719 : switch( nFunction )
1462 : {
1463 : case W_META_SETWINDOWORG:
1464 : {
1465 64 : aWinOrg = ReadYX();
1466 : }
1467 64 : break;
1468 :
1469 : case W_META_SETWINDOWEXT:
1470 : {
1471 62 : sal_Int16 nWidth(0), nHeight(0);
1472 62 : pStm->ReadInt16(nHeight);
1473 62 : pStm->ReadInt16(nWidth);
1474 62 : aWinExt = Size(nWidth, nHeight);
1475 : }
1476 62 : break;
1477 :
1478 : case W_META_SETVIEWPORTORG:
1479 : {
1480 0 : aViewportOrg = ReadYX();
1481 : }
1482 0 : break;
1483 :
1484 : case W_META_SETVIEWPORTEXT:
1485 : {
1486 0 : sal_Int16 nWidth(0), nHeight(0);
1487 0 : pStm->ReadInt16(nHeight);
1488 0 : pStm->ReadInt16(nWidth);
1489 0 : aViewportExt = Size(nWidth, nHeight);
1490 : }
1491 0 : break;
1492 :
1493 : case W_META_SETMAPMODE :
1494 24 : pStm->ReadInt16( nMapMode );
1495 24 : break;
1496 :
1497 : case W_META_MOVETO:
1498 : case W_META_LINETO:
1499 1 : GetWinExtMax( ReadYX(), aBound, nMapMode );
1500 1 : bBoundsDetermined = true;
1501 1 : break;
1502 :
1503 : case W_META_RECTANGLE:
1504 : case W_META_INTERSECTCLIPRECT:
1505 : case W_META_EXCLUDECLIPRECT :
1506 : case W_META_ELLIPSE:
1507 73 : GetWinExtMax( ReadRectangle(), aBound, nMapMode );
1508 73 : bBoundsDetermined = true;
1509 73 : break;
1510 :
1511 : case W_META_ROUNDRECT:
1512 0 : ReadYXExt(); // size
1513 0 : GetWinExtMax( ReadRectangle(), aBound, nMapMode );
1514 0 : bBoundsDetermined = true;
1515 0 : break;
1516 :
1517 : case W_META_ARC:
1518 : case W_META_PIE:
1519 : case W_META_CHORD:
1520 0 : ReadYX(); // end
1521 0 : ReadYX(); // start
1522 0 : GetWinExtMax( ReadRectangle(), aBound, nMapMode );
1523 0 : bBoundsDetermined = true;
1524 0 : break;
1525 :
1526 : case W_META_POLYGON:
1527 : {
1528 56 : bool bRecordOk = true;
1529 :
1530 56 : sal_uInt16 nPoints(0);
1531 56 : pStm->ReadUInt16( nPoints );
1532 :
1533 56 : if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
1534 : {
1535 1 : bRecordOk = false;
1536 : }
1537 : else
1538 : {
1539 936 : for(sal_uInt16 i = 0; i < nPoints; i++ )
1540 : {
1541 881 : GetWinExtMax( ReadPoint(), aBound, nMapMode );
1542 881 : bBoundsDetermined = true;
1543 : }
1544 : }
1545 :
1546 : SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polyline record claimed more points than the stream can provide");
1547 :
1548 56 : if (!bRecordOk)
1549 : {
1550 1 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1551 1 : bRet = false;
1552 1 : break;
1553 : }
1554 : }
1555 55 : break;
1556 :
1557 : case W_META_POLYPOLYGON:
1558 : {
1559 171 : bool bRecordOk = true;
1560 171 : sal_uInt16 nPoly(0), nPoints(0);
1561 171 : pStm->ReadUInt16(nPoly);
1562 171 : if (nPoly > pStm->remainingSize() / sizeof(sal_uInt16))
1563 : {
1564 0 : bRecordOk = false;
1565 : }
1566 : else
1567 : {
1568 439 : for(sal_uInt16 i = 0; i < nPoly; i++ )
1569 : {
1570 270 : sal_uInt16 nP = 0;
1571 270 : pStm->ReadUInt16( nP );
1572 270 : if (nP > SAL_MAX_UINT16 - nPoints)
1573 : {
1574 2 : bRecordOk = false;
1575 2 : break;
1576 : }
1577 268 : nPoints += nP;
1578 : }
1579 : }
1580 :
1581 : SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polypolygon record has more polygons than we can handle");
1582 :
1583 171 : bRecordOk = bRecordOk && pStm->good();
1584 :
1585 171 : if (!bRecordOk)
1586 : {
1587 2 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1588 2 : bRet = false;
1589 5 : break;
1590 : }
1591 :
1592 169 : if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
1593 : {
1594 1 : bRecordOk = false;
1595 : }
1596 : else
1597 : {
1598 7820 : for (sal_uInt16 i = 0; i < nPoints; i++ )
1599 : {
1600 7652 : GetWinExtMax( ReadPoint(), aBound, nMapMode );
1601 7652 : bBoundsDetermined = true;
1602 : }
1603 : }
1604 :
1605 : SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polypolygon record claimed more points than the stream can provide");
1606 :
1607 169 : bRecordOk &= pStm->good();
1608 :
1609 169 : if (!bRecordOk)
1610 : {
1611 1 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1612 1 : bRet = false;
1613 1 : break;
1614 : }
1615 : }
1616 168 : break;
1617 :
1618 : case W_META_POLYLINE:
1619 : {
1620 118 : bool bRecordOk = true;
1621 :
1622 118 : sal_uInt16 nPoints(0);
1623 118 : pStm->ReadUInt16(nPoints);
1624 118 : if (nPoints > pStm->remainingSize() / (2 * sizeof(sal_uInt16)))
1625 : {
1626 0 : bRecordOk = false;
1627 : }
1628 : else
1629 : {
1630 364 : for (sal_uInt16 i = 0; i < nPoints; ++i)
1631 : {
1632 246 : GetWinExtMax( ReadPoint(), aBound, nMapMode );
1633 246 : bBoundsDetermined = true;
1634 : }
1635 : }
1636 :
1637 : SAL_WARN_IF(!bRecordOk, "vcl.wmf", "polyline record claimed more points than the stream can provide");
1638 :
1639 118 : if (!bRecordOk)
1640 : {
1641 0 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1642 0 : bRet = false;
1643 0 : break;
1644 : }
1645 : }
1646 118 : break;
1647 :
1648 : case W_META_SETPIXEL:
1649 : {
1650 0 : ReadColor();
1651 0 : GetWinExtMax( ReadYX(), aBound, nMapMode );
1652 0 : bBoundsDetermined = true;
1653 : }
1654 0 : break;
1655 :
1656 : case W_META_TEXTOUT:
1657 : {
1658 : sal_uInt16 nLength;
1659 2 : pStm->ReadUInt16( nLength );
1660 : // todo: we also have to take care of the text width
1661 2 : if ( nLength )
1662 : {
1663 2 : pStm->SeekRel( ( nLength + 1 ) &~ 1 );
1664 2 : GetWinExtMax( ReadYX(), aBound, nMapMode );
1665 2 : bBoundsDetermined = true;
1666 : }
1667 : }
1668 2 : break;
1669 :
1670 : case W_META_EXTTEXTOUT:
1671 : {
1672 : sal_uInt16 nLen, nOptions;
1673 64 : Point aPosition;
1674 :
1675 64 : aPosition = ReadYX();
1676 64 : pStm->ReadUInt16( nLen ).ReadUInt16( nOptions );
1677 : // todo: we also have to take care of the text width
1678 64 : if( nLen )
1679 : {
1680 64 : GetWinExtMax( aPosition, aBound, nMapMode );
1681 64 : bBoundsDetermined = true;
1682 : }
1683 : }
1684 64 : break;
1685 : case W_META_BITBLT:
1686 : case W_META_STRETCHBLT:
1687 : case W_META_DIBBITBLT:
1688 : case W_META_DIBSTRETCHBLT:
1689 : case W_META_STRETCHDIB:
1690 : {
1691 : sal_Int32 nWinROP;
1692 : sal_uInt16 nSx, nSy, nSxe, nSye, nUsage;
1693 18 : pStm->ReadInt32( nWinROP );
1694 :
1695 18 : if( nFunction == W_META_STRETCHDIB )
1696 0 : pStm->ReadUInt16( nUsage );
1697 :
1698 : // nSye and nSxe is the number of pixels that has to been used
1699 18 : if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
1700 1 : pStm->ReadUInt16( nSye ).ReadUInt16( nSxe );
1701 : else
1702 17 : nSye = nSxe = 0; // set this to zero as indicator not to scale the bitmap later
1703 :
1704 : // nSy and nx is the offset of the first pixel
1705 18 : pStm->ReadUInt16( nSy ).ReadUInt16( nSx );
1706 :
1707 18 : if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
1708 : {
1709 18 : if ( nWinROP == PATCOPY )
1710 1 : pStm->ReadUInt16( nUsage ); // i don't know anything of this parameter, so its called nUsage
1711 : // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), false );
1712 :
1713 18 : Size aDestSize( ReadYXExt() );
1714 18 : if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
1715 : {
1716 18 : Rectangle aDestRect( ReadYX(), aDestSize );
1717 18 : GetWinExtMax( aDestRect, aBound, nMapMode );
1718 18 : bBoundsDetermined = true;
1719 : }
1720 : }
1721 : }
1722 18 : break;
1723 :
1724 : case W_META_PATBLT:
1725 : {
1726 : sal_uInt32 nROP;
1727 28 : pStm->ReadUInt32( nROP );
1728 28 : Size aSize = ReadYXExt();
1729 28 : GetWinExtMax( Rectangle( ReadYX(), aSize ), aBound, nMapMode );
1730 28 : bBoundsDetermined = true;
1731 : }
1732 28 : break;
1733 : }
1734 3719 : nPos += nRSize * 2;
1735 3719 : if ( nPos <= nEnd )
1736 3715 : pStm->Seek( nPos );
1737 : else
1738 : {
1739 4 : pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
1740 4 : bRet = false;
1741 : }
1742 : }
1743 : }
1744 : else
1745 : {
1746 0 : pStm->SetError( SVSTREAM_GENERALERROR );
1747 0 : bRet = false;
1748 : }
1749 :
1750 44 : if (bRet)
1751 : {
1752 35 : if (aWinExt)
1753 : {
1754 34 : rPlaceableBound = Rectangle(aWinOrg, *aWinExt);
1755 : SAL_INFO("vcl.wmf", "Window dimension "
1756 : " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
1757 : << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
1758 : }
1759 1 : else if (aViewportExt)
1760 : {
1761 0 : rPlaceableBound = Rectangle(aViewportOrg, *aViewportExt);
1762 : SAL_INFO("vcl.wmf", "Viewport dimension "
1763 : " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
1764 : << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
1765 : }
1766 1 : else if (bBoundsDetermined)
1767 : {
1768 0 : rPlaceableBound = aBound;
1769 : SAL_INFO("vcl.wmf", "Determined dimension "
1770 : " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
1771 : << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
1772 : }
1773 : else
1774 : {
1775 1 : rPlaceableBound.Left() = 0;
1776 1 : rPlaceableBound.Top() = 0;
1777 1 : rPlaceableBound.Right() = aMaxWidth;
1778 1 : rPlaceableBound.Bottom() = aMaxWidth;
1779 : SAL_INFO("vcl.wmf", "Default dimension "
1780 : " t: " << rPlaceableBound.Left() << " l: " << rPlaceableBound.Top()
1781 : << " b: " << rPlaceableBound.Right() << " r: " << rPlaceableBound.Bottom());
1782 : }
1783 : }
1784 :
1785 88 : return bRet;
1786 : }
1787 :
1788 105 : WMFReader::WMFReader(SvStream& rStreamWMF, GDIMetaFile& rGDIMetaFile,
1789 : FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER* pExtHeader)
1790 105 : : WinMtf(new WinMtfOutput(rGDIMetaFile) , rStreamWMF, pConfigItem)
1791 : , nUnitsPerInch(96)
1792 : , nRecSize(0)
1793 : , pEMFStream(NULL)
1794 : , nEMFRecCount(0)
1795 : , nEMFRec(0)
1796 : , nEMFSize(0)
1797 : , nSkipActions(0)
1798 : , nCurrentAction(0)
1799 : , nUnicodeEscapeAction(0)
1800 210 : , pExternalHeader(pExtHeader)
1801 105 : {}
1802 :
1803 210 : WMFReader::~WMFReader()
1804 : {
1805 105 : delete pEMFStream;
1806 906 : }
1807 :
1808 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|