xref: /AOO41X/main/filter/source/graphicfilter/ios2met/ios2met.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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_filter.hxx"
24 
25 #include <vcl/graph.hxx>
26 #include <tools/poly.hxx>
27 #include <vcl/virdev.hxx>
28 #include <vcl/lineinfo.hxx>
29 #include <svtools/fltcall.hxx>
30 #include <vcl/dibtools.hxx>
31 #include <math.h>
32 
33 // MT: NOOLDSV, someone should change the code...
34 enum PenStyle { PEN_NULL, PEN_SOLID, PEN_DOT, PEN_DASH, PEN_DASHDOT };
35 
36 
37 //============================== defines ===================================
38 
39 #define OOODEBUG(str,Num) //InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute();
40 
41 // -----------------------------Feld-Typen-------------------------------
42 
43 #define BegDocumnMagic 0xA8A8 /* Begin Document */
44 #define EndDocumnMagic 0xA8A9 /* End Document   */
45 
46 #define BegResGrpMagic 0xC6A8 /* Begin Resource Group */
47 #define EndResGrpMagic 0xC6A9 /* End Resource Group   */
48 
49 #define BegColAtrMagic 0x77A8 /* Begin Color Attribute Table */
50 #define EndColAtrMagic 0x77A9 /* End Color Attribute Table   */
51 #define BlkColAtrMagic 0x77B0 /* Color Attribute Table       */
52 #define MapColAtrMagic 0x77AB /* Map Color Attribute Table   */
53 
54 #define BegImgObjMagic 0xFBA8 /* Begin Image Object    */
55 #define EndImgObjMagic 0xFBA9 /* End Image Object      */
56 #define DscImgObjMagic 0xFBA6 /* Image Data Descriptor */
57 #define DatImgObjMagic 0xFBEE /* Image Picture Data    */
58 
59 #define BegObEnv1Magic 0xC7A8 /* Begin Object Environment Group */
60 #define EndObEnv1Magic 0xC7A9 /* End Object Environment Group   */
61 
62 #define BegGrfObjMagic 0xBBA8 /* Begin Graphics Object   */
63 #define EndGrfObjMagic 0xBBA9 /* End Graphics Object     */
64 #define DscGrfObjMagic 0xBBA6 /* Graphics Data Descritor */
65 #define DatGrfObjMagic 0xBBEE /* Graphics Data           */
66 
67 #define MapCodFntMagic 0x8AAB /* Map Coded Font    */
68 #define MapDatResMagic 0xC3AB /* Map Data Resource */
69 
70 // -----------------------------Order-Typen-------------------------------
71 
72 #define GOrdGivArc 0xC6   /* 1 Arc at given position   */
73 #define GOrdCurArc 0x86   /* 1 Arc at current position */
74 #define GOrdGivBzr 0xE5   /* 1 Beziercurve at given position   */
75 #define GOrdCurBzr 0xA5   /* 1 Beziercurve at current position */
76 #define GOrdGivBox 0xC0   /* 1 Box at given position   */
77 #define GOrdCurBox 0x80   /* 1 Box at current position */
78 #define GOrdGivFil 0xC5   /* 1 Fillet at given position   */
79 #define GOrdCurFil 0x85   /* 1 Fillet at current position */
80 #define GOrdGivCrc 0xC7   /* 1 Full arc (circle) at given position   */
81 #define GOrdCurCrc 0x87   /* 1 Full arc (circle) at current position */
82 #define GOrdGivLin 0xC1   /* 1 Line at given position   */
83 #define GOrdCurLin 0x81   /* 1 Line at current position */
84 #define GOrdGivMrk 0xC2   /* 1 Marker at given position   */
85 #define GOrdCurMrk 0x82   /* 1 Marker at current position */
86 #define GOrdGivArP 0xE3   /* 1 Partial arc at given position   */
87 #define GOrdCurArP 0xA3   /* 1 Partial arc at current position */
88 #define GOrdGivRLn 0xE1   /* 1 Relative line at given position   */
89 #define GOrdCurRLn 0xA1   /* 1 Relative line at current position */
90 #define GOrdGivSFl 0xE4   /* 1 Sharp fillet at given position   */
91 #define GOrdCurSFl 0xA4   /* 1 Sharp fillet at current position */
92 
93 #define GOrdGivStM 0xF1   /* 1 Character string move at given position   */
94 #define GOrdCurStM 0xB1   /* 1 Character string move at current position */
95 #define GOrdGivStr 0xC3   /* 1 Character string at given position   */
96 #define GOrdCurStr 0x83   /* 1 Character string at current position */
97 #define GOrdGivStx 0xFEF0 /* 2 Character string extended at given position   */
98 #define GOrdCurStx 0xFEB0 /* 2 Character string extended at current position */
99 
100 #define GOrdGivImg 0xD1   /* 1 Begin Image at given position   */
101 #define GOrdCurImg 0x91   /* 1 Begin Image at current position */
102 #define GOrdImgDat 0x92   /* 1 Image data                      */
103 #define GOrdEndImg 0x93   /* 1 End Image                       */
104 #define GOrdBegAra 0x68   /* 0 1 Begin area */
105 #define GOrdEndAra 0x60   /* 1 End area     */
106 #define GOrdBegElm 0xD2   /* 1 Begin element */
107 #define GOrdEndElm 0x49   /* 0 1 End element */
108 
109 #define GOrdBegPth 0xD0   /* 1 Begin path    */
110 #define GOrdEndPth 0x7F   /* 0 1 End path    */
111 #define GOrdFilPth 0xD7   /* 1 Fill path     */
112 #define GOrdModPth 0xD8   /* 1 Modify path   */
113 #define GOrdOutPth 0xD4   /* 1 Outline path  */
114 #define GOrdSClPth 0xB4   /* 1 Set clip path */
115 
116 #define GOrdNopNop 0x00   /* 0 0 No operation */
117 #define GOrdRemark 0x01   /* 1 Comment */
118 #define GOrdSegLab 0xD3   /* 1 Label */
119 #define GOrdBitBlt 0xD6   /* 1 Bitblt */
120 #define GOrdCalSeg 0x07   /* 1 Call Segment */
121 #define GOrdSSgBnd 0x32   /* 1 Set segment boundary */
122 #define GOrdSegChr 0x04   /* 1 Segment characteristics */
123 #define GOrdCloFig 0x7D   /* 0 1 Close Figure */
124 #define GOrdEndSym 0xFF   /* 0 0 End of symbol definition */
125 #define GOrdEndPlg 0x3E   /* 0 1 End prolog */
126 #define GOrdEscape 0xD5   /* 1 Escape */
127 #define GOrdExtEsc 0xFED5 /* 2 Extended Escape */
128 #define GOrdPolygn 0xF3   /* 2 Polygons */
129 
130 #define GOrdStkPop 0x3F   /* 0 1 Pop */
131 
132 #define GOrdSIvAtr 0x14   /* 1 Set individual attribute          */
133 #define GOrdPIvAtr 0x54   /* 1 Push and set individual attribute */
134 #define GOrdSColor 0x0A   /* 0 1 Set color          */
135 #define GOrdPColor 0x4A   /* 0 1 Push and set color */
136 #define GOrdSIxCol 0xA6   /* 1 Set indexed color          */
137 #define GOrdPIxCol 0xE6   /* 1 Push and set indexed color */
138 #define GOrdSXtCol 0x26   /* 1 Set extended color          */
139 #define GOrdPXtCol 0x66   /* 1 Push and set extended color */
140 #define GOrdSBgCol 0x25   /* 1 Set background color          */
141 #define GOrdPBgCol 0x65   /* 1 Push and set background color */
142 #define GOrdSBxCol 0xA7   /* 1 Set background indexed color          */
143 #define GOrdPBxCol 0xE7   /* 1 Push and set background indexed color */
144 #define GOrdSMixMd 0x0C   /* 0 1 Set mix          */
145 #define GOrdPMixMd 0x4C   /* 0 1 Push and set mix */
146 #define GOrdSBgMix 0x0D   /* 0 1 Set background mix          */
147 #define GOrdPBgMix 0x4D   /* 0 1 Push and set background mix */
148 
149 #define GOrdSPtSet 0x08   /* 0 1 Set pattern set          */
150 #define GOrdPPtSet 0x48   /* 0 1 Push and set pattern set */
151 #define GOrdSPtSym 0x28   /* 0 1 Set pattern symbol          */
152 #define GOrdPPtSym 0x09   /* 0 1 Push and set pattern symbol */
153 #define GOrdSPtRef 0xA0   /* 1 Set model pattern reference          */
154 #define GOrdPPtRef 0xE0   /* 1 Push and set pattern reference point */
155 
156 #define GOrdSLnEnd 0x1A   /* 0 1 Set line end          */
157 #define GOrdPLnEnd 0x5A   /* 0 1 Push and set line end */
158 #define GOrdSLnJoi 0x1B   /* 0 1 Set line join          */
159 #define GOrdPLnJoi 0x5B   /* 0 1 Push and set line join */
160 #define GOrdSLnTyp 0x18   /* 0 1 Set line type          */
161 #define GOrdPLnTyp 0x58   /* 0 1 Push and set line type */
162 #define GOrdSLnWdt 0x19   /* 0 1 Set line width          */
163 #define GOrdPLnWdt 0x59   /* 0 1 Push and set line width */
164 #define GOrdSFrLWd 0x11   /* 1 Set fractional line width          */
165 #define GOrdPFrLWd 0x51   /* 1 Push and set fractional line width */
166 #define GOrdSStLWd 0x15   /* 1 Set stroke line width          */
167 #define GOrdPStLWd 0x55   /* 1 Push and set stroke line width */
168 
169 #define GOrdSChDir 0x3A   /* 0 1 Set character direction          */
170 #define GOrdPChDir 0x7A   /* 0 1 Push and set character direction */
171 #define GOrdSChPrc 0x39   /* 0 1 Set character precision          */
172 #define GOrdPChPrc 0x79   /* 0 1 Push and set character precision */
173 #define GOrdSChSet 0x38   /* 0 1 Set character set          */
174 #define GOrdPChSet 0x78   /* 0 1 Push and set character set */
175 #define GOrdSChAng 0x34   /* 1 Set character angle          */
176 #define GOrdPChAng 0x74   /* 1 Push and set character angle */
177 #define GOrdSChBrx 0x05   /* 1 Set character break extra          */
178 #define GOrdPChBrx 0x45   /* 1 Push and set character break extra */
179 #define GOrdSChCel 0x33   /* 1 Set character cell          */
180 #define GOrdPChCel 0x03   /* 1 Push and set character cell */
181 #define GOrdSChXtr 0x17   /* 1 Set character extra          */
182 #define GOrdPChXtr 0x57   /* 1 Push and set character extra */
183 #define GOrdSChShr 0x35   /* 1 Set character shear          */
184 #define GOrdPChShr 0x75   /* 1 Push and set character shear */
185 #define GOrdSTxAlg 0x36   /* 0 2 Set text allingment          */
186 #define GOrdPTxAlg 0x76   /* 0 2 Push and set text allingment */
187 
188 #define GOrdSMkPrc 0x3B   /* 0 1 Set marker precision          */
189 #define GOrdPMkPrc 0x7B   /* 0 1 Push and set marker precision */
190 #define GOrdSMkSet 0x3C   /* 0 1 Set marker set          */
191 #define GOrdPMkSet 0x7C   /* 0 1 Push and set marker set */
192 #define GOrdSMkSym 0x29   /* 0 1 Set marker symbol          */
193 #define GOrdPMkSym 0x69   /* 0 1 Push and set marker symbol */
194 #define GOrdSMkCel 0x37   /* 1 Set marker cell          */
195 #define GOrdPMkCel 0x77   /* 1 Push and set marker cell */
196 
197 #define GOrdSArcPa 0x22   /* 1 Set arc parameters          */
198 #define GOrdPArcPa 0x62   /* 1 Push and set arc parameters */
199 
200 #define GOrdSCrPos 0x21   /* 1 Set current position          */
201 #define GOrdPCrPos 0x61   /* 1 Push and set current position */
202 
203 #define GOrdSMdTrn 0x24   /* 1 Set model transform          */
204 #define GOrdPMdTrn 0x64   /* 1 Push and set model transform */
205 #define GOrdSPkIdn 0x43   /* 1 Set pick identifier          */
206 #define GOrdPPkIdn 0x23   /* 1 Push and set pick identifier */
207 #define GOrdSVwTrn 0x31   /* 1 Set viewing transform */
208 #define GOrdSVwWin 0x27   /* 1 Set viewing window          */
209 #define GOrdPVwWin 0x67   /* 1 Push and set viewing window */
210 
211 //============================ OS2METReader ==================================
212 
213 struct OSPalette {
214     OSPalette * pSucc;
215     sal_uInt32 * p0RGB; // Darf auch NULL sein!
216     sal_uInt16 nSize;
217 };
218 
219 struct OSArea {
220     OSArea * pSucc;
221     sal_uInt8 nFlags;
222     PolyPolygon aPPoly;
223     sal_Bool bClosed;
224     Color      aCol;
225     Color      aBgCol;
226     RasterOp   eMix;
227     RasterOp   eBgMix;
228     sal_Bool       bFill;
OSAreaOSArea229     OSArea(){} ~OSArea(){}
230 };
231 
232 struct OSPath
233 {
234     OSPath*     pSucc;
235     sal_uInt32  nID;
236     PolyPolygon aPPoly;
237     sal_Bool        bClosed;
238     sal_Bool        bStroke;
239 
OSPathOSPath240                 OSPath(){}
~OSPathOSPath241                 ~OSPath(){}
242 };
243 
244 struct OSFont {
245     OSFont * pSucc;
246     sal_uLong nID;
247     Font aFont;
OSFontOSFont248     OSFont(){} ~OSFont(){}
249 };
250 
251 struct OSBitmap {
252     OSBitmap * pSucc;
253     sal_uLong nID;
254     Bitmap aBitmap;
255 
256     // Waehrend des Lesens der Bitmap benoetigt:
257     SvStream * pBMP; // Zeiger auf temporaere Windows-BMP-Datei oder NULL
258     sal_uInt32 nWidth, nHeight;
259     sal_uInt16 nBitsPerPixel;
260     sal_uLong nMapPos;
OSBitmapOSBitmap261     OSBitmap(){} ~OSBitmap(){}
262 };
263 
264 struct OSAttr {
265     OSAttr * pSucc;
266     sal_uInt16 nPushOrder;
267     sal_uInt8 nIvAttrA, nIvAttrP; // Spezialvariablen fuer den Order "GOrdPIvAtr"
268 
269     Color    aLinCol;
270     Color    aLinBgCol;
271     RasterOp eLinMix;
272     RasterOp eLinBgMix;
273     Color    aChrCol;
274     Color    aChrBgCol;
275     RasterOp eChrMix;
276     RasterOp eChrBgMix;
277     Color    aMrkCol;
278     Color    aMrkBgCol;
279     RasterOp eMrkMix;
280     RasterOp eMrkBgMix;
281     Color    aPatCol;
282     Color    aPatBgCol;
283     RasterOp ePatMix;
284     RasterOp ePatBgMix;
285     Color    aImgCol;
286     Color    aImgBgCol;
287     RasterOp eImgMix;
288     RasterOp eImgBgMix;
289     long     nArcP, nArcQ, nArcR, nArcS;
290     short    nChrAng;
291 //  long     nChrBreakExtra;
292     Size     aChrCellSize;
293 //  sal_uInt8     nChrDir;
294 //  long     nChrExtra;
295 //  sal_uInt8     nChrPrec;
296     sal_uLong    nChrSet;
297 //  Size     aChrShear;
298     Point    aCurPos;
299 //  long     nFracLinWidth;
300 //  sal_uInt8     nLinEnd;
301 //  sal_uInt8     nLinJoin;
302     PenStyle eLinStyle;
303     sal_uInt16   nLinWidth;
304     Size     aMrkCellSize;
305     sal_uInt8     nMrkPrec;
306     sal_uInt8     nMrkSet;
307     sal_uInt8     nMrkSymbol;
308 //  //...    aModTransform;
309 //  Point    aPatRef;
310 //  sal_uInt8     nPatSet;
311     sal_Bool     bFill;
312 //  sal_uLong    nPickId;
313 //  //...    aSegBound;
314     sal_uInt16   nStrLinWidth;
315 //  sal_uInt8     nTxtAlignHor,nTxtAlignVer;
316 //  //...    aViewTransform;
317 //  //...    aViewWindow;
~OSAttrOSAttr318     OSAttr(){} ~OSAttr(){}
319 };
320 
321 class OS2METReader {
322 
323 private:
324 
325     long ErrorCode;
326 
327     SvStream    * pOS2MET;             // Die einzulesende OS2MET-Datei
328     VirtualDevice * pVirDev;         // Hier werden die Drawing-Methoden aufgerufen.
329                                      // Dabei findet ein Recording in das GDIMetaFile
330                                      // statt.
331     sal_uLong         nOrigPos;          // Anfaengliche Position in pOS2MET
332     sal_uInt16        nOrigNumberFormat; // Anfaengliches Nummern-Format von pOS2MET
333     Rectangle aBoundingRect; // Boundingrectangle wie in Datei angegeben
334     Rectangle aCalcBndRect;  // selbst ermitteltes Boundingrectangle
335     MapMode aGlobMapMode;    // Aufloesung des Bildes
336     sal_Bool bCoord32;
337 
338     OSPalette  * pPaletteStack;
339 
340     LineInfo aLineInfo;
341 
342     OSArea   * pAreaStack; // Areas, die in Arbeit sind
343 
344     OSPath   * pPathStack; // Paths, die in Arbeit sind
345     OSPath   * pPathList;  // Vollendete Paths
346 
347     OSFont   * pFontList;
348 
349     OSBitmap * pBitmapList;
350 
351     OSAttr   aDefAttr;
352     OSAttr   aAttr;
353     OSAttr   * pAttrStack;
354 
355     SvStream * pOrdFile;
356 
357     sal_Bool Callback(sal_uInt16 nPercent);
358 
359     void AddPointsToPath(const Polygon & rPoly);
360     void AddPointsToArea(const Polygon & rPoly);
361     void CloseFigure();
362     void PushAttr(sal_uInt16 nPushOrder);
363     void PopAttr();
364 
365     void ChangeBrush( const Color& rPatColor, const Color& rBGColor, sal_Bool bFill );
366     void SetPen( const Color& rColor, sal_uInt16 nStrLinWidth = 0, PenStyle ePenStyle = PEN_SOLID );
367     void SetRasterOp(RasterOp eROP);
368 
369     void SetPalette0RGB(sal_uInt16 nIndex, sal_uLong nCol);
370     sal_uInt32 GetPalette0RGB(sal_uInt32 nIndex);
371         // Holt Farbe aus der Palette, oder, wenn nicht vorhanden,
372         // interpretiert nIndex als direkten RGB-Wert.
373     Color GetPaletteColor(sal_uInt32 nIndex);
374 
375 
376     sal_Bool        IsLineInfo();
377     void        DrawPolyLine( const Polygon& rPolygon );
378     void        DrawPolygon( const Polygon& rPolygon );
379     void        DrawPolyPolygon( const PolyPolygon& rPolygon );
380     sal_uInt16      ReadBigEndianWord();
381     sal_uLong       ReadBigEndian3BytesLong();
382     sal_uLong       ReadLittleEndian3BytesLong();
383     long        ReadCoord(sal_Bool b32);
384     Point       ReadPoint( const sal_Bool bAdjustBoundRect = sal_True );
385     RasterOp    OS2MixToRasterOp(sal_uInt8 nMix);
386     void        ReadLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
387     void        ReadRelLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
388     void        ReadBox(sal_Bool bGivenPos);
389     void        ReadBitBlt();
390     void        ReadChrStr(sal_Bool bGivenPos, sal_Bool bMove, sal_Bool bExtra, sal_uInt16 nOrderLen);
391     void        ReadArc(sal_Bool bGivenPos);
392     void        ReadFullArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize);
393     void        ReadPartialArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize);
394     void        ReadPolygons();
395     void        ReadBezier(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
396     void        ReadFillet(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
397     void        ReadFilletSharp(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
398     void        ReadMarker(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
399     void        ReadOrder(sal_uInt16 nOrderID, sal_uInt16 nOrderLen);
400     void        ReadDsc(sal_uInt16 nDscID, sal_uInt16 nDscLen);
401     void        ReadImageData(sal_uInt16 nDataID, sal_uInt16 nDataLen);
402     void        ReadFont(sal_uInt16 nFieldSize);
403     void        ReadField(sal_uInt16 nFieldType, sal_uInt16 nFieldSize);
404 
405 public:
406 
407     OS2METReader();
408     ~OS2METReader();
409 
410     void ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile );
411         // Liesst aus dem Stream eine OS2MET-Datei und fuellt das GDIMetaFile
412 
413 };
414 
415 //=================== Methoden von OS2METReader ==============================
416 
Callback(sal_uInt16)417 sal_Bool OS2METReader::Callback(sal_uInt16 /*nPercent*/)
418 {
419 /*
420     if (pCallback!=NULL) {
421         if (((*pCallback)(pCallerData,nPercent))==sal_True) {
422             pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
423             return sal_True;
424         }
425     }
426 */
427     return sal_False;
428 }
429 
OS2METReader()430 OS2METReader::OS2METReader()
431 {
432 }
433 
~OS2METReader()434 OS2METReader::~OS2METReader()
435 {
436 }
437 
IsLineInfo()438 sal_Bool OS2METReader::IsLineInfo()
439 {
440     return ( ! ( aLineInfo.IsDefault() || ( aLineInfo.GetStyle() == LINE_NONE ) || ( pVirDev->GetLineColor() == COL_TRANSPARENT ) ) );
441 }
442 
DrawPolyLine(const Polygon & rPolygon)443 void OS2METReader::DrawPolyLine( const Polygon& rPolygon )
444 {
445     if ( aLineInfo.GetStyle() == LINE_DASH || ( aLineInfo.GetWidth() > 1 ) )
446         pVirDev->DrawPolyLine( rPolygon, aLineInfo );
447     else
448         pVirDev->DrawPolyLine( rPolygon );
449 }
450 
DrawPolygon(const Polygon & rPolygon)451 void OS2METReader::DrawPolygon( const Polygon& rPolygon )
452 {
453     if ( IsLineInfo() )
454     {
455         pVirDev->Push( PUSH_LINECOLOR );
456         pVirDev->SetLineColor( COL_TRANSPARENT );
457         pVirDev->DrawPolygon( rPolygon );
458         pVirDev->Pop();
459         pVirDev->DrawPolyLine( rPolygon, aLineInfo );
460     }
461     else
462         pVirDev->DrawPolygon( rPolygon );
463 }
464 
DrawPolyPolygon(const PolyPolygon & rPolyPolygon)465 void OS2METReader::DrawPolyPolygon( const PolyPolygon& rPolyPolygon )
466 {
467     if ( IsLineInfo() )
468     {
469         pVirDev->Push( PUSH_LINECOLOR );
470         pVirDev->SetLineColor( COL_TRANSPARENT );
471         pVirDev->DrawPolyPolygon( rPolyPolygon );
472         pVirDev->Pop();
473         for ( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i++ )
474             pVirDev->DrawPolyLine( rPolyPolygon.GetObject( i ), aLineInfo );
475     }
476     else
477         pVirDev->DrawPolyPolygon( rPolyPolygon );
478 }
479 
AddPointsToArea(const Polygon & rPoly)480 void OS2METReader::AddPointsToArea(const Polygon & rPoly)
481 {
482     sal_uInt16 nOldSize, nNewSize,i;
483 
484     if (pAreaStack==NULL || rPoly.GetSize()==0) return;
485     PolyPolygon * pPP=&(pAreaStack->aPPoly);
486     if (pPP->Count()==0 || pAreaStack->bClosed==sal_True) pPP->Insert(rPoly);
487     else {
488         Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
489         nOldSize=aLastPoly.GetSize();
490         if (aLastPoly.GetPoint(nOldSize-1)==rPoly.GetPoint(0)) nOldSize--;
491         nNewSize=nOldSize+rPoly.GetSize();
492         aLastPoly.SetSize(nNewSize);
493         for (i=nOldSize; i<nNewSize; i++) {
494             aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
495         }
496         pPP->Replace(aLastPoly,pPP->Count()-1);
497     }
498     pAreaStack->bClosed=sal_False;
499 }
500 
AddPointsToPath(const Polygon & rPoly)501 void OS2METReader::AddPointsToPath(const Polygon & rPoly)
502 {
503     sal_uInt16 nOldSize, nNewSize,i;
504 
505     if (pPathStack==NULL || rPoly.GetSize()==0) return;
506     PolyPolygon * pPP=&(pPathStack->aPPoly);
507     if (pPP->Count()==0 /*|| pPathStack->bClosed==sal_True*/) pPP->Insert(rPoly);
508     else {
509         Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
510         nOldSize=aLastPoly.GetSize();
511         if (aLastPoly.GetPoint(nOldSize-1)!=rPoly.GetPoint(0)) pPP->Insert(rPoly);
512         else {
513             nOldSize--;
514             nNewSize=nOldSize+rPoly.GetSize();
515             aLastPoly.SetSize(nNewSize);
516             for (i=nOldSize; i<nNewSize; i++) {
517                 aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
518             }
519             pPP->Replace(aLastPoly,pPP->Count()-1);
520         }
521     }
522     pPathStack->bClosed=sal_False;
523 }
524 
CloseFigure()525 void OS2METReader::CloseFigure()
526 {
527     if (pAreaStack!=NULL) pAreaStack->bClosed=sal_True;
528     else if (pPathStack!=NULL) pPathStack->bClosed=sal_True;
529 }
530 
PushAttr(sal_uInt16 nPushOrder)531 void OS2METReader::PushAttr(sal_uInt16 nPushOrder)
532 {
533     OSAttr * p;
534     p=new OSAttr;
535     *p=aAttr;
536     p->pSucc=pAttrStack; pAttrStack=p;
537     p->nPushOrder=nPushOrder;
538 }
539 
PopAttr()540 void OS2METReader::PopAttr()
541 {
542     OSAttr * p=pAttrStack;
543 
544     if (p==NULL) return;
545     switch (p->nPushOrder) {
546 
547         case GOrdPIvAtr:
548             switch (p->nIvAttrA) {
549                 case 1: switch (p->nIvAttrP) {
550                     case 1: aAttr.aLinCol=p->aLinCol; break;
551                     case 2: aAttr.aChrCol=p->aChrCol; break;
552                     case 3: aAttr.aMrkCol=p->aMrkCol; break;
553                     case 4: aAttr.aPatCol=p->aPatCol; break;
554                     case 5: aAttr.aImgCol=p->aImgCol; break;
555                 } break;
556                 case 2: switch (p->nIvAttrP) {
557                     case 1: aAttr.aLinBgCol=p->aLinBgCol; break;
558                     case 2: aAttr.aChrBgCol=p->aChrBgCol; break;
559                     case 3: aAttr.aMrkBgCol=p->aMrkBgCol; break;
560                     case 4: aAttr.aPatBgCol=p->aPatBgCol; break;
561                     case 5: aAttr.aImgBgCol=p->aImgBgCol; break;
562                 } break;
563                 case 3: switch (p->nIvAttrP) {
564                     case 1: aAttr.eLinMix=p->eLinMix; break;
565                     case 2: aAttr.eChrMix=p->eChrMix; break;
566                     case 3: aAttr.eMrkMix=p->eMrkMix; break;
567                     case 4: aAttr.ePatMix=p->ePatMix; break;
568                     case 5: aAttr.eImgMix=p->eImgMix; break;
569                 } break;
570                 case 4: switch (p->nIvAttrP) {
571                     case 1: aAttr.eLinBgMix=p->eLinBgMix; break;
572                     case 2: aAttr.eChrBgMix=p->eChrBgMix; break;
573                     case 3: aAttr.eMrkBgMix=p->eMrkBgMix; break;
574                     case 4: aAttr.ePatBgMix=p->ePatBgMix; break;
575                     case 5: aAttr.eImgBgMix=p->eImgBgMix; break;
576                 } break;
577             }
578             break;
579 
580         case GOrdPLnTyp: aAttr.eLinStyle=p->eLinStyle; break;
581 
582         case GOrdPLnWdt: aAttr.nLinWidth=p->nLinWidth; break;
583 
584         case GOrdPStLWd: aAttr.nStrLinWidth=p->nStrLinWidth; break;
585 
586         case GOrdPChSet: aAttr.nChrSet=p->nChrSet; break;
587 
588         case GOrdPChAng: aAttr.nChrAng=p->nChrAng; break;
589 
590         case GOrdPMixMd:
591             aAttr.eLinMix=p->eLinMix;
592             aAttr.eChrMix=p->eChrMix;
593             aAttr.eMrkMix=p->eMrkMix;
594             aAttr.ePatMix=p->ePatMix;
595             aAttr.eImgMix=p->eImgMix;
596             break;
597 
598         case GOrdPBgMix:
599             aAttr.eLinBgMix=p->eLinBgMix;
600             aAttr.eChrBgMix=p->eChrBgMix;
601             aAttr.eMrkBgMix=p->eMrkBgMix;
602             aAttr.ePatBgMix=p->ePatBgMix;
603             aAttr.eImgBgMix=p->eImgBgMix;
604             break;
605 
606         case GOrdPPtSym: aAttr.bFill = p->bFill; break;
607 
608         case GOrdPColor:
609         case GOrdPIxCol:
610         case GOrdPXtCol:
611             aAttr.aLinCol=p->aLinCol;
612             aAttr.aChrCol=p->aChrCol;
613             aAttr.aMrkCol=p->aMrkCol;
614             aAttr.aPatCol=p->aPatCol;
615             aAttr.aImgCol=p->aImgCol;
616             break;
617 
618         case GOrdPBgCol:
619         case GOrdPBxCol:
620             aAttr.aLinBgCol=p->aLinBgCol;
621             aAttr.aChrBgCol=p->aChrBgCol;
622             aAttr.aMrkBgCol=p->aMrkBgCol;
623             aAttr.aPatBgCol=p->aPatBgCol;
624             aAttr.aImgBgCol=p->aImgBgCol;
625             break;
626 
627         case GOrdPMkPrc: aAttr.nMrkPrec=aDefAttr.nMrkPrec; break;
628 
629         case GOrdPMkSet: aAttr.nMrkSet=aDefAttr.nMrkSet; break;
630 
631         case GOrdPMkSym: aAttr.nMrkSymbol=aDefAttr.nMrkSymbol; break;
632 
633         case GOrdPMkCel: aAttr.aMrkCellSize=aDefAttr.aMrkCellSize; break;
634 
635         case GOrdPArcPa:
636             aAttr.nArcP=p->nArcP; aAttr.nArcQ=p->nArcQ;
637             aAttr.nArcR=p->nArcR; aAttr.nArcS=p->nArcS;
638             break;
639 
640         case GOrdPCrPos:
641             aAttr.aCurPos=p->aCurPos;
642             break;
643     }
644     pAttrStack=p->pSucc;
645     delete p;
646 }
647 
ChangeBrush(const Color & rPatColor,const Color &,sal_Bool bFill)648 void OS2METReader::ChangeBrush(const Color& rPatColor, const Color& /*rBGColor*/, sal_Bool bFill )
649 {
650     Color aColor;
651 
652     if( bFill )
653         aColor = rPatColor;
654     else
655         aColor = Color( COL_TRANSPARENT );
656 
657     if( pVirDev->GetFillColor() != aColor )
658         pVirDev->SetFillColor( aColor );
659 }
660 
SetPen(const Color & rColor,sal_uInt16 nLineWidth,PenStyle ePenStyle)661 void OS2METReader::SetPen( const Color& rColor, sal_uInt16 nLineWidth, PenStyle ePenStyle )
662 {
663     LineStyle eLineStyle( LINE_SOLID );
664 
665     if ( pVirDev->GetLineColor() != rColor )
666         pVirDev->SetLineColor( rColor );
667     aLineInfo.SetWidth( nLineWidth );
668 
669     sal_uInt16 nDotCount = 0;
670     sal_uInt16 nDashCount = 0;
671     switch ( ePenStyle )
672     {
673         case PEN_NULL :
674             eLineStyle = LINE_NONE;
675         break;
676         case PEN_DASHDOT :
677             nDashCount++;
678         case PEN_DOT :
679             nDotCount++;
680             nDashCount--;
681         case PEN_DASH :
682             nDashCount++;
683             aLineInfo.SetDotCount( nDotCount );
684             aLineInfo.SetDashCount( nDashCount );
685             aLineInfo.SetDistance( nLineWidth );
686             aLineInfo.SetDotLen( nLineWidth );
687             aLineInfo.SetDashLen( nLineWidth << 2 );
688             eLineStyle = LINE_DASH;
689         break;
690         case PEN_SOLID:
691         break;  // -Wall not handled...
692     }
693     aLineInfo.SetStyle( eLineStyle );
694 }
695 
SetRasterOp(RasterOp eROP)696 void OS2METReader::SetRasterOp(RasterOp eROP)
697 {
698     if (pVirDev->GetRasterOp()!=eROP) pVirDev->SetRasterOp(eROP);
699 }
700 
701 
SetPalette0RGB(sal_uInt16 nIndex,sal_uLong nCol)702 void OS2METReader::SetPalette0RGB(sal_uInt16 nIndex, sal_uLong nCol)
703 {
704     if (pPaletteStack==NULL) {
705         pPaletteStack=new OSPalette;
706         pPaletteStack->pSucc=NULL;
707         pPaletteStack->p0RGB=NULL;
708         pPaletteStack->nSize=0;
709     }
710     if (pPaletteStack->p0RGB==NULL || nIndex>=pPaletteStack->nSize) {
711         sal_uInt32 * pOld0RGB=pPaletteStack->p0RGB;
712         sal_uInt16 i,nOldSize=pPaletteStack->nSize;
713         if (pOld0RGB==NULL) nOldSize=0;
714         pPaletteStack->nSize=2*(nIndex+1);
715         if (pPaletteStack->nSize<256) pPaletteStack->nSize=256;
716         pPaletteStack->p0RGB = new sal_uInt32[pPaletteStack->nSize];
717         for (i=0; i<pPaletteStack->nSize; i++) {
718             if (i<nOldSize) pPaletteStack->p0RGB[i]=pOld0RGB[i];
719             else if (i==0) pPaletteStack->p0RGB[i]=0x00ffffff;
720             else pPaletteStack->p0RGB[i]=0;
721         }
722         if (pOld0RGB!=NULL) delete[] pOld0RGB;
723     }
724     pPaletteStack->p0RGB[nIndex]=nCol;
725 }
726 
GetPalette0RGB(sal_uInt32 nIndex)727 sal_uInt32 OS2METReader::GetPalette0RGB(sal_uInt32 nIndex)
728 {
729     if (pPaletteStack!=NULL && pPaletteStack->p0RGB!=NULL &&
730         pPaletteStack->nSize>nIndex) nIndex=pPaletteStack->p0RGB[nIndex];
731     return nIndex;
732 }
733 
GetPaletteColor(sal_uInt32 nIndex)734 Color OS2METReader::GetPaletteColor(sal_uInt32 nIndex)
735 {
736     nIndex=GetPalette0RGB(nIndex);
737     return Color(sal::static_int_cast< sal_uInt8 >((nIndex>>16)&0xff),
738                  sal::static_int_cast< sal_uInt8 >((nIndex>>8)&0xff),
739                  sal::static_int_cast< sal_uInt8 >(nIndex&0xff));
740 }
741 
742 
ReadBigEndianWord()743 sal_uInt16 OS2METReader::ReadBigEndianWord()
744 {
745     sal_uInt8 nLo,nHi;
746     *pOS2MET >> nHi >> nLo;
747     return (((sal_uInt16)nHi)<<8)|(((sal_uInt16)nLo)&0x00ff);
748 }
749 
ReadBigEndian3BytesLong()750 sal_uLong OS2METReader::ReadBigEndian3BytesLong()
751 {
752     sal_uInt16 nLo;
753     sal_uInt8 nHi;
754     *pOS2MET >> nHi;
755     nLo=ReadBigEndianWord();
756     return ((((sal_uLong)nHi)<<16)&0x00ff0000)|((sal_uLong)nLo);
757 }
758 
ReadLittleEndian3BytesLong()759 sal_uLong OS2METReader::ReadLittleEndian3BytesLong()
760 {
761     sal_uInt8 nHi,nMed,nLo;
762 
763     *pOS2MET >> nLo >> nMed >> nHi;
764     return ((((sal_uLong)nHi)&0xff)<<16)|((((sal_uLong)nMed)&0xff)<<8)|(((sal_uLong)nLo)&0xff);
765 }
766 
ReadCoord(sal_Bool b32)767 long OS2METReader::ReadCoord(sal_Bool b32)
768 {
769     long l;
770     short s;
771 
772     if (b32) *pOS2MET >> l;
773     else  { *pOS2MET >> s; l=(long)s; }
774     return l;
775 }
776 
ReadPoint(const sal_Bool bAdjustBoundRect)777 Point OS2METReader::ReadPoint( const sal_Bool bAdjustBoundRect )
778 {
779     long x,y;
780 
781     x=ReadCoord(bCoord32);
782     y=ReadCoord(bCoord32);
783     x=x-aBoundingRect.Left();
784     y=aBoundingRect.Bottom()-y;
785 
786     if ( bAdjustBoundRect )
787         aCalcBndRect.Union(Rectangle(x,y,x+1,y+1));
788 
789     return Point(x,y);
790 }
791 
OS2MixToRasterOp(sal_uInt8 nMix)792 RasterOp OS2METReader::OS2MixToRasterOp(sal_uInt8 nMix)
793 {
794     switch (nMix) {
795         case 0x0c: return ROP_INVERT;
796         case 0x04: return ROP_XOR;
797         case 0x0b: return ROP_XOR;
798         default:   return ROP_OVERPAINT;
799     }
800 }
801 
ReadLine(sal_Bool bGivenPos,sal_uInt16 nOrderLen)802 void OS2METReader::ReadLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
803 {
804     sal_uInt16 i,nPolySize;
805 
806     if (bCoord32) nPolySize=nOrderLen/8; else nPolySize=nOrderLen/4;
807     if (!bGivenPos) nPolySize++;
808     if (nPolySize==0) return;
809     Polygon aPolygon(nPolySize);
810     for (i=0; i<nPolySize; i++) {
811         if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
812         else aPolygon.SetPoint(ReadPoint(),i);
813     }
814     aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
815     if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
816     else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
817     else
818     {
819         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
820         SetRasterOp(aAttr.eLinMix);
821         DrawPolyLine( aPolygon );
822     }
823 }
824 
ReadRelLine(sal_Bool bGivenPos,sal_uInt16 nOrderLen)825 void OS2METReader::ReadRelLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
826 {
827     sal_uInt16 i,nPolySize;
828     Point aP0;
829 
830 
831     if (bGivenPos) {
832         aP0=ReadPoint();
833         if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
834     }
835     else aP0=aAttr.aCurPos;
836     nPolySize=nOrderLen/2;
837     if (nPolySize==0) return;
838     Polygon aPolygon(nPolySize);
839     for (i=0; i<nPolySize; i++) {
840 #if defined SOLARIS && defined PPC
841         sal_uInt8 nunsignedbyte;
842         *pOS2MET >> nunsignedbyte; aP0.X()+=(sal_Int8)nunsignedbyte;
843         *pOS2MET >> nunsignedbyte; aP0.Y()+=(sal_Int8)nunsignedbyte;
844 #else
845         sal_Int8 nsignedbyte;
846         *pOS2MET >> nsignedbyte; aP0.X()+=(long)nsignedbyte;
847         *pOS2MET >> nsignedbyte; aP0.Y()-=(long)nsignedbyte;
848 #endif
849         aCalcBndRect.Union(Rectangle(aP0,Size(1,1)));
850         aPolygon.SetPoint(aP0,i);
851     }
852     aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
853     if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
854     else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
855     else
856     {
857         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
858         SetRasterOp(aAttr.eLinMix);
859         DrawPolyLine( aPolygon );
860     }
861 }
862 
ReadBox(sal_Bool bGivenPos)863 void OS2METReader::ReadBox(sal_Bool bGivenPos)
864 {
865     sal_uInt8       nFlags;
866     Point       P0;
867     long        nHRound,nVRound;
868 
869     *pOS2MET >> nFlags;
870     pOS2MET->SeekRel(1);
871 
872     if ( bGivenPos )
873         P0 = ReadPoint();
874     else
875         P0 = aAttr.aCurPos;
876 
877     aAttr.aCurPos=ReadPoint();
878     nHRound=ReadCoord(bCoord32);
879     nVRound=ReadCoord(bCoord32);
880 
881     Rectangle aBoxRect( P0, aAttr.aCurPos );
882 
883     if ( pAreaStack )
884         AddPointsToArea( Polygon( aBoxRect ) );
885     else if ( pPathStack )
886         AddPointsToPath( Polygon( aBoxRect ) );
887     else
888     {
889         if ( nFlags & 0x20 )
890             SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
891         else
892             SetPen( COL_TRANSPARENT );
893 
894         if ( nFlags & 0x40 )
895         {
896             ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
897             SetRasterOp(aAttr.ePatMix);
898         }
899         else
900         {
901             ChangeBrush( Color( COL_TRANSPARENT ), Color( COL_TRANSPARENT ), sal_False );
902             SetRasterOp(aAttr.eLinMix);
903         }
904 
905         if ( IsLineInfo() )
906         {
907             Polygon aPolygon( aBoxRect, nHRound, nVRound );
908             if ( nFlags & 0x40 )
909             {
910                 pVirDev->Push( PUSH_LINECOLOR );
911                 pVirDev->SetLineColor( COL_TRANSPARENT );
912                 pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
913                 pVirDev->Pop();
914             }
915             pVirDev->DrawPolyLine( aPolygon, aLineInfo );
916         }
917         else
918             pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
919     }
920 }
921 
ReadBitBlt()922 void OS2METReader::ReadBitBlt()
923 {
924     Point aP1,aP2;
925     Size aSize;
926     sal_uInt32 nID;
927     OSBitmap * pB;
928     long nt;
929 
930     pOS2MET->SeekRel(4);
931     *pOS2MET >> nID;
932     pOS2MET->SeekRel(4);
933     aP1=ReadPoint(); aP2=ReadPoint();
934     if (aP1.X() > aP2.X()) { nt=aP1.X(); aP1.X()=aP2.X(); aP2.X()=nt; }
935     if (aP1.Y() > aP2.Y()) { nt=aP1.Y(); aP1.Y()=aP2.Y(); aP2.Y()=nt; }
936     aSize=Size(aP2.X()-aP1.X(),aP2.Y()-aP1.Y());
937 
938     pB=pBitmapList;
939     while (pB!=NULL && pB->nID!=nID) pB=pB->pSucc;
940     if (pB!=NULL) {
941         SetRasterOp(aAttr.ePatMix);
942         pVirDev->DrawBitmap(aP1,aSize,pB->aBitmap);
943     }
944 }
945 
ReadChrStr(sal_Bool bGivenPos,sal_Bool bMove,sal_Bool bExtra,sal_uInt16 nOrderLen)946 void OS2METReader::ReadChrStr(sal_Bool bGivenPos, sal_Bool bMove, sal_Bool bExtra, sal_uInt16 nOrderLen)
947 {
948     Point aP0;
949     sal_uInt16 i, nLen;
950     char * pChr;
951     OSFont * pF;
952     Font aFont;
953     Size aSize;
954 
955     pF = pFontList;
956     while (pF!=NULL && pF->nID!=aAttr.nChrSet) pF=pF->pSucc;
957     if (pF!=NULL)
958         aFont = pF->aFont;
959     aFont.SetColor(aAttr.aChrCol);
960     aFont.SetSize(Size(0,aAttr.aChrCellSize.Height()));
961     if ( aAttr.nChrAng != 0 )
962         aFont.SetOrientation(aAttr.nChrAng);
963 
964     if (bGivenPos)
965         aP0 = ReadPoint();
966     else
967         aP0 = aAttr.aCurPos;
968     if (bExtra)
969     {
970         pOS2MET->SeekRel(2);
971         ReadPoint( sal_False );
972         ReadPoint( sal_False );
973         *pOS2MET >> nLen;
974     }
975     else
976     {
977         if ( !bGivenPos )
978             nLen = nOrderLen;
979         else if ( bCoord32 )
980             nLen = nOrderLen-8;
981         else
982             nLen = nOrderLen-4;
983     }
984     pChr = new char[nLen+1];
985     for (i=0; i<nLen; i++)
986         *pOS2MET >> pChr[i];
987     pChr[nLen] = 0;
988     String aStr( (const sal_Char*)pChr, gsl_getSystemTextEncoding() );
989     SetRasterOp(aAttr.eChrMix);
990     if (pVirDev->GetFont()!=aFont)
991         pVirDev->SetFont(aFont);
992     pVirDev->DrawText(aP0,aStr);
993 
994     aSize = Size( pVirDev->GetTextWidth(aStr), pVirDev->GetTextHeight() );
995     if ( aAttr.nChrAng == 0 )
996     {
997         aCalcBndRect.Union(Rectangle( Point(aP0.X(),aP0.Y()-aSize.Height()),
998                                       Size(aSize.Width(),aSize.Height()*2)));
999         if (bMove)
1000             aAttr.aCurPos = Point( aP0.X() + aSize.Width(), aP0.Y());
1001     }
1002     else
1003     {
1004         Polygon aDummyPoly(4);
1005 
1006         aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() ), 0);                                 // TOP LEFT
1007         aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() - aSize.Height() ), 1);                // BOTTOM LEFT
1008         aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() ), 2);                 // TOP RIGHT
1009         aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() - aSize.Height() ), 3);// BOTTOM RIGHT
1010         aDummyPoly.Rotate( aP0, (short)aAttr.nChrAng );
1011         if ( bMove )
1012             aAttr.aCurPos = aDummyPoly.GetPoint( 0 );
1013         aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 0 ), aDummyPoly.GetPoint( 3 ) ) );
1014         aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 1 ), aDummyPoly.GetPoint( 2 ) ) );
1015     }
1016     delete[] pChr;
1017 }
1018 
ReadArc(sal_Bool bGivenPos)1019 void OS2METReader::ReadArc(sal_Bool bGivenPos)
1020 {
1021     Point aP1, aP2, aP3;
1022     double x1,y1,x2,y2,x3,y3,p,q,cx,cy,ncx,ncy,r,rx,ry,w1,w3;
1023     if (bGivenPos) aP1=ReadPoint(); else aP1=aAttr.aCurPos;
1024     aP2=ReadPoint(); aP3=ReadPoint();
1025     aAttr.aCurPos=aP3;
1026     SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1027     SetRasterOp(aAttr.eLinMix);
1028     // OK, gegeben sind 3 Punkte der Ellipse, und das Verhaeltnis
1029     // Breite zu Hoehe (als p zu q):
1030     x1=aP1.X(); y1=aP1.Y();
1031     x2=aP2.X(); y2=aP2.Y();
1032     x3=aP3.X(); y3=aP3.Y();
1033     p=aAttr.nArcP;q=aAttr.nArcQ;
1034     // Berechnet wird der Mittelpunkt cx,cy der Ellipse:
1035     ncy=2*p*p*((y3-y1)*(x2-x1)-(y1-y2)*(x1-x3));
1036     ncx=2*q*q*(x2-x1);
1037     if ( (ncx<0.001 && ncx>-0.001) || (ncy<0.001 && ncy>-0.001) ) {
1038         // Berechnung nicht moeglich, Punkte liegen auf einer Linie
1039         pVirDev->DrawLine(aP1,aP2);
1040         pVirDev->DrawLine(aP2,aP3);
1041         return;
1042     }
1043     cy=( q*q*((x3*x3-x1*x1)*(x2-x1)+(x2*x2-x1*x1)*(x1-x3)) +
1044          p*p*((y3*y3-y1*y1)*(x2-x1)+(y2*y2-y1*y1)*(x1-x3)) ) / ncy;
1045     cx=( q*q*(x2*x2-x1*x1)+p*p*(y2*y2-y1*y1)+cy*2*p*p*(y1-y2) ) / ncx;
1046     // Nun brauchen wir noch den Radius in x und y Richtung:
1047     r=sqrt(q*q*(x1-cx)*(x1-cx)+p*p*(y1-cy)*(y1-cy));
1048     rx=r/q; ry=r/p;
1049     // Jetzt stellt sich "nur noch" die Frage, wie Start- und Endpunkt
1050     // gewaehlt werden muessen, damit Punkt Nr. 2 innerhalb des
1051     // gezeichneten Bogens liegt:
1052     w1=fmod((atan2(x1-cx,y1-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w1<0) w1+=6.28318530718;
1053     w3=fmod((atan2(x3-cx,y3-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w3<0) w3+=6.28318530718;
1054     if (w3<w1) {
1055         pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
1056                                    (long)(cx+rx),(long)(cy+ry)),aP1,aP3);
1057     }
1058     else {
1059         pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
1060                                    (long)(cx+rx),(long)(cy+ry)),aP3,aP1);
1061     }
1062 }
1063 
ReadFullArc(sal_Bool bGivenPos,sal_uInt16 nOrderSize)1064 void OS2METReader::ReadFullArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize)
1065 {
1066     Point aCenter;
1067     long nP,nQ,nR,nS;
1068     Rectangle aRect;
1069     sal_uInt32 nMul; sal_uInt16 nMulS;
1070 
1071     if (bGivenPos) {
1072         aCenter=ReadPoint();
1073         if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
1074     }
1075     else aCenter=aAttr.aCurPos;
1076 
1077     nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
1078     if (nP<0) nP=-nP;
1079     if (nQ<0) nQ=-nQ;
1080     if (nR<0) nR=-nR;
1081     if (nS<0) nS=-nS;
1082     if (nOrderSize>=4) *pOS2MET >> nMul;
1083     else { *pOS2MET >> nMulS; nMul=((sal_uLong)nMulS)<<8; }
1084     if (nMul!=0x00010000) {
1085         nP=(nP*nMul)>>16;
1086         nQ=(nQ*nMul)>>16;
1087         nR=(nR*nMul)>>16;
1088         nS=(nS*nMul)>>16;
1089     }
1090 
1091     aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
1092                     aCenter.X()+nP,aCenter.Y()+nQ);
1093     aCalcBndRect.Union(aRect);
1094 
1095     if (pAreaStack!=NULL) {
1096         ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
1097         SetRasterOp(aAttr.ePatMix);
1098         if ((pAreaStack->nFlags&0x40)!=0)
1099             SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1100         else
1101             SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1102     }
1103     else
1104     {
1105         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1106         ChangeBrush(Color( COL_TRANSPARENT ),Color( COL_TRANSPARENT ),sal_False);
1107         SetRasterOp(aAttr.eLinMix);
1108     }
1109     pVirDev->DrawEllipse(aRect);
1110 }
1111 
ReadPartialArc(sal_Bool bGivenPos,sal_uInt16 nOrderSize)1112 void OS2METReader::ReadPartialArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize)
1113 {
1114     Point aP0, aCenter,aPStart,aPEnd;
1115     long nP,nQ,nR,nS,nStart, nSweep;
1116     Rectangle aRect;
1117     sal_uInt32 nMul; sal_uInt16 nMulS;
1118     double fStart, fEnd;
1119 
1120     if (bGivenPos) {
1121         aP0=ReadPoint();
1122         if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
1123     }
1124     else aP0=aAttr.aCurPos;
1125     aCenter=ReadPoint();
1126 
1127     nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
1128     if (nP<0) nP=-nP;
1129     if (nQ<0) nQ=-nQ;
1130     if (nR<0) nR=-nR;
1131     if (nS<0) nS=-nS;
1132     if (nOrderSize>=12) *pOS2MET >> nMul;
1133     else { *pOS2MET >> nMulS; nMul=((sal_uLong)nMulS)<<8; }
1134     if (nMul!=0x00010000) {
1135         nP=(nP*nMul)>>16;
1136         nQ=(nQ*nMul)>>16;
1137         nR=(nR*nMul)>>16;
1138         nS=(nS*nMul)>>16;
1139     }
1140 
1141     *pOS2MET >> nStart >> nSweep;
1142     fStart=((double)nStart)/65536.0/180.0*3.14159265359;
1143     fEnd=fStart+((double)nSweep)/65536.0/180.0*3.14159265359;
1144     aPStart=Point(aCenter.X()+(long)( cos(fStart)*nP),
1145                   aCenter.Y()+(long)(-sin(fStart)*nQ));
1146     aPEnd=  Point(aCenter.X()+(long)( cos(fEnd)*nP),
1147                   aCenter.Y()+(long)(-sin(fEnd)*nQ));
1148 
1149     aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
1150                     aCenter.X()+nP,aCenter.Y()+nQ);
1151     aCalcBndRect.Union(aRect);
1152 
1153     SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1154     SetRasterOp(aAttr.eLinMix);
1155 
1156     pVirDev->DrawLine(aP0,aPStart);
1157     pVirDev->DrawArc(aRect,aPStart,aPEnd);
1158     aAttr.aCurPos=aPEnd;
1159 }
1160 
ReadPolygons()1161 void OS2METReader::ReadPolygons()
1162 {
1163     sal_uInt32 i,j,nNumPolys, nNumPoints;
1164     PolyPolygon aPolyPoly;
1165     Polygon aPoly;
1166     Point aPoint;
1167     sal_uInt8 nFlags;
1168 
1169     *pOS2MET >> nFlags >> nNumPolys;
1170     for (i=0; i<nNumPolys; i++) {
1171         *pOS2MET >> nNumPoints;
1172         if (i==0) nNumPoints++;
1173         aPoly.SetSize((short)nNumPoints);
1174         for (j=0; j<nNumPoints; j++) {
1175             if (i==0 && j==0) aPoint=aAttr.aCurPos;
1176             else aPoint=ReadPoint();
1177             aPoly.SetPoint(aPoint,(short)j);
1178             if (i==nNumPolys-1 && j==nNumPoints-1) aAttr.aCurPos=aPoint;
1179         }
1180         aPolyPoly.Insert(aPoly);
1181     }
1182 
1183     ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
1184     SetRasterOp(aAttr.ePatMix);
1185     if ((nFlags&0x01)!=0)
1186         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1187     else
1188         SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1189     DrawPolyPolygon( aPolyPoly );
1190 }
1191 
ReadBezier(sal_Bool bGivenPos,sal_uInt16 nOrderLen)1192 void OS2METReader::ReadBezier(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1193 {
1194     sal_uInt16 i, nNumPoints = nOrderLen / ( bCoord32 ? 8 : 4 );
1195 
1196     if( !bGivenPos )
1197         nNumPoints++;
1198 
1199     if( !nNumPoints )
1200         return;
1201 
1202     Polygon aPolygon( nNumPoints );
1203 
1204     for( i=0; i < nNumPoints; i++ )
1205     {
1206         if( i==0 && !bGivenPos)
1207             aPolygon.SetPoint( aAttr.aCurPos, i );
1208         else
1209             aPolygon.SetPoint( ReadPoint(), i );
1210     }
1211 
1212     if( !( nNumPoints % 4 ) )
1213     {
1214         // create bezier polygon
1215         const sal_uInt16    nSegPoints = 25;
1216         const sal_uInt16    nSegments = aPolygon.GetSize() >> 2;
1217         Polygon         aBezPoly( nSegments * nSegPoints );
1218 
1219         sal_uInt16 nSeg, nBezPos, nStartPos;
1220         for( nSeg = 0, nBezPos = 0, nStartPos = 0; nSeg < nSegments; nSeg++, nStartPos += 4 )
1221         {
1222             const Polygon aSegPoly( aPolygon[ nStartPos ], aPolygon[ nStartPos + 1 ],
1223                                     aPolygon[ nStartPos + 3 ], aPolygon[ nStartPos + 2 ],
1224                                     nSegPoints );
1225 
1226             for( sal_uInt16 nSegPos = 0; nSegPos < nSegPoints; )
1227                 aBezPoly[ nBezPos++ ] = aSegPoly[ nSegPos++ ];
1228         }
1229 
1230         nNumPoints = nBezPos;
1231 
1232         if( nNumPoints != aBezPoly.GetSize() )
1233             aBezPoly.SetSize( nNumPoints );
1234 
1235         aPolygon = aBezPoly;
1236     }
1237 
1238     aAttr.aCurPos = aPolygon[ nNumPoints - 1 ];
1239 
1240     if (pAreaStack!=NULL)
1241         AddPointsToArea(aPolygon);
1242     else if (pPathStack!=NULL)
1243         AddPointsToPath(aPolygon);
1244     else
1245     {
1246         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1247         SetRasterOp(aAttr.eLinMix);
1248         DrawPolyLine( aPolygon );
1249     }
1250 }
1251 
ReadFillet(sal_Bool bGivenPos,sal_uInt16 nOrderLen)1252 void OS2METReader::ReadFillet(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1253 {
1254     sal_uInt16 i,nNumPoints;
1255 
1256     if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
1257     if (!bGivenPos) nNumPoints++;
1258     if (nNumPoints==0) return;
1259     Polygon aPolygon(nNumPoints);
1260     for (i=0; i<nNumPoints; i++) {
1261         if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
1262         else aPolygon.SetPoint(ReadPoint(),i);
1263     }
1264     aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
1265     if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
1266     else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
1267     else {
1268         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1269         SetRasterOp(aAttr.eLinMix);
1270         DrawPolyLine( aPolygon );
1271     }
1272 }
1273 
ReadFilletSharp(sal_Bool bGivenPos,sal_uInt16 nOrderLen)1274 void OS2METReader::ReadFilletSharp(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1275 {
1276     sal_uInt16 i,nNumPoints;
1277 
1278     if (bGivenPos) {
1279         aAttr.aCurPos=ReadPoint();
1280         if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
1281     }
1282     if (bCoord32) nNumPoints=1+nOrderLen/10;
1283     else nNumPoints=1+nOrderLen/6;
1284     Polygon aPolygon(nNumPoints);
1285     aPolygon.SetPoint(aAttr.aCurPos,0);
1286     for (i=1; i<nNumPoints; i++) aPolygon.SetPoint(ReadPoint(),i);
1287     aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
1288     if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
1289     else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
1290     else
1291     {
1292         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1293         SetRasterOp(aAttr.eLinMix);
1294         DrawPolyLine( aPolygon );
1295     }
1296 }
1297 
ReadMarker(sal_Bool bGivenPos,sal_uInt16 nOrderLen)1298 void OS2METReader::ReadMarker(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1299 {
1300     sal_uInt16 i,nNumPoints;
1301     long x,y;
1302 
1303     SetPen( aAttr.aMrkCol );
1304     SetRasterOp(aAttr.eMrkMix);
1305     if (aAttr.nMrkSymbol>=5 && aAttr.nMrkSymbol<=9)
1306     {
1307         ChangeBrush(aAttr.aMrkCol,aAttr.aMrkCol,sal_True);
1308     }
1309     else
1310     {
1311         ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1312     }
1313     if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
1314     if (!bGivenPos) nNumPoints++;
1315     for (i=0; i<nNumPoints; i++) {
1316         if (i!=0 || bGivenPos) aAttr.aCurPos=ReadPoint();
1317         x=aAttr.aCurPos.X(); y=aAttr.aCurPos.Y();
1318         aCalcBndRect.Union(Rectangle(x-5,y-5,x+5,y+5));
1319         switch (aAttr.nMrkSymbol) {
1320             case  2:   // PLUS
1321                 pVirDev->DrawLine(Point(x-4,y),Point(x+4,y));
1322                 pVirDev->DrawLine(Point(x,y-4),Point(x,y+4));
1323                 break;
1324             case  3:   // DIAMOND
1325             case  7: { // SOLIDDIAMOND
1326                 Polygon aPoly(4);
1327                 aPoly.SetPoint(Point(x,y+4),0);
1328                 aPoly.SetPoint(Point(x+4,y),1);
1329                 aPoly.SetPoint(Point(x,y-4),2);
1330                 aPoly.SetPoint(Point(x-4,y),3);
1331                 pVirDev->DrawPolygon(aPoly);
1332                 break;
1333             }
1334             case  4:   // SQARE
1335             case  8: { // SOLIDSUARE
1336                 Polygon aPoly(4);
1337                 aPoly.SetPoint(Point(x+4,y+4),0);
1338                 aPoly.SetPoint(Point(x+4,y-4),1);
1339                 aPoly.SetPoint(Point(x-4,y-4),2);
1340                 aPoly.SetPoint(Point(x-4,y+4),3);
1341                 pVirDev->DrawPolygon(aPoly);
1342                 break;
1343             }
1344             case  5: { // SIXPOINTSTAR
1345                 Polygon aPoly(12);
1346                 aPoly.SetPoint(Point(x  ,y-4),0);
1347                 aPoly.SetPoint(Point(x+2,y-2),1);
1348                 aPoly.SetPoint(Point(x+4,y-2),2);
1349                 aPoly.SetPoint(Point(x+2,y  ),3);
1350                 aPoly.SetPoint(Point(x+4,y+2),4);
1351                 aPoly.SetPoint(Point(x+2,y+2),5);
1352                 aPoly.SetPoint(Point(x  ,y+4),6);
1353                 aPoly.SetPoint(Point(x-2,y+2),7);
1354                 aPoly.SetPoint(Point(x-4,y+2),8);
1355                 aPoly.SetPoint(Point(x-2,y  ),9);
1356                 aPoly.SetPoint(Point(x-4,y-2),10);
1357                 aPoly.SetPoint(Point(x-2,y-2),11);
1358                 pVirDev->DrawPolygon(aPoly);
1359                 break;
1360             }
1361             case  6: { // EIGHTPOINTSTAR
1362                 Polygon aPoly(16);
1363                 aPoly.SetPoint(Point(x  ,y-4),0);
1364                 aPoly.SetPoint(Point(x+1,y-2),1);
1365                 aPoly.SetPoint(Point(x+3,y-3),2);
1366                 aPoly.SetPoint(Point(x+2,y-1),3);
1367                 aPoly.SetPoint(Point(x+4,y  ),4);
1368                 aPoly.SetPoint(Point(x+2,y+1),5);
1369                 aPoly.SetPoint(Point(x+3,y+3),6);
1370                 aPoly.SetPoint(Point(x+1,y+2),7);
1371                 aPoly.SetPoint(Point(x  ,y+4),8);
1372                 aPoly.SetPoint(Point(x-1,y+2),9);
1373                 aPoly.SetPoint(Point(x-3,y+3),10);
1374                 aPoly.SetPoint(Point(x-2,y+1),11);
1375                 aPoly.SetPoint(Point(x-4,y  ),12);
1376                 aPoly.SetPoint(Point(x-2,y-1),13);
1377                 aPoly.SetPoint(Point(x-3,y-3),14);
1378                 aPoly.SetPoint(Point(x-1,y-2),15);
1379                 pVirDev->DrawPolygon(aPoly);
1380                 break;
1381             }
1382             case  9:   // DOT
1383                 pVirDev->DrawEllipse(Rectangle(x-1,y-1,x+1,y+1));
1384                 break;
1385             case 10:   // SMALLCIRCLE
1386                 pVirDev->DrawEllipse(Rectangle(x-2,y-2,x+2,y+2));
1387                 break;
1388             case 64:   // BLANK
1389                 break;
1390             default:   // (=1) CROSS
1391                 pVirDev->DrawLine(Point(x-4,y-4),Point(x+4,y+4));
1392                 pVirDev->DrawLine(Point(x-4,y+4),Point(x+4,y-4));
1393                 break;
1394         }
1395     }
1396 }
1397 
ReadOrder(sal_uInt16 nOrderID,sal_uInt16 nOrderLen)1398 void OS2METReader::ReadOrder(sal_uInt16 nOrderID, sal_uInt16 nOrderLen)
1399 {
1400     switch (nOrderID) {
1401 
1402         case GOrdGivArc: ReadArc(sal_True); break;
1403         case GOrdCurArc: ReadArc(sal_False); break;
1404 
1405         case GOrdGivBzr: ReadBezier(sal_True,nOrderLen); break;
1406         case GOrdCurBzr: ReadBezier(sal_False,nOrderLen); break;
1407 
1408         case GOrdGivBox: ReadBox(sal_True); break;
1409         case GOrdCurBox: ReadBox(sal_False); break;
1410 
1411         case GOrdGivFil: ReadFillet(sal_True,nOrderLen); break;
1412         case GOrdCurFil: ReadFillet(sal_False,nOrderLen); break;
1413 
1414         case GOrdGivCrc: ReadFullArc(sal_True,nOrderLen); break;
1415         case GOrdCurCrc: ReadFullArc(sal_False,nOrderLen); break;
1416 
1417         case GOrdGivLin: ReadLine(sal_True, nOrderLen); break;
1418         case GOrdCurLin: ReadLine(sal_False, nOrderLen); break;
1419 
1420         case GOrdGivMrk: ReadMarker(sal_True, nOrderLen); break;
1421         case GOrdCurMrk: ReadMarker(sal_False, nOrderLen); break;
1422 
1423         case GOrdGivArP: ReadPartialArc(sal_True,nOrderLen); break;
1424         case GOrdCurArP: ReadPartialArc(sal_False,nOrderLen); break;
1425 
1426         case GOrdGivRLn: ReadRelLine(sal_True,nOrderLen); break;
1427         case GOrdCurRLn: ReadRelLine(sal_False,nOrderLen); break;
1428 
1429         case GOrdGivSFl: ReadFilletSharp(sal_True,nOrderLen); break;
1430         case GOrdCurSFl: ReadFilletSharp(sal_False,nOrderLen); break;
1431 
1432         case GOrdGivStM: ReadChrStr(sal_True , sal_True , sal_False, nOrderLen); break;
1433         case GOrdCurStM: ReadChrStr(sal_False, sal_True , sal_False, nOrderLen); break;
1434         case GOrdGivStr: ReadChrStr(sal_True , sal_False, sal_False, nOrderLen); break;
1435         case GOrdCurStr: ReadChrStr(sal_False, sal_False, sal_False, nOrderLen); break;
1436         case GOrdGivStx: ReadChrStr(sal_True , sal_False, sal_True , nOrderLen); break;
1437         case GOrdCurStx: ReadChrStr(sal_False, sal_False, sal_True , nOrderLen); break;
1438 
1439         case GOrdGivImg: OOODEBUG("GOrdGivImg",0);
1440             break;
1441         case GOrdCurImg: OOODEBUG("GOrdCurImg",0);
1442             break;
1443         case GOrdImgDat: OOODEBUG("GOrdImgDat",0);
1444             break;
1445         case GOrdEndImg: OOODEBUG("GOrdEndImg",0);
1446             break;
1447 
1448         case GOrdBegAra: {
1449             OSArea * p=new OSArea;
1450             p->bClosed=sal_False;
1451             p->pSucc=pAreaStack; pAreaStack=p;
1452             *pOS2MET >> (p->nFlags);
1453             p->aCol=aAttr.aPatCol;
1454             p->aBgCol=aAttr.aPatBgCol;
1455             p->eMix=aAttr.ePatMix;
1456             p->eBgMix=aAttr.ePatBgMix;
1457             p->bFill=aAttr.bFill;
1458             break;
1459         }
1460         case GOrdEndAra:
1461         {
1462             OSArea * p=pAreaStack;
1463             if ( p )
1464             {
1465                 pAreaStack = p->pSucc;
1466                 if ( pPathStack )
1467                 {
1468                     for ( sal_uInt16 i=0; i<p->aPPoly.Count(); i++ )
1469                     {
1470                         AddPointsToPath( p->aPPoly.GetObject( i ) );
1471                         CloseFigure();
1472                     }
1473                 }
1474                 else
1475                 {
1476                     if ( ( p->nFlags & 0x40 ) == 0 )
1477                         SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1478                     else
1479                         SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1480 
1481                     ChangeBrush(p->aCol,p->aBgCol,p->bFill);
1482                     SetRasterOp(p->eMix);
1483                     DrawPolyPolygon( p->aPPoly );
1484                 }
1485                 delete p;
1486             }
1487         }
1488         break;
1489 
1490         case GOrdBegElm:// OOODEBUG("GOrdBegElm",0);
1491             break;
1492         case GOrdEndElm:// OOODEBUG("GOrdEndElm",0);
1493             break;
1494 
1495         case GOrdBegPth: {
1496             OSPath * p=new OSPath;
1497             p->pSucc=pPathStack; pPathStack=p;
1498             pOS2MET->SeekRel(2);
1499             *pOS2MET >> p->nID;
1500             p->bClosed=sal_False;
1501             p->bStroke=sal_False;
1502             break;
1503         }
1504         case GOrdEndPth: {
1505             OSPath * p, * pprev, * psucc;
1506             if (pPathStack==NULL) break;
1507             p=pPathList; pprev=NULL;
1508             while (p!=NULL) {
1509                 psucc=p->pSucc;
1510                 if (p->nID==pPathStack->nID) {
1511                     if (pprev==NULL) pPathList=psucc; else pprev->pSucc=psucc;
1512                     delete p;
1513                 }
1514                 else pprev=p;
1515                 p=psucc;
1516             }
1517             p=pPathStack;
1518             pPathStack=p->pSucc;
1519             p->pSucc=pPathList; pPathList=p;
1520             break;
1521         }
1522         case GOrdFilPth:
1523         {
1524             sal_uInt32 nID;
1525             sal_uInt16  nDummy;
1526             OSPath* p = pPathList;
1527 
1528             *pOS2MET >> nDummy
1529                      >> nID;
1530 
1531             if ( ! ( nDummy & 0x20 ) )  // #30933# i do not know the exact meaning of this bit,
1532             {                           // but if set it seems to be better not to fill this path
1533                 while( p && p->nID != nID )
1534                     p = p->pSucc;
1535 
1536                 if( p )
1537                 {
1538                     if( p->bStroke )
1539                     {
1540                         SetPen( aAttr.aPatCol, aAttr.nStrLinWidth, PEN_SOLID );
1541                         ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1542                         SetRasterOp( aAttr.ePatMix );
1543                         if ( IsLineInfo() )
1544                         {
1545                             for ( sal_uInt16 i = 0; i < p->aPPoly.Count(); i++ )
1546                                 pVirDev->DrawPolyLine( p->aPPoly.GetObject( i ), aLineInfo );
1547                         }
1548                         else
1549                             pVirDev->DrawPolyPolygon( p->aPPoly );
1550                     }
1551                     else
1552                     {
1553                         SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1554                         ChangeBrush( aAttr.aPatCol, aAttr.aPatBgCol, aAttr.bFill );
1555                         SetRasterOp( aAttr.ePatMix );
1556                         pVirDev->DrawPolyPolygon( p->aPPoly );
1557                     }
1558                 }
1559             }
1560         }
1561         break;
1562 
1563         case GOrdModPth:
1564         {
1565             OSPath* p = pPathList;
1566 
1567             while( p && p->nID != 1 )
1568                 p = p->pSucc;
1569 
1570             if( p )
1571                 p->bStroke = sal_True;
1572         }
1573         break;
1574 
1575         case GOrdOutPth:
1576         {
1577             sal_uInt32 nID;
1578             sal_uInt16  i,nC;
1579             OSPath* p=pPathList;
1580             pOS2MET->SeekRel(2);
1581             *pOS2MET >> nID;
1582             while (p!=NULL && p->nID!=nID)
1583                 p=p->pSucc;
1584 
1585             if( p!=NULL )
1586             {
1587                 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1588                 SetRasterOp(aAttr.eLinMix);
1589                 ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1590                 nC=p->aPPoly.Count();
1591                 for (i=0; i<nC; i++)
1592                 {
1593                     if (i+1<nC || p->bClosed==sal_True)
1594                         DrawPolygon( p->aPPoly.GetObject( i ) );
1595                     else
1596                         DrawPolyLine( p->aPPoly.GetObject( i ) );
1597                 }
1598             }
1599             break;
1600         }
1601         case GOrdSClPth: {  OOODEBUG("GOrdSClPth",0);
1602             sal_uInt32 nID;
1603             OSPath * p=pPathList;
1604             pOS2MET->SeekRel(2);
1605             *pOS2MET >> nID;
1606             if (nID==0) p=NULL;
1607             while (p!=NULL && p->nID!=nID) p=p->pSucc;
1608             if (p!=NULL) pVirDev->SetClipRegion(Region(p->aPPoly));
1609             else pVirDev->SetClipRegion();
1610             break;
1611         }
1612         case GOrdNopNop:
1613             break;
1614         case GOrdRemark: //OOODEBUG("GOrdRemark",0);
1615             break;
1616         case GOrdSegLab: OOODEBUG("GOrdSegLab",0);
1617             break;
1618 
1619         case GOrdBitBlt: ReadBitBlt(); break;
1620 
1621         case GOrdCalSeg: OOODEBUG("GOrdCalSeg",0);
1622             break;
1623         case GOrdSSgBnd: OOODEBUG("GOrdSSgBnd",0);
1624             break;
1625         case GOrdSegChr: OOODEBUG("GOrdSegChr",0);
1626             break;
1627         case GOrdCloFig:
1628             CloseFigure();
1629             break;
1630         case GOrdEndSym: OOODEBUG("GOrdEndSym",0);
1631             break;
1632         case GOrdEndPlg: OOODEBUG("GOrdEndPlg",0);
1633             break;
1634         case GOrdEscape: OOODEBUG("GOrdEscape",0);
1635             break;
1636         case GOrdExtEsc: OOODEBUG("GOrdExtEsc",0);
1637             break;
1638 
1639         case GOrdPolygn: ReadPolygons(); break;
1640 
1641         case GOrdStkPop: PopAttr(); break;
1642 
1643         case GOrdPIvAtr: PushAttr(nOrderID);
1644         case GOrdSIvAtr: {
1645             sal_uInt8 nA, nP, nFlags, nMix;
1646             sal_uLong nVal;
1647             Color aCol;
1648             RasterOp eROP;
1649             *pOS2MET >> nA >> nP >> nFlags;
1650             if (nOrderID==GOrdPIvAtr) {
1651                 pAttrStack->nIvAttrA=nA;
1652                 pAttrStack->nIvAttrP=nP;
1653             }
1654             if (nA<=2) {
1655                 if ((nFlags&0x80)!=0) {
1656                     if (nA==1) switch (nP) {
1657                         case 1: aAttr.aLinCol=aDefAttr.aLinCol; break;
1658                         case 2: aAttr.aChrCol=aDefAttr.aChrCol; break;
1659                         case 3: aAttr.aMrkCol=aDefAttr.aMrkCol; break;
1660                         case 4: aAttr.aPatCol=aDefAttr.aPatCol; break;
1661                         case 5: aAttr.aImgCol=aDefAttr.aImgCol; break;
1662                     }
1663                     else switch (nP) {
1664                         case 1: aAttr.aLinBgCol=aDefAttr.aLinBgCol; break;
1665                         case 2: aAttr.aChrBgCol=aDefAttr.aChrBgCol; break;
1666                         case 3: aAttr.aMrkBgCol=aDefAttr.aMrkBgCol; break;
1667                         case 4: aAttr.aPatBgCol=aDefAttr.aPatBgCol; break;
1668                         case 5: aAttr.aImgBgCol=aDefAttr.aImgBgCol; break;
1669                     }
1670                 }
1671                 else {
1672                     nVal=ReadLittleEndian3BytesLong();
1673                     if      ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1674                     else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1675                     else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1676                     else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1677                     else aCol=GetPaletteColor(nVal);
1678                     if (nA==1) switch (nP) {
1679                         case 1: aAttr.aLinCol=aCol; break;
1680                         case 2: aAttr.aChrCol=aCol; break;
1681                         case 3: aAttr.aMrkCol=aCol; break;
1682                         case 4: aAttr.aPatCol=aCol; break;
1683                         case 5: aAttr.aImgCol=aCol; break;
1684                     }
1685                     else switch (nP) {
1686                         case 1: aAttr.aLinBgCol=aCol; break;
1687                         case 2: aAttr.aChrBgCol=aCol; break;
1688                         case 3: aAttr.aMrkBgCol=aCol; break;
1689                         case 4: aAttr.aPatBgCol=aCol; break;
1690                         case 5: aAttr.aImgBgCol=aCol; break;
1691                     }
1692                 }
1693             }
1694             else {
1695                 *pOS2MET >> nMix;
1696                 if (nMix==0) {
1697                     if (nA==1) switch (nP) {
1698                         case 1: aAttr.eLinMix=aDefAttr.eLinMix; break;
1699                         case 2: aAttr.eChrMix=aDefAttr.eChrMix; break;
1700                         case 3: aAttr.eMrkMix=aDefAttr.eMrkMix; break;
1701                         case 4: aAttr.ePatMix=aDefAttr.ePatMix; break;
1702                         case 5: aAttr.eImgMix=aDefAttr.eImgMix; break;
1703                     }
1704                     else switch (nP) {
1705                         case 1: aAttr.eLinBgMix=aDefAttr.eLinBgMix; break;
1706                         case 2: aAttr.eChrBgMix=aDefAttr.eChrBgMix; break;
1707                         case 3: aAttr.eMrkBgMix=aDefAttr.eMrkBgMix; break;
1708                         case 4: aAttr.ePatBgMix=aDefAttr.ePatBgMix; break;
1709                         case 5: aAttr.eImgBgMix=aDefAttr.eImgBgMix; break;
1710                     }
1711                 }
1712                 else {
1713                     eROP=OS2MixToRasterOp(nMix);
1714                     if (nA==1) switch (nP) {
1715                         case 1: aAttr.eLinMix=eROP; break;
1716                         case 2: aAttr.eChrMix=eROP; break;
1717                         case 3: aAttr.eMrkMix=eROP; break;
1718                         case 4: aAttr.ePatMix=eROP; break;
1719                         case 5: aAttr.eImgMix=eROP; break;
1720                     }
1721                     else switch (nP) {
1722                         case 1: aAttr.eLinBgMix=eROP; break;
1723                         case 2: aAttr.eChrBgMix=eROP; break;
1724                         case 3: aAttr.eMrkBgMix=eROP; break;
1725                         case 4: aAttr.ePatBgMix=eROP; break;
1726                         case 5: aAttr.eImgBgMix=eROP; break;
1727                     }
1728                 }
1729             }
1730             break;
1731         }
1732         case GOrdPIxCol: PushAttr(nOrderID);
1733         case GOrdSIxCol: {
1734             sal_uInt8 nFlags;
1735             sal_uLong nVal;
1736             Color aCol;
1737             *pOS2MET >> nFlags;
1738             if ((nFlags&0x80)!=0) {
1739                 aAttr.aLinCol=aDefAttr.aLinCol;
1740                 aAttr.aChrCol=aDefAttr.aChrCol;
1741                 aAttr.aMrkCol=aDefAttr.aMrkCol;
1742                 aAttr.aPatCol=aDefAttr.aPatCol;
1743                 aAttr.aImgCol=aDefAttr.aImgCol;
1744             }
1745             else {
1746                 nVal=ReadLittleEndian3BytesLong();
1747                 if      ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1748                 else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1749                 else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1750                 else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1751                 else aCol=GetPaletteColor(nVal);
1752                 aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
1753                 aAttr.aImgCol = aCol;
1754             }
1755             break;
1756         }
1757 
1758         case GOrdPColor:
1759         case GOrdPXtCol: PushAttr(nOrderID);
1760         case GOrdSColor:
1761         case GOrdSXtCol: {
1762             sal_uInt8 nbyte;
1763             sal_uInt16 nVal;
1764             Color aCol;
1765             if (nOrderID==GOrdPColor || nOrderID==GOrdSColor) {
1766                 *pOS2MET >> nbyte; nVal=((sal_uInt16)nbyte)|0xff00;
1767             }
1768             else *pOS2MET >> nVal;
1769             if (nVal==0x0000 || nVal==0xff00)  {
1770                 aAttr.aLinCol=aDefAttr.aLinCol;
1771                 aAttr.aChrCol=aDefAttr.aChrCol;
1772                 aAttr.aMrkCol=aDefAttr.aMrkCol;
1773                 aAttr.aPatCol=aDefAttr.aPatCol;
1774                 aAttr.aImgCol=aDefAttr.aImgCol;
1775             }
1776             else {
1777                 if      (nVal==0x0007) aCol=Color(COL_WHITE);
1778                 else if (nVal==0x0008) aCol=Color(COL_BLACK);
1779                 else if (nVal==0xff08) aCol=GetPaletteColor(1);
1780                 else aCol=GetPaletteColor(((sal_uLong)nVal) & 0x000000ff);
1781                 aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
1782                 aAttr.aImgCol = aCol;
1783             }
1784             break;
1785         }
1786 
1787         case GOrdPBgCol: PushAttr(nOrderID);
1788         case GOrdSBgCol: {
1789             sal_uInt16 nVal;
1790             Color aCol;
1791             *pOS2MET >> nVal;
1792             if (nVal==0x0000 || nVal==0xff00)  {
1793                 aAttr.aLinBgCol=aDefAttr.aLinBgCol;
1794                 aAttr.aChrBgCol=aDefAttr.aChrBgCol;
1795                 aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
1796                 aAttr.aPatBgCol=aDefAttr.aPatBgCol;
1797                 aAttr.aImgBgCol=aDefAttr.aImgBgCol;
1798             }
1799             else {
1800                 if      (nVal==0x0007) aCol=Color(COL_WHITE);
1801                 else if (nVal==0x0008) aCol=Color(COL_BLACK);
1802                 else if (nVal==0xff08) aCol=GetPaletteColor(0);
1803                 else aCol=GetPaletteColor(((sal_uLong)nVal) & 0x000000ff);
1804                 aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
1805                 aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
1806             }
1807             break;
1808         }
1809         case GOrdPBxCol: PushAttr(nOrderID);
1810         case GOrdSBxCol: {
1811             sal_uInt8 nFlags;
1812             sal_uLong nVal;
1813             Color aCol;
1814             *pOS2MET >> nFlags;
1815             if ((nFlags&0x80)!=0) {
1816                 aAttr.aLinBgCol=aDefAttr.aLinBgCol;
1817                 aAttr.aChrBgCol=aDefAttr.aChrBgCol;
1818                 aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
1819                 aAttr.aPatBgCol=aDefAttr.aPatBgCol;
1820                 aAttr.aImgBgCol=aDefAttr.aImgBgCol;
1821             }
1822             else {
1823                 nVal=ReadLittleEndian3BytesLong();
1824                 if      ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1825                 else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1826                 else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1827                 else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1828                 else aCol=GetPaletteColor(nVal);
1829                 aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
1830                 aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
1831             }
1832             break;
1833         }
1834 
1835         case GOrdPMixMd: PushAttr(nOrderID);
1836         case GOrdSMixMd: {
1837             sal_uInt8 nMix;
1838             *pOS2MET >> nMix;
1839             if (nMix==0) {
1840                 aAttr.eLinMix=aDefAttr.eLinMix;
1841                 aAttr.eChrMix=aDefAttr.eChrMix;
1842                 aAttr.eMrkMix=aDefAttr.eMrkMix;
1843                 aAttr.ePatMix=aDefAttr.ePatMix;
1844                 aAttr.eImgMix=aDefAttr.eImgMix;
1845             }
1846             else {
1847                 aAttr.eLinMix = aAttr.eChrMix = aAttr.eMrkMix =
1848                 aAttr.ePatMix = aAttr.eImgMix = OS2MixToRasterOp(nMix);
1849             }
1850             break;
1851         }
1852         case GOrdPBgMix: PushAttr(nOrderID);
1853         case GOrdSBgMix: {
1854             sal_uInt8 nMix;
1855             *pOS2MET >> nMix;
1856             if (nMix==0) {
1857                 aAttr.eLinBgMix=aDefAttr.eLinBgMix;
1858                 aAttr.eChrBgMix=aDefAttr.eChrBgMix;
1859                 aAttr.eMrkBgMix=aDefAttr.eMrkBgMix;
1860                 aAttr.ePatBgMix=aDefAttr.ePatBgMix;
1861                 aAttr.eImgBgMix=aDefAttr.eImgBgMix;
1862             }
1863             else {
1864                 aAttr.eLinBgMix = aAttr.eChrBgMix = aAttr.eMrkBgMix =
1865                 aAttr.ePatBgMix = aAttr.eImgBgMix = OS2MixToRasterOp(nMix);
1866             }
1867             break;
1868         }
1869         case GOrdPPtSet: PushAttr(nOrderID);
1870         case GOrdSPtSet: OOODEBUG("GOrdSPtSet",0);
1871             break;
1872 
1873         case GOrdPPtSym: PushAttr(nOrderID);
1874         case GOrdSPtSym: {
1875             sal_uInt8 nPatt;
1876             *pOS2MET >> nPatt;
1877             aAttr.bFill = ( nPatt != 0x0f );
1878             break;
1879         }
1880 
1881         case GOrdPPtRef: PushAttr(nOrderID);
1882         case GOrdSPtRef: OOODEBUG("GOrdSPtRef",0);
1883             break;
1884 
1885         case GOrdPLnEnd: PushAttr(nOrderID);
1886         case GOrdSLnEnd:
1887             break;
1888 
1889         case GOrdPLnJoi: PushAttr(nOrderID);
1890         case GOrdSLnJoi:
1891             break;
1892 
1893         case GOrdPLnTyp: PushAttr(nOrderID);
1894         case GOrdSLnTyp: {
1895             sal_uInt8 nType;
1896             *pOS2MET >> nType;
1897             switch (nType) {
1898                 case 0:         aAttr.eLinStyle=aDefAttr.eLinStyle; break;
1899                 case 1: case 4: aAttr.eLinStyle=PEN_DOT; break;
1900                 case 2: case 5: aAttr.eLinStyle=PEN_DASH; break;
1901                 case 3: case 6: aAttr.eLinStyle=PEN_DASHDOT; break;
1902                 case 8:         aAttr.eLinStyle=PEN_NULL; break;
1903                 default:        aAttr.eLinStyle=PEN_SOLID;
1904             }
1905             break;
1906         }
1907         case GOrdPLnWdt: PushAttr(nOrderID);
1908         case GOrdSLnWdt: {
1909             sal_uInt8 nbyte;
1910             *pOS2MET >> nbyte;
1911             if (nbyte==0) aAttr.nLinWidth=aDefAttr.nLinWidth;
1912             else aAttr.nLinWidth=(sal_uInt16)nbyte-1;
1913             break;
1914         }
1915         case GOrdPFrLWd: PushAttr(nOrderID);
1916         case GOrdSFrLWd:
1917             break;
1918 
1919         case GOrdPStLWd: PushAttr(nOrderID);
1920         case GOrdSStLWd :
1921         {
1922             sal_uInt8 nFlags;
1923             long nWd;
1924 
1925             *pOS2MET >> nFlags;
1926             if ( nFlags & 0x80 )
1927                 aAttr.nStrLinWidth = aDefAttr.nStrLinWidth;
1928             else
1929             {
1930                 pOS2MET->SeekRel( 1 );
1931                 nWd = ReadCoord( bCoord32 );
1932                 if ( nWd < 0 )
1933                     nWd = -nWd;
1934                 aAttr.nStrLinWidth = (sal_uInt16)nWd;
1935             }
1936             break;
1937         }
1938         case GOrdPChDir: PushAttr(nOrderID);
1939         case GOrdSChDir:
1940             break;
1941 
1942         case GOrdPChPrc: PushAttr(nOrderID);
1943         case GOrdSChPrc:
1944             break;
1945 
1946         case GOrdPChSet: PushAttr(nOrderID);
1947         case GOrdSChSet: {
1948             sal_uInt8 nbyte; *pOS2MET >> nbyte;
1949             aAttr.nChrSet=((sal_uLong)nbyte)&0xff;
1950             break;
1951         }
1952         case GOrdPChAng: PushAttr(nOrderID);
1953         case GOrdSChAng: {
1954             long nX,nY;
1955             nX=ReadCoord(bCoord32); nY=ReadCoord(bCoord32);
1956             if (nX>=0 && nY==0) aAttr.nChrAng=0;
1957             else {
1958                 aAttr.nChrAng=(short)(atan2((double)nY,(double)nX)/3.1415926539*1800.0);
1959                 while (aAttr.nChrAng<0) aAttr.nChrAng+=3600;
1960                 aAttr.nChrAng%=3600;
1961             }
1962             break;
1963         }
1964         case GOrdPChBrx: PushAttr(nOrderID);
1965         case GOrdSChBrx:
1966             break;
1967 
1968         case GOrdPChCel: PushAttr(nOrderID);
1969         case GOrdSChCel: {
1970             sal_uInt8 nbyte;
1971             sal_uInt16 nLen=nOrderLen;
1972             aAttr.aChrCellSize.Width()=ReadCoord(bCoord32);
1973             aAttr.aChrCellSize.Height()=ReadCoord(bCoord32);
1974             if (bCoord32) nLen-=8; else nLen-=4;
1975             if (nLen>=4) {
1976                 pOS2MET->SeekRel(4); nLen-=4;
1977             }
1978             if (nLen>=2) {
1979                 *pOS2MET >> nbyte;
1980                 if ((nbyte&0x80)==0 && aAttr.aChrCellSize==Size(0,0))
1981                     aAttr.aChrCellSize=aDefAttr.aChrCellSize;
1982             }
1983             break;
1984         }
1985         case GOrdPChXtr: PushAttr(nOrderID);
1986         case GOrdSChXtr:
1987             break;
1988 
1989         case GOrdPChShr: PushAttr(nOrderID);
1990         case GOrdSChShr:
1991             break;
1992 
1993         case GOrdPTxAlg: PushAttr(nOrderID);
1994         case GOrdSTxAlg: OOODEBUG("GOrdSTxAlg",0);
1995             break;
1996 
1997         case GOrdPMkPrc: PushAttr(nOrderID);
1998         case GOrdSMkPrc: {
1999             sal_uInt8 nbyte;
2000             *pOS2MET >> nbyte;
2001             if (nbyte==0) aAttr.nMrkPrec=aDefAttr.nMrkPrec;
2002             else aAttr.nMrkPrec=nbyte;
2003             break;
2004         }
2005 
2006         case GOrdPMkSet: PushAttr(nOrderID);
2007         case GOrdSMkSet: {
2008             sal_uInt8 nbyte;
2009             *pOS2MET >> nbyte;
2010             if (nbyte==0) aAttr.nMrkSet=aDefAttr.nMrkSet;
2011             else aAttr.nMrkSet=nbyte;
2012             break;
2013         }
2014 
2015         case GOrdPMkSym: PushAttr(nOrderID);
2016         case GOrdSMkSym: {
2017             sal_uInt8 nbyte;
2018             *pOS2MET >> nbyte;
2019             if (nbyte==0) aAttr.nMrkSymbol=aDefAttr.nMrkSymbol;
2020             else aAttr.nMrkSymbol=nbyte;
2021             break;
2022         }
2023 
2024         case GOrdPMkCel: PushAttr(nOrderID);
2025         case GOrdSMkCel: {
2026             sal_uInt8 nbyte;
2027             sal_uInt16 nLen=nOrderLen;
2028             aAttr.aMrkCellSize.Width()=ReadCoord(bCoord32);
2029             aAttr.aMrkCellSize.Height()=ReadCoord(bCoord32);
2030             if (bCoord32) nLen-=8; else nLen-=4;
2031             if (nLen>=2) {
2032                 *pOS2MET >> nbyte;
2033                 if ((nbyte&0x80)==0 && aAttr.aMrkCellSize==Size(0,0))
2034                     aAttr.aMrkCellSize=aDefAttr.aMrkCellSize;
2035             }
2036             break;
2037         }
2038 
2039         case GOrdPArcPa: PushAttr(nOrderID);
2040         case GOrdSArcPa:
2041             aAttr.nArcP=ReadCoord(bCoord32);
2042             aAttr.nArcQ=ReadCoord(bCoord32);
2043             aAttr.nArcR=ReadCoord(bCoord32);
2044             aAttr.nArcS=ReadCoord(bCoord32);
2045             break;
2046 
2047         case GOrdPCrPos: PushAttr(nOrderID);
2048         case GOrdSCrPos:
2049             aAttr.aCurPos=ReadPoint();
2050             break;
2051 
2052         case GOrdPMdTrn: PushAttr(nOrderID);
2053         case GOrdSMdTrn: OOODEBUG("GOrdSMdTrn",0);
2054             break;
2055 
2056         case GOrdPPkIdn: PushAttr(nOrderID);
2057         case GOrdSPkIdn: OOODEBUG("GOrdSPkIdn",0);
2058             break;
2059 
2060         case GOrdSVwTrn: OOODEBUG("GOrdSVwTrn",0);
2061             break;
2062 
2063         case GOrdPVwWin: PushAttr(nOrderID);
2064         case GOrdSVwWin: OOODEBUG("GOrdSVwWin",0);
2065             break;
2066         default: OOODEBUG("Order unbekannt:",nOrderID);
2067     }
2068 }
2069 
ReadDsc(sal_uInt16 nDscID,sal_uInt16)2070 void OS2METReader::ReadDsc(sal_uInt16 nDscID, sal_uInt16 /*nDscLen*/)
2071 {
2072     switch (nDscID) {
2073         case 0x00f7: { // 'Specify GVM Subset'
2074             sal_uInt8 nbyte;
2075             pOS2MET->SeekRel(6);
2076             *pOS2MET >> nbyte;
2077             if      (nbyte==0x05) bCoord32=sal_True;
2078             else if (nbyte==0x04) bCoord32=sal_False;
2079             else {
2080                 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2081                 ErrorCode=1;
2082             }
2083             break;
2084         }
2085         case 0x00f6:
2086         {
2087             // 'Set Picture Descriptor'
2088             sal_Bool b32;
2089             sal_uInt8 nbyte,nUnitType;
2090             long x1,y1,x2,y2,nt,xr,yr;
2091 
2092             pOS2MET->SeekRel(2);
2093             *pOS2MET >> nbyte;
2094 
2095             if (nbyte==0x05)
2096                 b32=sal_True;
2097             else if(nbyte==0x04)
2098                 b32=sal_False;
2099             else
2100             {
2101                 b32 = sal_False;   // -Wall added the case.
2102                 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2103                 ErrorCode=2;
2104             }
2105 
2106             *pOS2MET >> nUnitType;
2107 
2108             xr=ReadCoord(b32);
2109             yr=ReadCoord(b32);
2110 
2111             ReadCoord(b32);
2112 
2113             if (nUnitType==0x00 && xr>0 && yr>0)
2114                 aGlobMapMode=MapMode(MAP_INCH,Point(0,0),Fraction(10,xr),Fraction(10,yr));
2115             else if (nUnitType==0x01 && xr>0 && yr>0)
2116                 aGlobMapMode=MapMode(MAP_CM,Point(0,0),Fraction(10,xr),Fraction(10,yr));
2117             else
2118                 aGlobMapMode=MapMode();
2119 
2120             x1=ReadCoord(b32);
2121             x2=ReadCoord(b32);
2122             y1=ReadCoord(b32);
2123             y2=ReadCoord(b32);
2124 
2125             if (x1>x2)
2126             {
2127                 nt=x1;
2128                 x1=x2;
2129                 x2=nt;
2130             }
2131 
2132             if (y1>y2)
2133             {
2134                 nt=y1;
2135                 y1=y2;
2136                 y2=nt;
2137             }
2138 
2139             aBoundingRect.Left() = x1;
2140             aBoundingRect.Right() = x2;
2141             aBoundingRect.Top() = y1;
2142             aBoundingRect.Bottom() = y2;
2143 
2144             // no output beside this bounding rect
2145             pVirDev->IntersectClipRegion( Rectangle( Point(), aBoundingRect.GetSize() ) );
2146 
2147             break;
2148         }
2149         case 0x0021: // 'Set Current Defaults'
2150             break;
2151     }
2152 }
2153 
ReadImageData(sal_uInt16 nDataID,sal_uInt16 nDataLen)2154 void OS2METReader::ReadImageData(sal_uInt16 nDataID, sal_uInt16 nDataLen)
2155 {
2156     OSBitmap * p=pBitmapList; if (p==NULL) return; // Nanu ?
2157 
2158     switch (nDataID) {
2159 
2160         case 0x0070:   // Begin Segment
2161             break;
2162 
2163         case 0x0091:   // Begin Image Content
2164             break;
2165 
2166         case 0x0094:   // Image Size
2167             pOS2MET->SeekRel(5);
2168             p->nHeight=ReadBigEndianWord();
2169             p->nWidth=ReadBigEndianWord();
2170             break;
2171 
2172         case 0x0095:   // Image Encoding
2173             break;
2174 
2175         case 0x0096: { // Image IDE-Size
2176             sal_uInt8 nbyte;
2177             *pOS2MET >> nbyte; p->nBitsPerPixel=nbyte;
2178             break;
2179         }
2180 
2181         case 0x0097:   // Image LUT-ID
2182             break;
2183 
2184         case 0x009b:   // IDE Structure
2185             break;
2186 
2187         case 0xfe92: { // Image Data
2188             // Spaetestens jetzt brauchen wir die temporaere BMP-Datei
2189             // und darin mindestens den Header + Palette.
2190             if (p->pBMP==NULL) {
2191                 p->pBMP=new SvMemoryStream();
2192                 p->pBMP->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2193                 if (p->nWidth==0 || p->nHeight==0 || p->nBitsPerPixel==0) {
2194                     pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2195                     ErrorCode=3;
2196                     return;
2197                 }
2198                 // Schreibe (Windows-)BITMAPINFOHEADER:
2199                 *(p->pBMP) << ((sal_uInt32)40) << p->nWidth << p->nHeight;
2200                 *(p->pBMP) << ((sal_uInt16)1) << p->nBitsPerPixel;
2201                 *(p->pBMP) << ((sal_uInt32)0) << ((sal_uInt32)0) << ((sal_uInt32)0) << ((sal_uInt32)0);
2202                 *(p->pBMP) << ((sal_uInt32)0) << ((sal_uInt32)0);
2203                 // Schreibe Farbtabelle:
2204                 if (p->nBitsPerPixel<=8) {
2205                     sal_uInt16 i, nColTabSize=1<<(p->nBitsPerPixel);
2206                     for (i=0; i<nColTabSize; i++) *(p->pBMP) << GetPalette0RGB(i);
2207                 }
2208             }
2209             // OK, nun werden die Map-Daten ruebergeschoben. Leider haben OS2 und
2210             // BMP eine unterschiedliche Reihenfolge von RGB bei 24-Bit.
2211             sal_uInt8 * pBuf=new sal_uInt8[nDataLen];
2212             pOS2MET->Read(pBuf,nDataLen);
2213             if (p->nBitsPerPixel==24) {
2214                 sal_uLong i, j, nAlign, nBytesPerLine;
2215                 sal_uInt8 nTemp;
2216                 nBytesPerLine=(p->nWidth*3+3)&0xfffffffc;
2217                 nAlign=p->nMapPos-(p->nMapPos % nBytesPerLine);
2218                 i=0;
2219                 while (nAlign+i+2<p->nMapPos+nDataLen) {
2220                     if (nAlign+i>=p->nMapPos) {
2221                         j=nAlign+i-p->nMapPos;
2222                         nTemp=pBuf[j]; pBuf[j]=pBuf[j+2]; pBuf[j+2]=nTemp;
2223                     }
2224                     i+=3; if (i+2>=nBytesPerLine) {
2225                         nAlign+=nBytesPerLine;
2226                         i=0;
2227                     }
2228                 }
2229             }
2230             p->pBMP->Write(pBuf,nDataLen);
2231             p->nMapPos+=nDataLen;
2232             delete[] pBuf;
2233             break;
2234         }
2235         case 0x0093:   // End Image Content
2236             break;
2237 
2238         case 0x0071:   // End Segment
2239             break;
2240     }
2241 }
2242 
ReadFont(sal_uInt16 nFieldSize)2243 void OS2METReader::ReadFont(sal_uInt16 nFieldSize)
2244 {
2245     sal_uLong nPos, nMaxPos;
2246     sal_uInt16 nLen;
2247     sal_uInt8 nByte, nTripType, nTripType2;
2248     OSFont * pF=new OSFont;
2249     pF->pSucc=pFontList; pFontList=pF;
2250     pF->nID=0;
2251     pF->aFont.SetTransparent(sal_True);
2252     pF->aFont.SetAlign(ALIGN_BASELINE);
2253 
2254     nPos=pOS2MET->Tell();
2255     nMaxPos=nPos+(sal_uLong)nFieldSize;
2256     pOS2MET->SeekRel(2); nPos+=2;
2257     while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2258         *pOS2MET >> nByte; nLen =((sal_uInt16)nByte) & 0x00ff;
2259         *pOS2MET >> nTripType;
2260         switch (nTripType) {
2261             case 0x02:
2262                 *pOS2MET >> nTripType2;
2263                 switch (nTripType2) {
2264                     case 0x84:   // Font name
2265                         break;
2266                     case 0x08: { // Font Typeface
2267                         char str[33];
2268                         pOS2MET->SeekRel(1);
2269                         pOS2MET->Read( &str, 32 );
2270                         str[ 32 ] = 0;
2271                         String aStr( (const sal_Char*)str, gsl_getSystemTextEncoding() );
2272                         if ( aStr.CompareIgnoreCaseToAscii( "Helv" ) == COMPARE_EQUAL )
2273                             aStr = String::CreateFromAscii( "Helvetica" );
2274                         pF->aFont.SetName( aStr );
2275                         break;
2276                     }
2277                 }
2278                 break;
2279             case 0x24:   // Icid
2280                 *pOS2MET >> nTripType2;
2281                 switch (nTripType2) {
2282                     case 0x05:   //Icid
2283                         *pOS2MET >> nByte;
2284                         pF->nID=((sal_uLong)nByte)&0xff;
2285                         break;
2286                 }
2287                 break;
2288             case 0x20:   // Font Binary GCID
2289                 break;
2290             case 0x1f: { // Font Attributes
2291                 FontWeight eWeight;
2292                 sal_uInt8 nbyte;
2293                 *pOS2MET >> nbyte;
2294                 switch (nbyte) {
2295                     case 1:  eWeight=WEIGHT_THIN;       break;
2296                     case 2:  eWeight=WEIGHT_ULTRALIGHT; break;
2297                     case 3:  eWeight=WEIGHT_LIGHT;      break;
2298                     case 4:  eWeight=WEIGHT_SEMILIGHT;  break;
2299                     case 5:  eWeight=WEIGHT_NORMAL;     break;
2300                     case 6:  eWeight=WEIGHT_SEMIBOLD;   break;
2301                     case 7:  eWeight=WEIGHT_BOLD;       break;
2302                     case 8:  eWeight=WEIGHT_ULTRABOLD;  break;
2303                     case 9:  eWeight=WEIGHT_BLACK;      break;
2304                     default: eWeight=WEIGHT_DONTKNOW;
2305                 }
2306                 pF->aFont.SetWeight(eWeight);
2307                 break;
2308             }
2309         }
2310         nPos+=nLen; pOS2MET->Seek(nPos);
2311     }
2312 }
2313 
ReadField(sal_uInt16 nFieldType,sal_uInt16 nFieldSize)2314 void OS2METReader::ReadField(sal_uInt16 nFieldType, sal_uInt16 nFieldSize)
2315 {
2316     switch (nFieldType) {
2317         case BegDocumnMagic:
2318             break;
2319         case EndDocumnMagic:
2320             break;
2321         case BegResGrpMagic:
2322             break;
2323         case EndResGrpMagic:
2324             break;
2325         case BegColAtrMagic:
2326             break;
2327         case EndColAtrMagic:
2328             break;
2329         case BlkColAtrMagic: {
2330             sal_uLong nPos, nMaxPos;
2331             sal_uInt8 nbyte;
2332             sal_uLong nCol;
2333             sal_uInt16 nStartIndex, nEndIndex, i, nElemLen, nBytesPerCol;
2334 
2335             nPos=pOS2MET->Tell();
2336             nMaxPos=nPos+(sal_uLong)nFieldSize;
2337             pOS2MET->SeekRel(3); nPos+=3;
2338             while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2339                 *pOS2MET >> nbyte; nElemLen=((sal_uInt16)nbyte) & 0x00ff;
2340                 if (nElemLen>11) {
2341                     pOS2MET->SeekRel(4);
2342                     nStartIndex=ReadBigEndianWord();
2343                     pOS2MET->SeekRel(3);
2344                     *pOS2MET >> nbyte; nBytesPerCol=((sal_uInt16)nbyte) & 0x00ff;
2345                     nEndIndex=nStartIndex+(nElemLen-11)/nBytesPerCol;
2346                     for (i=nStartIndex; i<nEndIndex; i++) {
2347                         if (nBytesPerCol > 3) pOS2MET->SeekRel(nBytesPerCol-3);
2348                         nCol=ReadBigEndian3BytesLong();
2349                         SetPalette0RGB(i,nCol);
2350                     }
2351                 }
2352                 else if (nElemLen<10) {
2353                     pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2354                     ErrorCode=4;
2355                 }
2356                 nPos+=(sal_uLong)nElemLen;
2357                 pOS2MET->Seek(nPos);
2358             }
2359             break;
2360         }
2361         case MapColAtrMagic:
2362             break;
2363         case BegImgObjMagic: {
2364             // neue Bitmap schonmal herstellen: (wird spaeter gefuellt)
2365             OSBitmap * pB=new OSBitmap;
2366             pB->pSucc=pBitmapList; pBitmapList=pB;
2367             pB->pBMP=NULL; pB->nWidth=0; pB->nHeight=0; pB->nBitsPerPixel=0;
2368             pB->nMapPos=0;
2369             // ID der Bitmap ermitteln:
2370             sal_uInt8 i,nbyte,nbyte2;
2371             pB->nID=0;
2372             for (i=0; i<4; i++) {
2373                 *pOS2MET >> nbyte >> nbyte2;
2374                 nbyte=((nbyte-0x30)<<4)|(nbyte2-0x30);
2375                 pB->nID=(pB->nID>>8)|(((sal_uLong)nbyte)<<24);
2376             }
2377             // neue Palette auf den Paletten-Stack bringen: (wird spaeter gefuellt)
2378             OSPalette * pP=new OSPalette;
2379             pP->pSucc=pPaletteStack; pPaletteStack=pP;
2380             pP->p0RGB=NULL; pP->nSize=0;
2381             break;
2382         }
2383         case EndImgObjMagic: {
2384             // Temporaere Windows-BMP-Datei auslesen:
2385             if (pBitmapList==NULL || pBitmapList->pBMP==NULL ||
2386                 pBitmapList->pBMP->GetError()!=0) {
2387                 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2388                 ErrorCode=5;
2389                 return;
2390             }
2391             pBitmapList->pBMP->Seek(0);
2392 
2393             ReadDIB(pBitmapList->aBitmap, *(pBitmapList->pBMP), false);
2394 
2395             if (pBitmapList->pBMP->GetError()!=0) {
2396                 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2397                 ErrorCode=6;
2398             }
2399             delete pBitmapList->pBMP; pBitmapList->pBMP=NULL;
2400             // Palette vom Stack killen:
2401             OSPalette * pP=pPaletteStack;
2402             if (pP!=NULL) {
2403                 pPaletteStack=pP->pSucc;
2404                 if (pP->p0RGB!=NULL) delete[] pP->p0RGB;
2405                 delete pP;
2406             }
2407             break;
2408         }
2409         case DscImgObjMagic:
2410             break;
2411         case DatImgObjMagic: {
2412             sal_uInt16 nDataID, nDataLen;
2413             sal_uInt8 nbyte;
2414             sal_uLong nPos, nMaxPos;
2415 
2416             nPos=pOS2MET->Tell();
2417             nMaxPos=nPos+(sal_uLong)nFieldSize;
2418             while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2419                 *pOS2MET >> nbyte; nDataID=((sal_uInt16)nbyte)&0x00ff;
2420                 if (nDataID==0x00fe) {
2421                     *pOS2MET >> nbyte;
2422                     nDataID=(nDataID<<8)|(((sal_uInt16)nbyte)&0x00ff);
2423                     nDataLen=ReadBigEndianWord();
2424                     nPos+=4;
2425                 }
2426                 else {
2427                     *pOS2MET >> nbyte; nDataLen=((sal_uInt16)nbyte)&0x00ff;
2428                     nPos+=2;
2429                 }
2430                 ReadImageData(nDataID, nDataLen);
2431                 nPos+=(sal_uLong)nDataLen;
2432                 pOS2MET->Seek(nPos);
2433             }
2434             break;
2435         }
2436 
2437         case BegObEnv1Magic:
2438             break;
2439         case EndObEnv1Magic:
2440             break;
2441         case BegGrfObjMagic:
2442             break;
2443         case EndGrfObjMagic: {
2444             SvStream * pSave;
2445             sal_uLong nPos, nMaxPos;
2446             sal_uInt16 nOrderID, nOrderLen;
2447             sal_uInt8 nbyte;
2448 
2449             if (pOrdFile==NULL) break;
2450 
2451             // in pOrdFile wurden alle "DatGrfObj"-Felder gesammelt, so
2452             // dass die darin enthaltnen "Orders" zusammenhangend und nicht durch
2453             // "Fields" segmentiert sind. Um sie aus dem MemoryStream auszulesen,
2454             // ohne grosse Umstaende deswegen zu haben (frueher wurden die "Orders"
2455             // direkt aus pOS2MET gelesen), hier ein kleiner Trick:
2456             pSave=pOS2MET;
2457             pOS2MET=pOrdFile; //(!)
2458             nMaxPos=pOS2MET->Tell();
2459             pOS2MET->Seek(0);
2460 
2461             // "Segmentheader":
2462             *pOS2MET >> nbyte;
2463             if (nbyte==0x70) { // Header vorhanden
2464                 pOS2MET->SeekRel(15); // brauchen wir aber nicht
2465             }
2466             else pOS2MET->SeekRel(-1); // Kein Header, Byte zurueck
2467 
2468             // Schleife ueber Order:
2469             while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
2470                 *pOS2MET >> nbyte; nOrderID=((sal_uInt16)nbyte) & 0x00ff;
2471                 if (nOrderID==0x00fe) {
2472                     *pOS2MET >> nbyte;
2473                     nOrderID=(nOrderID << 8) | (((sal_uInt16)nbyte) & 0x00ff);
2474                 }
2475                 if (nOrderID>0x00ff || nOrderID==GOrdPolygn) {
2476                     // ooo: Laut OS2-Doku sollte die Orderlaenge nun als Big-Endian-Word
2477                     // gegeben sein (Zitat: "Highorder byte precedes loworder byte").
2478                     // Tatsaechlich gibt es aber Dateien, die die Laenge als
2479                     // Little-Endian-Word angeben (zu mindestens fuer nOrderID==GOrdPolygn).
2480                     // Also werfen wir eine Muenze oder was ?
2481                     *pOS2MET >> nbyte; nOrderLen=(sal_uInt16)nbyte&0x00ff;
2482                     *pOS2MET >> nbyte; if (nbyte!=0) nOrderLen=nOrderLen<<8|(((sal_uInt16)nbyte)&0x00ff);
2483                 }
2484                 else if (nOrderID==GOrdSTxAlg || nOrderID==GOrdPTxAlg) nOrderLen=2;
2485                 else if ((nOrderID&0xff88)==0x0008) nOrderLen=1;
2486                 else if (nOrderID==0x0000 || nOrderID==0x00ff) nOrderLen=0;
2487                 else { *pOS2MET >> nbyte; nOrderLen=((sal_uInt16)nbyte) & 0x00ff; }
2488                 nPos=pOS2MET->Tell();
2489                 ReadOrder(nOrderID, nOrderLen);
2490                 if (nPos+nOrderLen < pOS2MET->Tell()) {
2491                     OOODEBUG("Order kuerzer als er denkt! OrderID:",nOrderID);
2492                     OOODEBUG("...und zwar bei Position (Parameteranfang):",nPos);
2493                 }
2494                 else if (nPos+nOrderLen != pOS2MET->Tell()) {
2495                     OOODEBUG(String(nOrderID)+String(" Order nicht alles gelesen! bei:"),nPos);
2496                 }
2497                 pOS2MET->Seek(nPos+nOrderLen);
2498             }
2499 
2500             pOS2MET=pSave;
2501             if (pOrdFile->GetError()) {
2502                 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2503                 ErrorCode=10;
2504             }
2505             delete pOrdFile; pOrdFile=NULL;
2506             break;
2507         }
2508         case DscGrfObjMagic: {
2509             sal_uLong nPos, nMaxPos;
2510             sal_uInt16 nDscID, nDscLen;
2511             sal_uInt8 nbyte;
2512 
2513             nMaxPos=pOS2MET->Tell()+(sal_uLong)nFieldSize;
2514             while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
2515                 *pOS2MET >> nbyte; nDscID =((sal_uInt16)nbyte) & 0x00ff;
2516                 *pOS2MET >> nbyte; nDscLen=((sal_uInt16)nbyte) & 0x00ff;
2517                 nPos=pOS2MET->Tell();
2518                 ReadDsc(nDscID, nDscLen);
2519                 pOS2MET->Seek(nPos+nDscLen);
2520             }
2521             break;
2522         }
2523         case DatGrfObjMagic: {
2524             if (pOrdFile==NULL) {
2525                 pOrdFile = new SvMemoryStream;
2526                 pOrdFile->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2527             }
2528             sal_uInt8 * pBuf; pBuf = new sal_uInt8[nFieldSize];
2529             pOS2MET->Read(pBuf,nFieldSize);
2530             pOrdFile->Write(pBuf,nFieldSize);
2531             delete[] pBuf;
2532             break;
2533         }
2534         case MapCodFntMagic:
2535             ReadFont(nFieldSize);
2536             break;
2537 
2538         case MapDatResMagic:
2539             break;
2540     }
2541 }
2542 
ReadOS2MET(SvStream & rStreamOS2MET,GDIMetaFile & rGDIMetaFile)2543 void OS2METReader::ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile )
2544 {
2545     sal_uInt16 nFieldSize;
2546     sal_uInt16 nFieldType;
2547     sal_uLong nPos, nStartPos, nEndPos, nPercent, nLastPercent;
2548     sal_uInt8 nMagicByte;
2549 
2550     ErrorCode=0;
2551 
2552     pOS2MET             = &rStreamOS2MET;
2553     nOrigPos            = pOS2MET->Tell();
2554     nOrigNumberFormat   = pOS2MET->GetNumberFormatInt();
2555 
2556     bCoord32 = sal_True;
2557     pPaletteStack=NULL;
2558     pAreaStack=NULL;
2559     pPathStack=NULL;
2560     pPathList=NULL;
2561     pFontList=NULL;
2562     pBitmapList=NULL;
2563     pAttrStack=NULL;
2564 
2565     aDefAttr.aLinCol     =Color(COL_BLACK);
2566     aDefAttr.aLinBgCol   =Color(COL_WHITE);
2567     aDefAttr.eLinMix     =ROP_OVERPAINT;
2568     aDefAttr.eLinBgMix   =ROP_OVERPAINT;
2569     aDefAttr.aChrCol     =Color(COL_BLACK);
2570     aDefAttr.aChrBgCol   =Color(COL_WHITE);
2571     aDefAttr.eChrMix     =ROP_OVERPAINT;
2572     aDefAttr.eChrBgMix   =ROP_OVERPAINT;
2573     aDefAttr.aMrkCol     =Color(COL_BLACK);
2574     aDefAttr.aMrkBgCol   =Color(COL_WHITE);
2575     aDefAttr.eMrkMix     =ROP_OVERPAINT;
2576     aDefAttr.eMrkBgMix   =ROP_OVERPAINT;
2577     aDefAttr.aPatCol     =Color(COL_BLACK);
2578     aDefAttr.aPatBgCol   =Color(COL_WHITE);
2579     aDefAttr.ePatMix     =ROP_OVERPAINT;
2580     aDefAttr.ePatBgMix   =ROP_OVERPAINT;
2581     aDefAttr.aImgCol     =Color(COL_BLACK);
2582     aDefAttr.aImgBgCol   =Color(COL_WHITE);
2583     aDefAttr.eImgMix     =ROP_OVERPAINT;
2584     aDefAttr.eImgBgMix   =ROP_OVERPAINT;
2585     aDefAttr.nArcP       =1;
2586     aDefAttr.nArcQ       =1;
2587     aDefAttr.nArcR       =0;
2588     aDefAttr.nArcS       =0;
2589     aDefAttr.nChrAng     =0;
2590     aDefAttr.aChrCellSize=Size(12,12);
2591     aDefAttr.nChrSet     =0;
2592     aDefAttr.aCurPos     =Point(0,0);
2593     aDefAttr.eLinStyle   =PEN_SOLID;
2594     aDefAttr.nLinWidth   =0;
2595     aDefAttr.aMrkCellSize=Size(10,10);
2596     aDefAttr.nMrkPrec    =0x01;
2597     aDefAttr.nMrkSet     =0xff;
2598     aDefAttr.nMrkSymbol  =0x01;
2599     aDefAttr.bFill       =sal_True;
2600     aDefAttr.nStrLinWidth=0;
2601 
2602     aAttr=aDefAttr;
2603 
2604     pOrdFile=NULL;
2605 
2606     pVirDev = new VirtualDevice();
2607     pVirDev->EnableOutput(sal_False);
2608     rGDIMetaFile.Record(pVirDev);
2609 
2610     pOS2MET->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2611 
2612     nStartPos=pOS2MET->Tell();
2613     nEndPos=pOS2MET->Seek(STREAM_SEEK_TO_END); pOS2MET->Seek(nStartPos);
2614     Callback(0); nLastPercent=0;
2615 
2616     nPos=pOS2MET->Tell();
2617     if ( nStartPos == nEndPos )
2618     {
2619         nEndPos = 100;
2620         nStartPos = 0;
2621     }
2622 
2623     for (;;) {
2624 
2625         nPercent=(nPos-nStartPos)*100/(nEndPos-nStartPos);
2626         if (nLastPercent+4<=nPercent) {
2627             if (Callback((sal_uInt16)nPercent)==sal_True) break;
2628             nLastPercent=nPercent;
2629         }
2630 
2631         nFieldSize=ReadBigEndianWord();
2632 
2633         *pOS2MET >> nMagicByte;
2634         if (nMagicByte!=0xd3) {
2635             pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2636             ErrorCode=7;
2637             break;
2638         }
2639         *pOS2MET >> nFieldType;
2640 
2641         pOS2MET->SeekRel(3);
2642         nPos+=8; nFieldSize-=8;
2643 
2644         if (pOS2MET->GetError()) break;
2645         if (pOS2MET->IsEof()) {
2646             pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2647             ErrorCode=8;
2648             break;
2649         }
2650 
2651         if (nFieldType==EndDocumnMagic) break;
2652 
2653         ReadField(nFieldType, nFieldSize);
2654 
2655         nPos+=(sal_uLong)nFieldSize;
2656         if (pOS2MET->Tell()>nPos)  {
2657             pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2658             ErrorCode=9;
2659             break;
2660         }
2661         pOS2MET->Seek(nPos);
2662     }
2663 
2664     rGDIMetaFile.Stop();
2665     delete pVirDev;
2666 
2667     rGDIMetaFile.SetPrefMapMode( aGlobMapMode );
2668 
2669     if( aBoundingRect.GetWidth() && aBoundingRect.GetHeight() )
2670         rGDIMetaFile.SetPrefSize( aBoundingRect.GetSize() );
2671     else
2672     {
2673         if( aCalcBndRect.Left() || aCalcBndRect.Top() )
2674             rGDIMetaFile.Move( -aCalcBndRect.Left(), -aCalcBndRect.Top() );
2675 
2676         rGDIMetaFile.SetPrefSize( aCalcBndRect.GetSize() );
2677     }
2678 
2679     if (pOrdFile!=NULL) delete pOrdFile;
2680 
2681     while (pAreaStack!=NULL) {
2682         OSArea * p=pAreaStack;
2683         pAreaStack=p->pSucc;
2684         delete p;
2685     }
2686 
2687     while (pPathStack!=NULL) {
2688         OSPath * p=pPathStack;
2689         pPathStack=p->pSucc;
2690         delete p;
2691     }
2692 
2693     while (pPathList!=NULL) {
2694         OSPath * p=pPathList;
2695         pPathList=p->pSucc;
2696         delete p;
2697     }
2698 
2699     while (pFontList!=NULL) {
2700         OSFont * p=pFontList;
2701         pFontList=p->pSucc;
2702         delete p;
2703     }
2704 
2705     while (pBitmapList!=NULL) {
2706         OSBitmap * p=pBitmapList;
2707         pBitmapList=p->pSucc;
2708         if (p->pBMP!=NULL) delete p->pBMP;
2709         delete p;
2710     }
2711 
2712     while (pAttrStack!=NULL) {
2713         OSAttr * p=pAttrStack;
2714         pAttrStack=p->pSucc;
2715         delete p;
2716     }
2717 
2718     while (pPaletteStack!=NULL) {
2719         OSPalette * p=pPaletteStack;
2720         pPaletteStack=p->pSucc;
2721         if (p->p0RGB!=NULL) delete[] p->p0RGB;
2722         delete p;
2723     }
2724 
2725     pOS2MET->SetNumberFormatInt(nOrigNumberFormat);
2726 
2727     if (pOS2MET->GetError()) {
2728         OOODEBUG("Fehler Nr.:",ErrorCode);
2729         pOS2MET->Seek(nOrigPos);
2730     }
2731 }
2732 
2733 //================== GraphicImport - die exportierte Funktion ================
2734 
GraphicImport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem *,sal_Bool)2735 extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool )
2736 {
2737     OS2METReader    aOS2METReader;
2738     GDIMetaFile     aMTF;
2739     sal_Bool            bRet = sal_False;
2740 
2741     aOS2METReader.ReadOS2MET( rStream, aMTF );
2742 
2743     if ( !rStream.GetError() )
2744     {
2745         rGraphic=Graphic( aMTF );
2746         bRet = sal_True;
2747     }
2748 
2749     return bRet;
2750 }
2751 
2752