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