Bump for 4.0-15
[LibreOffice.git] / filter / source / graphicfilter / ios2met / ios2met.cxx
blob21dae7b075eba21ad7b97b964adf1ead11e66828
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/graph.hxx>
22 #include <tools/poly.hxx>
23 #include <vcl/virdev.hxx>
24 #include <vcl/lineinfo.hxx>
26 #include <math.h>
28 class FilterConfigItem;
30 // MT: NOOLDSV, someone should change the code...
31 enum PenStyle { PEN_NULL, PEN_SOLID, PEN_DOT, PEN_DASH, PEN_DASHDOT };
34 //============================== defines ===================================
36 #define OOODEBUG(str,Num) //InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute();
38 // -----------------------------Feld-Typen-------------------------------
40 #define BegDocumnMagic 0xA8A8 /* Begin Document */
41 #define EndDocumnMagic 0xA8A9 /* End Document */
43 #define BegResGrpMagic 0xC6A8 /* Begin Resource Group */
44 #define EndResGrpMagic 0xC6A9 /* End Resource Group */
46 #define BegColAtrMagic 0x77A8 /* Begin Color Attribute Table */
47 #define EndColAtrMagic 0x77A9 /* End Color Attribute Table */
48 #define BlkColAtrMagic 0x77B0 /* Color Attribute Table */
49 #define MapColAtrMagic 0x77AB /* Map Color Attribute Table */
51 #define BegImgObjMagic 0xFBA8 /* Begin Image Object */
52 #define EndImgObjMagic 0xFBA9 /* End Image Object */
53 #define DscImgObjMagic 0xFBA6 /* Image Data Descriptor */
54 #define DatImgObjMagic 0xFBEE /* Image Picture Data */
56 #define BegObEnv1Magic 0xC7A8 /* Begin Object Environment Group */
57 #define EndObEnv1Magic 0xC7A9 /* End Object Environment Group */
59 #define BegGrfObjMagic 0xBBA8 /* Begin Graphics Object */
60 #define EndGrfObjMagic 0xBBA9 /* End Graphics Object */
61 #define DscGrfObjMagic 0xBBA6 /* Graphics Data Descritor */
62 #define DatGrfObjMagic 0xBBEE /* Graphics Data */
64 #define MapCodFntMagic 0x8AAB /* Map Coded Font */
65 #define MapDatResMagic 0xC3AB /* Map Data Resource */
67 // -----------------------------Order-Typen-------------------------------
69 #define GOrdGivArc 0xC6 /* 1 Arc at given position */
70 #define GOrdCurArc 0x86 /* 1 Arc at current position */
71 #define GOrdGivBzr 0xE5 /* 1 Beziercurve at given position */
72 #define GOrdCurBzr 0xA5 /* 1 Beziercurve at current position */
73 #define GOrdGivBox 0xC0 /* 1 Box at given position */
74 #define GOrdCurBox 0x80 /* 1 Box at current position */
75 #define GOrdGivFil 0xC5 /* 1 Fillet at given position */
76 #define GOrdCurFil 0x85 /* 1 Fillet at current position */
77 #define GOrdGivCrc 0xC7 /* 1 Full arc (circle) at given position */
78 #define GOrdCurCrc 0x87 /* 1 Full arc (circle) at current position */
79 #define GOrdGivLin 0xC1 /* 1 Line at given position */
80 #define GOrdCurLin 0x81 /* 1 Line at current position */
81 #define GOrdGivMrk 0xC2 /* 1 Marker at given position */
82 #define GOrdCurMrk 0x82 /* 1 Marker at current position */
83 #define GOrdGivArP 0xE3 /* 1 Partial arc at given position */
84 #define GOrdCurArP 0xA3 /* 1 Partial arc at current position */
85 #define GOrdGivRLn 0xE1 /* 1 Relative line at given position */
86 #define GOrdCurRLn 0xA1 /* 1 Relative line at current position */
87 #define GOrdGivSFl 0xE4 /* 1 Sharp fillet at given position */
88 #define GOrdCurSFl 0xA4 /* 1 Sharp fillet at current position */
90 #define GOrdGivStM 0xF1 /* 1 Character string move at given position */
91 #define GOrdCurStM 0xB1 /* 1 Character string move at current position */
92 #define GOrdGivStr 0xC3 /* 1 Character string at given position */
93 #define GOrdCurStr 0x83 /* 1 Character string at current position */
94 #define GOrdGivStx 0xFEF0 /* 2 Character string extended at given position */
95 #define GOrdCurStx 0xFEB0 /* 2 Character string extended at current position */
97 #define GOrdGivImg 0xD1 /* 1 Begin Image at given position */
98 #define GOrdCurImg 0x91 /* 1 Begin Image at current position */
99 #define GOrdImgDat 0x92 /* 1 Image data */
100 #define GOrdEndImg 0x93 /* 1 End Image */
101 #define GOrdBegAra 0x68 /* 0 1 Begin area */
102 #define GOrdEndAra 0x60 /* 1 End area */
103 #define GOrdBegElm 0xD2 /* 1 Begin element */
104 #define GOrdEndElm 0x49 /* 0 1 End element */
106 #define GOrdBegPth 0xD0 /* 1 Begin path */
107 #define GOrdEndPth 0x7F /* 0 1 End path */
108 #define GOrdFilPth 0xD7 /* 1 Fill path */
109 #define GOrdModPth 0xD8 /* 1 Modify path */
110 #define GOrdOutPth 0xD4 /* 1 Outline path */
111 #define GOrdSClPth 0xB4 /* 1 Set clip path */
113 #define GOrdNopNop 0x00 /* 0 0 No operation */
114 #define GOrdRemark 0x01 /* 1 Comment */
115 #define GOrdSegLab 0xD3 /* 1 Label */
116 #define GOrdBitBlt 0xD6 /* 1 Bitblt */
117 #define GOrdCalSeg 0x07 /* 1 Call Segment */
118 #define GOrdSSgBnd 0x32 /* 1 Set segment boundary */
119 #define GOrdSegChr 0x04 /* 1 Segment characteristics */
120 #define GOrdCloFig 0x7D /* 0 1 Close Figure */
121 #define GOrdEndSym 0xFF /* 0 0 End of symbol definition */
122 #define GOrdEndPlg 0x3E /* 0 1 End prolog */
123 #define GOrdEscape 0xD5 /* 1 Escape */
124 #define GOrdExtEsc 0xFED5 /* 2 Extended Escape */
125 #define GOrdPolygn 0xF3 /* 2 Polygons */
127 #define GOrdStkPop 0x3F /* 0 1 Pop */
129 #define GOrdSIvAtr 0x14 /* 1 Set individual attribute */
130 #define GOrdPIvAtr 0x54 /* 1 Push and set individual attribute */
131 #define GOrdSColor 0x0A /* 0 1 Set color */
132 #define GOrdPColor 0x4A /* 0 1 Push and set color */
133 #define GOrdSIxCol 0xA6 /* 1 Set indexed color */
134 #define GOrdPIxCol 0xE6 /* 1 Push and set indexed color */
135 #define GOrdSXtCol 0x26 /* 1 Set extended color */
136 #define GOrdPXtCol 0x66 /* 1 Push and set extended color */
137 #define GOrdSBgCol 0x25 /* 1 Set background color */
138 #define GOrdPBgCol 0x65 /* 1 Push and set background color */
139 #define GOrdSBxCol 0xA7 /* 1 Set background indexed color */
140 #define GOrdPBxCol 0xE7 /* 1 Push and set background indexed color */
141 #define GOrdSMixMd 0x0C /* 0 1 Set mix */
142 #define GOrdPMixMd 0x4C /* 0 1 Push and set mix */
143 #define GOrdSBgMix 0x0D /* 0 1 Set background mix */
144 #define GOrdPBgMix 0x4D /* 0 1 Push and set background mix */
146 #define GOrdSPtSet 0x08 /* 0 1 Set pattern set */
147 #define GOrdPPtSet 0x48 /* 0 1 Push and set pattern set */
148 #define GOrdSPtSym 0x28 /* 0 1 Set pattern symbol */
149 #define GOrdPPtSym 0x09 /* 0 1 Push and set pattern symbol */
150 #define GOrdSPtRef 0xA0 /* 1 Set model pattern reference */
151 #define GOrdPPtRef 0xE0 /* 1 Push and set pattern reference point */
153 #define GOrdSLnEnd 0x1A /* 0 1 Set line end */
154 #define GOrdPLnEnd 0x5A /* 0 1 Push and set line end */
155 #define GOrdSLnJoi 0x1B /* 0 1 Set line join */
156 #define GOrdPLnJoi 0x5B /* 0 1 Push and set line join */
157 #define GOrdSLnTyp 0x18 /* 0 1 Set line type */
158 #define GOrdPLnTyp 0x58 /* 0 1 Push and set line type */
159 #define GOrdSLnWdt 0x19 /* 0 1 Set line width */
160 #define GOrdPLnWdt 0x59 /* 0 1 Push and set line width */
161 #define GOrdSFrLWd 0x11 /* 1 Set fractional line width */
162 #define GOrdPFrLWd 0x51 /* 1 Push and set fractional line width */
163 #define GOrdSStLWd 0x15 /* 1 Set stroke line width */
164 #define GOrdPStLWd 0x55 /* 1 Push and set stroke line width */
166 #define GOrdSChDir 0x3A /* 0 1 Set character direction */
167 #define GOrdPChDir 0x7A /* 0 1 Push and set character direction */
168 #define GOrdSChPrc 0x39 /* 0 1 Set character precision */
169 #define GOrdPChPrc 0x79 /* 0 1 Push and set character precision */
170 #define GOrdSChSet 0x38 /* 0 1 Set character set */
171 #define GOrdPChSet 0x78 /* 0 1 Push and set character set */
172 #define GOrdSChAng 0x34 /* 1 Set character angle */
173 #define GOrdPChAng 0x74 /* 1 Push and set character angle */
174 #define GOrdSChBrx 0x05 /* 1 Set character break extra */
175 #define GOrdPChBrx 0x45 /* 1 Push and set character break extra */
176 #define GOrdSChCel 0x33 /* 1 Set character cell */
177 #define GOrdPChCel 0x03 /* 1 Push and set character cell */
178 #define GOrdSChXtr 0x17 /* 1 Set character extra */
179 #define GOrdPChXtr 0x57 /* 1 Push and set character extra */
180 #define GOrdSChShr 0x35 /* 1 Set character shear */
181 #define GOrdPChShr 0x75 /* 1 Push and set character shear */
182 #define GOrdSTxAlg 0x36 /* 0 2 Set text allingment */
183 #define GOrdPTxAlg 0x76 /* 0 2 Push and set text allingment */
185 #define GOrdSMkPrc 0x3B /* 0 1 Set marker precision */
186 #define GOrdPMkPrc 0x7B /* 0 1 Push and set marker precision */
187 #define GOrdSMkSet 0x3C /* 0 1 Set marker set */
188 #define GOrdPMkSet 0x7C /* 0 1 Push and set marker set */
189 #define GOrdSMkSym 0x29 /* 0 1 Set marker symbol */
190 #define GOrdPMkSym 0x69 /* 0 1 Push and set marker symbol */
191 #define GOrdSMkCel 0x37 /* 1 Set marker cell */
192 #define GOrdPMkCel 0x77 /* 1 Push and set marker cell */
194 #define GOrdSArcPa 0x22 /* 1 Set arc parameters */
195 #define GOrdPArcPa 0x62 /* 1 Push and set arc parameters */
197 #define GOrdSCrPos 0x21 /* 1 Set current position */
198 #define GOrdPCrPos 0x61 /* 1 Push and set current position */
200 #define GOrdSMdTrn 0x24 /* 1 Set model transform */
201 #define GOrdPMdTrn 0x64 /* 1 Push and set model transform */
202 #define GOrdSPkIdn 0x43 /* 1 Set pick identifier */
203 #define GOrdPPkIdn 0x23 /* 1 Push and set pick identifier */
204 #define GOrdSVwTrn 0x31 /* 1 Set viewing transform */
205 #define GOrdSVwWin 0x27 /* 1 Set viewing window */
206 #define GOrdPVwWin 0x67 /* 1 Push and set viewing window */
208 //============================ OS2METReader ==================================
210 struct OSPalette {
211 OSPalette * pSucc;
212 sal_uInt32 * p0RGB; // May be NULL!
213 sal_uInt16 nSize;
216 struct OSArea {
217 OSArea * pSucc;
218 sal_uInt8 nFlags;
219 PolyPolygon aPPoly;
220 sal_Bool bClosed;
221 Color aCol;
222 Color aBgCol;
223 RasterOp eMix;
224 RasterOp eBgMix;
225 sal_Bool bFill;
226 OSArea(){} ~OSArea(){}
229 struct OSPath
231 OSPath* pSucc;
232 sal_uInt32 nID;
233 PolyPolygon aPPoly;
234 sal_Bool bClosed;
235 sal_Bool bStroke;
237 OSPath(){}
238 ~OSPath(){}
241 struct OSFont {
242 OSFont * pSucc;
243 sal_uLong nID;
244 Font aFont;
245 OSFont(){} ~OSFont(){}
248 struct OSBitmap {
249 OSBitmap * pSucc;
250 sal_uLong nID;
251 Bitmap aBitmap;
253 // required during reading of the bitmap:
254 SvStream * pBMP; // pointer to temporary Windows-BMP file or NULL
255 sal_uInt32 nWidth, nHeight;
256 sal_uInt16 nBitsPerPixel;
257 sal_uLong nMapPos;
258 OSBitmap(){} ~OSBitmap(){}
261 struct OSAttr {
262 OSAttr * pSucc;
263 sal_uInt16 nPushOrder;
264 sal_uInt8 nIvAttrA, nIvAttrP; // special variables for the Order "GOrdPIvAtr"
266 Color aLinCol;
267 Color aLinBgCol;
268 RasterOp eLinMix;
269 RasterOp eLinBgMix;
270 Color aChrCol;
271 Color aChrBgCol;
272 RasterOp eChrMix;
273 RasterOp eChrBgMix;
274 Color aMrkCol;
275 Color aMrkBgCol;
276 RasterOp eMrkMix;
277 RasterOp eMrkBgMix;
278 Color aPatCol;
279 Color aPatBgCol;
280 RasterOp ePatMix;
281 RasterOp ePatBgMix;
282 Color aImgCol;
283 Color aImgBgCol;
284 RasterOp eImgMix;
285 RasterOp eImgBgMix;
286 long nArcP, nArcQ, nArcR, nArcS;
287 short nChrAng;
288 // long nChrBreakExtra;
289 Size aChrCellSize;
290 // sal_uInt8 nChrDir;
291 // long nChrExtra;
292 // sal_uInt8 nChrPrec;
293 sal_uLong nChrSet;
294 // Size aChrShear;
295 Point aCurPos;
296 // long nFracLinWidth;
297 // sal_uInt8 nLinEnd;
298 // sal_uInt8 nLinJoin;
299 PenStyle eLinStyle;
300 sal_uInt16 nLinWidth;
301 Size aMrkCellSize;
302 sal_uInt8 nMrkPrec;
303 sal_uInt8 nMrkSet;
304 sal_uInt8 nMrkSymbol;
305 // //... aModTransform;
306 // Point aPatRef;
307 // sal_uInt8 nPatSet;
308 sal_Bool bFill;
309 // sal_uLong nPickId;
310 // //... aSegBound;
311 sal_uInt16 nStrLinWidth;
312 // sal_uInt8 nTxtAlignHor,nTxtAlignVer;
313 // //... aViewTransform;
314 // //... aViewWindow;
315 OSAttr(){} ~OSAttr(){}
318 class OS2METReader {
320 private:
322 long ErrorCode;
324 SvStream * pOS2MET; // Die einzulesende OS2MET-Datei
325 VirtualDevice * pVirDev; // here the drawing methods are being called
326 // Dabei findet ein Recording in das GDIMetaFile
327 // statt.
328 sal_uLong nOrigPos; // Anfaengliche Position in pOS2MET
329 sal_uInt16 nOrigNumberFormat; // Anfaengliches Nummern-Format von pOS2MET
330 Rectangle aBoundingRect; // Boundingrectangle wie in Datei angegeben
331 Rectangle aCalcBndRect; // selbst ermitteltes Boundingrectangle
332 MapMode aGlobMapMode; // resolution of the picture
333 sal_Bool bCoord32;
335 OSPalette * pPaletteStack;
337 LineInfo aLineInfo;
339 OSArea * pAreaStack; // Areas that are being worked on
341 OSPath * pPathStack; // Paths that are being worked on
342 OSPath * pPathList; // finished Paths
344 OSFont * pFontList;
346 OSBitmap * pBitmapList;
348 OSAttr aDefAttr;
349 OSAttr aAttr;
350 OSAttr * pAttrStack;
352 SvStream * pOrdFile;
354 sal_Bool Callback(sal_uInt16 nPercent);
356 void AddPointsToPath(const Polygon & rPoly);
357 void AddPointsToArea(const Polygon & rPoly);
358 void CloseFigure();
359 void PushAttr(sal_uInt16 nPushOrder);
360 void PopAttr();
362 void ChangeBrush( const Color& rPatColor, const Color& rBGColor, sal_Bool bFill );
363 void SetPen( const Color& rColor, sal_uInt16 nStrLinWidth = 0, PenStyle ePenStyle = PEN_SOLID );
364 void SetRasterOp(RasterOp eROP);
366 void SetPalette0RGB(sal_uInt16 nIndex, sal_uLong nCol);
367 sal_uInt32 GetPalette0RGB(sal_uInt32 nIndex);
368 // gets color from palette, or, if it doesn't exist,
369 // interprets nIndex as immediate RGB value.
370 Color GetPaletteColor(sal_uInt32 nIndex);
373 sal_Bool IsLineInfo();
374 void DrawPolyLine( const Polygon& rPolygon );
375 void DrawPolygon( const Polygon& rPolygon );
376 void DrawPolyPolygon( const PolyPolygon& rPolygon );
377 sal_uInt16 ReadBigEndianWord();
378 sal_uLong ReadBigEndian3BytesLong();
379 sal_uLong ReadLittleEndian3BytesLong();
380 long ReadCoord(sal_Bool b32);
381 Point ReadPoint( const sal_Bool bAdjustBoundRect = sal_True );
382 RasterOp OS2MixToRasterOp(sal_uInt8 nMix);
383 void ReadLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
384 void ReadRelLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
385 void ReadBox(sal_Bool bGivenPos);
386 void ReadBitBlt();
387 void ReadChrStr(sal_Bool bGivenPos, sal_Bool bMove, sal_Bool bExtra, sal_uInt16 nOrderLen);
388 void ReadArc(sal_Bool bGivenPos);
389 void ReadFullArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize);
390 void ReadPartialArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize);
391 void ReadPolygons();
392 void ReadBezier(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
393 void ReadFillet(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
394 void ReadFilletSharp(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
395 void ReadMarker(sal_Bool bGivenPos, sal_uInt16 nOrderLen);
396 void ReadOrder(sal_uInt16 nOrderID, sal_uInt16 nOrderLen);
397 void ReadDsc(sal_uInt16 nDscID, sal_uInt16 nDscLen);
398 void ReadImageData(sal_uInt16 nDataID, sal_uInt16 nDataLen);
399 void ReadFont(sal_uInt16 nFieldSize);
400 void ReadField(sal_uInt16 nFieldType, sal_uInt16 nFieldSize);
402 public:
404 OS2METReader();
405 ~OS2METReader();
407 void ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile );
408 // Reads from the stream a OS2MET file und and fills up the GDIMetaFile
412 //=================== Methods of OS2METReader ==============================
414 sal_Bool OS2METReader::Callback(sal_uInt16 /*nPercent*/)
416 return sal_False;
419 OS2METReader::OS2METReader()
423 OS2METReader::~OS2METReader()
427 sal_Bool OS2METReader::IsLineInfo()
429 return ( ! ( aLineInfo.IsDefault() || ( aLineInfo.GetStyle() == LINE_NONE ) || ( pVirDev->GetLineColor() == COL_TRANSPARENT ) ) );
432 void OS2METReader::DrawPolyLine( const Polygon& rPolygon )
434 if ( aLineInfo.GetStyle() == LINE_DASH || ( aLineInfo.GetWidth() > 1 ) )
435 pVirDev->DrawPolyLine( rPolygon, aLineInfo );
436 else
437 pVirDev->DrawPolyLine( rPolygon );
440 void OS2METReader::DrawPolygon( const Polygon& rPolygon )
442 if ( IsLineInfo() )
444 pVirDev->Push( PUSH_LINECOLOR );
445 pVirDev->SetLineColor( COL_TRANSPARENT );
446 pVirDev->DrawPolygon( rPolygon );
447 pVirDev->Pop();
448 pVirDev->DrawPolyLine( rPolygon, aLineInfo );
450 else
451 pVirDev->DrawPolygon( rPolygon );
454 void OS2METReader::DrawPolyPolygon( const PolyPolygon& rPolyPolygon )
456 if ( IsLineInfo() )
458 pVirDev->Push( PUSH_LINECOLOR );
459 pVirDev->SetLineColor( COL_TRANSPARENT );
460 pVirDev->DrawPolyPolygon( rPolyPolygon );
461 pVirDev->Pop();
462 for ( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i++ )
463 pVirDev->DrawPolyLine( rPolyPolygon.GetObject( i ), aLineInfo );
465 else
466 pVirDev->DrawPolyPolygon( rPolyPolygon );
469 void OS2METReader::AddPointsToArea(const Polygon & rPoly)
471 sal_uInt16 nOldSize, nNewSize,i;
473 if (pAreaStack==NULL || rPoly.GetSize()==0) return;
474 PolyPolygon * pPP=&(pAreaStack->aPPoly);
475 if (pPP->Count()==0 || pAreaStack->bClosed==sal_True) pPP->Insert(rPoly);
476 else {
477 Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
478 nOldSize=aLastPoly.GetSize();
479 if (aLastPoly.GetPoint(nOldSize-1)==rPoly.GetPoint(0)) nOldSize--;
480 nNewSize=nOldSize+rPoly.GetSize();
481 aLastPoly.SetSize(nNewSize);
482 for (i=nOldSize; i<nNewSize; i++) {
483 aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
485 pPP->Replace(aLastPoly,pPP->Count()-1);
487 pAreaStack->bClosed=sal_False;
490 void OS2METReader::AddPointsToPath(const Polygon & rPoly)
492 sal_uInt16 nOldSize, nNewSize,i;
494 if (pPathStack==NULL || rPoly.GetSize()==0) return;
495 PolyPolygon * pPP=&(pPathStack->aPPoly);
496 if (pPP->Count()==0 /*|| pPathStack->bClosed==sal_True*/) pPP->Insert(rPoly);
497 else {
498 Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
499 nOldSize=aLastPoly.GetSize();
500 if (aLastPoly.GetPoint(nOldSize-1)!=rPoly.GetPoint(0)) pPP->Insert(rPoly);
501 else {
502 nOldSize--;
503 nNewSize=nOldSize+rPoly.GetSize();
504 aLastPoly.SetSize(nNewSize);
505 for (i=nOldSize; i<nNewSize; i++) {
506 aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
508 pPP->Replace(aLastPoly,pPP->Count()-1);
511 pPathStack->bClosed=sal_False;
514 void OS2METReader::CloseFigure()
516 if (pAreaStack!=NULL) pAreaStack->bClosed=sal_True;
517 else if (pPathStack!=NULL) pPathStack->bClosed=sal_True;
520 void OS2METReader::PushAttr(sal_uInt16 nPushOrder)
522 OSAttr * p;
523 p=new OSAttr;
524 *p=aAttr;
525 p->pSucc=pAttrStack; pAttrStack=p;
526 p->nPushOrder=nPushOrder;
529 void OS2METReader::PopAttr()
531 OSAttr * p=pAttrStack;
533 if (p==NULL) return;
534 switch (p->nPushOrder) {
536 case GOrdPIvAtr:
537 switch (p->nIvAttrA) {
538 case 1: switch (p->nIvAttrP) {
539 case 1: aAttr.aLinCol=p->aLinCol; break;
540 case 2: aAttr.aChrCol=p->aChrCol; break;
541 case 3: aAttr.aMrkCol=p->aMrkCol; break;
542 case 4: aAttr.aPatCol=p->aPatCol; break;
543 case 5: aAttr.aImgCol=p->aImgCol; break;
544 } break;
545 case 2: switch (p->nIvAttrP) {
546 case 1: aAttr.aLinBgCol=p->aLinBgCol; break;
547 case 2: aAttr.aChrBgCol=p->aChrBgCol; break;
548 case 3: aAttr.aMrkBgCol=p->aMrkBgCol; break;
549 case 4: aAttr.aPatBgCol=p->aPatBgCol; break;
550 case 5: aAttr.aImgBgCol=p->aImgBgCol; break;
551 } break;
552 case 3: switch (p->nIvAttrP) {
553 case 1: aAttr.eLinMix=p->eLinMix; break;
554 case 2: aAttr.eChrMix=p->eChrMix; break;
555 case 3: aAttr.eMrkMix=p->eMrkMix; break;
556 case 4: aAttr.ePatMix=p->ePatMix; break;
557 case 5: aAttr.eImgMix=p->eImgMix; break;
558 } break;
559 case 4: switch (p->nIvAttrP) {
560 case 1: aAttr.eLinBgMix=p->eLinBgMix; break;
561 case 2: aAttr.eChrBgMix=p->eChrBgMix; break;
562 case 3: aAttr.eMrkBgMix=p->eMrkBgMix; break;
563 case 4: aAttr.ePatBgMix=p->ePatBgMix; break;
564 case 5: aAttr.eImgBgMix=p->eImgBgMix; break;
565 } break;
567 break;
569 case GOrdPLnTyp: aAttr.eLinStyle=p->eLinStyle; break;
571 case GOrdPLnWdt: aAttr.nLinWidth=p->nLinWidth; break;
573 case GOrdPStLWd: aAttr.nStrLinWidth=p->nStrLinWidth; break;
575 case GOrdPChSet: aAttr.nChrSet=p->nChrSet; break;
577 case GOrdPChAng: aAttr.nChrAng=p->nChrAng; break;
579 case GOrdPMixMd:
580 aAttr.eLinMix=p->eLinMix;
581 aAttr.eChrMix=p->eChrMix;
582 aAttr.eMrkMix=p->eMrkMix;
583 aAttr.ePatMix=p->ePatMix;
584 aAttr.eImgMix=p->eImgMix;
585 break;
587 case GOrdPBgMix:
588 aAttr.eLinBgMix=p->eLinBgMix;
589 aAttr.eChrBgMix=p->eChrBgMix;
590 aAttr.eMrkBgMix=p->eMrkBgMix;
591 aAttr.ePatBgMix=p->ePatBgMix;
592 aAttr.eImgBgMix=p->eImgBgMix;
593 break;
595 case GOrdPPtSym: aAttr.bFill = p->bFill; break;
597 case GOrdPColor:
598 case GOrdPIxCol:
599 case GOrdPXtCol:
600 aAttr.aLinCol=p->aLinCol;
601 aAttr.aChrCol=p->aChrCol;
602 aAttr.aMrkCol=p->aMrkCol;
603 aAttr.aPatCol=p->aPatCol;
604 aAttr.aImgCol=p->aImgCol;
605 break;
607 case GOrdPBgCol:
608 case GOrdPBxCol:
609 aAttr.aLinBgCol=p->aLinBgCol;
610 aAttr.aChrBgCol=p->aChrBgCol;
611 aAttr.aMrkBgCol=p->aMrkBgCol;
612 aAttr.aPatBgCol=p->aPatBgCol;
613 aAttr.aImgBgCol=p->aImgBgCol;
614 break;
616 case GOrdPMkPrc: aAttr.nMrkPrec=aDefAttr.nMrkPrec; break;
618 case GOrdPMkSet: aAttr.nMrkSet=aDefAttr.nMrkSet; break;
620 case GOrdPMkSym: aAttr.nMrkSymbol=aDefAttr.nMrkSymbol; break;
622 case GOrdPMkCel: aAttr.aMrkCellSize=aDefAttr.aMrkCellSize; break;
624 case GOrdPArcPa:
625 aAttr.nArcP=p->nArcP; aAttr.nArcQ=p->nArcQ;
626 aAttr.nArcR=p->nArcR; aAttr.nArcS=p->nArcS;
627 break;
629 case GOrdPCrPos:
630 aAttr.aCurPos=p->aCurPos;
631 break;
633 pAttrStack=p->pSucc;
634 delete p;
637 void OS2METReader::ChangeBrush(const Color& rPatColor, const Color& /*rBGColor*/, sal_Bool bFill )
639 Color aColor;
641 if( bFill )
642 aColor = rPatColor;
643 else
644 aColor = Color( COL_TRANSPARENT );
646 if( pVirDev->GetFillColor() != aColor )
647 pVirDev->SetFillColor( aColor );
650 void OS2METReader::SetPen( const Color& rColor, sal_uInt16 nLineWidth, PenStyle ePenStyle )
652 LineStyle eLineStyle( LINE_SOLID );
654 if ( pVirDev->GetLineColor() != rColor )
655 pVirDev->SetLineColor( rColor );
656 aLineInfo.SetWidth( nLineWidth );
658 sal_uInt16 nDotCount = 0;
659 sal_uInt16 nDashCount = 0;
660 switch ( ePenStyle )
662 case PEN_NULL :
663 eLineStyle = LINE_NONE;
664 break;
665 case PEN_DASHDOT :
666 nDashCount++;
667 case PEN_DOT :
668 nDotCount++;
669 nDashCount--;
670 case PEN_DASH :
671 nDashCount++;
672 aLineInfo.SetDotCount( nDotCount );
673 aLineInfo.SetDashCount( nDashCount );
674 aLineInfo.SetDistance( nLineWidth );
675 aLineInfo.SetDotLen( nLineWidth );
676 aLineInfo.SetDashLen( nLineWidth << 2 );
677 eLineStyle = LINE_DASH;
678 break;
679 case PEN_SOLID:
680 break; // -Wall not handled...
682 aLineInfo.SetStyle( eLineStyle );
685 void OS2METReader::SetRasterOp(RasterOp eROP)
687 if (pVirDev->GetRasterOp()!=eROP) pVirDev->SetRasterOp(eROP);
691 void OS2METReader::SetPalette0RGB(sal_uInt16 nIndex, sal_uLong nCol)
693 if (pPaletteStack==NULL) {
694 pPaletteStack=new OSPalette;
695 pPaletteStack->pSucc=NULL;
696 pPaletteStack->p0RGB=NULL;
697 pPaletteStack->nSize=0;
699 if (pPaletteStack->p0RGB==NULL || nIndex>=pPaletteStack->nSize) {
700 sal_uInt32 * pOld0RGB=pPaletteStack->p0RGB;
701 sal_uInt16 i,nOldSize=pPaletteStack->nSize;
702 if (pOld0RGB==NULL) nOldSize=0;
703 pPaletteStack->nSize=2*(nIndex+1);
704 if (pPaletteStack->nSize<256) pPaletteStack->nSize=256;
705 pPaletteStack->p0RGB = new sal_uInt32[pPaletteStack->nSize];
706 for (i=0; i<pPaletteStack->nSize; i++) {
707 if (i<nOldSize) pPaletteStack->p0RGB[i]=pOld0RGB[i];
708 else if (i==0) pPaletteStack->p0RGB[i]=0x00ffffff;
709 else pPaletteStack->p0RGB[i]=0;
711 if (pOld0RGB!=NULL) delete[] pOld0RGB;
713 pPaletteStack->p0RGB[nIndex]=nCol;
716 sal_uInt32 OS2METReader::GetPalette0RGB(sal_uInt32 nIndex)
718 if (pPaletteStack!=NULL && pPaletteStack->p0RGB!=NULL &&
719 pPaletteStack->nSize>nIndex) nIndex=pPaletteStack->p0RGB[nIndex];
720 return nIndex;
723 Color OS2METReader::GetPaletteColor(sal_uInt32 nIndex)
725 nIndex=GetPalette0RGB(nIndex);
726 return Color(sal::static_int_cast< sal_uInt8 >((nIndex>>16)&0xff),
727 sal::static_int_cast< sal_uInt8 >((nIndex>>8)&0xff),
728 sal::static_int_cast< sal_uInt8 >(nIndex&0xff));
732 sal_uInt16 OS2METReader::ReadBigEndianWord()
734 sal_uInt8 nLo,nHi;
735 *pOS2MET >> nHi >> nLo;
736 return (((sal_uInt16)nHi)<<8)|(((sal_uInt16)nLo)&0x00ff);
739 sal_uLong OS2METReader::ReadBigEndian3BytesLong()
741 sal_uInt16 nLo;
742 sal_uInt8 nHi;
743 *pOS2MET >> nHi;
744 nLo=ReadBigEndianWord();
745 return ((((sal_uLong)nHi)<<16)&0x00ff0000)|((sal_uLong)nLo);
748 sal_uLong OS2METReader::ReadLittleEndian3BytesLong()
750 sal_uInt8 nHi,nMed,nLo;
752 *pOS2MET >> nLo >> nMed >> nHi;
753 return ((((sal_uLong)nHi)&0xff)<<16)|((((sal_uLong)nMed)&0xff)<<8)|(((sal_uLong)nLo)&0xff);
756 long OS2METReader::ReadCoord(sal_Bool b32)
758 sal_Int32 l;
760 if (b32) *pOS2MET >> l;
761 else { short s;*pOS2MET >> s; l=(sal_Int32)s; }
762 return l;
765 Point OS2METReader::ReadPoint( const sal_Bool bAdjustBoundRect )
767 long x,y;
769 x=ReadCoord(bCoord32);
770 y=ReadCoord(bCoord32);
771 x=x-aBoundingRect.Left();
772 y=aBoundingRect.Bottom()-y;
774 if ( bAdjustBoundRect )
775 aCalcBndRect.Union(Rectangle(x,y,x+1,y+1));
777 return Point(x,y);
780 RasterOp OS2METReader::OS2MixToRasterOp(sal_uInt8 nMix)
782 switch (nMix) {
783 case 0x0c: return ROP_INVERT;
784 case 0x04: return ROP_XOR;
785 case 0x0b: return ROP_XOR;
786 default: return ROP_OVERPAINT;
790 void OS2METReader::ReadLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
792 sal_uInt16 i,nPolySize;
794 if (bCoord32) nPolySize=nOrderLen/8; else nPolySize=nOrderLen/4;
795 if (!bGivenPos) nPolySize++;
796 if (nPolySize==0) return;
797 Polygon aPolygon(nPolySize);
798 for (i=0; i<nPolySize; i++) {
799 if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
800 else aPolygon.SetPoint(ReadPoint(),i);
802 aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
803 if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
804 else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
805 else
807 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
808 SetRasterOp(aAttr.eLinMix);
809 DrawPolyLine( aPolygon );
813 void OS2METReader::ReadRelLine(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
815 sal_uInt16 i,nPolySize;
816 Point aP0;
819 if (bGivenPos) {
820 aP0=ReadPoint();
821 if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
823 else aP0=aAttr.aCurPos;
824 nPolySize=nOrderLen/2;
825 if (nPolySize==0) return;
826 Polygon aPolygon(nPolySize);
827 for (i=0; i<nPolySize; i++) {
828 #if defined SOLARIS && defined PPC
829 sal_uInt8 nunsignedbyte;
830 *pOS2MET >> nunsignedbyte; aP0.X()+=(sal_Int8)nunsignedbyte;
831 *pOS2MET >> nunsignedbyte; aP0.Y()+=(sal_Int8)nunsignedbyte;
832 #else
833 sal_Int8 nsignedbyte;
834 *pOS2MET >> nsignedbyte; aP0.X()+=(long)nsignedbyte;
835 *pOS2MET >> nsignedbyte; aP0.Y()-=(long)nsignedbyte;
836 #endif
837 aCalcBndRect.Union(Rectangle(aP0,Size(1,1)));
838 aPolygon.SetPoint(aP0,i);
840 aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
841 if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
842 else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
843 else
845 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
846 SetRasterOp(aAttr.eLinMix);
847 DrawPolyLine( aPolygon );
851 void OS2METReader::ReadBox(sal_Bool bGivenPos)
853 sal_uInt8 nFlags;
854 Point P0;
855 long nHRound,nVRound;
857 *pOS2MET >> nFlags;
858 pOS2MET->SeekRel(1);
860 if ( bGivenPos )
861 P0 = ReadPoint();
862 else
863 P0 = aAttr.aCurPos;
865 aAttr.aCurPos=ReadPoint();
866 nHRound=ReadCoord(bCoord32);
867 nVRound=ReadCoord(bCoord32);
869 Rectangle aBoxRect( P0, aAttr.aCurPos );
871 if ( pAreaStack )
872 AddPointsToArea( Polygon( aBoxRect ) );
873 else if ( pPathStack )
874 AddPointsToPath( Polygon( aBoxRect ) );
875 else
877 if ( nFlags & 0x20 )
878 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
879 else
880 SetPen( COL_TRANSPARENT );
882 if ( nFlags & 0x40 )
884 ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
885 SetRasterOp(aAttr.ePatMix);
887 else
889 ChangeBrush( Color( COL_TRANSPARENT ), Color( COL_TRANSPARENT ), sal_False );
890 SetRasterOp(aAttr.eLinMix);
893 if ( IsLineInfo() )
895 Polygon aPolygon( aBoxRect, nHRound, nVRound );
896 if ( nFlags & 0x40 )
898 pVirDev->Push( PUSH_LINECOLOR );
899 pVirDev->SetLineColor( COL_TRANSPARENT );
900 pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
901 pVirDev->Pop();
903 pVirDev->DrawPolyLine( aPolygon, aLineInfo );
905 else
906 pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
910 void OS2METReader::ReadBitBlt()
912 Point aP1,aP2;
913 Size aSize;
914 sal_uInt32 nID;
915 OSBitmap * pB;
916 long nt;
918 pOS2MET->SeekRel(4);
919 *pOS2MET >> nID;
920 pOS2MET->SeekRel(4);
921 aP1=ReadPoint(); aP2=ReadPoint();
922 if (aP1.X() > aP2.X()) { nt=aP1.X(); aP1.X()=aP2.X(); aP2.X()=nt; }
923 if (aP1.Y() > aP2.Y()) { nt=aP1.Y(); aP1.Y()=aP2.Y(); aP2.Y()=nt; }
924 aSize=Size(aP2.X()-aP1.X(),aP2.Y()-aP1.Y());
926 pB=pBitmapList;
927 while (pB!=NULL && pB->nID!=nID) pB=pB->pSucc;
928 if (pB!=NULL) {
929 SetRasterOp(aAttr.ePatMix);
930 pVirDev->DrawBitmap(aP1,aSize,pB->aBitmap);
934 void OS2METReader::ReadChrStr(sal_Bool bGivenPos, sal_Bool bMove, sal_Bool bExtra, sal_uInt16 nOrderLen)
936 Point aP0;
937 sal_uInt16 i, nLen;
938 char * pChr;
939 OSFont * pF;
940 Font aFont;
941 Size aSize;
943 pF = pFontList;
944 while (pF!=NULL && pF->nID!=aAttr.nChrSet) pF=pF->pSucc;
945 if (pF!=NULL)
946 aFont = pF->aFont;
947 aFont.SetColor(aAttr.aChrCol);
948 aFont.SetSize(Size(0,aAttr.aChrCellSize.Height()));
949 if ( aAttr.nChrAng != 0 )
950 aFont.SetOrientation(aAttr.nChrAng);
952 if (bGivenPos)
953 aP0 = ReadPoint();
954 else
955 aP0 = aAttr.aCurPos;
956 if (bExtra)
958 pOS2MET->SeekRel(2);
959 ReadPoint( sal_False );
960 ReadPoint( sal_False );
961 *pOS2MET >> nLen;
963 else
965 if ( !bGivenPos )
966 nLen = nOrderLen;
967 else if ( bCoord32 )
968 nLen = nOrderLen-8;
969 else
970 nLen = nOrderLen-4;
972 pChr = new char[nLen+1];
973 for (i=0; i<nLen; i++)
974 *pOS2MET >> pChr[i];
975 pChr[nLen] = 0;
976 String aStr( (const sal_Char*)pChr, osl_getThreadTextEncoding() );
977 SetRasterOp(aAttr.eChrMix);
978 if (pVirDev->GetFont()!=aFont)
979 pVirDev->SetFont(aFont);
980 pVirDev->DrawText(aP0,aStr);
982 aSize = Size( pVirDev->GetTextWidth(aStr), pVirDev->GetTextHeight() );
983 if ( aAttr.nChrAng == 0 )
985 aCalcBndRect.Union(Rectangle( Point(aP0.X(),aP0.Y()-aSize.Height()),
986 Size(aSize.Width(),aSize.Height()*2)));
987 if (bMove)
988 aAttr.aCurPos = Point( aP0.X() + aSize.Width(), aP0.Y());
990 else
992 Polygon aDummyPoly(4);
994 aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() ), 0); // TOP LEFT
995 aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() - aSize.Height() ), 1); // BOTTOM LEFT
996 aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() ), 2); // TOP RIGHT
997 aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() - aSize.Height() ), 3);// BOTTOM RIGHT
998 aDummyPoly.Rotate( aP0, (short)aAttr.nChrAng );
999 if ( bMove )
1000 aAttr.aCurPos = aDummyPoly.GetPoint( 0 );
1001 aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 0 ), aDummyPoly.GetPoint( 3 ) ) );
1002 aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 1 ), aDummyPoly.GetPoint( 2 ) ) );
1004 delete[] pChr;
1007 void OS2METReader::ReadArc(sal_Bool bGivenPos)
1009 Point aP1, aP2, aP3;
1010 double x1,y1,x2,y2,x3,y3,p,q,cx,cy,ncx,ncy,r,rx,ry,w1,w3;
1011 if (bGivenPos) aP1=ReadPoint(); else aP1=aAttr.aCurPos;
1012 aP2=ReadPoint(); aP3=ReadPoint();
1013 aAttr.aCurPos=aP3;
1014 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1015 SetRasterOp(aAttr.eLinMix);
1016 // OK, gegeben sind 3 Punkte der Ellipse, und das Verhaeltnis
1017 // Breite zu Hoehe (als p zu q):
1018 x1=aP1.X(); y1=aP1.Y();
1019 x2=aP2.X(); y2=aP2.Y();
1020 x3=aP3.X(); y3=aP3.Y();
1021 p=aAttr.nArcP;q=aAttr.nArcQ;
1022 // Berechnet wird der Mittelpunkt cx,cy der Ellipse:
1023 ncy=2*p*p*((y3-y1)*(x2-x1)-(y1-y2)*(x1-x3));
1024 ncx=2*q*q*(x2-x1);
1025 if ( (ncx<0.001 && ncx>-0.001) || (ncy<0.001 && ncy>-0.001) ) {
1026 // Berechnung nicht moeglich, Punkte liegen auf einer Linie
1027 pVirDev->DrawLine(aP1,aP2);
1028 pVirDev->DrawLine(aP2,aP3);
1029 return;
1031 cy=( q*q*((x3*x3-x1*x1)*(x2-x1)+(x2*x2-x1*x1)*(x1-x3)) +
1032 p*p*((y3*y3-y1*y1)*(x2-x1)+(y2*y2-y1*y1)*(x1-x3)) ) / ncy;
1033 cx=( q*q*(x2*x2-x1*x1)+p*p*(y2*y2-y1*y1)+cy*2*p*p*(y1-y2) ) / ncx;
1034 // now we still need the radius in x and y direction:
1035 r=sqrt(q*q*(x1-cx)*(x1-cx)+p*p*(y1-cy)*(y1-cy));
1036 rx=r/q; ry=r/p;
1037 // Jetzt stellt sich "nur noch" die Frage, wie Start- und Endpunkt
1038 // gewaehlt werden muessen, damit Punkt Nr. 2 innerhalb des
1039 // gezeichneten Bogens liegt:
1040 w1=fmod((atan2(x1-cx,y1-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w1<0) w1+=6.28318530718;
1041 w3=fmod((atan2(x3-cx,y3-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w3<0) w3+=6.28318530718;
1042 if (w3<w1) {
1043 pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
1044 (long)(cx+rx),(long)(cy+ry)),aP1,aP3);
1046 else {
1047 pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
1048 (long)(cx+rx),(long)(cy+ry)),aP3,aP1);
1052 void OS2METReader::ReadFullArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize)
1054 Point aCenter;
1055 long nP,nQ,nR,nS;
1056 Rectangle aRect;
1057 sal_uInt32 nMul; sal_uInt16 nMulS;
1059 if (bGivenPos) {
1060 aCenter=ReadPoint();
1061 if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
1063 else aCenter=aAttr.aCurPos;
1065 nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
1066 if (nP<0) nP=-nP;
1067 if (nQ<0) nQ=-nQ;
1068 if (nR<0) nR=-nR;
1069 if (nS<0) nS=-nS;
1070 if (nOrderSize>=4) *pOS2MET >> nMul;
1071 else { *pOS2MET >> nMulS; nMul=((sal_uLong)nMulS)<<8; }
1072 if (nMul!=0x00010000) {
1073 nP=(nP*nMul)>>16;
1074 nQ=(nQ*nMul)>>16;
1075 nR=(nR*nMul)>>16;
1076 nS=(nS*nMul)>>16;
1079 aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
1080 aCenter.X()+nP,aCenter.Y()+nQ);
1081 aCalcBndRect.Union(aRect);
1083 if (pAreaStack!=NULL) {
1084 ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
1085 SetRasterOp(aAttr.ePatMix);
1086 if ((pAreaStack->nFlags&0x40)!=0)
1087 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1088 else
1089 SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1091 else
1093 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1094 ChangeBrush(Color( COL_TRANSPARENT ),Color( COL_TRANSPARENT ),sal_False);
1095 SetRasterOp(aAttr.eLinMix);
1097 pVirDev->DrawEllipse(aRect);
1100 void OS2METReader::ReadPartialArc(sal_Bool bGivenPos, sal_uInt16 nOrderSize)
1102 Point aP0, aCenter,aPStart,aPEnd;
1103 sal_Int32 nP,nQ,nR,nS,nStart, nSweep;
1104 Rectangle aRect;
1105 sal_uInt32 nMul; sal_uInt16 nMulS;
1106 double fStart, fEnd;
1108 if (bGivenPos) {
1109 aP0=ReadPoint();
1110 if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
1112 else aP0=aAttr.aCurPos;
1113 aCenter=ReadPoint();
1115 nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
1116 if (nP<0) nP=-nP;
1117 if (nQ<0) nQ=-nQ;
1118 if (nR<0) nR=-nR;
1119 if (nS<0) nS=-nS;
1120 if (nOrderSize>=12) *pOS2MET >> nMul;
1121 else { *pOS2MET >> nMulS; nMul=((sal_uLong)nMulS)<<8; }
1122 if (nMul!=0x00010000) {
1123 nP=(nP*nMul)>>16;
1124 nQ=(nQ*nMul)>>16;
1125 nR=(nR*nMul)>>16;
1126 nS=(nS*nMul)>>16;
1129 *pOS2MET >> nStart >> nSweep;
1130 fStart=((double)nStart)/65536.0/180.0*3.14159265359;
1131 fEnd=fStart+((double)nSweep)/65536.0/180.0*3.14159265359;
1132 aPStart=Point(aCenter.X()+(sal_Int32)( cos(fStart)*nP),
1133 aCenter.Y()+(sal_Int32)(-sin(fStart)*nQ));
1134 aPEnd= Point(aCenter.X()+(sal_Int32)( cos(fEnd)*nP),
1135 aCenter.Y()+(sal_Int32)(-sin(fEnd)*nQ));
1137 aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
1138 aCenter.X()+nP,aCenter.Y()+nQ);
1139 aCalcBndRect.Union(aRect);
1141 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1142 SetRasterOp(aAttr.eLinMix);
1144 pVirDev->DrawLine(aP0,aPStart);
1145 pVirDev->DrawArc(aRect,aPStart,aPEnd);
1146 aAttr.aCurPos=aPEnd;
1149 void OS2METReader::ReadPolygons()
1151 sal_uInt32 i,j,nNumPolys, nNumPoints;
1152 PolyPolygon aPolyPoly;
1153 Polygon aPoly;
1154 Point aPoint;
1155 sal_uInt8 nFlags;
1157 *pOS2MET >> nFlags >> nNumPolys;
1158 for (i=0; i<nNumPolys; i++) {
1159 *pOS2MET >> nNumPoints;
1160 if (i==0) nNumPoints++;
1161 aPoly.SetSize((short)nNumPoints);
1162 for (j=0; j<nNumPoints; j++) {
1163 if (i==0 && j==0) aPoint=aAttr.aCurPos;
1164 else aPoint=ReadPoint();
1165 aPoly.SetPoint(aPoint,(short)j);
1166 if (i==nNumPolys-1 && j==nNumPoints-1) aAttr.aCurPos=aPoint;
1168 aPolyPoly.Insert(aPoly);
1171 ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
1172 SetRasterOp(aAttr.ePatMix);
1173 if ((nFlags&0x01)!=0)
1174 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1175 else
1176 SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1177 DrawPolyPolygon( aPolyPoly );
1180 void OS2METReader::ReadBezier(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1182 sal_uInt16 i, nNumPoints = nOrderLen / ( bCoord32 ? 8 : 4 );
1184 if( !bGivenPos )
1185 nNumPoints++;
1187 if( !nNumPoints )
1188 return;
1190 Polygon aPolygon( nNumPoints );
1192 for( i=0; i < nNumPoints; i++ )
1194 if( i==0 && !bGivenPos)
1195 aPolygon.SetPoint( aAttr.aCurPos, i );
1196 else
1197 aPolygon.SetPoint( ReadPoint(), i );
1200 if( !( nNumPoints % 4 ) )
1202 // create bezier polygon
1203 const sal_uInt16 nSegPoints = 25;
1204 const sal_uInt16 nSegments = aPolygon.GetSize() >> 2;
1205 Polygon aBezPoly( nSegments * nSegPoints );
1207 sal_uInt16 nSeg, nBezPos, nStartPos;
1208 for( nSeg = 0, nBezPos = 0, nStartPos = 0; nSeg < nSegments; nSeg++, nStartPos += 4 )
1210 const Polygon aSegPoly( aPolygon[ nStartPos ], aPolygon[ nStartPos + 1 ],
1211 aPolygon[ nStartPos + 3 ], aPolygon[ nStartPos + 2 ],
1212 nSegPoints );
1214 for( sal_uInt16 nSegPos = 0; nSegPos < nSegPoints; )
1215 aBezPoly[ nBezPos++ ] = aSegPoly[ nSegPos++ ];
1218 nNumPoints = nBezPos;
1220 if( nNumPoints != aBezPoly.GetSize() )
1221 aBezPoly.SetSize( nNumPoints );
1223 aPolygon = aBezPoly;
1226 aAttr.aCurPos = aPolygon[ nNumPoints - 1 ];
1228 if (pAreaStack!=NULL)
1229 AddPointsToArea(aPolygon);
1230 else if (pPathStack!=NULL)
1231 AddPointsToPath(aPolygon);
1232 else
1234 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1235 SetRasterOp(aAttr.eLinMix);
1236 DrawPolyLine( aPolygon );
1240 void OS2METReader::ReadFillet(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1242 sal_uInt16 i,nNumPoints;
1244 if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
1245 if (!bGivenPos) nNumPoints++;
1246 if (nNumPoints==0) return;
1247 Polygon aPolygon(nNumPoints);
1248 for (i=0; i<nNumPoints; i++) {
1249 if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
1250 else aPolygon.SetPoint(ReadPoint(),i);
1252 aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
1253 if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
1254 else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
1255 else {
1256 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1257 SetRasterOp(aAttr.eLinMix);
1258 DrawPolyLine( aPolygon );
1262 void OS2METReader::ReadFilletSharp(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1264 sal_uInt16 i,nNumPoints;
1266 if (bGivenPos) {
1267 aAttr.aCurPos=ReadPoint();
1268 if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
1270 if (bCoord32) nNumPoints=1+nOrderLen/10;
1271 else nNumPoints=1+nOrderLen/6;
1272 Polygon aPolygon(nNumPoints);
1273 aPolygon.SetPoint(aAttr.aCurPos,0);
1274 for (i=1; i<nNumPoints; i++) aPolygon.SetPoint(ReadPoint(),i);
1275 aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
1276 if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
1277 else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
1278 else
1280 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1281 SetRasterOp(aAttr.eLinMix);
1282 DrawPolyLine( aPolygon );
1286 void OS2METReader::ReadMarker(sal_Bool bGivenPos, sal_uInt16 nOrderLen)
1288 sal_uInt16 i,nNumPoints;
1289 long x,y;
1291 SetPen( aAttr.aMrkCol );
1292 SetRasterOp(aAttr.eMrkMix);
1293 if (aAttr.nMrkSymbol>=5 && aAttr.nMrkSymbol<=9)
1295 ChangeBrush(aAttr.aMrkCol,aAttr.aMrkCol,sal_True);
1297 else
1299 ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1301 if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
1302 if (!bGivenPos) nNumPoints++;
1303 for (i=0; i<nNumPoints; i++) {
1304 if (i!=0 || bGivenPos) aAttr.aCurPos=ReadPoint();
1305 x=aAttr.aCurPos.X(); y=aAttr.aCurPos.Y();
1306 aCalcBndRect.Union(Rectangle(x-5,y-5,x+5,y+5));
1307 switch (aAttr.nMrkSymbol) {
1308 case 2: // PLUS
1309 pVirDev->DrawLine(Point(x-4,y),Point(x+4,y));
1310 pVirDev->DrawLine(Point(x,y-4),Point(x,y+4));
1311 break;
1312 case 3: // DIAMOND
1313 case 7: { // SOLIDDIAMOND
1314 Polygon aPoly(4);
1315 aPoly.SetPoint(Point(x,y+4),0);
1316 aPoly.SetPoint(Point(x+4,y),1);
1317 aPoly.SetPoint(Point(x,y-4),2);
1318 aPoly.SetPoint(Point(x-4,y),3);
1319 pVirDev->DrawPolygon(aPoly);
1320 break;
1322 case 4: // SQARE
1323 case 8: { // SOLIDSUARE
1324 Polygon aPoly(4);
1325 aPoly.SetPoint(Point(x+4,y+4),0);
1326 aPoly.SetPoint(Point(x+4,y-4),1);
1327 aPoly.SetPoint(Point(x-4,y-4),2);
1328 aPoly.SetPoint(Point(x-4,y+4),3);
1329 pVirDev->DrawPolygon(aPoly);
1330 break;
1332 case 5: { // SIXPOINTSTAR
1333 Polygon aPoly(12);
1334 aPoly.SetPoint(Point(x ,y-4),0);
1335 aPoly.SetPoint(Point(x+2,y-2),1);
1336 aPoly.SetPoint(Point(x+4,y-2),2);
1337 aPoly.SetPoint(Point(x+2,y ),3);
1338 aPoly.SetPoint(Point(x+4,y+2),4);
1339 aPoly.SetPoint(Point(x+2,y+2),5);
1340 aPoly.SetPoint(Point(x ,y+4),6);
1341 aPoly.SetPoint(Point(x-2,y+2),7);
1342 aPoly.SetPoint(Point(x-4,y+2),8);
1343 aPoly.SetPoint(Point(x-2,y ),9);
1344 aPoly.SetPoint(Point(x-4,y-2),10);
1345 aPoly.SetPoint(Point(x-2,y-2),11);
1346 pVirDev->DrawPolygon(aPoly);
1347 break;
1349 case 6: { // EIGHTPOINTSTAR
1350 Polygon aPoly(16);
1351 aPoly.SetPoint(Point(x ,y-4),0);
1352 aPoly.SetPoint(Point(x+1,y-2),1);
1353 aPoly.SetPoint(Point(x+3,y-3),2);
1354 aPoly.SetPoint(Point(x+2,y-1),3);
1355 aPoly.SetPoint(Point(x+4,y ),4);
1356 aPoly.SetPoint(Point(x+2,y+1),5);
1357 aPoly.SetPoint(Point(x+3,y+3),6);
1358 aPoly.SetPoint(Point(x+1,y+2),7);
1359 aPoly.SetPoint(Point(x ,y+4),8);
1360 aPoly.SetPoint(Point(x-1,y+2),9);
1361 aPoly.SetPoint(Point(x-3,y+3),10);
1362 aPoly.SetPoint(Point(x-2,y+1),11);
1363 aPoly.SetPoint(Point(x-4,y ),12);
1364 aPoly.SetPoint(Point(x-2,y-1),13);
1365 aPoly.SetPoint(Point(x-3,y-3),14);
1366 aPoly.SetPoint(Point(x-1,y-2),15);
1367 pVirDev->DrawPolygon(aPoly);
1368 break;
1370 case 9: // DOT
1371 pVirDev->DrawEllipse(Rectangle(x-1,y-1,x+1,y+1));
1372 break;
1373 case 10: // SMALLCIRCLE
1374 pVirDev->DrawEllipse(Rectangle(x-2,y-2,x+2,y+2));
1375 break;
1376 case 64: // BLANK
1377 break;
1378 default: // (=1) CROSS
1379 pVirDev->DrawLine(Point(x-4,y-4),Point(x+4,y+4));
1380 pVirDev->DrawLine(Point(x-4,y+4),Point(x+4,y-4));
1381 break;
1386 void OS2METReader::ReadOrder(sal_uInt16 nOrderID, sal_uInt16 nOrderLen)
1388 switch (nOrderID) {
1390 case GOrdGivArc: ReadArc(sal_True); break;
1391 case GOrdCurArc: ReadArc(sal_False); break;
1393 case GOrdGivBzr: ReadBezier(sal_True,nOrderLen); break;
1394 case GOrdCurBzr: ReadBezier(sal_False,nOrderLen); break;
1396 case GOrdGivBox: ReadBox(sal_True); break;
1397 case GOrdCurBox: ReadBox(sal_False); break;
1399 case GOrdGivFil: ReadFillet(sal_True,nOrderLen); break;
1400 case GOrdCurFil: ReadFillet(sal_False,nOrderLen); break;
1402 case GOrdGivCrc: ReadFullArc(sal_True,nOrderLen); break;
1403 case GOrdCurCrc: ReadFullArc(sal_False,nOrderLen); break;
1405 case GOrdGivLin: ReadLine(sal_True, nOrderLen); break;
1406 case GOrdCurLin: ReadLine(sal_False, nOrderLen); break;
1408 case GOrdGivMrk: ReadMarker(sal_True, nOrderLen); break;
1409 case GOrdCurMrk: ReadMarker(sal_False, nOrderLen); break;
1411 case GOrdGivArP: ReadPartialArc(sal_True,nOrderLen); break;
1412 case GOrdCurArP: ReadPartialArc(sal_False,nOrderLen); break;
1414 case GOrdGivRLn: ReadRelLine(sal_True,nOrderLen); break;
1415 case GOrdCurRLn: ReadRelLine(sal_False,nOrderLen); break;
1417 case GOrdGivSFl: ReadFilletSharp(sal_True,nOrderLen); break;
1418 case GOrdCurSFl: ReadFilletSharp(sal_False,nOrderLen); break;
1420 case GOrdGivStM: ReadChrStr(sal_True , sal_True , sal_False, nOrderLen); break;
1421 case GOrdCurStM: ReadChrStr(sal_False, sal_True , sal_False, nOrderLen); break;
1422 case GOrdGivStr: ReadChrStr(sal_True , sal_False, sal_False, nOrderLen); break;
1423 case GOrdCurStr: ReadChrStr(sal_False, sal_False, sal_False, nOrderLen); break;
1424 case GOrdGivStx: ReadChrStr(sal_True , sal_False, sal_True , nOrderLen); break;
1425 case GOrdCurStx: ReadChrStr(sal_False, sal_False, sal_True , nOrderLen); break;
1427 case GOrdGivImg: OOODEBUG("GOrdGivImg",0);
1428 break;
1429 case GOrdCurImg: OOODEBUG("GOrdCurImg",0);
1430 break;
1431 case GOrdImgDat: OOODEBUG("GOrdImgDat",0);
1432 break;
1433 case GOrdEndImg: OOODEBUG("GOrdEndImg",0);
1434 break;
1436 case GOrdBegAra: {
1437 OSArea * p=new OSArea;
1438 p->bClosed=sal_False;
1439 p->pSucc=pAreaStack; pAreaStack=p;
1440 *pOS2MET >> (p->nFlags);
1441 p->aCol=aAttr.aPatCol;
1442 p->aBgCol=aAttr.aPatBgCol;
1443 p->eMix=aAttr.ePatMix;
1444 p->eBgMix=aAttr.ePatBgMix;
1445 p->bFill=aAttr.bFill;
1446 break;
1448 case GOrdEndAra:
1450 OSArea * p=pAreaStack;
1451 if ( p )
1453 pAreaStack = p->pSucc;
1454 if ( pPathStack )
1456 for ( sal_uInt16 i=0; i<p->aPPoly.Count(); i++ )
1458 AddPointsToPath( p->aPPoly.GetObject( i ) );
1459 CloseFigure();
1462 else
1464 if ( ( p->nFlags & 0x40 ) == 0 )
1465 SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1466 else
1467 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1469 ChangeBrush(p->aCol,p->aBgCol,p->bFill);
1470 SetRasterOp(p->eMix);
1471 DrawPolyPolygon( p->aPPoly );
1473 delete p;
1476 break;
1478 case GOrdBegElm:// OOODEBUG("GOrdBegElm",0);
1479 break;
1480 case GOrdEndElm:// OOODEBUG("GOrdEndElm",0);
1481 break;
1483 case GOrdBegPth: {
1484 OSPath * p=new OSPath;
1485 p->pSucc=pPathStack; pPathStack=p;
1486 pOS2MET->SeekRel(2);
1487 *pOS2MET >> p->nID;
1488 p->bClosed=sal_False;
1489 p->bStroke=sal_False;
1490 break;
1492 case GOrdEndPth: {
1493 OSPath * p, * pprev, * psucc;
1494 if (pPathStack==NULL) break;
1495 p=pPathList; pprev=NULL;
1496 while (p!=NULL) {
1497 psucc=p->pSucc;
1498 if (p->nID==pPathStack->nID) {
1499 if (pprev==NULL) pPathList=psucc; else pprev->pSucc=psucc;
1500 delete p;
1502 else pprev=p;
1503 p=psucc;
1505 p=pPathStack;
1506 pPathStack=p->pSucc;
1507 p->pSucc=pPathList; pPathList=p;
1508 break;
1510 case GOrdFilPth:
1512 sal_uInt32 nID;
1513 sal_uInt16 nDummy;
1514 OSPath* p = pPathList;
1516 *pOS2MET >> nDummy
1517 >> nID;
1519 if ( ! ( nDummy & 0x20 ) ) // #30933# i do not know the exact meaning of this bit,
1520 { // but if set it seems to be better not to fill this path
1521 while( p && p->nID != nID )
1522 p = p->pSucc;
1524 if( p )
1526 if( p->bStroke )
1528 SetPen( aAttr.aPatCol, aAttr.nStrLinWidth, PEN_SOLID );
1529 ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1530 SetRasterOp( aAttr.ePatMix );
1531 if ( IsLineInfo() )
1533 for ( sal_uInt16 i = 0; i < p->aPPoly.Count(); i++ )
1534 pVirDev->DrawPolyLine( p->aPPoly.GetObject( i ), aLineInfo );
1536 else
1537 pVirDev->DrawPolyPolygon( p->aPPoly );
1539 else
1541 SetPen( COL_TRANSPARENT, 0, PEN_NULL );
1542 ChangeBrush( aAttr.aPatCol, aAttr.aPatBgCol, aAttr.bFill );
1543 SetRasterOp( aAttr.ePatMix );
1544 pVirDev->DrawPolyPolygon( p->aPPoly );
1549 break;
1551 case GOrdModPth:
1553 OSPath* p = pPathList;
1555 while( p && p->nID != 1 )
1556 p = p->pSucc;
1558 if( p )
1559 p->bStroke = sal_True;
1561 break;
1563 case GOrdOutPth:
1565 sal_uInt32 nID;
1566 sal_uInt16 i,nC;
1567 OSPath* p=pPathList;
1568 pOS2MET->SeekRel(2);
1569 *pOS2MET >> nID;
1570 while (p!=NULL && p->nID!=nID)
1571 p=p->pSucc;
1573 if( p!=NULL )
1575 SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
1576 SetRasterOp(aAttr.eLinMix);
1577 ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),sal_False);
1578 nC=p->aPPoly.Count();
1579 for (i=0; i<nC; i++)
1581 if (i+1<nC || p->bClosed==sal_True)
1582 DrawPolygon( p->aPPoly.GetObject( i ) );
1583 else
1584 DrawPolyLine( p->aPPoly.GetObject( i ) );
1587 break;
1589 case GOrdSClPth: { OOODEBUG("GOrdSClPth",0);
1590 sal_uInt32 nID;
1591 OSPath * p=pPathList;
1592 pOS2MET->SeekRel(2);
1593 *pOS2MET >> nID;
1594 if (nID==0) p=NULL;
1595 while (p!=NULL && p->nID!=nID) p=p->pSucc;
1596 if (p!=NULL) pVirDev->SetClipRegion(Region(p->aPPoly));
1597 else pVirDev->SetClipRegion();
1598 break;
1600 case GOrdNopNop:
1601 break;
1602 case GOrdRemark: //OOODEBUG("GOrdRemark",0);
1603 break;
1604 case GOrdSegLab: OOODEBUG("GOrdSegLab",0);
1605 break;
1607 case GOrdBitBlt: ReadBitBlt(); break;
1609 case GOrdCalSeg: OOODEBUG("GOrdCalSeg",0);
1610 break;
1611 case GOrdSSgBnd: OOODEBUG("GOrdSSgBnd",0);
1612 break;
1613 case GOrdSegChr: OOODEBUG("GOrdSegChr",0);
1614 break;
1615 case GOrdCloFig:
1616 CloseFigure();
1617 break;
1618 case GOrdEndSym: OOODEBUG("GOrdEndSym",0);
1619 break;
1620 case GOrdEndPlg: OOODEBUG("GOrdEndPlg",0);
1621 break;
1622 case GOrdEscape: OOODEBUG("GOrdEscape",0);
1623 break;
1624 case GOrdExtEsc: OOODEBUG("GOrdExtEsc",0);
1625 break;
1627 case GOrdPolygn: ReadPolygons(); break;
1629 case GOrdStkPop: PopAttr(); break;
1631 case GOrdPIvAtr: PushAttr(nOrderID);
1632 case GOrdSIvAtr: {
1633 sal_uInt8 nA, nP, nFlags, nMix;
1634 sal_uLong nVal;
1635 Color aCol;
1636 RasterOp eROP;
1637 *pOS2MET >> nA >> nP >> nFlags;
1638 if (nOrderID==GOrdPIvAtr) {
1639 pAttrStack->nIvAttrA=nA;
1640 pAttrStack->nIvAttrP=nP;
1642 if (nA<=2) {
1643 if ((nFlags&0x80)!=0) {
1644 if (nA==1) switch (nP) {
1645 case 1: aAttr.aLinCol=aDefAttr.aLinCol; break;
1646 case 2: aAttr.aChrCol=aDefAttr.aChrCol; break;
1647 case 3: aAttr.aMrkCol=aDefAttr.aMrkCol; break;
1648 case 4: aAttr.aPatCol=aDefAttr.aPatCol; break;
1649 case 5: aAttr.aImgCol=aDefAttr.aImgCol; break;
1651 else switch (nP) {
1652 case 1: aAttr.aLinBgCol=aDefAttr.aLinBgCol; break;
1653 case 2: aAttr.aChrBgCol=aDefAttr.aChrBgCol; break;
1654 case 3: aAttr.aMrkBgCol=aDefAttr.aMrkBgCol; break;
1655 case 4: aAttr.aPatBgCol=aDefAttr.aPatBgCol; break;
1656 case 5: aAttr.aImgBgCol=aDefAttr.aImgBgCol; break;
1659 else {
1660 nVal=ReadLittleEndian3BytesLong();
1661 if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1662 else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1663 else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1664 else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1665 else aCol=GetPaletteColor(nVal);
1666 if (nA==1) switch (nP) {
1667 case 1: aAttr.aLinCol=aCol; break;
1668 case 2: aAttr.aChrCol=aCol; break;
1669 case 3: aAttr.aMrkCol=aCol; break;
1670 case 4: aAttr.aPatCol=aCol; break;
1671 case 5: aAttr.aImgCol=aCol; break;
1673 else switch (nP) {
1674 case 1: aAttr.aLinBgCol=aCol; break;
1675 case 2: aAttr.aChrBgCol=aCol; break;
1676 case 3: aAttr.aMrkBgCol=aCol; break;
1677 case 4: aAttr.aPatBgCol=aCol; break;
1678 case 5: aAttr.aImgBgCol=aCol; break;
1682 else {
1683 *pOS2MET >> nMix;
1684 if (nMix==0) {
1685 if (nA==1) switch (nP) {
1686 case 1: aAttr.eLinMix=aDefAttr.eLinMix; break;
1687 case 2: aAttr.eChrMix=aDefAttr.eChrMix; break;
1688 case 3: aAttr.eMrkMix=aDefAttr.eMrkMix; break;
1689 case 4: aAttr.ePatMix=aDefAttr.ePatMix; break;
1690 case 5: aAttr.eImgMix=aDefAttr.eImgMix; break;
1692 else switch (nP) {
1693 case 1: aAttr.eLinBgMix=aDefAttr.eLinBgMix; break;
1694 case 2: aAttr.eChrBgMix=aDefAttr.eChrBgMix; break;
1695 case 3: aAttr.eMrkBgMix=aDefAttr.eMrkBgMix; break;
1696 case 4: aAttr.ePatBgMix=aDefAttr.ePatBgMix; break;
1697 case 5: aAttr.eImgBgMix=aDefAttr.eImgBgMix; break;
1700 else {
1701 eROP=OS2MixToRasterOp(nMix);
1702 if (nA==1) switch (nP) {
1703 case 1: aAttr.eLinMix=eROP; break;
1704 case 2: aAttr.eChrMix=eROP; break;
1705 case 3: aAttr.eMrkMix=eROP; break;
1706 case 4: aAttr.ePatMix=eROP; break;
1707 case 5: aAttr.eImgMix=eROP; break;
1709 else switch (nP) {
1710 case 1: aAttr.eLinBgMix=eROP; break;
1711 case 2: aAttr.eChrBgMix=eROP; break;
1712 case 3: aAttr.eMrkBgMix=eROP; break;
1713 case 4: aAttr.ePatBgMix=eROP; break;
1714 case 5: aAttr.eImgBgMix=eROP; break;
1718 break;
1720 case GOrdPIxCol: PushAttr(nOrderID);
1721 case GOrdSIxCol: {
1722 sal_uInt8 nFlags;
1723 sal_uLong nVal;
1724 Color aCol;
1725 *pOS2MET >> nFlags;
1726 if ((nFlags&0x80)!=0) {
1727 aAttr.aLinCol=aDefAttr.aLinCol;
1728 aAttr.aChrCol=aDefAttr.aChrCol;
1729 aAttr.aMrkCol=aDefAttr.aMrkCol;
1730 aAttr.aPatCol=aDefAttr.aPatCol;
1731 aAttr.aImgCol=aDefAttr.aImgCol;
1733 else {
1734 nVal=ReadLittleEndian3BytesLong();
1735 if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1736 else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1737 else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1738 else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1739 else aCol=GetPaletteColor(nVal);
1740 aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
1741 aAttr.aImgCol = aCol;
1743 break;
1746 case GOrdPColor:
1747 case GOrdPXtCol: PushAttr(nOrderID);
1748 case GOrdSColor:
1749 case GOrdSXtCol: {
1750 sal_uInt8 nbyte;
1751 sal_uInt16 nVal;
1752 Color aCol;
1753 if (nOrderID==GOrdPColor || nOrderID==GOrdSColor) {
1754 *pOS2MET >> nbyte; nVal=((sal_uInt16)nbyte)|0xff00;
1756 else *pOS2MET >> nVal;
1757 if (nVal==0x0000 || nVal==0xff00) {
1758 aAttr.aLinCol=aDefAttr.aLinCol;
1759 aAttr.aChrCol=aDefAttr.aChrCol;
1760 aAttr.aMrkCol=aDefAttr.aMrkCol;
1761 aAttr.aPatCol=aDefAttr.aPatCol;
1762 aAttr.aImgCol=aDefAttr.aImgCol;
1764 else {
1765 if (nVal==0x0007) aCol=Color(COL_WHITE);
1766 else if (nVal==0x0008) aCol=Color(COL_BLACK);
1767 else if (nVal==0xff08) aCol=GetPaletteColor(1);
1768 else aCol=GetPaletteColor(((sal_uLong)nVal) & 0x000000ff);
1769 aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
1770 aAttr.aImgCol = aCol;
1772 break;
1775 case GOrdPBgCol: PushAttr(nOrderID);
1776 case GOrdSBgCol: {
1777 sal_uInt16 nVal;
1778 Color aCol;
1779 *pOS2MET >> nVal;
1780 if (nVal==0x0000 || nVal==0xff00) {
1781 aAttr.aLinBgCol=aDefAttr.aLinBgCol;
1782 aAttr.aChrBgCol=aDefAttr.aChrBgCol;
1783 aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
1784 aAttr.aPatBgCol=aDefAttr.aPatBgCol;
1785 aAttr.aImgBgCol=aDefAttr.aImgBgCol;
1787 else {
1788 if (nVal==0x0007) aCol=Color(COL_WHITE);
1789 else if (nVal==0x0008) aCol=Color(COL_BLACK);
1790 else if (nVal==0xff08) aCol=GetPaletteColor(0);
1791 else aCol=GetPaletteColor(((sal_uLong)nVal) & 0x000000ff);
1792 aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
1793 aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
1795 break;
1797 case GOrdPBxCol: PushAttr(nOrderID);
1798 case GOrdSBxCol: {
1799 sal_uInt8 nFlags;
1800 sal_uLong nVal;
1801 Color aCol;
1802 *pOS2MET >> nFlags;
1803 if ((nFlags&0x80)!=0) {
1804 aAttr.aLinBgCol=aDefAttr.aLinBgCol;
1805 aAttr.aChrBgCol=aDefAttr.aChrBgCol;
1806 aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
1807 aAttr.aPatBgCol=aDefAttr.aPatBgCol;
1808 aAttr.aImgBgCol=aDefAttr.aImgBgCol;
1810 else {
1811 nVal=ReadLittleEndian3BytesLong();
1812 if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
1813 else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
1814 else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
1815 else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
1816 else aCol=GetPaletteColor(nVal);
1817 aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
1818 aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
1820 break;
1823 case GOrdPMixMd: PushAttr(nOrderID);
1824 case GOrdSMixMd: {
1825 sal_uInt8 nMix;
1826 *pOS2MET >> nMix;
1827 if (nMix==0) {
1828 aAttr.eLinMix=aDefAttr.eLinMix;
1829 aAttr.eChrMix=aDefAttr.eChrMix;
1830 aAttr.eMrkMix=aDefAttr.eMrkMix;
1831 aAttr.ePatMix=aDefAttr.ePatMix;
1832 aAttr.eImgMix=aDefAttr.eImgMix;
1834 else {
1835 aAttr.eLinMix = aAttr.eChrMix = aAttr.eMrkMix =
1836 aAttr.ePatMix = aAttr.eImgMix = OS2MixToRasterOp(nMix);
1838 break;
1840 case GOrdPBgMix: PushAttr(nOrderID);
1841 case GOrdSBgMix: {
1842 sal_uInt8 nMix;
1843 *pOS2MET >> nMix;
1844 if (nMix==0) {
1845 aAttr.eLinBgMix=aDefAttr.eLinBgMix;
1846 aAttr.eChrBgMix=aDefAttr.eChrBgMix;
1847 aAttr.eMrkBgMix=aDefAttr.eMrkBgMix;
1848 aAttr.ePatBgMix=aDefAttr.ePatBgMix;
1849 aAttr.eImgBgMix=aDefAttr.eImgBgMix;
1851 else {
1852 aAttr.eLinBgMix = aAttr.eChrBgMix = aAttr.eMrkBgMix =
1853 aAttr.ePatBgMix = aAttr.eImgBgMix = OS2MixToRasterOp(nMix);
1855 break;
1857 case GOrdPPtSet: PushAttr(nOrderID);
1858 case GOrdSPtSet: OOODEBUG("GOrdSPtSet",0);
1859 break;
1861 case GOrdPPtSym: PushAttr(nOrderID);
1862 case GOrdSPtSym: {
1863 sal_uInt8 nPatt;
1864 *pOS2MET >> nPatt;
1865 aAttr.bFill = ( nPatt != 0x0f );
1866 break;
1869 case GOrdPPtRef: PushAttr(nOrderID);
1870 case GOrdSPtRef: OOODEBUG("GOrdSPtRef",0);
1871 break;
1873 case GOrdPLnEnd: PushAttr(nOrderID);
1874 case GOrdSLnEnd:
1875 break;
1877 case GOrdPLnJoi: PushAttr(nOrderID);
1878 case GOrdSLnJoi:
1879 break;
1881 case GOrdPLnTyp: PushAttr(nOrderID);
1882 case GOrdSLnTyp: {
1883 sal_uInt8 nType;
1884 *pOS2MET >> nType;
1885 switch (nType) {
1886 case 0: aAttr.eLinStyle=aDefAttr.eLinStyle; break;
1887 case 1: case 4: aAttr.eLinStyle=PEN_DOT; break;
1888 case 2: case 5: aAttr.eLinStyle=PEN_DASH; break;
1889 case 3: case 6: aAttr.eLinStyle=PEN_DASHDOT; break;
1890 case 8: aAttr.eLinStyle=PEN_NULL; break;
1891 default: aAttr.eLinStyle=PEN_SOLID;
1893 break;
1895 case GOrdPLnWdt: PushAttr(nOrderID);
1896 case GOrdSLnWdt: {
1897 sal_uInt8 nbyte;
1898 *pOS2MET >> nbyte;
1899 if (nbyte==0) aAttr.nLinWidth=aDefAttr.nLinWidth;
1900 else aAttr.nLinWidth=(sal_uInt16)nbyte-1;
1901 break;
1903 case GOrdPFrLWd: PushAttr(nOrderID);
1904 case GOrdSFrLWd:
1905 break;
1907 case GOrdPStLWd: PushAttr(nOrderID);
1908 case GOrdSStLWd :
1910 sal_uInt8 nFlags;
1912 *pOS2MET >> nFlags;
1913 if ( nFlags & 0x80 )
1914 aAttr.nStrLinWidth = aDefAttr.nStrLinWidth;
1915 else
1917 pOS2MET->SeekRel( 1 );
1918 long nWd = ReadCoord( bCoord32 );
1919 if ( nWd < 0 )
1920 nWd = -nWd;
1921 aAttr.nStrLinWidth = (sal_uInt16)nWd;
1923 break;
1925 case GOrdPChDir: PushAttr(nOrderID);
1926 case GOrdSChDir:
1927 break;
1929 case GOrdPChPrc: PushAttr(nOrderID);
1930 case GOrdSChPrc:
1931 break;
1933 case GOrdPChSet: PushAttr(nOrderID);
1934 case GOrdSChSet: {
1935 sal_uInt8 nbyte; *pOS2MET >> nbyte;
1936 aAttr.nChrSet=((sal_uLong)nbyte)&0xff;
1937 break;
1939 case GOrdPChAng: PushAttr(nOrderID);
1940 case GOrdSChAng: {
1941 long nX,nY;
1942 nX=ReadCoord(bCoord32); nY=ReadCoord(bCoord32);
1943 if (nX>=0 && nY==0) aAttr.nChrAng=0;
1944 else {
1945 aAttr.nChrAng=(short)(atan2((double)nY,(double)nX)/3.1415926539*1800.0);
1946 while (aAttr.nChrAng<0) aAttr.nChrAng+=3600;
1947 aAttr.nChrAng%=3600;
1949 break;
1951 case GOrdPChBrx: PushAttr(nOrderID);
1952 case GOrdSChBrx:
1953 break;
1955 case GOrdPChCel: PushAttr(nOrderID);
1956 case GOrdSChCel: {
1957 sal_uInt8 nbyte;
1958 sal_uInt16 nLen=nOrderLen;
1959 aAttr.aChrCellSize.Width()=ReadCoord(bCoord32);
1960 aAttr.aChrCellSize.Height()=ReadCoord(bCoord32);
1961 if (bCoord32) nLen-=8; else nLen-=4;
1962 if (nLen>=4) {
1963 pOS2MET->SeekRel(4); nLen-=4;
1965 if (nLen>=2) {
1966 *pOS2MET >> nbyte;
1967 if ((nbyte&0x80)==0 && aAttr.aChrCellSize==Size(0,0))
1968 aAttr.aChrCellSize=aDefAttr.aChrCellSize;
1970 break;
1972 case GOrdPChXtr: PushAttr(nOrderID);
1973 case GOrdSChXtr:
1974 break;
1976 case GOrdPChShr: PushAttr(nOrderID);
1977 case GOrdSChShr:
1978 break;
1980 case GOrdPTxAlg: PushAttr(nOrderID);
1981 case GOrdSTxAlg: OOODEBUG("GOrdSTxAlg",0);
1982 break;
1984 case GOrdPMkPrc: PushAttr(nOrderID);
1985 case GOrdSMkPrc: {
1986 sal_uInt8 nbyte;
1987 *pOS2MET >> nbyte;
1988 if (nbyte==0) aAttr.nMrkPrec=aDefAttr.nMrkPrec;
1989 else aAttr.nMrkPrec=nbyte;
1990 break;
1993 case GOrdPMkSet: PushAttr(nOrderID);
1994 case GOrdSMkSet: {
1995 sal_uInt8 nbyte;
1996 *pOS2MET >> nbyte;
1997 if (nbyte==0) aAttr.nMrkSet=aDefAttr.nMrkSet;
1998 else aAttr.nMrkSet=nbyte;
1999 break;
2002 case GOrdPMkSym: PushAttr(nOrderID);
2003 case GOrdSMkSym: {
2004 sal_uInt8 nbyte;
2005 *pOS2MET >> nbyte;
2006 if (nbyte==0) aAttr.nMrkSymbol=aDefAttr.nMrkSymbol;
2007 else aAttr.nMrkSymbol=nbyte;
2008 break;
2011 case GOrdPMkCel: PushAttr(nOrderID);
2012 case GOrdSMkCel: {
2013 sal_uInt8 nbyte;
2014 sal_uInt16 nLen=nOrderLen;
2015 aAttr.aMrkCellSize.Width()=ReadCoord(bCoord32);
2016 aAttr.aMrkCellSize.Height()=ReadCoord(bCoord32);
2017 if (bCoord32) nLen-=8; else nLen-=4;
2018 if (nLen>=2) {
2019 *pOS2MET >> nbyte;
2020 if ((nbyte&0x80)==0 && aAttr.aMrkCellSize==Size(0,0))
2021 aAttr.aMrkCellSize=aDefAttr.aMrkCellSize;
2023 break;
2026 case GOrdPArcPa: PushAttr(nOrderID);
2027 case GOrdSArcPa:
2028 aAttr.nArcP=ReadCoord(bCoord32);
2029 aAttr.nArcQ=ReadCoord(bCoord32);
2030 aAttr.nArcR=ReadCoord(bCoord32);
2031 aAttr.nArcS=ReadCoord(bCoord32);
2032 break;
2034 case GOrdPCrPos: PushAttr(nOrderID);
2035 case GOrdSCrPos:
2036 aAttr.aCurPos=ReadPoint();
2037 break;
2039 case GOrdPMdTrn: PushAttr(nOrderID);
2040 case GOrdSMdTrn: OOODEBUG("GOrdSMdTrn",0);
2041 break;
2043 case GOrdPPkIdn: PushAttr(nOrderID);
2044 case GOrdSPkIdn: OOODEBUG("GOrdSPkIdn",0);
2045 break;
2047 case GOrdSVwTrn: OOODEBUG("GOrdSVwTrn",0);
2048 break;
2050 case GOrdPVwWin: PushAttr(nOrderID);
2051 case GOrdSVwWin: OOODEBUG("GOrdSVwWin",0);
2052 break;
2053 default: OOODEBUG("Order unbekannt:",nOrderID);
2057 void OS2METReader::ReadDsc(sal_uInt16 nDscID, sal_uInt16 /*nDscLen*/)
2059 switch (nDscID) {
2060 case 0x00f7: { // 'Specify GVM Subset'
2061 sal_uInt8 nbyte;
2062 pOS2MET->SeekRel(6);
2063 *pOS2MET >> nbyte;
2064 if (nbyte==0x05) bCoord32=sal_True;
2065 else if (nbyte==0x04) bCoord32=sal_False;
2066 else {
2067 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2068 ErrorCode=1;
2070 break;
2072 case 0x00f6:
2074 // 'Set Picture Descriptor'
2075 sal_Bool b32;
2076 sal_uInt8 nbyte,nUnitType;
2077 long x1,y1,x2,y2,nt,xr,yr;
2079 pOS2MET->SeekRel(2);
2080 *pOS2MET >> nbyte;
2082 if (nbyte==0x05)
2083 b32=sal_True;
2084 else if(nbyte==0x04)
2085 b32=sal_False;
2086 else
2088 b32 = sal_False; // -Wall added the case.
2089 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2090 ErrorCode=2;
2093 *pOS2MET >> nUnitType;
2095 xr=ReadCoord(b32);
2096 yr=ReadCoord(b32);
2098 ReadCoord(b32);
2100 if (nUnitType==0x00 && xr>0 && yr>0)
2101 aGlobMapMode=MapMode(MAP_INCH,Point(0,0),Fraction(10,xr),Fraction(10,yr));
2102 else if (nUnitType==0x01 && xr>0 && yr>0)
2103 aGlobMapMode=MapMode(MAP_CM,Point(0,0),Fraction(10,xr),Fraction(10,yr));
2104 else
2105 aGlobMapMode=MapMode();
2107 x1=ReadCoord(b32);
2108 x2=ReadCoord(b32);
2109 y1=ReadCoord(b32);
2110 y2=ReadCoord(b32);
2112 if (x1>x2)
2114 nt=x1;
2115 x1=x2;
2116 x2=nt;
2119 if (y1>y2)
2121 nt=y1;
2122 y1=y2;
2123 y2=nt;
2126 aBoundingRect.Left() = x1;
2127 aBoundingRect.Right() = x2;
2128 aBoundingRect.Top() = y1;
2129 aBoundingRect.Bottom() = y2;
2131 // no output beside this bounding rect
2132 pVirDev->IntersectClipRegion( Rectangle( Point(), aBoundingRect.GetSize() ) );
2134 break;
2136 case 0x0021: // 'Set Current Defaults'
2137 break;
2141 void OS2METReader::ReadImageData(sal_uInt16 nDataID, sal_uInt16 nDataLen)
2143 OSBitmap * p=pBitmapList; if (p==NULL) return;
2145 switch (nDataID) {
2147 case 0x0070: // Begin Segment
2148 break;
2150 case 0x0091: // Begin Image Content
2151 break;
2153 case 0x0094: // Image Size
2154 pOS2MET->SeekRel(5);
2155 p->nHeight=ReadBigEndianWord();
2156 p->nWidth=ReadBigEndianWord();
2157 break;
2159 case 0x0095: // Image Encoding
2160 break;
2162 case 0x0096: { // Image IDE-Size
2163 sal_uInt8 nbyte;
2164 *pOS2MET >> nbyte; p->nBitsPerPixel=nbyte;
2165 break;
2168 case 0x0097: // Image LUT-ID
2169 break;
2171 case 0x009b: // IDE Structure
2172 break;
2174 case 0xfe92: { // Image Data
2175 // Spaetestens jetzt brauchen wir die temporaere BMP-Datei
2176 // und darin mindestens den Header + Palette.
2177 if (p->pBMP==NULL) {
2178 p->pBMP=new SvMemoryStream();
2179 p->pBMP->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2180 if (p->nWidth==0 || p->nHeight==0 || p->nBitsPerPixel==0) {
2181 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2182 ErrorCode=3;
2183 return;
2185 // write (Windows-)BITMAPINFOHEADER:
2186 *(p->pBMP) << ((sal_uInt32)40) << p->nWidth << p->nHeight;
2187 *(p->pBMP) << ((sal_uInt16)1) << p->nBitsPerPixel;
2188 *(p->pBMP) << ((sal_uInt32)0) << ((sal_uInt32)0) << ((sal_uInt32)0) << ((sal_uInt32)0);
2189 *(p->pBMP) << ((sal_uInt32)0) << ((sal_uInt32)0);
2190 // write color table:
2191 if (p->nBitsPerPixel<=8) {
2192 sal_uInt16 i, nColTabSize=1<<(p->nBitsPerPixel);
2193 for (i=0; i<nColTabSize; i++) *(p->pBMP) << GetPalette0RGB(i);
2196 // OK, nun werden die Map-Daten ruebergeschoben. Leider haben OS2 und
2197 // BMP eine unterschiedliche Reihenfolge von RGB bei 24-Bit.
2198 sal_uInt8 * pBuf=new sal_uInt8[nDataLen];
2199 pOS2MET->Read(pBuf,nDataLen);
2200 if (p->nBitsPerPixel==24) {
2201 sal_uLong i, j, nAlign, nBytesPerLine;
2202 sal_uInt8 nTemp;
2203 nBytesPerLine=(p->nWidth*3+3)&0xfffffffc;
2204 nAlign=p->nMapPos-(p->nMapPos % nBytesPerLine);
2205 i=0;
2206 while (nAlign+i+2<p->nMapPos+nDataLen) {
2207 if (nAlign+i>=p->nMapPos) {
2208 j=nAlign+i-p->nMapPos;
2209 nTemp=pBuf[j]; pBuf[j]=pBuf[j+2]; pBuf[j+2]=nTemp;
2211 i+=3; if (i+2>=nBytesPerLine) {
2212 nAlign+=nBytesPerLine;
2213 i=0;
2217 p->pBMP->Write(pBuf,nDataLen);
2218 p->nMapPos+=nDataLen;
2219 delete[] pBuf;
2220 break;
2222 case 0x0093: // End Image Content
2223 break;
2225 case 0x0071: // End Segment
2226 break;
2230 void OS2METReader::ReadFont(sal_uInt16 nFieldSize)
2232 sal_uLong nPos, nMaxPos;
2233 sal_uInt16 nLen;
2234 sal_uInt8 nByte, nTripType, nTripType2;
2235 OSFont * pF=new OSFont;
2236 pF->pSucc=pFontList; pFontList=pF;
2237 pF->nID=0;
2238 pF->aFont.SetTransparent(sal_True);
2239 pF->aFont.SetAlign(ALIGN_BASELINE);
2241 nPos=pOS2MET->Tell();
2242 nMaxPos=nPos+(sal_uLong)nFieldSize;
2243 pOS2MET->SeekRel(2); nPos+=2;
2244 while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2245 *pOS2MET >> nByte; nLen =((sal_uInt16)nByte) & 0x00ff;
2246 *pOS2MET >> nTripType;
2247 switch (nTripType) {
2248 case 0x02:
2249 *pOS2MET >> nTripType2;
2250 switch (nTripType2) {
2251 case 0x84: // Font name
2252 break;
2253 case 0x08: { // Font Typeface
2254 char str[33];
2255 pOS2MET->SeekRel(1);
2256 pOS2MET->Read( &str, 32 );
2257 str[ 32 ] = 0;
2258 String aStr( (const sal_Char*)str, osl_getThreadTextEncoding() );
2259 if ( aStr.CompareIgnoreCaseToAscii( "Helv" ) == COMPARE_EQUAL )
2260 aStr = rtl::OUString("Helvetica");
2261 pF->aFont.SetName( aStr );
2262 break;
2265 break;
2266 case 0x24: // Icid
2267 *pOS2MET >> nTripType2;
2268 switch (nTripType2) {
2269 case 0x05: //Icid
2270 *pOS2MET >> nByte;
2271 pF->nID=((sal_uLong)nByte)&0xff;
2272 break;
2274 break;
2275 case 0x20: // Font Binary GCID
2276 break;
2277 case 0x1f: { // Font Attributes
2278 FontWeight eWeight;
2279 sal_uInt8 nbyte;
2280 *pOS2MET >> nbyte;
2281 switch (nbyte) {
2282 case 1: eWeight=WEIGHT_THIN; break;
2283 case 2: eWeight=WEIGHT_ULTRALIGHT; break;
2284 case 3: eWeight=WEIGHT_LIGHT; break;
2285 case 4: eWeight=WEIGHT_SEMILIGHT; break;
2286 case 5: eWeight=WEIGHT_NORMAL; break;
2287 case 6: eWeight=WEIGHT_SEMIBOLD; break;
2288 case 7: eWeight=WEIGHT_BOLD; break;
2289 case 8: eWeight=WEIGHT_ULTRABOLD; break;
2290 case 9: eWeight=WEIGHT_BLACK; break;
2291 default: eWeight=WEIGHT_DONTKNOW;
2293 pF->aFont.SetWeight(eWeight);
2294 break;
2297 nPos+=nLen; pOS2MET->Seek(nPos);
2301 void OS2METReader::ReadField(sal_uInt16 nFieldType, sal_uInt16 nFieldSize)
2303 switch (nFieldType) {
2304 case BegDocumnMagic:
2305 break;
2306 case EndDocumnMagic:
2307 break;
2308 case BegResGrpMagic:
2309 break;
2310 case EndResGrpMagic:
2311 break;
2312 case BegColAtrMagic:
2313 break;
2314 case EndColAtrMagic:
2315 break;
2316 case BlkColAtrMagic: {
2317 sal_uLong nPos, nMaxPos;
2318 sal_uInt8 nbyte;
2319 sal_uLong nCol;
2320 sal_uInt16 nStartIndex, nEndIndex, i, nElemLen, nBytesPerCol;
2322 nPos=pOS2MET->Tell();
2323 nMaxPos=nPos+(sal_uLong)nFieldSize;
2324 pOS2MET->SeekRel(3); nPos+=3;
2325 while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2326 *pOS2MET >> nbyte; nElemLen=((sal_uInt16)nbyte) & 0x00ff;
2327 if (nElemLen>11) {
2328 pOS2MET->SeekRel(4);
2329 nStartIndex=ReadBigEndianWord();
2330 pOS2MET->SeekRel(3);
2331 *pOS2MET >> nbyte; nBytesPerCol=((sal_uInt16)nbyte) & 0x00ff;
2332 nEndIndex=nStartIndex+(nElemLen-11)/nBytesPerCol;
2333 for (i=nStartIndex; i<nEndIndex; i++) {
2334 if (nBytesPerCol > 3) pOS2MET->SeekRel(nBytesPerCol-3);
2335 nCol=ReadBigEndian3BytesLong();
2336 SetPalette0RGB(i,nCol);
2339 else if (nElemLen<10) {
2340 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2341 ErrorCode=4;
2343 nPos+=(sal_uLong)nElemLen;
2344 pOS2MET->Seek(nPos);
2346 break;
2348 case MapColAtrMagic:
2349 break;
2350 case BegImgObjMagic: {
2351 // neue Bitmap schonmal herstellen: (wird spaeter gefuellt)
2352 OSBitmap * pB=new OSBitmap;
2353 pB->pSucc=pBitmapList; pBitmapList=pB;
2354 pB->pBMP=NULL; pB->nWidth=0; pB->nHeight=0; pB->nBitsPerPixel=0;
2355 pB->nMapPos=0;
2356 // determine ID of the bitmap:
2357 sal_uInt8 i,nbyte,nbyte2;
2358 pB->nID=0;
2359 for (i=0; i<4; i++) {
2360 *pOS2MET >> nbyte >> nbyte2;
2361 nbyte=((nbyte-0x30)<<4)|(nbyte2-0x30);
2362 pB->nID=(pB->nID>>8)|(((sal_uLong)nbyte)<<24);
2364 // neue Palette auf den Paletten-Stack bringen: (wird spaeter gefuellt)
2365 OSPalette * pP=new OSPalette;
2366 pP->pSucc=pPaletteStack; pPaletteStack=pP;
2367 pP->p0RGB=NULL; pP->nSize=0;
2368 break;
2370 case EndImgObjMagic: {
2371 // Temporaere Windows-BMP-Datei auslesen:
2372 if (pBitmapList==NULL || pBitmapList->pBMP==NULL ||
2373 pBitmapList->pBMP->GetError()!=0) {
2374 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2375 ErrorCode=5;
2376 return;
2378 pBitmapList->pBMP->Seek(0);
2380 pBitmapList->aBitmap.Read( *( pBitmapList->pBMP ), sal_False );
2382 if (pBitmapList->pBMP->GetError()!=0) {
2383 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2384 ErrorCode=6;
2386 delete pBitmapList->pBMP; pBitmapList->pBMP=NULL;
2387 // kill palette from stack:
2388 OSPalette * pP=pPaletteStack;
2389 if (pP!=NULL) {
2390 pPaletteStack=pP->pSucc;
2391 if (pP->p0RGB!=NULL) delete[] pP->p0RGB;
2392 delete pP;
2394 break;
2396 case DscImgObjMagic:
2397 break;
2398 case DatImgObjMagic: {
2399 sal_uInt16 nDataID, nDataLen;
2400 sal_uInt8 nbyte;
2401 sal_uLong nPos, nMaxPos;
2403 nPos=pOS2MET->Tell();
2404 nMaxPos=nPos+(sal_uLong)nFieldSize;
2405 while (nPos<nMaxPos && pOS2MET->GetError()==0) {
2406 *pOS2MET >> nbyte; nDataID=((sal_uInt16)nbyte)&0x00ff;
2407 if (nDataID==0x00fe) {
2408 *pOS2MET >> nbyte;
2409 nDataID=(nDataID<<8)|(((sal_uInt16)nbyte)&0x00ff);
2410 nDataLen=ReadBigEndianWord();
2411 nPos+=4;
2413 else {
2414 *pOS2MET >> nbyte; nDataLen=((sal_uInt16)nbyte)&0x00ff;
2415 nPos+=2;
2417 ReadImageData(nDataID, nDataLen);
2418 nPos+=(sal_uLong)nDataLen;
2419 pOS2MET->Seek(nPos);
2421 break;
2424 case BegObEnv1Magic:
2425 break;
2426 case EndObEnv1Magic:
2427 break;
2428 case BegGrfObjMagic:
2429 break;
2430 case EndGrfObjMagic: {
2431 SvStream * pSave;
2432 sal_uLong nPos, nMaxPos;
2433 sal_uInt16 nOrderID, nOrderLen;
2434 sal_uInt8 nbyte;
2436 if (pOrdFile==NULL) break;
2438 // in pOrdFile wurden alle "DatGrfObj"-Felder gesammelt, so
2439 // dass die darin enthaltnen "Orders" zusammenhangend und nicht durch
2440 // "Fields" segmentiert sind. Um sie aus dem MemoryStream auszulesen,
2441 // ohne grosse Umstaende deswegen zu haben (frueher wurden die "Orders"
2442 // direkt aus pOS2MET gelesen), hier ein kleiner Trick:
2443 pSave=pOS2MET;
2444 pOS2MET=pOrdFile; //(!)
2445 nMaxPos=pOS2MET->Tell();
2446 pOS2MET->Seek(0);
2448 // "Segment header":
2449 *pOS2MET >> nbyte;
2450 if (nbyte==0x70) { // header exists
2451 pOS2MET->SeekRel(15); // but we don't need it
2453 else pOS2MET->SeekRel(-1); // no header, go back one byte
2455 // loop through Order:
2456 while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
2457 *pOS2MET >> nbyte; nOrderID=((sal_uInt16)nbyte) & 0x00ff;
2458 if (nOrderID==0x00fe) {
2459 *pOS2MET >> nbyte;
2460 nOrderID=(nOrderID << 8) | (((sal_uInt16)nbyte) & 0x00ff);
2462 if (nOrderID>0x00ff || nOrderID==GOrdPolygn) {
2463 // ooo: Laut OS2-Doku sollte die Orderlaenge nun als Big-Endian-Word
2464 // gegeben sein (Zitat: "Highorder byte precedes loworder byte").
2465 // Tatsaechlich gibt es aber Dateien, die die Laenge als
2466 // Little-Endian-Word angeben (zu mindestens fuer nOrderID==GOrdPolygn).
2467 // Also werfen wir eine Muenze oder was ?
2468 *pOS2MET >> nbyte; nOrderLen=(sal_uInt16)nbyte&0x00ff;
2469 *pOS2MET >> nbyte; if (nbyte!=0) nOrderLen=nOrderLen<<8|(((sal_uInt16)nbyte)&0x00ff);
2471 else if (nOrderID==GOrdSTxAlg || nOrderID==GOrdPTxAlg) nOrderLen=2;
2472 else if ((nOrderID&0xff88)==0x0008) nOrderLen=1;
2473 else if (nOrderID==0x0000 || nOrderID==0x00ff) nOrderLen=0;
2474 else { *pOS2MET >> nbyte; nOrderLen=((sal_uInt16)nbyte) & 0x00ff; }
2475 nPos=pOS2MET->Tell();
2476 ReadOrder(nOrderID, nOrderLen);
2477 if (nPos+nOrderLen < pOS2MET->Tell()) {
2478 OOODEBUG("Order shorter than he assumes! OrderID:",nOrderID);
2479 OOODEBUG("...und zwar bei Position (Parameteranfang):",nPos);
2481 else if (nPos+nOrderLen != pOS2MET->Tell()) {
2482 OOODEBUG(String(nOrderID)+String(" Order nicht alles gelesen! bei:"),nPos);
2484 pOS2MET->Seek(nPos+nOrderLen);
2487 pOS2MET=pSave;
2488 if (pOrdFile->GetError()) {
2489 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2490 ErrorCode=10;
2492 delete pOrdFile; pOrdFile=NULL;
2493 break;
2495 case DscGrfObjMagic: {
2496 sal_uLong nPos, nMaxPos;
2497 sal_uInt16 nDscID, nDscLen;
2498 sal_uInt8 nbyte;
2500 nMaxPos=pOS2MET->Tell()+(sal_uLong)nFieldSize;
2501 while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
2502 *pOS2MET >> nbyte; nDscID =((sal_uInt16)nbyte) & 0x00ff;
2503 *pOS2MET >> nbyte; nDscLen=((sal_uInt16)nbyte) & 0x00ff;
2504 nPos=pOS2MET->Tell();
2505 ReadDsc(nDscID, nDscLen);
2506 pOS2MET->Seek(nPos+nDscLen);
2508 break;
2510 case DatGrfObjMagic: {
2511 if (pOrdFile==NULL) {
2512 pOrdFile = new SvMemoryStream;
2513 pOrdFile->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2515 sal_uInt8 * pBuf; pBuf = new sal_uInt8[nFieldSize];
2516 pOS2MET->Read(pBuf,nFieldSize);
2517 pOrdFile->Write(pBuf,nFieldSize);
2518 delete[] pBuf;
2519 break;
2521 case MapCodFntMagic:
2522 ReadFont(nFieldSize);
2523 break;
2525 case MapDatResMagic:
2526 break;
2530 void OS2METReader::ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile )
2532 sal_uInt16 nFieldSize;
2533 sal_uInt16 nFieldType;
2534 sal_uLong nPos, nStartPos, nEndPos, nPercent, nLastPercent;
2535 sal_uInt8 nMagicByte;
2537 ErrorCode=0;
2539 pOS2MET = &rStreamOS2MET;
2540 nOrigPos = pOS2MET->Tell();
2541 nOrigNumberFormat = pOS2MET->GetNumberFormatInt();
2543 bCoord32 = sal_True;
2544 pPaletteStack=NULL;
2545 pAreaStack=NULL;
2546 pPathStack=NULL;
2547 pPathList=NULL;
2548 pFontList=NULL;
2549 pBitmapList=NULL;
2550 pAttrStack=NULL;
2552 aDefAttr.aLinCol =Color(COL_BLACK);
2553 aDefAttr.aLinBgCol =Color(COL_WHITE);
2554 aDefAttr.eLinMix =ROP_OVERPAINT;
2555 aDefAttr.eLinBgMix =ROP_OVERPAINT;
2556 aDefAttr.aChrCol =Color(COL_BLACK);
2557 aDefAttr.aChrBgCol =Color(COL_WHITE);
2558 aDefAttr.eChrMix =ROP_OVERPAINT;
2559 aDefAttr.eChrBgMix =ROP_OVERPAINT;
2560 aDefAttr.aMrkCol =Color(COL_BLACK);
2561 aDefAttr.aMrkBgCol =Color(COL_WHITE);
2562 aDefAttr.eMrkMix =ROP_OVERPAINT;
2563 aDefAttr.eMrkBgMix =ROP_OVERPAINT;
2564 aDefAttr.aPatCol =Color(COL_BLACK);
2565 aDefAttr.aPatBgCol =Color(COL_WHITE);
2566 aDefAttr.ePatMix =ROP_OVERPAINT;
2567 aDefAttr.ePatBgMix =ROP_OVERPAINT;
2568 aDefAttr.aImgCol =Color(COL_BLACK);
2569 aDefAttr.aImgBgCol =Color(COL_WHITE);
2570 aDefAttr.eImgMix =ROP_OVERPAINT;
2571 aDefAttr.eImgBgMix =ROP_OVERPAINT;
2572 aDefAttr.nArcP =1;
2573 aDefAttr.nArcQ =1;
2574 aDefAttr.nArcR =0;
2575 aDefAttr.nArcS =0;
2576 aDefAttr.nChrAng =0;
2577 aDefAttr.aChrCellSize=Size(12,12);
2578 aDefAttr.nChrSet =0;
2579 aDefAttr.aCurPos =Point(0,0);
2580 aDefAttr.eLinStyle =PEN_SOLID;
2581 aDefAttr.nLinWidth =0;
2582 aDefAttr.aMrkCellSize=Size(10,10);
2583 aDefAttr.nMrkPrec =0x01;
2584 aDefAttr.nMrkSet =0xff;
2585 aDefAttr.nMrkSymbol =0x01;
2586 aDefAttr.bFill =sal_True;
2587 aDefAttr.nStrLinWidth=0;
2589 aAttr=aDefAttr;
2591 pOrdFile=NULL;
2593 pVirDev = new VirtualDevice();
2594 pVirDev->EnableOutput(sal_False);
2595 rGDIMetaFile.Record(pVirDev);
2597 pOS2MET->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2599 nStartPos=pOS2MET->Tell();
2600 nEndPos=pOS2MET->Seek(STREAM_SEEK_TO_END); pOS2MET->Seek(nStartPos);
2601 Callback(0); nLastPercent=0;
2603 nPos=pOS2MET->Tell();
2604 if ( nStartPos == nEndPos )
2606 nEndPos = 100;
2607 nStartPos = 0;
2610 for (;;) {
2612 nPercent=(nPos-nStartPos)*100/(nEndPos-nStartPos);
2613 if (nLastPercent+4<=nPercent) {
2614 if (Callback((sal_uInt16)nPercent)==sal_True) break;
2615 nLastPercent=nPercent;
2618 nFieldSize=ReadBigEndianWord();
2620 *pOS2MET >> nMagicByte;
2621 if (nMagicByte!=0xd3) {
2622 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2623 ErrorCode=7;
2624 break;
2626 *pOS2MET >> nFieldType;
2628 pOS2MET->SeekRel(3);
2629 nPos+=8; nFieldSize-=8;
2631 if (pOS2MET->GetError()) break;
2632 if (pOS2MET->IsEof()) {
2633 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2634 ErrorCode=8;
2635 break;
2638 if (nFieldType==EndDocumnMagic) break;
2640 ReadField(nFieldType, nFieldSize);
2642 nPos+=(sal_uLong)nFieldSize;
2643 if (pOS2MET->Tell()>nPos) {
2644 pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
2645 ErrorCode=9;
2646 break;
2648 pOS2MET->Seek(nPos);
2651 rGDIMetaFile.Stop();
2652 delete pVirDev;
2654 rGDIMetaFile.SetPrefMapMode( aGlobMapMode );
2656 if( aBoundingRect.GetWidth() && aBoundingRect.GetHeight() )
2657 rGDIMetaFile.SetPrefSize( aBoundingRect.GetSize() );
2658 else
2660 if( aCalcBndRect.Left() || aCalcBndRect.Top() )
2661 rGDIMetaFile.Move( -aCalcBndRect.Left(), -aCalcBndRect.Top() );
2663 rGDIMetaFile.SetPrefSize( aCalcBndRect.GetSize() );
2666 if (pOrdFile!=NULL) delete pOrdFile;
2668 while (pAreaStack!=NULL) {
2669 OSArea * p=pAreaStack;
2670 pAreaStack=p->pSucc;
2671 delete p;
2674 while (pPathStack!=NULL) {
2675 OSPath * p=pPathStack;
2676 pPathStack=p->pSucc;
2677 delete p;
2680 while (pPathList!=NULL) {
2681 OSPath * p=pPathList;
2682 pPathList=p->pSucc;
2683 delete p;
2686 while (pFontList!=NULL) {
2687 OSFont * p=pFontList;
2688 pFontList=p->pSucc;
2689 delete p;
2692 while (pBitmapList!=NULL) {
2693 OSBitmap * p=pBitmapList;
2694 pBitmapList=p->pSucc;
2695 if (p->pBMP!=NULL) delete p->pBMP;
2696 delete p;
2699 while (pAttrStack!=NULL) {
2700 OSAttr * p=pAttrStack;
2701 pAttrStack=p->pSucc;
2702 delete p;
2705 while (pPaletteStack!=NULL) {
2706 OSPalette * p=pPaletteStack;
2707 pPaletteStack=p->pSucc;
2708 if (p->p0RGB!=NULL) delete[] p->p0RGB;
2709 delete p;
2712 pOS2MET->SetNumberFormatInt(nOrigNumberFormat);
2714 if (pOS2MET->GetError()) {
2715 OOODEBUG("Fehler Nr.:",ErrorCode);
2716 pOS2MET->Seek(nOrigPos);
2720 //================== GraphicImport - die exportierte Funktion ================
2722 #ifdef DISABLE_DYNLOADING
2723 #define GraphicImport imeGraphicImport
2724 #endif
2726 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool __LOADONCALLAPI
2727 GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool)
2729 OS2METReader aOS2METReader;
2730 GDIMetaFile aMTF;
2731 sal_Bool bRet = sal_False;
2733 aOS2METReader.ReadOS2MET( rStream, aMTF );
2735 if ( !rStream.GetError() )
2737 rGraphic=Graphic( aMTF );
2738 bRet = sal_True;
2741 return bRet;
2744 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */