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 <osl/endian.h>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <vcl/dibtools.hxx>
29
30 //=========================== GDI-Array ===================================
31
32 #define EMR_HEADER 1
33 #define EMR_POLYBEZIER 2
34 #define EMR_POLYGON 3
35 #define EMR_POLYLINE 4
36 #define EMR_POLYBEZIERTO 5
37 #define EMR_POLYLINETO 6
38 #define EMR_POLYPOLYLINE 7
39 #define EMR_POLYPOLYGON 8
40 #define EMR_SETWINDOWEXTEX 9
41 #define EMR_SETWINDOWORGEX 10
42 #define EMR_SETVIEWPORTEXTEX 11
43 #define EMR_SETVIEWPORTORGEX 12
44 #define EMR_SETBRUSHORGEX 13
45 #define EMR_EOF 14
46 #define EMR_SETPIXELV 15
47 #define EMR_SETMAPPERFLAGS 16
48 #define EMR_SETMAPMODE 17
49 #define EMR_SETBKMODE 18
50 #define EMR_SETPOLYFILLMODE 19
51 #define EMR_SETROP2 20
52 #define EMR_SETSTRETCHBLTMODE 21
53 #define EMR_SETTEXTALIGN 22
54 #define EMR_SETCOLORADJUSTMENT 23
55 #define EMR_SETTEXTCOLOR 24
56 #define EMR_SETBKCOLOR 25
57 #define EMR_OFFSETCLIPRGN 26
58 #define EMR_MOVETOEX 27
59 #define EMR_SETMETARGN 28
60 #define EMR_EXCLUDECLIPRECT 29
61 #define EMR_INTERSECTCLIPRECT 30
62 #define EMR_SCALEVIEWPORTEXTEX 31
63 #define EMR_SCALEWINDOWEXTEX 32
64 #define EMR_SAVEDC 33
65 #define EMR_RESTOREDC 34
66 #define EMR_SETWORLDTRANSFORM 35
67 #define EMR_MODIFYWORLDTRANSFORM 36
68 #define EMR_SELECTOBJECT 37
69 #define EMR_CREATEPEN 38
70 #define EMR_CREATEBRUSHINDIRECT 39
71 #define EMR_DELETEOBJECT 40
72 #define EMR_ANGLEARC 41
73 #define EMR_ELLIPSE 42
74 #define EMR_RECTANGLE 43
75 #define EMR_ROUNDRECT 44
76 #define EMR_ARC 45
77 #define EMR_CHORD 46
78 #define EMR_PIE 47
79 #define EMR_SELECTPALETTE 48
80 #define EMR_CREATEPALETTE 49
81 #define EMR_SETPALETTEENTRIES 50
82 #define EMR_RESIZEPALETTE 51
83 #define EMR_REALIZEPALETTE 52
84 #define EMR_EXTFLOODFILL 53
85 #define EMR_LINETO 54
86 #define EMR_ARCTO 55
87 #define EMR_POLYDRAW 56
88 #define EMR_SETARCDIRECTION 57
89 #define EMR_SETMITERLIMIT 58
90 #define EMR_BEGINPATH 59
91 #define EMR_ENDPATH 60
92 #define EMR_CLOSEFIGURE 61
93 #define EMR_FILLPATH 62
94 #define EMR_STROKEANDFILLPATH 63
95 #define EMR_STROKEPATH 64
96 #define EMR_FLATTENPATH 65
97 #define EMR_WIDENPATH 66
98 #define EMR_SELECTCLIPPATH 67
99 #define EMR_ABORTPATH 68
100
101 #define EMR_GDICOMMENT 70
102 #define EMR_FILLRGN 71
103 #define EMR_FRAMERGN 72
104 #define EMR_INVERTRGN 73
105 #define EMR_PAINTRGN 74
106 #define EMR_EXTSELECTCLIPRGN 75
107 #define EMR_BITBLT 76
108 #define EMR_STRETCHBLT 77
109 #define EMR_MASKBLT 78
110 #define EMR_PLGBLT 79
111 #define EMR_SETDIBITSTODEVICE 80
112 #define EMR_STRETCHDIBITS 81
113 #define EMR_EXTCREATEFONTINDIRECTW 82
114 #define EMR_EXTTEXTOUTA 83
115 #define EMR_EXTTEXTOUTW 84
116 #define EMR_POLYBEZIER16 85
117 #define EMR_POLYGON16 86
118 #define EMR_POLYLINE16 87
119 #define EMR_POLYBEZIERTO16 88
120 #define EMR_POLYLINETO16 89
121 #define EMR_POLYPOLYLINE16 90
122 #define EMR_POLYPOLYGON16 91
123 #define EMR_POLYDRAW16 92
124 #define EMR_CREATEMONOBRUSH 93
125 #define EMR_CREATEDIBPATTERNBRUSHPT 94
126 #define EMR_EXTCREATEPEN 95
127 #define EMR_POLYTEXTOUTA 96
128 #define EMR_POLYTEXTOUTW 97
129
130 // WINDOWS VERSION >= 0x400
131 #define EMR_SETICMMODE 98
132 #define EMR_CREATECOLORSPACE 99
133 #define EMR_SETCOLORSPACE 100
134 #define EMR_DELETECOLORSPACE 101
135 #define EMR_GLSRECORD 102
136 #define EMR_GLSBOUNDEDRECORD 103
137 #define EMR_PIXELFORMAT 104
138
139 // WINDOWS VERSION >= 0x500
140 #define EMR_DRAWESCAPE 105
141 #define EMR_EXTESCAPE 106
142 #define EMR_STARTDOC 107
143 #define EMR_SMALLTEXTOUT 108
144 #define EMR_FORCEUFIMAPPING 109
145 #define EMR_NAMEDESCAPE 110
146 #define EMR_COLORCORRECTPALETTE 111
147 #define EMR_SETICMPROFILEA 112
148 #define EMR_SETICMPROFILEW 113
149 #define EMR_ALPHABLEND 114
150 #define EMR_ALPHADIBBLEND 115
151 #define EMR_TRANSPARENTBLT 116
152 #define EMR_TRANSPARENTDIB 117
153 #define EMR_GRADIENTFILL 118
154 #define EMR_SETLINKEDUFIS 119
155 #define EMR_SETTEXTJUSTIFICATION 120
156
157
158 //-----------------------------------------------------------------------------------
159
160 #ifdef OSL_BIGENDIAN
161 // currently unused
GetSwapFloat(SvStream & rSt)162 static float GetSwapFloat( SvStream& rSt )
163 {
164 float fTmp;
165 sal_Int8* pPtr = (sal_Int8*)&fTmp;
166 rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
167 return fTmp;
168 }
169 #endif
170
171 struct BLENDFUNCTION{
172 unsigned char aBlendOperation;
173 unsigned char aBlendFlags;
174 unsigned char aSrcConstantAlpha;
175 unsigned char aAlphaFormat;
176
177 friend SvStream& operator>>( SvStream& rIn, BLENDFUNCTION& rBlendFun );
178 };
179
operator >>(SvStream & rIn,BLENDFUNCTION & rBlendFun)180 SvStream& operator>>( SvStream& rIn, BLENDFUNCTION& rBlendFun )
181 {
182 rIn >> rBlendFun.aBlendOperation >> rBlendFun.aBlendFlags >>
183 rBlendFun.aSrcConstantAlpha >> rBlendFun.aAlphaFormat;
184 return rIn;
185 }
operator >>(SvStream & rIn,XForm & rXForm)186 SvStream& operator>>( SvStream& rIn, XForm& rXForm )
187 {
188 if ( sizeof( float ) != 4 )
189 {
190 DBG_ERROR( "EnhWMFReader::sizeof( float ) != 4" );
191 rXForm = XForm();
192 }
193 else
194 {
195 #ifdef OSL_BIGENDIAN
196 rXForm.eM11 = GetSwapFloat( rIn );
197 rXForm.eM12 = GetSwapFloat( rIn );
198 rXForm.eM21 = GetSwapFloat( rIn );
199 rXForm.eM22 = GetSwapFloat( rIn );
200 rXForm.eDx = GetSwapFloat( rIn );
201 rXForm.eDy = GetSwapFloat( rIn );
202 #else
203 rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
204 >> rXForm.eDx >> rXForm.eDy;
205 #endif
206 }
207 return rIn;
208 }
209
ImplReadRegion(PolyPolygon & rPolyPoly,SvStream & rSt,sal_uInt32 nLen)210 static sal_Bool ImplReadRegion( PolyPolygon& rPolyPoly, SvStream& rSt, sal_uInt32 nLen )
211 {
212 sal_Bool bOk = sal_False;
213 if ( nLen )
214 {
215 sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
216 rSt >> nHdSize
217 >> nType
218 >> nCount
219 >> nRgnSize;
220
221 if ( nCount && ( nType == RDH_RECTANGLES ) &&
222 ( nLen >= ( ( nCount << 4 ) + ( nHdSize - 16 ) ) ) )
223 {
224 sal_Int32 nx1, ny1, nx2, ny2;
225
226 for ( i = 0; i < nCount; i++ )
227 {
228 rSt >> nx1 >> ny1 >> nx2 >> ny2;
229
230 Rectangle aRect( Point( nx1, ny1 ), Point( nx2, ny2 ) );
231 Polygon aPolygon( aRect );
232 PolyPolygon aPolyPolyOr1( aPolygon );
233 PolyPolygon aPolyPolyOr2( rPolyPoly );
234 rPolyPoly.GetUnion( aPolyPolyOr1, aPolyPolyOr2 );
235 rPolyPoly = aPolyPolyOr2;
236 }
237 bOk = sal_True;
238 }
239 }
240 return bOk;
241 }
242
ReadEnhWMF()243 sal_Bool EnhWMFReader::ReadEnhWMF()
244 {
245 sal_uInt32 nStretchBltMode = 0;
246 sal_uInt32 nRecType, nRecSize, nNextPos,
247 nW, nH, nPoints, nColor, nIndex,
248 nDat32, nNom1, nDen1, nNom2, nDen2;
249 sal_Int32 nX32, nY32, nx32, ny32;
250 sal_Int16 nX16, nY16;
251
252 sal_Bool bFlag, bStatus = ReadHeader();
253
254 while( bStatus && nRecordCount-- )
255 {
256 *pWMF >> nRecType >> nRecSize;
257
258 if ( ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameter sind immer durch 4 teilbar
259 {
260 bStatus = sal_False;
261 break;
262 }
263
264 nNextPos = pWMF->Tell() + ( nRecSize - 8 );
265
266 if ( nNextPos > nEndPos )
267 {
268 bStatus = sal_False;
269 break;
270 }
271
272 if( aBmpSaveList.Count() && ( nRecType != EMR_STRETCHBLT ) && ( nRecType != EMR_STRETCHDIBITS ) )
273 pOut->ResolveBitmapActions( aBmpSaveList );
274
275 bFlag = sal_False;
276
277 switch( nRecType )
278 {
279 case EMR_POLYBEZIERTO :
280 bFlag = sal_True;
281 case EMR_POLYBEZIER :
282 {
283 pWMF->SeekRel( 16 );
284 *pWMF >> nPoints;
285 sal_uInt16 i = 0;
286 if ( bFlag )
287 {
288 i++;
289 nPoints++;
290 }
291 Polygon aPoly( (sal_uInt16)nPoints );
292 for( ; i < (sal_uInt16)nPoints; i++ )
293 {
294 *pWMF >> nX32 >> nY32;
295 aPoly[ i ] = Point( nX32, nY32 );
296 }
297 pOut->DrawPolyBezier( aPoly, bFlag, bRecordPath );
298 }
299 break;
300
301 case EMR_POLYGON :
302 {
303 pWMF->SeekRel( 16 );
304 *pWMF >> nPoints;
305 Polygon aPoly( (sal_uInt16)nPoints );
306 for( sal_uInt16 k = 0; k < (sal_uInt16)nPoints; k++ )
307 {
308 *pWMF >> nX32 >> nY32;
309 aPoly[ k ] = Point( nX32, nY32 );
310 }
311 pOut->DrawPolygon( aPoly, bRecordPath );
312 }
313 break;
314
315 case EMR_POLYLINETO :
316 bFlag = sal_True;
317 case EMR_POLYLINE :
318 {
319 pWMF->SeekRel( 0x10 );
320 *pWMF >> nPoints;
321 sal_uInt16 i = 0;
322 if ( bFlag )
323 {
324 i++;
325 nPoints++;
326 }
327 Polygon aPolygon( (sal_uInt16)nPoints );
328 for ( ; i < (sal_uInt16)nPoints; i++ )
329 {
330 *pWMF >> nX32 >> nY32;
331 aPolygon[ i ] = Point( nX32, nY32 );
332 }
333 pOut->DrawPolyLine( aPolygon, bFlag, bRecordPath );
334 }
335 break;
336
337 case EMR_POLYPOLYLINE :
338 {
339 sal_Int32 i, nPoly;
340 pWMF->SeekRel( 0x10 );
341
342 // Anzahl der Polygone:
343 *pWMF >> nPoly >> i;
344
345 // taking the amount of points of each polygon, retrieving the total number of points
346 if ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) )
347 {
348 if ( ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() ) )
349 {
350 sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
351
352 for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
353 {
354 *pWMF >> nPoints;
355 pnPoints[ i ] = (sal_uInt16)nPoints;
356 }
357
358 // Polygonpunkte holen:
359
360 for ( i = 0; ( i < nPoly ) && !pWMF->IsEof(); i++ )
361 {
362 Polygon aPoly( pnPoints[ i ] );
363 for( sal_uInt16 k = 0; k < pnPoints[ i ]; k++ )
364 {
365 *pWMF >> nX32 >> nY32;
366 aPoly[ k ] = Point( nX32, nY32 );
367 }
368 pOut->DrawPolyLine( aPoly, sal_False, bRecordPath );
369 }
370 delete[] pnPoints;
371 }
372 }
373 }
374 break;
375
376 case EMR_POLYPOLYGON :
377 {
378 sal_uInt32 nPoly(0);
379 sal_uInt32 nGesPoints(0);
380 sal_uInt32 nReadPoints(0);
381 pWMF->SeekRel( 0x10 );
382
383 // Anzahl der Polygone:
384 *pWMF >> nPoly >> nGesPoints;
385
386 if ( ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) && !pWMF->IsEof() )
387 {
388 if ( ( nPoly * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() ) )
389 {
390 sal_uInt32 i(0);
391 sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
392
393 for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
394 {
395 *pWMF >> nPoints;
396 pnPoints[ i ] = (sal_uInt16)nPoints;
397 }
398
399 if ( ( nGesPoints * (sizeof(sal_uInt32)+sizeof(sal_uInt32)) ) <= ( nEndPos - pWMF->Tell() ) && !pWMF->IsEof())
400 {
401 PolyPolygon aPolyPoly(nPoly, nPoly);
402
403 for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
404 {
405 const sal_uInt16 nPointCount(pnPoints[i]);
406 Point* pPtAry = new Point[nPointCount];
407
408 for(sal_uInt16 j(0); j < nPointCount && !pWMF->IsEof(); j++)
409 {
410 *pWMF >> nX32 >> nY32;
411 pPtAry[ j ] = Point( nX32, nY32 );
412 nReadPoints++;
413 }
414
415 aPolyPoly.Insert(Polygon(nPointCount, pPtAry));
416 delete[] pPtAry;
417 }
418
419 pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
420 }
421
422 delete[] pnPoints;
423 }
424 }
425
426 OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON is unequal imported number (!)");
427 }
428 break;
429
430 case EMR_SETWINDOWEXTEX :
431 { // #75383#
432 *pWMF >> nW >> nH;
433 pOut->SetWinExt( Size( nW, nH ) );
434 }
435 break;
436
437 case EMR_SETWINDOWORGEX :
438 {
439 *pWMF >> nX32 >> nY32;
440 pOut->SetWinOrg( Point( nX32, nY32 ) );
441 }
442 break;
443
444 case EMR_SCALEWINDOWEXTEX :
445 {
446 *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
447 pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
448 }
449 break;
450
451 case EMR_SETVIEWPORTORGEX :
452 {
453 *pWMF >> nX32 >> nY32;
454 pOut->SetDevOrg( Point( nX32, nY32 ) );
455 }
456 break;
457
458 case EMR_SCALEVIEWPORTEXTEX :
459 {
460 *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
461 pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
462 }
463 break;
464
465 case EMR_SETVIEWPORTEXTEX :
466 {
467 *pWMF >> nW >> nH;
468 pOut->SetDevExt( Size( nW, nH ) );
469 }
470 break;
471
472 case EMR_EOF :
473 nRecordCount = 0; // #76846#
474 break;
475
476 case EMR_SETPIXELV :
477 {
478 *pWMF >> nX32 >> nY32;
479 pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
480 }
481 break;
482
483 case EMR_SETMAPMODE :
484 {
485 sal_uInt32 nMapMode;
486 *pWMF >> nMapMode;
487 pOut->SetMapMode( nMapMode );
488 }
489 break;
490
491 case EMR_SETBKMODE :
492 {
493 *pWMF >> nDat32;
494 pOut->SetBkMode( nDat32 );
495 }
496 break;
497
498 case EMR_SETPOLYFILLMODE :
499 break;
500
501 case EMR_SETROP2 :
502 {
503 *pWMF >> nDat32;
504 pOut->SetRasterOp( nDat32 );
505 }
506 break;
507
508 case EMR_SETSTRETCHBLTMODE :
509 {
510 *pWMF >> nStretchBltMode;
511 }
512 break;
513
514 case EMR_SETTEXTALIGN :
515 {
516 *pWMF >> nDat32;
517 pOut->SetTextAlign( nDat32 );
518 }
519 break;
520
521 case EMR_SETTEXTCOLOR :
522 {
523 pOut->SetTextColor( ReadColor() );
524 }
525 break;
526
527 case EMR_SETBKCOLOR :
528 {
529 pOut->SetBkColor( ReadColor() );
530 }
531 break;
532
533 case EMR_OFFSETCLIPRGN :
534 {
535 *pWMF >> nX32 >> nY32;
536 pOut->MoveClipRegion( Size( nX32, nY32 ) );
537 }
538 break;
539
540 case EMR_MOVETOEX :
541 {
542 *pWMF >> nX32 >> nY32;
543 pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
544 }
545 break;
546
547 case EMR_INTERSECTCLIPRECT :
548 {
549 *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
550 pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
551 }
552 break;
553
554 case EMR_SAVEDC :
555 {
556 pOut->Push();
557 }
558 break;
559
560 case EMR_RESTOREDC :
561 {
562 pOut->Pop();
563 }
564 break;
565
566 case EMR_SETWORLDTRANSFORM :
567 {
568 XForm aTempXForm;
569 *pWMF >> aTempXForm;
570 pOut->SetWorldTransform( aTempXForm );
571 }
572 break;
573
574 case EMR_MODIFYWORLDTRANSFORM :
575 {
576 sal_uInt32 nMode;
577 XForm aTempXForm;
578 *pWMF >> aTempXForm >> nMode;
579 pOut->ModifyWorldTransform( aTempXForm, nMode );
580 }
581 break;
582
583 case EMR_SELECTOBJECT :
584 {
585 *pWMF >> nIndex;
586 pOut->SelectObject( nIndex );
587 }
588 break;
589
590 case EMR_CREATEPEN :
591 {
592 *pWMF >> nIndex;
593 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
594 {
595
596 LineInfo aLineInfo;
597 sal_uInt32 nStyle;
598 Size aSize;
599
600 *pWMF >> nStyle >> aSize.Width() >> aSize.Height();
601
602 if ( aSize.Width() )
603 aLineInfo.SetWidth( aSize.Width() );
604
605 sal_Bool bTransparent = sal_False;
606 sal_uInt16 nDashCount = 0;
607 sal_uInt16 nDotCount = 0;
608 switch( nStyle )
609 {
610 case PS_DASHDOTDOT :
611 nDotCount++;
612 case PS_DASHDOT :
613 nDashCount++;
614 case PS_DOT :
615 nDotCount++;
616 break;
617 case PS_DASH :
618 nDashCount++;
619 break;
620 case PS_NULL :
621 bTransparent = sal_True;
622 aLineInfo.SetStyle( LINE_NONE );
623 break;
624 default :
625 case PS_INSIDEFRAME :
626 case PS_SOLID :
627 aLineInfo.SetStyle( LINE_SOLID );
628 }
629 if ( nDashCount | nDotCount )
630 {
631 aLineInfo.SetStyle( LINE_DASH );
632 aLineInfo.SetDashCount( nDashCount );
633 aLineInfo.SetDotCount( nDotCount );
634 }
635 pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
636 }
637 }
638 break;
639
640 case EMR_EXTCREATEPEN :
641 {
642 sal_Int32 elpHatch;
643 sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
644 Color aColorRef;
645
646 *pWMF >> nIndex;
647 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
648 {
649 *pWMF >> offBmi >> cbBmi >> offBits >> cbBits >> nStyle >> nWidth >> nBrushStyle;
650 aColorRef = ReadColor();
651 *pWMF >> elpHatch >> elpNumEntries;
652
653 LineInfo aLineInfo;
654 if ( nWidth )
655 aLineInfo.SetWidth( nWidth );
656
657 sal_Bool bTransparent = sal_False;
658 sal_uInt16 nDashCount = 0;
659 sal_uInt16 nDotCount = 0;
660
661 switch( nStyle & PS_STYLE_MASK )
662 {
663 case PS_DASHDOTDOT :
664 nDotCount++;
665 case PS_DASHDOT :
666 nDashCount++;
667 case PS_DOT :
668 nDotCount++;
669 break;
670 case PS_DASH :
671 nDashCount++;
672 break;
673 case PS_NULL :
674 bTransparent = sal_True;
675 aLineInfo.SetStyle( LINE_NONE );
676 break;
677
678 default :
679 case PS_INSIDEFRAME :
680 case PS_SOLID :
681 aLineInfo.SetStyle( LINE_SOLID );
682 }
683 if ( nDashCount | nDotCount )
684 {
685 aLineInfo.SetStyle( LINE_DASH );
686 aLineInfo.SetDashCount( nDashCount );
687 aLineInfo.SetDotCount( nDotCount );
688 }
689 pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( aColorRef, aLineInfo, bTransparent ) );
690 }
691 }
692 break;
693
694 case EMR_CREATEBRUSHINDIRECT :
695 {
696 sal_uInt32 nStyle;
697 *pWMF >> nIndex;
698 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
699 {
700 *pWMF >> nStyle;
701 pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
702 }
703 }
704 break;
705
706 case EMR_DELETEOBJECT :
707 {
708 *pWMF >> nIndex;
709 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
710 pOut->DeleteObject( nIndex );
711 }
712 break;
713
714 case EMR_ELLIPSE :
715 {
716 *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
717 pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
718 }
719 break;
720
721 case EMR_RECTANGLE :
722 {
723 *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
724 pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
725 }
726 break;
727
728 case EMR_ROUNDRECT :
729 {
730 *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nW >> nH;
731 Size aSize( Size( nW, nH ) );
732 pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
733 }
734 break;
735
736 case EMR_ARC :
737 {
738 sal_uInt32 nStartX, nStartY, nEndX, nEndY;
739 *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
740 pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
741 }
742 break;
743
744 case EMR_CHORD :
745 {
746 sal_uInt32 nStartX, nStartY, nEndX, nEndY;
747 *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
748 pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
749 }
750 break;
751
752 case EMR_PIE :
753 {
754 sal_uInt32 nStartX, nStartY, nEndX, nEndY;
755 *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
756 const Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
757
758 // #i73608# OutputDevice deviates from WMF
759 // semantics. start==end means full ellipse here.
760 if( nStartX == nEndX && nStartY == nEndY )
761 pOut->DrawEllipse( aRect );
762 else
763 pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
764 }
765 break;
766
767 case EMR_LINETO :
768 {
769 *pWMF >> nX32 >> nY32;
770 pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
771 }
772 break;
773
774 case EMR_ARCTO :
775 {
776 sal_uInt32 nStartX, nStartY, nEndX, nEndY;
777 *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
778 pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), sal_True );
779 }
780 break;
781
782 case EMR_BEGINPATH :
783 {
784 pOut->ClearPath();
785 bRecordPath = sal_True;
786 }
787 break;
788
789 case EMR_ABORTPATH :
790 pOut->ClearPath();
791 case EMR_ENDPATH :
792 bRecordPath = sal_False;
793 break;
794
795 case EMR_CLOSEFIGURE :
796 pOut->ClosePath();
797 break;
798
799 case EMR_FILLPATH :
800 pOut->StrokeAndFillPath( sal_False, sal_True );
801 break;
802
803 case EMR_STROKEANDFILLPATH :
804 pOut->StrokeAndFillPath( sal_True, sal_True );
805 break;
806
807 case EMR_STROKEPATH :
808 pOut->StrokeAndFillPath( sal_True, sal_False );
809 break;
810
811 case EMR_SELECTCLIPPATH :
812 {
813 sal_Int32 nClippingMode;
814 *pWMF >> nClippingMode;
815 pOut->SetClipPath( pOut->GetPathObj(), nClippingMode, sal_True );
816 }
817 break;
818
819 case EMR_EXTSELECTCLIPRGN :
820 {
821 sal_Int32 iMode, cbRgnData;
822 *pWMF >> cbRgnData
823 >> iMode;
824
825 PolyPolygon aPolyPoly;
826 if ( cbRgnData )
827 ImplReadRegion( aPolyPoly, *pWMF, nRecSize );
828 pOut->SetClipPath( aPolyPoly, iMode, sal_False );
829 }
830 break;
831 case EMR_ALPHABLEND:
832 {
833 sal_Int32 xDest, yDest, cxDest, cyDest;
834
835 BLENDFUNCTION aFunc;
836 sal_Int32 xSrc, ySrc;
837 XForm xformSrc;
838 sal_uInt32 BkColorSrc,iUsageSrc ,offBmiSrc,cbBmiSrc,offBitsSrc,cbBitsSrc ,cxSrc,cySrc ;
839
840 sal_uInt32 nStart = pWMF->Tell() - 8;
841 pWMF->SeekRel( 0x10 );
842
843 *pWMF >> xDest >> yDest >> cxDest >> cyDest >> aFunc >> xSrc >> ySrc
844 >> xformSrc >> BkColorSrc >> iUsageSrc >> offBmiSrc >> cbBmiSrc
845 >> offBitsSrc >> cbBitsSrc >>cxSrc>>cySrc ;
846
847 sal_uInt32 dwRop = SRCAND|SRCINVERT;
848
849 Bitmap aBitmap;
850 Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
851
852 if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
853 bStatus = sal_False;
854 else
855 {
856 sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
857 if ( nSize <= ( nEndPos - nStartPos ) )
858 {
859 char* pBuf = new char[ nSize ];
860 SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
861 aTmp.ObjectOwnsMemory( sal_True );
862 aTmp << (sal_uInt8)'B'
863 << (sal_uInt8)'M'
864 << (sal_uInt32)cbBitsSrc
865 << (sal_uInt16)0
866 << (sal_uInt16)0
867 << (sal_uInt32)cbBmiSrc + 14;
868 pWMF->Seek( nStart + offBmiSrc );
869 pWMF->Read( pBuf + 14, cbBmiSrc );
870 pWMF->Seek( nStart + offBitsSrc );
871 pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
872 aTmp.Seek( 0 );
873 ReadDIB(aBitmap, aTmp, true);
874
875 // test if it is sensible to crop
876 if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
877 ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
878 ( xSrc + static_cast< sal_Int32 >(cxSrc) <= static_cast< sal_Int32 >(aBitmap.GetSizePixel().Width()) ) &&
879 ( ySrc + static_cast< sal_Int32 >(cySrc) <= static_cast< sal_Int32 >(aBitmap.GetSizePixel().Height()) ) )
880 {
881 Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
882 aBitmap.Crop( aCropRect );
883 }
884 aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop ), LIST_APPEND );
885 }
886 }
887 }
888 break;
889 case EMR_BITBLT : // PASSTHROUGH INTENDED
890 case EMR_STRETCHBLT :
891 {
892 sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
893 sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
894 XForm xformSrc;
895
896 sal_uInt32 nStart = pWMF->Tell() - 8;
897
898 pWMF->SeekRel( 0x10 );
899 *pWMF >> xDest >> yDest >> cxDest >> cyDest >> dwRop >> xSrc >> ySrc
900 >> xformSrc >> nColor >> iUsageSrc >> offBmiSrc >> cbBmiSrc
901 >> offBitsSrc >> cbBitsSrc;
902
903 if ( nRecType == EMR_STRETCHBLT )
904 *pWMF >> cxSrc >> cySrc;
905 else
906 cxSrc = cySrc = 0;
907
908 Bitmap aBitmap;
909 Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
910
911 cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
912 cyDest = abs( (int)cyDest ); // and also 122889
913
914 if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
915 bStatus = sal_False;
916 else
917 {
918 sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
919 if ( nSize <= ( nEndPos - nStartPos ) )
920 {
921 char* pBuf = new char[ nSize ];
922 SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
923 aTmp.ObjectOwnsMemory( sal_True );
924 aTmp << (sal_uInt8)'B'
925 << (sal_uInt8)'M'
926 << (sal_uInt32)cbBitsSrc
927 << (sal_uInt16)0
928 << (sal_uInt16)0
929 << (sal_uInt32)cbBmiSrc + 14;
930 pWMF->Seek( nStart + offBmiSrc );
931 pWMF->Read( pBuf + 14, cbBmiSrc );
932 pWMF->Seek( nStart + offBitsSrc );
933 pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
934 aTmp.Seek( 0 );
935 ReadDIB(aBitmap, aTmp, true);
936
937 // test if it is sensible to crop
938 if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
939 ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
940 ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
941 ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
942 {
943 Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
944 aBitmap.Crop( aCropRect );
945 }
946 aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop ), LIST_APPEND );
947 }
948 }
949 }
950 break;
951
952 case EMR_STRETCHDIBITS :
953 {
954 sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
955 sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
956 sal_uInt32 nStart = pWMF->Tell() - 8;
957
958 pWMF->SeekRel( 0x10 );
959 *pWMF >> xDest >> yDest >> xSrc >> ySrc >> cxSrc >> cySrc >> offBmiSrc >> cbBmiSrc >> offBitsSrc
960 >> cbBitsSrc >> iUsageSrc >> dwRop >> cxDest >> cyDest;
961
962 Bitmap aBitmap;
963 Rectangle aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
964
965 cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
966 cyDest = abs( (int)cyDest ); // and also 122889
967
968 if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
969 bStatus = sal_False;
970 else
971 {
972 sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
973 if ( nSize <= ( nEndPos - nStartPos ) )
974 {
975 char* pBuf = new char[ nSize ];
976 SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
977 aTmp.ObjectOwnsMemory( sal_True );
978 aTmp << (sal_uInt8)'B'
979 << (sal_uInt8)'M'
980 << (sal_uInt32)cbBitsSrc
981 << (sal_uInt16)0
982 << (sal_uInt16)0
983 << (sal_uInt32)cbBmiSrc + 14;
984 pWMF->Seek( nStart + offBmiSrc );
985 pWMF->Read( pBuf + 14, cbBmiSrc );
986 pWMF->Seek( nStart + offBitsSrc );
987 pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
988 aTmp.Seek( 0 );
989 ReadDIB(aBitmap, aTmp, true);
990
991 // test if it is sensible to crop
992 if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
993 ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
994 ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
995 ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
996 {
997 Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
998 aBitmap.Crop( aCropRect );
999 }
1000 aBmpSaveList.Insert( new BSaveStruct( aBitmap, aRect, dwRop ), LIST_APPEND );
1001 }
1002 }
1003 }
1004 break;
1005
1006 case EMR_EXTCREATEFONTINDIRECTW :
1007 {
1008 *pWMF >> nIndex;
1009 if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
1010 {
1011 LOGFONTW aLogFont;
1012 *pWMF >> aLogFont.lfHeight >> aLogFont.lfWidth >> aLogFont.lfEscapement >> aLogFont.lfOrientation >> aLogFont.lfWeight >> aLogFont.lfItalic
1013 >> aLogFont.lfUnderline >> aLogFont.lfStrikeOut >> aLogFont.lfCharSet >> aLogFont.lfOutPrecision >> aLogFont.lfClipPrecision
1014 >> aLogFont.lfQuality >> aLogFont.lfPitchAndFamily;
1015
1016 sal_Unicode lfFaceName[ LF_FACESIZE ];
1017
1018 for ( int i = 0; i < LF_FACESIZE; i++ )
1019 {
1020 sal_uInt16 nChar;
1021 *pWMF >> nChar;
1022 lfFaceName[ i ] = nChar;
1023 }
1024 aLogFont.alfFaceName = UniString( lfFaceName );
1025
1026 // #123216# Not used in the test case of #121382# (always identity in XForm), also
1027 // no hints in ms docu if FontSize should be scaled with WT. Using with the example
1028 // from #123216# creates errors, so removing.
1029 //
1030 // // #121382# Need to apply WorldTransform to FontHeight/Width; this should be completely
1031 // // changed to basegfx::B2DHomMatrix instead of 'struct XForm', but not now due to time
1032 // // constraints and dangers
1033 // const XForm& rXF = pOut->GetWorldTransform();
1034 // const basegfx::B2DHomMatrix aWT(rXF.eM11, rXF.eM21, rXF.eDx, rXF.eM12, rXF.eM22, rXF.eDy);
1035 // const basegfx::B2DVector aTransVec(aWT * basegfx::B2DVector(aLogFont.lfWidth, aLogFont.lfHeight));
1036 // aLogFont.lfWidth = aTransVec.getX();
1037 // aLogFont.lfHeight = aTransVec.getY();
1038
1039 pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
1040 }
1041 }
1042 break;
1043
1044 case EMR_EXTTEXTOUTA :
1045 bFlag = sal_True;
1046 case EMR_EXTTEXTOUTW :
1047 {
1048 sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
1049 sal_uInt32 nCurPos, nLen, nOffString, nOptions, offDx;
1050 sal_Int32* pDX = NULL;
1051
1052 nCurPos = pWMF->Tell() - 8;
1053
1054 *pWMF >> nLeft >> nTop >> nRight >> nBottom >> nGfxMode >> nXScale >> nYScale
1055 >> ptlReferenceX >> ptlReferenceY >> nLen >> nOffString >> nOptions;
1056
1057 pWMF->SeekRel( 0x10 );
1058 *pWMF >> offDx;
1059
1060 sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
1061 if ( nOptions & ETO_RTLREADING )
1062 nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
1063 pOut->SetTextLayoutMode( nTextLayoutMode );
1064 DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
1065
1066 Point aPos( ptlReferenceX, ptlReferenceY );
1067 if ( nLen && ( nLen < SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
1068 {
1069 if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
1070 {
1071 pWMF->Seek( nCurPos + offDx );
1072 if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
1073 {
1074 pDX = new sal_Int32[ nLen ];
1075 sal_uInt32 i;
1076 for ( i = 0; i < nLen; i++ )
1077 *pWMF >> pDX[ i ];
1078 }
1079 }
1080 pWMF->Seek( nCurPos + nOffString );
1081 String aText;
1082 if ( bFlag )
1083 {
1084 if ( nLen <= ( nEndPos - pWMF->Tell() ) )
1085 {
1086 sal_Char* pBuf = new sal_Char[ nLen ];
1087 pWMF->Read( pBuf, nLen );
1088 aText = String( pBuf, (sal_uInt16)nLen, pOut->GetCharSet() );
1089 delete[] pBuf;
1090
1091 if ( aText.Len() != nLen )
1092 {
1093 sal_uInt16 i, j, k;
1094 sal_Int32* pOldDx = pDX;
1095 pDX = new sal_Int32[ aText.Len() ];
1096 for ( i = 0, j = 0; i < aText.Len(); i++ )
1097 {
1098 ByteString aCharacter( aText.GetChar( i ), pOut->GetCharSet() );
1099 pDX[ i ] = 0;
1100 for ( k = 0; ( k < aCharacter.Len() ) && ( j < nLen ) && ( i < aText.Len() ); k++ )
1101 pDX[ i ] += pOldDx[ j++ ];
1102 }
1103 delete[] pOldDx;
1104 }
1105 }
1106 }
1107 else
1108 {
1109 if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
1110 {
1111 sal_Unicode* pBuf = new sal_Unicode[ nLen ];
1112 pWMF->Read( pBuf, nLen << 1 );
1113 #ifdef OSL_BIGENDIAN
1114 sal_Char nTmp, *pTmp = (sal_Char*)( pBuf + nLen );
1115 while ( pTmp-- != (sal_Char*)pBuf )
1116 {
1117 nTmp = *pTmp--;
1118 pTmp[ 1 ] = *pTmp;
1119 *pTmp = nTmp;
1120 }
1121 #endif
1122 aText = String( pBuf, (xub_StrLen)nLen );
1123 delete[] pBuf;
1124 }
1125 }
1126 pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
1127 }
1128 delete[] pDX;
1129 }
1130 break;
1131
1132 case EMR_POLYBEZIERTO16 :
1133 bFlag = sal_True;
1134 case EMR_POLYBEZIER16 :
1135 {
1136 pWMF->SeekRel( 16 );
1137 *pWMF >> nPoints;
1138 sal_uInt16 i = 0;
1139 if ( bFlag )
1140 {
1141 i++;
1142 nPoints++;
1143 }
1144 Polygon aPoly( (sal_uInt16)nPoints );
1145 for( ; i < (sal_uInt16)nPoints; i++ )
1146 {
1147 *pWMF >> nX16 >> nY16;
1148 aPoly[ i ] = Point( nX16, nY16 );
1149 }
1150 pOut->DrawPolyBezier( aPoly, bFlag, bRecordPath ); // Line( aPoly, bFlag );
1151 }
1152 break;
1153
1154 case EMR_POLYGON16 :
1155 {
1156 pWMF->SeekRel( 16 );
1157 *pWMF >> nPoints;
1158 Polygon aPoly( (sal_uInt16)nPoints );
1159 for( sal_uInt16 k = 0; k < (sal_uInt16)nPoints; k++ )
1160 {
1161 *pWMF >> nX16 >> nY16;
1162 aPoly[ k ] = Point( nX16, nY16 );
1163 }
1164 pOut->DrawPolygon( aPoly, bRecordPath );
1165 }
1166 break;
1167
1168 case EMR_POLYLINETO16 :
1169 bFlag = sal_True;
1170 case EMR_POLYLINE16 :
1171 {
1172 pWMF->SeekRel( 16 );
1173 *pWMF >> nPoints;
1174 sal_uInt16 i = 0;
1175 if ( bFlag )
1176 {
1177 i++;
1178 nPoints++;
1179 }
1180
1181 Polygon aPoly( (sal_uInt16)nPoints );
1182 for( ; i < (sal_uInt16)nPoints; i++ )
1183 {
1184 *pWMF >> nX16 >> nY16;
1185 aPoly[ i ] = Point( nX16, nY16 );
1186 }
1187 pOut->DrawPolyLine( aPoly, bFlag, bRecordPath );
1188 }
1189 break;
1190
1191 case EMR_POLYPOLYLINE16 :
1192 {
1193 sal_uInt16* pnPoints;
1194
1195 sal_Int32 i, nPoly, nGesPoints;
1196 pWMF->SeekRel( 0x10 );
1197 // Anzahl der Polygone:
1198 *pWMF >> nPoly >> nGesPoints;
1199
1200 // taking the amount of points of each polygon, retrieving the total number of points
1201 if ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) )
1202 {
1203 if ( ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() ) )
1204 {
1205 pnPoints = new sal_uInt16[ nPoly ];
1206 for ( i = 0; i < nPoly; i++ )
1207 {
1208 *pWMF >> nPoints;
1209 pnPoints[ i ] = (sal_uInt16)nPoints;
1210 }
1211 // Polygonpunkte holen:
1212 for ( i = 0; ( i < nPoly ) && !pWMF->IsEof(); i++ )
1213 {
1214 Polygon aPolygon( pnPoints[ i ] );
1215 for ( sal_uInt16 k = 0; k < pnPoints[ i ]; k++ )
1216 {
1217 *pWMF >> nX16 >> nY16;
1218 aPolygon[ k ] = Point( nX16, nY16 );
1219 }
1220 pOut->DrawPolyLine( aPolygon, sal_False, bRecordPath );
1221 }
1222 delete[] pnPoints;
1223 }
1224 }
1225 }
1226 break;
1227
1228 case EMR_POLYPOLYGON16 :
1229 {
1230 sal_uInt32 nPoly(0);
1231 sal_uInt32 nGesPoints(0);
1232 pWMF->SeekRel( 0x10 );
1233 // Anzahl der Polygone:
1234 *pWMF >> nPoly >> nGesPoints;
1235 sal_uInt32 nReadPoints(0);
1236
1237 if ( ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) && !pWMF->IsEof() )
1238 {
1239 if ( ( static_cast< sal_uInt32 >( nPoly ) * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) )
1240 {
1241 sal_uInt32 i(0);
1242 sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
1243
1244 for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
1245 {
1246 *pWMF >> nPoints;
1247 pnPoints[ i ] = (sal_uInt16)nPoints;
1248 }
1249
1250 if ( ( nGesPoints * (sizeof(sal_uInt16)+sizeof(sal_uInt16)) ) <= ( nEndPos - pWMF->Tell() ) && !pWMF->IsEof() )
1251 {
1252 PolyPolygon aPolyPoly(nPoly, nPoly);
1253
1254 for ( i = 0; i < nPoly && !pWMF->IsEof(); i++ )
1255 {
1256 const sal_uInt16 nPointCount(pnPoints[i]);
1257 Point* pPtAry = new Point[nPointCount];
1258
1259 for(sal_uInt16 b(0); b < nPointCount && !pWMF->IsEof(); b++)
1260 {
1261 *pWMF >> nX16 >> nY16;
1262 pPtAry[b] = Point( nX16, nY16 );
1263 nReadPoints++;
1264 }
1265
1266 aPolyPoly.Insert(Polygon(nPointCount, pPtAry));
1267 delete[] pPtAry;
1268 }
1269
1270 // create PolyPolygon actions
1271 pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
1272 }
1273
1274 delete[] pnPoints;
1275 }
1276 }
1277
1278 OSL_ENSURE(nReadPoints == nGesPoints, "The number Points processed from EMR_POLYPOLYGON16 is unequal imported number (!)");
1279 }
1280 break;
1281
1282 case EMR_FILLRGN :
1283 {
1284 sal_uInt32 nLen;
1285 PolyPolygon aPolyPoly;
1286 pWMF->SeekRel( 0x10 );
1287 *pWMF >> nLen >> nIndex;
1288
1289 if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
1290 {
1291 pOut->Push();
1292 pOut->SelectObject( nIndex );
1293 pOut->DrawPolyPolygon( aPolyPoly, sal_False );
1294 pOut->Pop();
1295 }
1296 }
1297 break;
1298 case EMR_CREATEDIBPATTERNBRUSHPT :
1299 {
1300 sal_uInt32 nTmp32;
1301 sal_uInt32 nOffset;
1302 *pWMF >> nIndex;
1303 Bitmap aBmp;
1304 BitmapReadAccess* pBmp;
1305 sal_uInt32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
1306
1307 *pWMF >> nTmp32;
1308 *pWMF >> nOffset;
1309 for ( sal_uInt32 i = 0; i < (nOffset - 20)/4; i ++ )
1310 {
1311 *pWMF >> nTmp32;
1312 }
1313
1314 ReadDIB(aBmp, *pWMF, false);
1315 pBmp = aBmp.AcquireReadAccess();
1316 if ( pBmp )
1317 {
1318 for ( sal_Int32 y = 0; y < pBmp->Height(); y++ )
1319 {
1320 for ( sal_Int32 x = 0; x < pBmp->Width(); x++ )
1321 {
1322 const BitmapColor aColor( pBmp->GetColor( y, x ) );
1323
1324 nRed += aColor.GetRed();
1325 nGreen += aColor.GetGreen();
1326 nBlue += aColor.GetBlue();
1327 }
1328 }
1329 nCount = pBmp->Height() * pBmp->Width();
1330 if ( !nCount )
1331 nCount++;
1332 aBmp.ReleaseAccess( pBmp );
1333 }
1334 Color aColor( (sal_Char)( nRed / nCount ), (sal_Char)( nGreen / nCount ), (sal_Char)( nBlue / nCount ) );
1335 pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aColor, sal_False ) );
1336 }
1337 break;
1338
1339 #ifdef WIN_MTF_ASSERT
1340 default : WinMtfAssertHandler( "Unknown Meta Action" ); break;
1341 case EMR_MASKBLT : WinMtfAssertHandler( "MaskBlt" ); break;
1342 case EMR_PLGBLT : WinMtfAssertHandler( "PlgBlt" ); break;
1343 case EMR_SETDIBITSTODEVICE : WinMtfAssertHandler( "SetDIBitsToDevice" ); break;
1344 case EMR_FRAMERGN : WinMtfAssertHandler( "FrameRgn" ); break;
1345 case EMR_INVERTRGN : WinMtfAssertHandler( "InvertRgn" ); break;
1346 case EMR_PAINTRGN : WinMtfAssertHandler( "PaintRgn" ); break;
1347 case EMR_FLATTENPATH : WinMtfAssertHandler( "FlattenPath" ); break;
1348 case EMR_WIDENPATH : WinMtfAssertHandler( "WidenPath" ); break;
1349 case EMR_POLYDRAW : WinMtfAssertHandler( "Polydraw" ); break;
1350 case EMR_SETARCDIRECTION : WinMtfAssertHandler( "SetArcDirection" ); break;
1351 case EMR_SETPALETTEENTRIES : WinMtfAssertHandler( "SetPaletteEntries" ); break;
1352 case EMR_RESIZEPALETTE : WinMtfAssertHandler( "ResizePalette" ); break;
1353 case EMR_EXTFLOODFILL : WinMtfAssertHandler( "ExtFloodFill" ); break;
1354 case EMR_ANGLEARC : WinMtfAssertHandler( "AngleArc" ); break;
1355 case EMR_SETCOLORADJUSTMENT : WinMtfAssertHandler( "SetColorAdjustment" ); break;
1356 case EMR_POLYDRAW16 : WinMtfAssertHandler( "PolyDraw16" ); break;
1357 case EMR_POLYTEXTOUTA : WinMtfAssertHandler( "PolyTextOutA" ); break;
1358 case EMR_POLYTEXTOUTW : WinMtfAssertHandler( "PolyTextOutW" ); break;
1359 case EMR_CREATECOLORSPACE : WinMtfAssertHandler( "CreateColorSpace" ); break;
1360 case EMR_SETCOLORSPACE : WinMtfAssertHandler( "SetColorSpace" ); break;
1361 case EMR_DELETECOLORSPACE : WinMtfAssertHandler( "DeleteColorSpace" ); break;
1362 case EMR_GLSRECORD : WinMtfAssertHandler( "GlsRecord" ); break;
1363 case EMR_GLSBOUNDEDRECORD : WinMtfAssertHandler( "GlsBoundRecord" ); break;
1364 case EMR_PIXELFORMAT : WinMtfAssertHandler( "PixelFormat" ); break;
1365 case EMR_DRAWESCAPE : WinMtfAssertHandler( "DrawEscape" ); break;
1366 case EMR_EXTESCAPE : WinMtfAssertHandler( "ExtEscape" ); break;
1367 case EMR_STARTDOC : WinMtfAssertHandler( "StartDoc" ); break;
1368 case EMR_SMALLTEXTOUT : WinMtfAssertHandler( "SmallTextOut" ); break;
1369 case EMR_FORCEUFIMAPPING : WinMtfAssertHandler( "ForceUFIMapping" ); break;
1370 case EMR_NAMEDESCAPE : WinMtfAssertHandler( "NamedEscape" ); break;
1371 case EMR_COLORCORRECTPALETTE : WinMtfAssertHandler( "ColorCorrectPalette" ); break;
1372 case EMR_SETICMPROFILEA : WinMtfAssertHandler( "SetICMProfileA" ); break;
1373 case EMR_SETICMPROFILEW : WinMtfAssertHandler( "SetICMProfileW" ); break;
1374 case EMR_TRANSPARENTBLT : WinMtfAssertHandler( "TransparenBlt" ); break;
1375 case EMR_TRANSPARENTDIB : WinMtfAssertHandler( "TransparenDib" ); break;
1376 case EMR_GRADIENTFILL : WinMtfAssertHandler( "GradientFill" ); break;
1377 case EMR_SETLINKEDUFIS : WinMtfAssertHandler( "SetLinkedUFIS" ); break;
1378
1379 case EMR_SETMAPPERFLAGS : WinMtfAssertHandler( "SetMapperFlags", 0 ); break;
1380 case EMR_SETICMMODE : WinMtfAssertHandler( "SetICMMode", 0 ); break;
1381 case EMR_CREATEMONOBRUSH : WinMtfAssertHandler( "CreateMonoBrush", 0 ); break;
1382 case EMR_SETBRUSHORGEX : WinMtfAssertHandler( "SetBrushOrgEx", 0 ); break;
1383 case EMR_SETMETARGN : WinMtfAssertHandler( "SetMetArgn", 0 ); break;
1384 case EMR_SETMITERLIMIT : WinMtfAssertHandler( "SetMiterLimit", 0 ); break;
1385 case EMR_EXCLUDECLIPRECT : WinMtfAssertHandler( "ExcludeClipRect", 0 ); break;
1386 case EMR_REALIZEPALETTE : WinMtfAssertHandler( "RealizePalette", 0 ); break;
1387 case EMR_SELECTPALETTE : WinMtfAssertHandler( "SelectPalette", 0 ); break;
1388 case EMR_CREATEPALETTE : WinMtfAssertHandler( "CreatePalette", 0 ); break;
1389 case EMR_ALPHADIBBLEND : WinMtfAssertHandler( "AlphaDibBlend", 0 ); break;
1390 case EMR_SETTEXTJUSTIFICATION : WinMtfAssertHandler( "SetTextJustification", 0 ); break;
1391
1392 case EMR_GDICOMMENT :
1393 case EMR_HEADER : // has already been read at ReadHeader()
1394 break;
1395 #endif
1396 }
1397 pWMF->Seek( nNextPos );
1398 }
1399 if( aBmpSaveList.Count() )
1400 pOut->ResolveBitmapActions( aBmpSaveList );
1401
1402 if ( bStatus )
1403 pWMF->Seek(nEndPos);
1404
1405 return bStatus;
1406 };
1407
1408 //-----------------------------------------------------------------------------------
1409
ReadHeader()1410 sal_Bool EnhWMFReader::ReadHeader()
1411 {
1412 sal_uInt32 nsal_uInt32, nHeaderSize, nPalEntries;
1413 sal_Int32 nLeft, nTop, nRight, nBottom;
1414
1415 // METAFILEHEADER SPARE ICH MIR HIER
1416 // Einlesen des METAHEADER
1417 *pWMF >> nsal_uInt32 >> nHeaderSize;
1418 if ( nsal_uInt32 != 1 ) // Typ
1419 return sal_False;
1420
1421 // bound size
1422 Rectangle rclBounds; // rectangle in logical units 1/100th mm
1423 *pWMF >> nLeft >> nTop >> nRight >> nBottom;
1424 rclBounds.Left() = nLeft;
1425 rclBounds.Top() = nTop;
1426 rclBounds.Right() = nRight;
1427 rclBounds.Bottom() = nBottom;
1428
1429 // picture frame size
1430 Rectangle rclFrame; // rectangle in device units
1431 *pWMF >> nLeft >> nTop >> nRight >> nBottom;
1432 rclFrame.Left() = nLeft;
1433 rclFrame.Top() = nTop;
1434 rclFrame.Right() = nRight;
1435 rclFrame.Bottom() = nBottom;
1436
1437 *pWMF >> nsal_uInt32; // signature
1438
1439 if ( nsal_uInt32 != 0x464d4520 )
1440 return sal_False;
1441
1442 *pWMF >> nsal_uInt32; // nVersion
1443 *pWMF >> nEndPos; // size of metafile
1444 nEndPos += nStartPos;
1445
1446 sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
1447 pWMF->Seek( STREAM_SEEK_TO_END );
1448 if ( pWMF->Tell() < nEndPos )
1449 nEndPos = pWMF->Tell();
1450 pWMF->Seek( nStrmPos );
1451
1452 *pWMF >> nRecordCount;
1453
1454 if ( !nRecordCount )
1455 return sal_False;
1456
1457 pWMF->SeekRel( 0xc );
1458
1459 sal_Int32 nPixX, nPixY, nMillX, nMillY;
1460 *pWMF >> nPalEntries >> nPixX >> nPixY >> nMillX >> nMillY;
1461
1462 pOut->SetrclFrame( rclFrame );
1463 pOut->SetrclBounds( rclBounds );
1464 pOut->SetRefPix( Size( nPixX, nPixY ) );
1465 pOut->SetRefMill( Size( nMillX, nMillY ) );
1466
1467 pWMF->Seek( nStartPos + nHeaderSize );
1468 return sal_True;
1469 }
1470
1471 //-----------------------------------------------------------------------------------
1472
ReadRectangle(sal_Int32 x1,sal_Int32 y1,sal_Int32 x2,sal_Int32 y2)1473 Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
1474 {
1475 Point aTL ( Point( x1, y1 ) );
1476 Point aBR( Point( --x2, --y2 ) );
1477 return Rectangle( aTL, aBR );
1478 }
1479
~EnhWMFReader()1480 EnhWMFReader::~EnhWMFReader()
1481 {
1482
1483 };
1484
1485 /* vim: set noet sw=4 ts=4: */
1486