summaryrefslogtreecommitdiff
path: root/goodies/source/filter.vcl/ios2met/ios2met.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'goodies/source/filter.vcl/ios2met/ios2met.cxx')
-rw-r--r--goodies/source/filter.vcl/ios2met/ios2met.cxx2847
1 files changed, 2847 insertions, 0 deletions
diff --git a/goodies/source/filter.vcl/ios2met/ios2met.cxx b/goodies/source/filter.vcl/ios2met/ios2met.cxx
new file mode 100644
index 000000000000..e03dd1b4ab94
--- /dev/null
+++ b/goodies/source/filter.vcl/ios2met/ios2met.cxx
@@ -0,0 +1,2847 @@
+/*************************************************************************
+ *
+ * $RCSfile: ios2met.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:30:15 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#include <math.h>
+#include <vcl/graph.hxx>
+#include <vcl/poly.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/lineinfo.hxx>
+#include <svtools/fltcall.hxx>
+
+#ifndef NOOLDSV
+#include <vcl/gdiobj.hxx>
+#else // NOOLDSV
+enum PenStyle { PEN_NULL, PEN_SOLID, PEN_DOT, PEN_DASH, PEN_DASHDOT };
+#endif // NOOLDSV
+
+
+//============================== defines ===================================
+
+#define OOODEBUG(str,Num) //InfoBox(NULL,String(str)+String(" ")+String(Num)).Execute();
+
+// -----------------------------Feld-Typen-------------------------------
+
+#define BegDocumnMagic 0xA8A8 /* Begin Document */
+#define EndDocumnMagic 0xA8A9 /* End Document */
+
+#define BegResGrpMagic 0xC6A8 /* Begin Resource Group */
+#define EndResGrpMagic 0xC6A9 /* End Resource Group */
+
+#define BegColAtrMagic 0x77A8 /* Begin Color Attribute Table */
+#define EndColAtrMagic 0x77A9 /* End Color Attribute Table */
+#define BlkColAtrMagic 0x77B0 /* Color Attribute Table */
+#define MapColAtrMagic 0x77AB /* Map Color Attribute Table */
+
+#define BegImgObjMagic 0xFBA8 /* Begin Image Object */
+#define EndImgObjMagic 0xFBA9 /* End Image Object */
+#define DscImgObjMagic 0xFBA6 /* Image Data Descriptor */
+#define DatImgObjMagic 0xFBEE /* Image Picture Data */
+
+#define BegObEnv1Magic 0xC7A8 /* Begin Object Environment Group */
+#define EndObEnv1Magic 0xC7A9 /* End Object Environment Group */
+
+#define BegGrfObjMagic 0xBBA8 /* Begin Graphics Object */
+#define EndGrfObjMagic 0xBBA9 /* End Graphics Object */
+#define DscGrfObjMagic 0xBBA6 /* Graphics Data Descritor */
+#define DatGrfObjMagic 0xBBEE /* Graphics Data */
+
+#define MapCodFntMagic 0x8AAB /* Map Coded Font */
+#define MapDatResMagic 0xC3AB /* Map Data Resource */
+
+// -----------------------------Order-Typen-------------------------------
+
+#define GOrdGivArc 0xC6 /* 1 Arc at given position */
+#define GOrdCurArc 0x86 /* 1 Arc at current position */
+#define GOrdGivBzr 0xE5 /* 1 Beziercurve at given position */
+#define GOrdCurBzr 0xA5 /* 1 Beziercurve at current position */
+#define GOrdGivBox 0xC0 /* 1 Box at given position */
+#define GOrdCurBox 0x80 /* 1 Box at current position */
+#define GOrdGivFil 0xC5 /* 1 Fillet at given position */
+#define GOrdCurFil 0x85 /* 1 Fillet at current position */
+#define GOrdGivCrc 0xC7 /* 1 Full arc (circle) at given position */
+#define GOrdCurCrc 0x87 /* 1 Full arc (circle) at current position */
+#define GOrdGivLin 0xC1 /* 1 Line at given position */
+#define GOrdCurLin 0x81 /* 1 Line at current position */
+#define GOrdGivMrk 0xC2 /* 1 Marker at given position */
+#define GOrdCurMrk 0x82 /* 1 Marker at current position */
+#define GOrdGivArP 0xE3 /* 1 Partial arc at given position */
+#define GOrdCurArP 0xA3 /* 1 Partial arc at current position */
+#define GOrdGivRLn 0xE1 /* 1 Relative line at given position */
+#define GOrdCurRLn 0xA1 /* 1 Relative line at current position */
+#define GOrdGivSFl 0xE4 /* 1 Sharp fillet at given position */
+#define GOrdCurSFl 0xA4 /* 1 Sharp fillet at current position */
+
+#define GOrdGivStM 0xF1 /* 1 Character string move at given position */
+#define GOrdCurStM 0xB1 /* 1 Character string move at current position */
+#define GOrdGivStr 0xC3 /* 1 Character string at given position */
+#define GOrdCurStr 0x83 /* 1 Character string at current position */
+#define GOrdGivStx 0xFEF0 /* 2 Character string extended at given position */
+#define GOrdCurStx 0xFEB0 /* 2 Character string extended at current position */
+
+#define GOrdGivImg 0xD1 /* 1 Begin Image at given position */
+#define GOrdCurImg 0x91 /* 1 Begin Image at current position */
+#define GOrdImgDat 0x92 /* 1 Image data */
+#define GOrdEndImg 0x93 /* 1 End Image */
+#define GOrdBegAra 0x68 /* 0 1 Begin area */
+#define GOrdEndAra 0x60 /* 1 End area */
+#define GOrdBegElm 0xD2 /* 1 Begin element */
+#define GOrdEndElm 0x49 /* 0 1 End element */
+
+#define GOrdBegPth 0xD0 /* 1 Begin path */
+#define GOrdEndPth 0x7F /* 0 1 End path */
+#define GOrdFilPth 0xD7 /* 1 Fill path */
+#define GOrdModPth 0xD8 /* 1 Modify path */
+#define GOrdOutPth 0xD4 /* 1 Outline path */
+#define GOrdSClPth 0xB4 /* 1 Set clip path */
+
+#define GOrdNopNop 0x00 /* 0 0 No operation */
+#define GOrdRemark 0x01 /* 1 Comment */
+#define GOrdSegLab 0xD3 /* 1 Label */
+#define GOrdBitBlt 0xD6 /* 1 Bitblt */
+#define GOrdCalSeg 0x07 /* 1 Call Segment */
+#define GOrdSSgBnd 0x32 /* 1 Set segment boundary */
+#define GOrdSegChr 0x04 /* 1 Segment characteristics */
+#define GOrdCloFig 0x7D /* 0 1 Close Figure */
+#define GOrdEndSym 0xFF /* 0 0 End of symbol definition */
+#define GOrdEndPlg 0x3E /* 0 1 End prolog */
+#define GOrdEscape 0xD5 /* 1 Escape */
+#define GOrdExtEsc 0xFED5 /* 2 Extended Escape */
+#define GOrdPolygn 0xF3 /* 2 Polygons */
+
+#define GOrdStkPop 0x3F /* 0 1 Pop */
+
+#define GOrdSIvAtr 0x14 /* 1 Set individual attribute */
+#define GOrdPIvAtr 0x54 /* 1 Push and set individual attribute */
+#define GOrdSColor 0x0A /* 0 1 Set color */
+#define GOrdPColor 0x4A /* 0 1 Push and set color */
+#define GOrdSIxCol 0xA6 /* 1 Set indexed color */
+#define GOrdPIxCol 0xE6 /* 1 Push and set indexed color */
+#define GOrdSXtCol 0x26 /* 1 Set extended color */
+#define GOrdPXtCol 0x66 /* 1 Push and set extended color */
+#define GOrdSBgCol 0x25 /* 1 Set background color */
+#define GOrdPBgCol 0x65 /* 1 Push and set background color */
+#define GOrdSBxCol 0xA7 /* 1 Set background indexed color */
+#define GOrdPBxCol 0xE7 /* 1 Push and set background indexed color */
+#define GOrdSMixMd 0x0C /* 0 1 Set mix */
+#define GOrdPMixMd 0x4C /* 0 1 Push and set mix */
+#define GOrdSBgMix 0x0D /* 0 1 Set background mix */
+#define GOrdPBgMix 0x4D /* 0 1 Push and set background mix */
+
+#define GOrdSPtSet 0x08 /* 0 1 Set pattern set */
+#define GOrdPPtSet 0x48 /* 0 1 Push and set pattern set */
+#define GOrdSPtSym 0x28 /* 0 1 Set pattern symbol */
+#define GOrdPPtSym 0x09 /* 0 1 Push and set pattern symbol */
+#define GOrdSPtRef 0xA0 /* 1 Set model pattern reference */
+#define GOrdPPtRef 0xE0 /* 1 Push and set pattern reference point */
+
+#define GOrdSLnEnd 0x1A /* 0 1 Set line end */
+#define GOrdPLnEnd 0x5A /* 0 1 Push and set line end */
+#define GOrdSLnJoi 0x1B /* 0 1 Set line join */
+#define GOrdPLnJoi 0x5B /* 0 1 Push and set line join */
+#define GOrdSLnTyp 0x18 /* 0 1 Set line type */
+#define GOrdPLnTyp 0x58 /* 0 1 Push and set line type */
+#define GOrdSLnWdt 0x19 /* 0 1 Set line width */
+#define GOrdPLnWdt 0x59 /* 0 1 Push and set line width */
+#define GOrdSFrLWd 0x11 /* 1 Set fractional line width */
+#define GOrdPFrLWd 0x51 /* 1 Push and set fractional line width */
+#define GOrdSStLWd 0x15 /* 1 Set stroke line width */
+#define GOrdPStLWd 0x55 /* 1 Push and set stroke line width */
+
+#define GOrdSChDir 0x3A /* 0 1 Set character direction */
+#define GOrdPChDir 0x7A /* 0 1 Push and set character direction */
+#define GOrdSChPrc 0x39 /* 0 1 Set character precision */
+#define GOrdPChPrc 0x79 /* 0 1 Push and set character precision */
+#define GOrdSChSet 0x38 /* 0 1 Set character set */
+#define GOrdPChSet 0x78 /* 0 1 Push and set character set */
+#define GOrdSChAng 0x34 /* 1 Set character angle */
+#define GOrdPChAng 0x74 /* 1 Push and set character angle */
+#define GOrdSChBrx 0x05 /* 1 Set character break extra */
+#define GOrdPChBrx 0x45 /* 1 Push and set character break extra */
+#define GOrdSChCel 0x33 /* 1 Set character cell */
+#define GOrdPChCel 0x03 /* 1 Push and set character cell */
+#define GOrdSChXtr 0x17 /* 1 Set character extra */
+#define GOrdPChXtr 0x57 /* 1 Push and set character extra */
+#define GOrdSChShr 0x35 /* 1 Set character shear */
+#define GOrdPChShr 0x75 /* 1 Push and set character shear */
+#define GOrdSTxAlg 0x36 /* 0 2 Set text allingment */
+#define GOrdPTxAlg 0x76 /* 0 2 Push and set text allingment */
+
+#define GOrdSMkPrc 0x3B /* 0 1 Set marker precision */
+#define GOrdPMkPrc 0x7B /* 0 1 Push and set marker precision */
+#define GOrdSMkSet 0x3C /* 0 1 Set marker set */
+#define GOrdPMkSet 0x7C /* 0 1 Push and set marker set */
+#define GOrdSMkSym 0x29 /* 0 1 Set marker symbol */
+#define GOrdPMkSym 0x69 /* 0 1 Push and set marker symbol */
+#define GOrdSMkCel 0x37 /* 1 Set marker cell */
+#define GOrdPMkCel 0x77 /* 1 Push and set marker cell */
+
+#define GOrdSArcPa 0x22 /* 1 Set arc parameters */
+#define GOrdPArcPa 0x62 /* 1 Push and set arc parameters */
+
+#define GOrdSCrPos 0x21 /* 1 Set current position */
+#define GOrdPCrPos 0x61 /* 1 Push and set current position */
+
+#define GOrdSMdTrn 0x24 /* 1 Set model transform */
+#define GOrdPMdTrn 0x64 /* 1 Push and set model transform */
+#define GOrdSPkIdn 0x43 /* 1 Set pick identifier */
+#define GOrdPPkIdn 0x23 /* 1 Push and set pick identifier */
+#define GOrdSVwTrn 0x31 /* 1 Set viewing transform */
+#define GOrdSVwWin 0x27 /* 1 Set viewing window */
+#define GOrdPVwWin 0x67 /* 1 Push and set viewing window */
+
+//============================ OS2METReader ==================================
+
+struct OSPalette {
+ OSPalette * pSucc;
+ ULONG * p0RGB; // Darf auch NULL sein!
+ USHORT nSize;
+};
+
+struct OSArea {
+ OSArea * pSucc;
+ BYTE nFlags;
+ PolyPolygon aPPoly;
+ BOOL bClosed;
+ Color aCol;
+ Color aBgCol;
+ RasterOp eMix;
+ RasterOp eBgMix;
+ BOOL bFill;
+ OSArea(){} ~OSArea(){}
+};
+
+struct OSPath
+{
+ OSPath* pSucc;
+ ULONG nID;
+ PolyPolygon aPPoly;
+ BOOL bClosed;
+ BOOL bStroke;
+
+ OSPath(){}
+ ~OSPath(){}
+};
+
+struct OSFont {
+ OSFont * pSucc;
+ ULONG nID;
+ Font aFont;
+ OSFont(){} ~OSFont(){}
+};
+
+struct OSBitmap {
+ OSBitmap * pSucc;
+ ULONG nID;
+ Bitmap aBitmap;
+
+ // Waehrend des Lesens der Bitmap benoetigt:
+ SvStream * pBMP; // Zeiger auf temporaere Windows-BMP-Datei oder NULL
+ ULONG nWidth, nHeight;
+ USHORT nBitsPerPixel;
+ ULONG nMapPos;
+ OSBitmap(){} ~OSBitmap(){}
+};
+
+struct OSAttr {
+ OSAttr * pSucc;
+ USHORT nPushOrder;
+ BYTE nIvAttrA, nIvAttrP; // Spezialvariablen fuer den Order "GOrdPIvAtr"
+
+ Color aLinCol;
+ Color aLinBgCol;
+ RasterOp eLinMix;
+ RasterOp eLinBgMix;
+ Color aChrCol;
+ Color aChrBgCol;
+ RasterOp eChrMix;
+ RasterOp eChrBgMix;
+ Color aMrkCol;
+ Color aMrkBgCol;
+ RasterOp eMrkMix;
+ RasterOp eMrkBgMix;
+ Color aPatCol;
+ Color aPatBgCol;
+ RasterOp ePatMix;
+ RasterOp ePatBgMix;
+ Color aImgCol;
+ Color aImgBgCol;
+ RasterOp eImgMix;
+ RasterOp eImgBgMix;
+ long nArcP, nArcQ, nArcR, nArcS;
+ short nChrAng;
+// long nChrBreakExtra;
+ Size aChrCellSize;
+// BYTE nChrDir;
+// long nChrExtra;
+// BYTE nChrPrec;
+ ULONG nChrSet;
+// Size aChrShear;
+ Point aCurPos;
+// long nFracLinWidth;
+// BYTE nLinEnd;
+// BYTE nLinJoin;
+ PenStyle eLinStyle;
+ USHORT nLinWidth;
+ Size aMrkCellSize;
+ BYTE nMrkPrec;
+ BYTE nMrkSet;
+ BYTE nMrkSymbol;
+// //... aModTransform;
+// Point aPatRef;
+// BYTE nPatSet;
+ BOOL bFill;
+// ULONG nPickId;
+// //... aSegBound;
+ USHORT nStrLinWidth;
+// BYTE nTxtAlignHor,nTxtAlignVer;
+// //... aViewTransform;
+// //... aViewWindow;
+ OSAttr(){} ~OSAttr(){}
+};
+
+class OS2METReader {
+
+private:
+
+ long ErrorCode;
+
+ PFilterCallback pCallback;
+ void * pCallerData;
+
+ SvStream * pOS2MET; // Die einzulesende OS2MET-Datei
+ VirtualDevice * pVirDev; // Hier werden die Drawing-Methoden aufgerufen.
+ // Dabei findet ein Recording in das GDIMetaFile
+ // statt.
+ ULONG nOrigPos; // Anfaengliche Position in pOS2MET
+ UINT16 nOrigNumberFormat; // Anfaengliches Nummern-Format von pOS2MET
+ Rectangle aBoundingRect; // Boundingrectangle wie in Datei angegeben
+ Rectangle aCalcBndRect; // selbst ermitteltes Boundingrectangle
+ MapMode aGlobMapMode; // Aufloesung des Bildes
+ BOOL bCoord32;
+
+ OSPalette * pPaletteStack;
+
+ LineInfo aLineInfo;
+
+ OSArea * pAreaStack; // Areas, die in Arbeit sind
+
+ OSPath * pPathStack; // Paths, die in Arbeit sind
+ OSPath * pPathList; // Vollendete Paths
+
+ OSFont * pFontList;
+
+ OSBitmap * pBitmapList;
+
+ OSAttr aDefAttr;
+ OSAttr aAttr;
+ OSAttr * pAttrStack;
+
+ SvStream * pOrdFile;
+
+ BOOL Callback(USHORT nPercent);
+
+ void AddPointsToPath(const Polygon & rPoly);
+ void AddPointsToArea(const Polygon & rPoly);
+ void CloseFigure();
+ void PushAttr(USHORT nPushOrder);
+ void PopAttr();
+
+ void ChangeBrush( const Color& rPatColor, const Color& rBGColor, BOOL bFill );
+ void SetPen( const Color& rColor, USHORT nStrLinWidth = 0, PenStyle ePenStyle = PEN_SOLID );
+ void SetRasterOp(RasterOp eROP);
+
+ void SetPalette0RGB(USHORT nIndex, ULONG nCol);
+ ULONG GetPalette0RGB(ULONG nIndex);
+ // Holt Farbe aus der Palette, oder, wenn nicht vorhanden,
+ // interpretiert nIndex als direkten RGB-Wert.
+ Color GetPaletteColor(ULONG nIndex);
+
+
+ BOOL IsLineInfo();
+ void DrawPolyLine( const Polygon& rPolygon );
+ void DrawPolygon( const Polygon& rPolygon );
+ void DrawPolyPolygon( const PolyPolygon& rPolygon );
+ USHORT ReadBigEndianWord();
+ ULONG ReadBigEndian3BytesLong();
+ ULONG ReadLittleEndian3BytesLong();
+ long ReadCoord(BOOL b32);
+ Point ReadPoint( const BOOL bAdjustBoundRect = TRUE );
+ RasterOp OS2MixToRasterOp(BYTE nMix);
+ void ReadLine(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadRelLine(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadBox(BOOL bGivenPos);
+ void ReadBitBlt();
+ void ReadChrStr(BOOL bGivenPos, BOOL bMove, BOOL bExtra, USHORT nOrderLen);
+ void ReadArc(BOOL bGivenPos);
+ void ReadFullArc(BOOL bGivenPos, USHORT nOrderSize);
+ void ReadPartialArc(BOOL bGivenPos, USHORT nOrderSize);
+ void ReadPolygons();
+ void ReadBezier(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadFillet(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadFilletSharp(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadMarker(BOOL bGivenPos, USHORT nOrderLen);
+ void ReadOrder(USHORT nOrderID, USHORT nOrderLen);
+ void ReadDsc(USHORT nDscID, USHORT nDscLen);
+ void ReadImageData(USHORT nDataID, USHORT nDataLen);
+ void ReadFont(USHORT nFieldSize);
+ void ReadField(USHORT nFieldType, USHORT nFieldSize);
+
+public:
+
+ OS2METReader();
+ ~OS2METReader();
+
+ void ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile, PFilterCallback pcallback, void * pcallerdata);
+ // Liesst aus dem Stream eine OS2MET-Datei und fuellt das GDIMetaFile
+
+};
+
+//=================== Methoden von OS2METReader ==============================
+
+BOOL OS2METReader::Callback(USHORT nPercent)
+{
+ if (pCallback!=NULL) {
+ if (((*pCallback)(pCallerData,nPercent))==TRUE) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+OS2METReader::OS2METReader()
+{
+}
+
+OS2METReader::~OS2METReader()
+{
+}
+
+BOOL OS2METReader::IsLineInfo()
+{
+ return ( ! ( aLineInfo.IsDefault() || ( aLineInfo.GetStyle() == LINE_NONE ) || ( pVirDev->GetLineColor() == COL_TRANSPARENT ) ) );
+}
+
+void OS2METReader::DrawPolyLine( const Polygon& rPolygon )
+{
+ if ( aLineInfo.GetStyle() == LINE_DASH || ( aLineInfo.GetWidth() > 1 ) )
+ pVirDev->DrawPolyLine( rPolygon, aLineInfo );
+ else
+ pVirDev->DrawPolyLine( rPolygon );
+}
+
+void OS2METReader::DrawPolygon( const Polygon& rPolygon )
+{
+ if ( IsLineInfo() )
+ {
+ pVirDev->Push( PUSH_LINECOLOR );
+ pVirDev->SetLineColor( COL_TRANSPARENT );
+ pVirDev->DrawPolygon( rPolygon );
+ pVirDev->Pop();
+ pVirDev->DrawPolyLine( rPolygon, aLineInfo );
+ }
+ else
+ pVirDev->DrawPolygon( rPolygon );
+}
+
+void OS2METReader::DrawPolyPolygon( const PolyPolygon& rPolyPolygon )
+{
+ if ( IsLineInfo() )
+ {
+ pVirDev->Push( PUSH_LINECOLOR );
+ pVirDev->SetLineColor( COL_TRANSPARENT );
+ pVirDev->DrawPolyPolygon( rPolyPolygon );
+ pVirDev->Pop();
+ for ( USHORT i = 0; i < rPolyPolygon.Count(); i++ )
+ pVirDev->DrawPolyLine( rPolyPolygon.GetObject( i ), aLineInfo );
+ }
+ else
+ pVirDev->DrawPolyPolygon( rPolyPolygon );
+}
+
+void OS2METReader::AddPointsToArea(const Polygon & rPoly)
+{
+ USHORT nOldSize, nNewSize,i;
+
+ if (pAreaStack==NULL || rPoly.GetSize()==0) return;
+ PolyPolygon * pPP=&(pAreaStack->aPPoly);
+ if (pPP->Count()==0 || pAreaStack->bClosed==TRUE) pPP->Insert(rPoly);
+ else {
+ Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
+ nOldSize=aLastPoly.GetSize();
+ if (aLastPoly.GetPoint(nOldSize-1)==rPoly.GetPoint(0)) nOldSize--;
+ nNewSize=nOldSize+rPoly.GetSize();
+ aLastPoly.SetSize(nNewSize);
+ for (i=nOldSize; i<nNewSize; i++) {
+ aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
+ }
+ pPP->Replace(aLastPoly,pPP->Count()-1);
+ }
+ pAreaStack->bClosed=FALSE;
+}
+
+void OS2METReader::AddPointsToPath(const Polygon & rPoly)
+{
+ USHORT nOldSize, nNewSize,i;
+
+ if (pPathStack==NULL || rPoly.GetSize()==0) return;
+ PolyPolygon * pPP=&(pPathStack->aPPoly);
+ if (pPP->Count()==0 /*|| pPathStack->bClosed==TRUE*/) pPP->Insert(rPoly);
+ else {
+ Polygon aLastPoly(pPP->GetObject(pPP->Count()-1));
+ nOldSize=aLastPoly.GetSize();
+ if (aLastPoly.GetPoint(nOldSize-1)!=rPoly.GetPoint(0)) pPP->Insert(rPoly);
+ else {
+ nOldSize--;
+ nNewSize=nOldSize+rPoly.GetSize();
+ aLastPoly.SetSize(nNewSize);
+ for (i=nOldSize; i<nNewSize; i++) {
+ aLastPoly.SetPoint(rPoly.GetPoint(i-nOldSize),i);
+ }
+ pPP->Replace(aLastPoly,pPP->Count()-1);
+ }
+ }
+ pPathStack->bClosed=FALSE;
+}
+
+void OS2METReader::CloseFigure()
+{
+ if (pAreaStack!=NULL) pAreaStack->bClosed=TRUE;
+ else if (pPathStack!=NULL) pPathStack->bClosed=TRUE;
+}
+
+void OS2METReader::PushAttr(USHORT nPushOrder)
+{
+ OSAttr * p;
+ p=new OSAttr;
+ *p=aAttr;
+ p->pSucc=pAttrStack; pAttrStack=p;
+ p->nPushOrder=nPushOrder;
+}
+
+void OS2METReader::PopAttr()
+{
+ OSAttr * p=pAttrStack;
+
+ if (p==NULL) return;
+ switch (p->nPushOrder) {
+
+ case GOrdPIvAtr:
+ switch (p->nIvAttrA) {
+ case 1: switch (p->nIvAttrP) {
+ case 1: aAttr.aLinCol=p->aLinCol; break;
+ case 2: aAttr.aChrCol=p->aChrCol; break;
+ case 3: aAttr.aMrkCol=p->aMrkCol; break;
+ case 4: aAttr.aPatCol=p->aPatCol; break;
+ case 5: aAttr.aImgCol=p->aImgCol; break;
+ } break;
+ case 2: switch (p->nIvAttrP) {
+ case 1: aAttr.aLinBgCol=p->aLinBgCol; break;
+ case 2: aAttr.aChrBgCol=p->aChrBgCol; break;
+ case 3: aAttr.aMrkBgCol=p->aMrkBgCol; break;
+ case 4: aAttr.aPatBgCol=p->aPatBgCol; break;
+ case 5: aAttr.aImgBgCol=p->aImgBgCol; break;
+ } break;
+ case 3: switch (p->nIvAttrP) {
+ case 1: aAttr.eLinMix=p->eLinMix; break;
+ case 2: aAttr.eChrMix=p->eChrMix; break;
+ case 3: aAttr.eMrkMix=p->eMrkMix; break;
+ case 4: aAttr.ePatMix=p->ePatMix; break;
+ case 5: aAttr.eImgMix=p->eImgMix; break;
+ } break;
+ case 4: switch (p->nIvAttrP) {
+ case 1: aAttr.eLinBgMix=p->eLinBgMix; break;
+ case 2: aAttr.eChrBgMix=p->eChrBgMix; break;
+ case 3: aAttr.eMrkBgMix=p->eMrkBgMix; break;
+ case 4: aAttr.ePatBgMix=p->ePatBgMix; break;
+ case 5: aAttr.eImgBgMix=p->eImgBgMix; break;
+ } break;
+ }
+ break;
+
+ case GOrdPLnTyp: aAttr.eLinStyle=p->eLinStyle; break;
+
+ case GOrdPLnWdt: aAttr.nLinWidth=p->nLinWidth; break;
+
+ case GOrdPStLWd: aAttr.nStrLinWidth=p->nStrLinWidth; break;
+
+ case GOrdPChSet: aAttr.nChrSet=p->nChrSet; break;
+
+ case GOrdPChAng: aAttr.nChrAng=p->nChrAng; break;
+
+ case GOrdPMixMd:
+ aAttr.eLinMix=p->eLinMix;
+ aAttr.eChrMix=p->eChrMix;
+ aAttr.eMrkMix=p->eMrkMix;
+ aAttr.ePatMix=p->ePatMix;
+ aAttr.eImgMix=p->eImgMix;
+ break;
+
+ case GOrdPBgMix:
+ aAttr.eLinBgMix=p->eLinBgMix;
+ aAttr.eChrBgMix=p->eChrBgMix;
+ aAttr.eMrkBgMix=p->eMrkBgMix;
+ aAttr.ePatBgMix=p->ePatBgMix;
+ aAttr.eImgBgMix=p->eImgBgMix;
+ break;
+
+ case GOrdPPtSym: aAttr.bFill = p->bFill; break;
+
+ case GOrdPColor:
+ case GOrdPIxCol:
+ case GOrdPXtCol:
+ aAttr.aLinCol=p->aLinCol;
+ aAttr.aChrCol=p->aChrCol;
+ aAttr.aMrkCol=p->aMrkCol;
+ aAttr.aPatCol=p->aPatCol;
+ aAttr.aImgCol=p->aImgCol;
+ break;
+
+ case GOrdPBgCol:
+ case GOrdPBxCol:
+ aAttr.aLinBgCol=p->aLinBgCol;
+ aAttr.aChrBgCol=p->aChrBgCol;
+ aAttr.aMrkBgCol=p->aMrkBgCol;
+ aAttr.aPatBgCol=p->aPatBgCol;
+ aAttr.aImgBgCol=p->aImgBgCol;
+ break;
+
+ case GOrdPMkPrc: aAttr.nMrkPrec=aDefAttr.nMrkPrec; break;
+
+ case GOrdPMkSet: aAttr.nMrkSet=aDefAttr.nMrkSet; break;
+
+ case GOrdPMkSym: aAttr.nMrkSymbol=aDefAttr.nMrkSymbol; break;
+
+ case GOrdPMkCel: aAttr.aMrkCellSize=aDefAttr.aMrkCellSize; break;
+
+ case GOrdPArcPa:
+ aAttr.nArcP=p->nArcP; aAttr.nArcQ=p->nArcQ;
+ aAttr.nArcR=p->nArcR; aAttr.nArcS=p->nArcS;
+ break;
+
+ case GOrdPCrPos:
+ aAttr.aCurPos=p->aCurPos;
+ break;
+ }
+ pAttrStack=p->pSucc;
+ delete p;
+}
+
+void OS2METReader::ChangeBrush(const Color& rPatColor, const Color& rBGColor, BOOL bFill )
+{
+ Color aColor;
+
+ if( bFill )
+ aColor = rPatColor;
+ else
+ aColor = Color( COL_TRANSPARENT );
+
+ if( pVirDev->GetFillColor() != aColor )
+ pVirDev->SetFillColor( aColor );
+}
+
+void OS2METReader::SetPen( const Color& rColor, USHORT nLineWidth, PenStyle ePenStyle )
+{
+ LineStyle eLineStyle( LINE_SOLID );
+
+ if ( pVirDev->GetLineColor() != rColor )
+ pVirDev->SetLineColor( rColor );
+ aLineInfo.SetWidth( nLineWidth );
+
+ USHORT nDotCount = 0;
+ USHORT nDashCount = 0;
+ switch ( ePenStyle )
+ {
+ case PEN_NULL :
+ eLineStyle = LINE_NONE;
+ break;
+ case PEN_DASHDOT :
+ nDashCount++;
+ case PEN_DOT :
+ nDotCount++;
+ nDashCount--;
+ case PEN_DASH :
+ nDashCount++;
+ aLineInfo.SetDotCount( nDotCount );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDistance( nLineWidth );
+ aLineInfo.SetDotLen( nLineWidth );
+ aLineInfo.SetDashLen( nLineWidth << 2 );
+ eLineStyle = LINE_DASH;
+ break;
+ }
+ aLineInfo.SetStyle( eLineStyle );
+}
+
+void OS2METReader::SetRasterOp(RasterOp eROP)
+{
+ if (pVirDev->GetRasterOp()!=eROP) pVirDev->SetRasterOp(eROP);
+}
+
+
+void OS2METReader::SetPalette0RGB(USHORT nIndex, ULONG nCol)
+{
+ if (pPaletteStack==NULL) {
+ pPaletteStack=new OSPalette;
+ pPaletteStack->pSucc=NULL;
+ pPaletteStack->p0RGB=NULL;
+ pPaletteStack->nSize=0;
+ }
+ if (pPaletteStack->p0RGB==NULL || nIndex>=pPaletteStack->nSize) {
+ ULONG * pOld0RGB=pPaletteStack->p0RGB;
+ USHORT i,nOldSize=pPaletteStack->nSize;
+ if (pOld0RGB==NULL) nOldSize=0;
+ pPaletteStack->nSize=2*(nIndex+1);
+ if (pPaletteStack->nSize<256) pPaletteStack->nSize=256;
+ pPaletteStack->p0RGB = new ULONG[pPaletteStack->nSize];
+ for (i=0; i<pPaletteStack->nSize; i++) {
+ if (i<nOldSize) pPaletteStack->p0RGB[i]=pOld0RGB[i];
+ else if (i==0) pPaletteStack->p0RGB[i]=0x00ffffff;
+ else pPaletteStack->p0RGB[i]=0;
+ }
+ if (pOld0RGB!=NULL) delete pOld0RGB;
+ }
+ pPaletteStack->p0RGB[nIndex]=nCol;
+}
+
+ULONG OS2METReader::GetPalette0RGB(ULONG nIndex)
+{
+ if (pPaletteStack!=NULL && pPaletteStack->p0RGB!=NULL &&
+ pPaletteStack->nSize>nIndex) nIndex=pPaletteStack->p0RGB[nIndex];
+ return nIndex;
+}
+
+Color OS2METReader::GetPaletteColor(ULONG nIndex)
+{
+ nIndex=GetPalette0RGB(nIndex);
+ return Color((((USHORT)(nIndex>>8))&0xff00)>>8,
+ (((USHORT) nIndex)&0xff00)>>8,
+ (((USHORT)(nIndex<<8))&0xff00)>>8);
+}
+
+
+USHORT OS2METReader::ReadBigEndianWord()
+{
+ BYTE nLo,nHi;
+ *pOS2MET >> nHi >> nLo;
+ return (((USHORT)nHi)<<8)|(((USHORT)nLo)&0x00ff);
+}
+
+ULONG OS2METReader::ReadBigEndian3BytesLong()
+{
+ USHORT nLo;
+ BYTE nHi;
+ *pOS2MET >> nHi;
+ nLo=ReadBigEndianWord();
+ return ((((ULONG)nHi)<<16)&0x00ff0000)|((ULONG)nLo);
+}
+
+ULONG OS2METReader::ReadLittleEndian3BytesLong()
+{
+ BYTE nHi,nMed,nLo;
+
+ *pOS2MET >> nLo >> nMed >> nHi;
+ return ((((ULONG)nHi)&0xff)<<16)|((((ULONG)nMed)&0xff)<<8)|(((ULONG)nLo)&0xff);
+}
+
+long OS2METReader::ReadCoord(BOOL b32)
+{
+ long l;
+ short s;
+
+ if (b32) *pOS2MET >> l;
+ else { *pOS2MET >> s; l=(long)s; }
+ return l;
+}
+
+Point OS2METReader::ReadPoint( const BOOL bAdjustBoundRect )
+{
+ long x,y;
+
+ x=ReadCoord(bCoord32);
+ y=ReadCoord(bCoord32);
+ x=x-aBoundingRect.Left();
+ y=aBoundingRect.Bottom()-y;
+
+ if ( bAdjustBoundRect )
+ aCalcBndRect.Union(Rectangle(x,y,x+1,y+1));
+
+ return Point(x,y);
+}
+
+RasterOp OS2METReader::OS2MixToRasterOp(BYTE nMix)
+{
+ switch (nMix) {
+ case 0x0c: return ROP_INVERT;
+ case 0x04: return ROP_XOR;
+ case 0x0b: return ROP_XOR;
+ default: return ROP_OVERPAINT;
+ }
+}
+
+void OS2METReader::ReadLine(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i,nPolySize;
+
+ if (bCoord32) nPolySize=nOrderLen/8; else nPolySize=nOrderLen/4;
+ if (!bGivenPos) nPolySize++;
+ if (nPolySize==0) return;
+ Polygon aPolygon(nPolySize);
+ for (i=0; i<nPolySize; i++) {
+ if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
+ else aPolygon.SetPoint(ReadPoint(),i);
+ }
+ aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
+ if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
+ else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
+ else
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ DrawPolyLine( aPolygon );
+ }
+}
+
+void OS2METReader::ReadRelLine(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i,nPolySize;
+ Point aP0;
+
+
+ if (bGivenPos) {
+ aP0=ReadPoint();
+ if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
+ }
+ else aP0=aAttr.aCurPos;
+ nPolySize=nOrderLen/2;
+ if (nPolySize==0) return;
+ Polygon aPolygon(nPolySize);
+ for (i=0; i<nPolySize; i++) {
+#if (defined SOLARIS && defined PPC) || defined IRIX
+ UINT8 nunsignedbyte;
+ *pOS2MET >> nunsignedbyte; aP0.X()+=(INT8)nunsignedbyte;
+ *pOS2MET >> nunsignedbyte; aP0.Y()+=(INT8)nunsignedbyte;
+#else
+ INT8 nsignedbyte;
+ *pOS2MET >> nsignedbyte; aP0.X()+=(long)nsignedbyte;
+ *pOS2MET >> nsignedbyte; aP0.Y()-=(long)nsignedbyte;
+#endif
+ aCalcBndRect.Union(Rectangle(aP0,Size(1,1)));
+ aPolygon.SetPoint(aP0,i);
+ }
+ aAttr.aCurPos=aPolygon.GetPoint(nPolySize-1);
+ if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
+ else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
+ else
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ DrawPolyLine( aPolygon );
+ }
+}
+
+void OS2METReader::ReadBox(BOOL bGivenPos)
+{
+ BYTE nFlags;
+ Point P0;
+ long nHRound,nVRound;
+
+ *pOS2MET >> nFlags;
+ pOS2MET->SeekRel(1);
+
+ if ( bGivenPos )
+ P0 = ReadPoint();
+ else
+ P0 = aAttr.aCurPos;
+
+ aAttr.aCurPos=ReadPoint();
+ nHRound=ReadCoord(bCoord32);
+ nVRound=ReadCoord(bCoord32);
+
+ Rectangle aBoxRect( P0, aAttr.aCurPos );
+
+ if ( pAreaStack )
+ AddPointsToArea( Polygon( aBoxRect ) );
+ else if ( pPathStack )
+ AddPointsToPath( Polygon( aBoxRect ) );
+ else
+ {
+ if ( nFlags & 0x20 )
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ else
+ SetPen( COL_TRANSPARENT );
+
+ if ( nFlags & 0x40 )
+ {
+ ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
+ SetRasterOp(aAttr.ePatMix);
+ }
+ else
+ {
+ ChangeBrush( Color( COL_TRANSPARENT ), Color( COL_TRANSPARENT ), FALSE );
+ SetRasterOp(aAttr.eLinMix);
+ }
+
+ if ( IsLineInfo() )
+ {
+ Polygon aPolygon( aBoxRect, nHRound, nVRound );
+ if ( nFlags & 0x40 )
+ {
+ pVirDev->Push( PUSH_LINECOLOR );
+ pVirDev->SetLineColor( COL_TRANSPARENT );
+ pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
+ pVirDev->Pop();
+ }
+ pVirDev->DrawPolyLine( aPolygon, aLineInfo );
+ }
+ else
+ pVirDev->DrawRect( aBoxRect, nHRound, nVRound );
+ }
+}
+
+void OS2METReader::ReadBitBlt()
+{
+ Point aP1,aP2;
+ Size aSize;
+ ULONG nID;
+ OSBitmap * pB;
+ long nt;
+
+ pOS2MET->SeekRel(4);
+ *pOS2MET >> nID;
+ pOS2MET->SeekRel(4);
+ aP1=ReadPoint(); aP2=ReadPoint();
+ if (aP1.X() > aP2.X()) { nt=aP1.X(); aP1.X()=aP2.X(); aP2.X()=nt; }
+ if (aP1.Y() > aP2.Y()) { nt=aP1.Y(); aP1.Y()=aP2.Y(); aP2.Y()=nt; }
+ aSize=Size(aP2.X()-aP1.X(),aP2.Y()-aP1.Y());
+
+ pB=pBitmapList;
+ while (pB!=NULL && pB->nID!=nID) pB=pB->pSucc;
+ if (pB!=NULL) {
+ SetRasterOp(aAttr.ePatMix);
+ pVirDev->DrawBitmap(aP1,aSize,pB->aBitmap);
+ }
+}
+
+void OS2METReader::ReadChrStr(BOOL bGivenPos, BOOL bMove, BOOL bExtra, USHORT nOrderLen)
+{
+ Point aP0;
+ USHORT i, nLen;
+ char * pChr;
+ OSFont * pF;
+ Font aFont;
+ Size aSize;
+
+ pF = pFontList;
+ while (pF!=NULL && pF->nID!=aAttr.nChrSet) pF=pF->pSucc;
+ if (pF!=NULL)
+ aFont = pF->aFont;
+ aFont.SetColor(aAttr.aChrCol);
+ aFont.SetSize(Size(0,aAttr.aChrCellSize.Height()));
+ if ( aAttr.nChrAng != 0 )
+ aFont.SetOrientation(aAttr.nChrAng);
+
+ if (bGivenPos)
+ aP0 = ReadPoint();
+ else
+ aP0 = aAttr.aCurPos;
+ if (bExtra)
+ {
+ pOS2MET->SeekRel(2);
+ ReadPoint( FALSE );
+ ReadPoint( FALSE );
+ *pOS2MET >> nLen;
+ }
+ else
+ {
+ if ( !bGivenPos )
+ nLen = nOrderLen;
+ else if ( bCoord32 )
+ nLen = nOrderLen-8;
+ else
+ nLen = nOrderLen-4;
+ }
+ pChr = new char[nLen+1];
+ for (i=0; i<nLen; i++)
+ *pOS2MET >> pChr[i];
+ pChr[nLen]=0;
+ String aStr( String::CreateFromAscii( pChr ) );
+
+ SetRasterOp(aAttr.eChrMix);
+ if (pVirDev->GetFont()!=aFont)
+ pVirDev->SetFont(aFont);
+ pVirDev->DrawText(aP0,aStr);
+
+ aSize = Size( pVirDev->GetTextWidth(aStr), pVirDev->GetTextHeight() );
+ if ( aAttr.nChrAng == 0 )
+ {
+ aCalcBndRect.Union(Rectangle( Point(aP0.X(),aP0.Y()-aSize.Height()),
+ Size(aSize.Width(),aSize.Height()*2)));
+ if (bMove)
+ aAttr.aCurPos = Point( aP0.X() + aSize.Width(), aP0.Y());
+ }
+ else
+ {
+ Polygon aDummyPoly(4);
+
+ aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() ), 0); // TOP LEFT
+ aDummyPoly.SetPoint( Point( aP0.X(), aP0.Y() - aSize.Height() ), 1); // BOTTOM LEFT
+ aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() ), 2); // TOP RIGHT
+ aDummyPoly.SetPoint( Point( aP0.X() + aSize.Width(), aP0.Y() - aSize.Height() ), 3);// BOTTOM RIGHT
+ aDummyPoly.Rotate( aP0, (short)aAttr.nChrAng );
+ if ( bMove )
+ aAttr.aCurPos = aDummyPoly.GetPoint( 0 );
+ aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 0 ), aDummyPoly.GetPoint( 3 ) ) );
+ aCalcBndRect.Union( Rectangle( aDummyPoly.GetPoint( 1 ), aDummyPoly.GetPoint( 2 ) ) );
+ }
+ delete pChr;
+}
+
+void OS2METReader::ReadArc(BOOL bGivenPos)
+{
+ Point aP1, aP2, aP3;
+ double x1,y1,x2,y2,x3,y3,p,q,cx,cy,ncx,ncy,r,rx,ry,w1,w3;
+ if (bGivenPos) aP1=ReadPoint(); else aP1=aAttr.aCurPos;
+ aP2=ReadPoint(); aP3=ReadPoint();
+ aAttr.aCurPos=aP3;
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ // OK, gegeben sind 3 Punkte der Ellipse, und das Verhaeltnis
+ // Breite zu Hoehe (als p zu q):
+ x1=aP1.X(); y1=aP1.Y();
+ x2=aP2.X(); y2=aP2.Y();
+ x3=aP3.X(); y3=aP3.Y();
+ p=aAttr.nArcP;q=aAttr.nArcQ;
+ // Berechnet wird der Mittelpunkt cx,cy der Ellipse:
+ ncy=2*p*p*((y3-y1)*(x2-x1)-(y1-y2)*(x1-x3));
+ ncx=2*q*q*(x2-x1);
+ if ( (ncx<0.001 && ncx>-0.001) || (ncy<0.001 && ncy>-0.001) ) {
+ // Berechnung nicht moeglich, Punkte liegen auf einer Linie
+ pVirDev->DrawLine(aP1,aP2);
+ pVirDev->DrawLine(aP2,aP3);
+ return;
+ }
+ cy=( q*q*((x3*x3-x1*x1)*(x2-x1)+(x2*x2-x1*x1)*(x1-x3)) +
+ p*p*((y3*y3-y1*y1)*(x2-x1)+(y2*y2-y1*y1)*(x1-x3)) ) / ncy;
+ cx=( q*q*(x2*x2-x1*x1)+p*p*(y2*y2-y1*y1)+cy*2*p*p*(y1-y2) ) / ncx;
+ // Nun brauchen wir noch den Radius in x und y Richtung:
+ r=sqrt(q*q*(x1-cx)*(x1-cx)+p*p*(y1-cy)*(y1-cy));
+ rx=r/q; ry=r/p;
+ // Jetzt stellt sich "nur noch" die Frage, wie Start- und Endpunkt
+ // gewaehlt werden muessen, damit Punkt Nr. 2 innerhalb des
+ // gezeichneten Bogens liegt:
+ w1=fmod((atan2(x1-cx,y1-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w1<0) w1+=6.28318530718;
+ w3=fmod((atan2(x3-cx,y3-cy)-atan2(x2-cx,y2-cy)),6.28318530718); if (w3<0) w3+=6.28318530718;
+ if (w3<w1) {
+ pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
+ (long)(cx+rx),(long)(cy+ry)),aP1,aP3);
+ }
+ else {
+ pVirDev->DrawArc(Rectangle((long)(cx-rx),(long)(cy-ry),
+ (long)(cx+rx),(long)(cy+ry)),aP3,aP1);
+ }
+}
+
+void OS2METReader::ReadFullArc(BOOL bGivenPos, USHORT nOrderSize)
+{
+ Point aCenter;
+ long nP,nQ,nR,nS;
+ Rectangle aRect;
+ ULONG nMul; USHORT nMulS;
+
+ if (bGivenPos) {
+ aCenter=ReadPoint();
+ if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
+ }
+ else aCenter=aAttr.aCurPos;
+
+ nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
+ if (nP<0) nP=-nP;
+ if (nQ<0) nQ=-nQ;
+ if (nR<0) nR=-nR;
+ if (nS<0) nS=-nS;
+ if (nOrderSize>=4) *pOS2MET >> nMul;
+ else { *pOS2MET >> nMulS; nMul=((ULONG)nMulS)<<8; }
+ if (nMul!=0x00010000) {
+ nP=(nP*nMul)>>16;
+ nQ=(nQ*nMul)>>16;
+ nR=(nR*nMul)>>16;
+ nS=(nS*nMul)>>16;
+ }
+
+ aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
+ aCenter.X()+nP,aCenter.Y()+nQ);
+ aCalcBndRect.Union(aRect);
+
+ if (pAreaStack!=NULL) {
+ ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
+ SetRasterOp(aAttr.ePatMix);
+ if ((pAreaStack->nFlags&0x40)!=0)
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ else
+ SetPen( COL_TRANSPARENT, 0, PEN_NULL );
+ }
+ else
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ ChangeBrush(Color( COL_TRANSPARENT ),Color( COL_TRANSPARENT ),FALSE);
+ SetRasterOp(aAttr.eLinMix);
+ }
+ pVirDev->DrawEllipse(aRect);
+}
+
+void OS2METReader::ReadPartialArc(BOOL bGivenPos, USHORT nOrderSize)
+{
+ Point aP0, aCenter,aPStart,aPEnd;
+ long nP,nQ,nR,nS,nStart, nSweep;
+ Rectangle aRect;
+ ULONG nMul; USHORT nMulS;
+ double fStart, fEnd;
+
+ if (bGivenPos) {
+ aP0=ReadPoint();
+ if (bCoord32) nOrderSize-=8; else nOrderSize-=4;
+ }
+ else aP0=aAttr.aCurPos;
+ aCenter=ReadPoint();
+
+ nP=aAttr.nArcP; nQ=aAttr.nArcQ; nR=aAttr.nArcR; nS=aAttr.nArcS;
+ if (nP<0) nP=-nP;
+ if (nQ<0) nQ=-nQ;
+ if (nR<0) nR=-nR;
+ if (nS<0) nS=-nS;
+ if (nOrderSize>=12) *pOS2MET >> nMul;
+ else { *pOS2MET >> nMulS; nMul=((ULONG)nMulS)<<8; }
+ if (nMul!=0x00010000) {
+ nP=(nP*nMul)>>16;
+ nQ=(nQ*nMul)>>16;
+ nR=(nR*nMul)>>16;
+ nS=(nS*nMul)>>16;
+ }
+
+ *pOS2MET >> nStart >> nSweep;
+ fStart=((double)nStart)/65536.0/180.0*3.14159265359;
+ fEnd=fStart+((double)nSweep)/65536.0/180.0*3.14159265359;
+ aPStart=Point(aCenter.X()+(long)( cos(fStart)*nP),
+ aCenter.Y()+(long)(-sin(fStart)*nQ));
+ aPEnd= Point(aCenter.X()+(long)( cos(fEnd)*nP),
+ aCenter.Y()+(long)(-sin(fEnd)*nQ));
+
+ aRect=Rectangle(aCenter.X()-nP,aCenter.Y()-nQ,
+ aCenter.X()+nP,aCenter.Y()+nQ);
+ aCalcBndRect.Union(aRect);
+
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+
+ pVirDev->DrawLine(aP0,aPStart);
+ pVirDev->DrawArc(aRect,aPStart,aPEnd);
+ aAttr.aCurPos=aPEnd;
+}
+
+void OS2METReader::ReadPolygons()
+{
+ ULONG i,j,nNumPolys, nNumPoints;
+ PolyPolygon aPolyPoly;
+ Polygon aPoly;
+ Point aPoint;
+ BYTE nFlags;
+
+ *pOS2MET >> nFlags >> nNumPolys;
+ for (i=0; i<nNumPolys; i++) {
+ *pOS2MET >> nNumPoints;
+ if (i==0) nNumPoints++;
+ aPoly.SetSize((short)nNumPoints);
+ for (j=0; j<nNumPoints; j++) {
+ if (i==0 && j==0) aPoint=aAttr.aCurPos;
+ else aPoint=ReadPoint();
+ aPoly.SetPoint(aPoint,(short)j);
+ if (i==nNumPolys-1 && j==nNumPoints-1) aAttr.aCurPos=aPoint;
+ }
+ aPolyPoly.Insert(aPoly);
+ }
+
+ ChangeBrush(aAttr.aPatCol,aAttr.aPatBgCol,aAttr.bFill);
+ SetRasterOp(aAttr.ePatMix);
+ if ((nFlags&0x01)!=0)
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ else
+ SetPen( COL_TRANSPARENT, 0, PEN_NULL );
+ DrawPolyPolygon( aPolyPoly );
+}
+
+void OS2METReader::ReadBezier(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i, nNumPoints = nOrderLen / ( bCoord32 ? 8 : 4 );
+
+ if( !bGivenPos )
+ nNumPoints++;
+
+ if( !nNumPoints )
+ return;
+
+ Polygon aPolygon( nNumPoints );
+
+ for( i=0; i < nNumPoints; i++ )
+ {
+ if( i==0 && !bGivenPos)
+ aPolygon.SetPoint( aAttr.aCurPos, i );
+ else
+ aPolygon.SetPoint( ReadPoint(), i );
+ }
+
+ if( !( nNumPoints % 4 ) )
+ {
+ // create bezier polygon
+ const USHORT nSegPoints = 25;
+ const USHORT nSegments = aPolygon.GetSize() >> 2;
+ Polygon aBezPoly( nSegments * nSegPoints );
+
+ USHORT nSeg, nBezPos, nStartPos;
+ for( nSeg = 0, nBezPos = 0, nStartPos = 0; nSeg < nSegments; nSeg++, nStartPos += 4 )
+ {
+ const Polygon aSegPoly( aPolygon[ nStartPos ], aPolygon[ nStartPos + 1 ],
+ aPolygon[ nStartPos + 3 ], aPolygon[ nStartPos + 2 ],
+ nSegPoints );
+
+ for( USHORT nSegPos = 0; nSegPos < nSegPoints; )
+ aBezPoly[ nBezPos++ ] = aSegPoly[ nSegPos++ ];
+ }
+
+ nNumPoints = nBezPos;
+
+ if( nNumPoints != aBezPoly.GetSize() )
+ aBezPoly.SetSize( nNumPoints );
+
+ aPolygon = aBezPoly;
+ }
+
+ aAttr.aCurPos = aPolygon[ nNumPoints - 1 ];
+
+ if (pAreaStack!=NULL)
+ AddPointsToArea(aPolygon);
+ else if (pPathStack!=NULL)
+ AddPointsToPath(aPolygon);
+ else
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ DrawPolyLine( aPolygon );
+ }
+}
+
+void OS2METReader::ReadFillet(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i,nNumPoints;
+
+ if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
+ if (!bGivenPos) nNumPoints++;
+ if (nNumPoints==0) return;
+ Polygon aPolygon(nNumPoints);
+ for (i=0; i<nNumPoints; i++) {
+ if (i==0 && !bGivenPos) aPolygon.SetPoint(aAttr.aCurPos,i);
+ else aPolygon.SetPoint(ReadPoint(),i);
+ }
+ aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
+ if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
+ else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
+ else {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ DrawPolyLine( aPolygon );
+ }
+}
+
+void OS2METReader::ReadFilletSharp(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i,nNumPoints;
+
+ if (bGivenPos) {
+ aAttr.aCurPos=ReadPoint();
+ if (bCoord32) nOrderLen-=8; else nOrderLen-=4;
+ }
+ if (bCoord32) nNumPoints=1+nOrderLen/10;
+ else nNumPoints=1+nOrderLen/6;
+ Polygon aPolygon(nNumPoints);
+ aPolygon.SetPoint(aAttr.aCurPos,0);
+ for (i=1; i<nNumPoints; i++) aPolygon.SetPoint(ReadPoint(),i);
+ aAttr.aCurPos=aPolygon.GetPoint(nNumPoints-1);
+ if (pAreaStack!=NULL) AddPointsToArea(aPolygon);
+ else if (pPathStack!=NULL) AddPointsToPath(aPolygon);
+ else
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ DrawPolyLine( aPolygon );
+ }
+}
+
+void OS2METReader::ReadMarker(BOOL bGivenPos, USHORT nOrderLen)
+{
+ USHORT i,nNumPoints;
+ long x,y;
+
+ SetPen( aAttr.aMrkCol );
+ SetRasterOp(aAttr.eMrkMix);
+ if (aAttr.nMrkSymbol>=5 && aAttr.nMrkSymbol<=9)
+ {
+ ChangeBrush(aAttr.aMrkCol,aAttr.aMrkCol,TRUE);
+ }
+ else
+ {
+ ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),FALSE);
+ }
+ if (bCoord32) nNumPoints=nOrderLen/8; else nNumPoints=nOrderLen/4;
+ if (!bGivenPos) nNumPoints++;
+ for (i=0; i<nNumPoints; i++) {
+ if (i!=0 || bGivenPos) aAttr.aCurPos=ReadPoint();
+ x=aAttr.aCurPos.X(); y=aAttr.aCurPos.Y();
+ aCalcBndRect.Union(Rectangle(x-5,y-5,x+5,y+5));
+ switch (aAttr.nMrkSymbol) {
+ case 2: // PLUS
+ pVirDev->DrawLine(Point(x-4,y),Point(x+4,y));
+ pVirDev->DrawLine(Point(x,y-4),Point(x,y+4));
+ break;
+ case 3: // DIAMOND
+ case 7: { // SOLIDDIAMOND
+ Polygon aPoly(4);
+ aPoly.SetPoint(Point(x,y+4),0);
+ aPoly.SetPoint(Point(x+4,y),1);
+ aPoly.SetPoint(Point(x,y-4),2);
+ aPoly.SetPoint(Point(x-4,y),3);
+ pVirDev->DrawPolygon(aPoly);
+ break;
+ }
+ case 4: // SQARE
+ case 8: { // SOLIDSUARE
+ Polygon aPoly(4);
+ aPoly.SetPoint(Point(x+4,y+4),0);
+ aPoly.SetPoint(Point(x+4,y-4),1);
+ aPoly.SetPoint(Point(x-4,y-4),2);
+ aPoly.SetPoint(Point(x-4,y+4),3);
+ pVirDev->DrawPolygon(aPoly);
+ break;
+ }
+ case 5: { // SIXPOINTSTAR
+ Polygon aPoly(12);
+ aPoly.SetPoint(Point(x ,y-4),0);
+ aPoly.SetPoint(Point(x+2,y-2),1);
+ aPoly.SetPoint(Point(x+4,y-2),2);
+ aPoly.SetPoint(Point(x+2,y ),3);
+ aPoly.SetPoint(Point(x+4,y+2),4);
+ aPoly.SetPoint(Point(x+2,y+2),5);
+ aPoly.SetPoint(Point(x ,y+4),6);
+ aPoly.SetPoint(Point(x-2,y+2),7);
+ aPoly.SetPoint(Point(x-4,y+2),8);
+ aPoly.SetPoint(Point(x-2,y ),9);
+ aPoly.SetPoint(Point(x-4,y-2),10);
+ aPoly.SetPoint(Point(x-2,y-2),11);
+ pVirDev->DrawPolygon(aPoly);
+ break;
+ }
+ case 6: { // EIGHTPOINTSTAR
+ Polygon aPoly(16);
+ aPoly.SetPoint(Point(x ,y-4),0);
+ aPoly.SetPoint(Point(x+1,y-2),1);
+ aPoly.SetPoint(Point(x+3,y-3),2);
+ aPoly.SetPoint(Point(x+2,y-1),3);
+ aPoly.SetPoint(Point(x+4,y ),4);
+ aPoly.SetPoint(Point(x+2,y+1),5);
+ aPoly.SetPoint(Point(x+3,y+3),6);
+ aPoly.SetPoint(Point(x+1,y+2),7);
+ aPoly.SetPoint(Point(x ,y+4),8);
+ aPoly.SetPoint(Point(x-1,y+2),9);
+ aPoly.SetPoint(Point(x-3,y+3),10);
+ aPoly.SetPoint(Point(x-2,y+1),11);
+ aPoly.SetPoint(Point(x-4,y ),12);
+ aPoly.SetPoint(Point(x-2,y-1),13);
+ aPoly.SetPoint(Point(x-3,y-3),14);
+ aPoly.SetPoint(Point(x-1,y-2),15);
+ pVirDev->DrawPolygon(aPoly);
+ break;
+ }
+ case 9: // DOT
+ pVirDev->DrawEllipse(Rectangle(x-1,y-1,x+1,y+1));
+ break;
+ case 10: // SMALLCIRCLE
+ pVirDev->DrawEllipse(Rectangle(x-2,y-2,x+2,y+2));
+ break;
+ case 64: // BLANK
+ break;
+ default: // (=1) CROSS
+ pVirDev->DrawLine(Point(x-4,y-4),Point(x+4,y+4));
+ pVirDev->DrawLine(Point(x-4,y+4),Point(x+4,y-4));
+ break;
+ }
+ }
+}
+
+void OS2METReader::ReadOrder(USHORT nOrderID, USHORT nOrderLen)
+{
+ switch (nOrderID) {
+
+ case GOrdGivArc: ReadArc(TRUE); break;
+ case GOrdCurArc: ReadArc(FALSE); break;
+
+ case GOrdGivBzr: ReadBezier(TRUE,nOrderLen); break;
+ case GOrdCurBzr: ReadBezier(FALSE,nOrderLen); break;
+
+ case GOrdGivBox: ReadBox(TRUE); break;
+ case GOrdCurBox: ReadBox(FALSE); break;
+
+ case GOrdGivFil: ReadFillet(TRUE,nOrderLen); break;
+ case GOrdCurFil: ReadFillet(FALSE,nOrderLen); break;
+
+ case GOrdGivCrc: ReadFullArc(TRUE,nOrderLen); break;
+ case GOrdCurCrc: ReadFullArc(FALSE,nOrderLen); break;
+
+ case GOrdGivLin: ReadLine(TRUE, nOrderLen); break;
+ case GOrdCurLin: ReadLine(FALSE, nOrderLen); break;
+
+ case GOrdGivMrk: ReadMarker(TRUE, nOrderLen); break;
+ case GOrdCurMrk: ReadMarker(FALSE, nOrderLen); break;
+
+ case GOrdGivArP: ReadPartialArc(TRUE,nOrderLen); break;
+ case GOrdCurArP: ReadPartialArc(FALSE,nOrderLen); break;
+
+ case GOrdGivRLn: ReadRelLine(TRUE,nOrderLen); break;
+ case GOrdCurRLn: ReadRelLine(FALSE,nOrderLen); break;
+
+ case GOrdGivSFl: ReadFilletSharp(TRUE,nOrderLen); break;
+ case GOrdCurSFl: ReadFilletSharp(FALSE,nOrderLen); break;
+
+ case GOrdGivStM: ReadChrStr(TRUE , TRUE , FALSE, nOrderLen); break;
+ case GOrdCurStM: ReadChrStr(FALSE, TRUE , FALSE, nOrderLen); break;
+ case GOrdGivStr: ReadChrStr(TRUE , FALSE, FALSE, nOrderLen); break;
+ case GOrdCurStr: ReadChrStr(FALSE, FALSE, FALSE, nOrderLen); break;
+ case GOrdGivStx: ReadChrStr(TRUE , FALSE, TRUE , nOrderLen); break;
+ case GOrdCurStx: ReadChrStr(FALSE, FALSE, TRUE , nOrderLen); break;
+
+ case GOrdGivImg: OOODEBUG("GOrdGivImg",0);
+ break;
+ case GOrdCurImg: OOODEBUG("GOrdCurImg",0);
+ break;
+ case GOrdImgDat: OOODEBUG("GOrdImgDat",0);
+ break;
+ case GOrdEndImg: OOODEBUG("GOrdEndImg",0);
+ break;
+
+ case GOrdBegAra: {
+ OSArea * p=new OSArea;
+ p->bClosed=FALSE;
+ p->pSucc=pAreaStack; pAreaStack=p;
+ *pOS2MET >> (p->nFlags);
+ p->aCol=aAttr.aPatCol;
+ p->aBgCol=aAttr.aPatBgCol;
+ p->eMix=aAttr.ePatMix;
+ p->eBgMix=aAttr.ePatBgMix;
+ p->bFill=aAttr.bFill;
+ break;
+ }
+ case GOrdEndAra:
+ {
+ OSArea * p=pAreaStack;
+ if ( p )
+ {
+ pAreaStack = p->pSucc;
+ if ( pPathStack )
+ {
+ for ( USHORT i=0; i<p->aPPoly.Count(); i++ )
+ {
+ AddPointsToPath( p->aPPoly.GetObject( i ) );
+ CloseFigure();
+ }
+ }
+ else
+ {
+ if ( ( p->nFlags & 0x40 ) == 0 )
+ SetPen( COL_TRANSPARENT, 0, PEN_NULL );
+ else
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+
+ ChangeBrush(p->aCol,p->aBgCol,p->bFill);
+ SetRasterOp(p->eMix);
+ DrawPolyPolygon( p->aPPoly );
+ }
+ delete p;
+ }
+ }
+ break;
+
+ case GOrdBegElm:// OOODEBUG("GOrdBegElm",0);
+ break;
+ case GOrdEndElm:// OOODEBUG("GOrdEndElm",0);
+ break;
+
+ case GOrdBegPth: {
+ OSPath * p=new OSPath;
+ p->pSucc=pPathStack; pPathStack=p;
+ pOS2MET->SeekRel(2);
+ *pOS2MET >> p->nID;
+ p->bClosed=FALSE;
+ p->bStroke=FALSE;
+ break;
+ }
+ case GOrdEndPth: {
+ OSPath * p, * pprev, * psucc;
+ if (pPathStack==NULL) break;
+ p=pPathList; pprev=NULL;
+ while (p!=NULL) {
+ psucc=p->pSucc;
+ if (p->nID==pPathStack->nID) {
+ if (pprev==NULL) pPathList=psucc; else pprev->pSucc=psucc;
+ delete p;
+ }
+ else pprev=p;
+ p=psucc;
+ }
+ p=pPathStack;
+ pPathStack=p->pSucc;
+ p->pSucc=pPathList; pPathList=p;
+ break;
+ }
+ case GOrdFilPth:
+ {
+ ULONG nID;
+ UINT16 nDummy;
+ OSPath* p = pPathList;
+
+ *pOS2MET >> nDummy
+ >> nID;
+
+ if ( ! ( nDummy & 0x20 ) ) // #30933# i do not know the exact meaning of this bit,
+ { // but if set it seems to be better not to fill this path
+ while( p && p->nID != nID )
+ p = p->pSucc;
+
+ if( p )
+ {
+ if( p->bStroke )
+ {
+ SetPen( aAttr.aPatCol, aAttr.nStrLinWidth, PEN_SOLID );
+ ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),FALSE);
+ SetRasterOp( aAttr.ePatMix );
+ if ( IsLineInfo() )
+ {
+ for ( USHORT i = 0; i < p->aPPoly.Count(); i++ )
+ pVirDev->DrawPolyLine( p->aPPoly.GetObject( i ), aLineInfo );
+ }
+ else
+ pVirDev->DrawPolyPolygon( p->aPPoly );
+ }
+ else
+ {
+ SetPen( COL_TRANSPARENT, 0, PEN_NULL );
+ ChangeBrush( aAttr.aPatCol, aAttr.aPatBgCol, aAttr.bFill );
+ SetRasterOp( aAttr.ePatMix );
+ pVirDev->DrawPolyPolygon( p->aPPoly );
+ }
+ }
+ }
+ }
+ break;
+
+ case GOrdModPth:
+ {
+ OSPath* p = pPathList;
+
+ while( p && p->nID != 1 )
+ p = p->pSucc;
+
+ if( p )
+ p->bStroke = TRUE;
+ }
+ break;
+
+ case GOrdOutPth:
+ {
+ ULONG nID;
+ USHORT i,nC;
+ OSPath* p=pPathList;
+ pOS2MET->SeekRel(2);
+ *pOS2MET >> nID;
+ while (p!=NULL && p->nID!=nID)
+ p=p->pSucc;
+
+ if( p!=NULL )
+ {
+ SetPen( aAttr.aLinCol, aAttr.nStrLinWidth, aAttr.eLinStyle );
+ SetRasterOp(aAttr.eLinMix);
+ ChangeBrush(Color(COL_TRANSPARENT),Color(COL_TRANSPARENT),FALSE);
+ nC=p->aPPoly.Count();
+ for (i=0; i<nC; i++)
+ {
+ if (i+1<nC || p->bClosed==TRUE)
+ DrawPolygon( p->aPPoly.GetObject( i ) );
+ else
+ DrawPolyLine( p->aPPoly.GetObject( i ) );
+ }
+ }
+ break;
+ }
+ case GOrdSClPth: { OOODEBUG("GOrdSClPth",0);
+ ULONG nID;
+ OSPath * p=pPathList;
+ pOS2MET->SeekRel(2);
+ *pOS2MET >> nID;
+ if (nID==0) p=NULL;
+ while (p!=NULL && p->nID!=nID) p=p->pSucc;
+ if (p!=NULL) pVirDev->SetClipRegion(Region(p->aPPoly));
+ else pVirDev->SetClipRegion();
+ break;
+ }
+ case GOrdNopNop:
+ break;
+ case GOrdRemark: //OOODEBUG("GOrdRemark",0);
+ break;
+ case GOrdSegLab: OOODEBUG("GOrdSegLab",0);
+ break;
+
+ case GOrdBitBlt: ReadBitBlt(); break;
+
+ case GOrdCalSeg: OOODEBUG("GOrdCalSeg",0);
+ break;
+ case GOrdSSgBnd: OOODEBUG("GOrdSSgBnd",0);
+ break;
+ case GOrdSegChr: OOODEBUG("GOrdSegChr",0);
+ break;
+ case GOrdCloFig:
+ CloseFigure();
+ break;
+ case GOrdEndSym: OOODEBUG("GOrdEndSym",0);
+ break;
+ case GOrdEndPlg: OOODEBUG("GOrdEndPlg",0);
+ break;
+ case GOrdEscape: OOODEBUG("GOrdEscape",0);
+ break;
+ case GOrdExtEsc: OOODEBUG("GOrdExtEsc",0);
+ break;
+
+ case GOrdPolygn: ReadPolygons(); break;
+
+ case GOrdStkPop: PopAttr(); break;
+
+ case GOrdPIvAtr: PushAttr(nOrderID);
+ case GOrdSIvAtr: {
+ BYTE nA, nP, nFlags, nMix;
+ ULONG nVal;
+ Color aCol;
+ RasterOp eROP;
+ *pOS2MET >> nA >> nP >> nFlags;
+ if (nOrderID==GOrdPIvAtr) {
+ pAttrStack->nIvAttrA=nA;
+ pAttrStack->nIvAttrP=nP;
+ }
+ if (nA<=2) {
+ if ((nFlags&0x80)!=0) {
+ if (nA==1) switch (nP) {
+ case 1: aAttr.aLinCol=aDefAttr.aLinCol; break;
+ case 2: aAttr.aChrCol=aDefAttr.aChrCol; break;
+ case 3: aAttr.aMrkCol=aDefAttr.aMrkCol; break;
+ case 4: aAttr.aPatCol=aDefAttr.aPatCol; break;
+ case 5: aAttr.aImgCol=aDefAttr.aImgCol; break;
+ }
+ else switch (nP) {
+ case 1: aAttr.aLinBgCol=aDefAttr.aLinBgCol; break;
+ case 2: aAttr.aChrBgCol=aDefAttr.aChrBgCol; break;
+ case 3: aAttr.aMrkBgCol=aDefAttr.aMrkBgCol; break;
+ case 4: aAttr.aPatBgCol=aDefAttr.aPatBgCol; break;
+ case 5: aAttr.aImgBgCol=aDefAttr.aImgBgCol; break;
+ }
+ }
+ else {
+ nVal=ReadLittleEndian3BytesLong();
+ if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
+ else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
+ else aCol=GetPaletteColor(nVal);
+ if (nA==1) switch (nP) {
+ case 1: aAttr.aLinCol=aCol; break;
+ case 2: aAttr.aChrCol=aCol; break;
+ case 3: aAttr.aMrkCol=aCol; break;
+ case 4: aAttr.aPatCol=aCol; break;
+ case 5: aAttr.aImgCol=aCol; break;
+ }
+ else switch (nP) {
+ case 1: aAttr.aLinBgCol=aCol; break;
+ case 2: aAttr.aChrBgCol=aCol; break;
+ case 3: aAttr.aMrkBgCol=aCol; break;
+ case 4: aAttr.aPatBgCol=aCol; break;
+ case 5: aAttr.aImgBgCol=aCol; break;
+ }
+ }
+ }
+ else {
+ *pOS2MET >> nMix;
+ if (nMix==0) {
+ if (nA==1) switch (nP) {
+ case 1: aAttr.eLinMix=aDefAttr.eLinMix; break;
+ case 2: aAttr.eChrMix=aDefAttr.eChrMix; break;
+ case 3: aAttr.eMrkMix=aDefAttr.eMrkMix; break;
+ case 4: aAttr.ePatMix=aDefAttr.ePatMix; break;
+ case 5: aAttr.eImgMix=aDefAttr.eImgMix; break;
+ }
+ else switch (nP) {
+ case 1: aAttr.eLinBgMix=aDefAttr.eLinBgMix; break;
+ case 2: aAttr.eChrBgMix=aDefAttr.eChrBgMix; break;
+ case 3: aAttr.eMrkBgMix=aDefAttr.eMrkBgMix; break;
+ case 4: aAttr.ePatBgMix=aDefAttr.ePatBgMix; break;
+ case 5: aAttr.eImgBgMix=aDefAttr.eImgBgMix; break;
+ }
+ }
+ else {
+ eROP=OS2MixToRasterOp(nMix);
+ if (nA==1) switch (nP) {
+ case 1: aAttr.eLinMix=eROP; break;
+ case 2: aAttr.eChrMix=eROP; break;
+ case 3: aAttr.eMrkMix=eROP; break;
+ case 4: aAttr.ePatMix=eROP; break;
+ case 5: aAttr.eImgMix=eROP; break;
+ }
+ else switch (nP) {
+ case 1: aAttr.eLinBgMix=eROP; break;
+ case 2: aAttr.eChrBgMix=eROP; break;
+ case 3: aAttr.eMrkBgMix=eROP; break;
+ case 4: aAttr.ePatBgMix=eROP; break;
+ case 5: aAttr.eImgBgMix=eROP; break;
+ }
+ }
+ }
+ break;
+ }
+ case GOrdPIxCol: PushAttr(nOrderID);
+ case GOrdSIxCol: {
+ BYTE nFlags;
+ ULONG nVal;
+ Color aCol;
+ *pOS2MET >> nFlags;
+ if ((nFlags&0x80)!=0) {
+ aAttr.aLinCol=aDefAttr.aLinCol;
+ aAttr.aChrCol=aDefAttr.aChrCol;
+ aAttr.aMrkCol=aDefAttr.aMrkCol;
+ aAttr.aPatCol=aDefAttr.aPatCol;
+ aAttr.aImgCol=aDefAttr.aImgCol;
+ }
+ else {
+ nVal=ReadLittleEndian3BytesLong();
+ if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
+ else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
+ else aCol=GetPaletteColor(nVal);
+ aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
+ aAttr.aImgCol = aCol;
+ }
+ break;
+ }
+
+ case GOrdPColor:
+ case GOrdPXtCol: PushAttr(nOrderID);
+ case GOrdSColor:
+ case GOrdSXtCol: {
+ BYTE nbyte;
+ USHORT nVal;
+ Color aCol;
+ if (nOrderID==GOrdPColor || nOrderID==GOrdSColor) {
+ *pOS2MET >> nbyte; nVal=((USHORT)nbyte)|0xff00;
+ }
+ else *pOS2MET >> nVal;
+ if (nVal==0x0000 || nVal==0xff00) {
+ aAttr.aLinCol=aDefAttr.aLinCol;
+ aAttr.aChrCol=aDefAttr.aChrCol;
+ aAttr.aMrkCol=aDefAttr.aMrkCol;
+ aAttr.aPatCol=aDefAttr.aPatCol;
+ aAttr.aImgCol=aDefAttr.aImgCol;
+ }
+ else {
+ if (nVal==0x0007) aCol=Color(COL_WHITE);
+ else if (nVal==0x0008) aCol=Color(COL_BLACK);
+ else if (nVal==0xff08) aCol=GetPaletteColor(1);
+ else aCol=GetPaletteColor(((ULONG)nVal) & 0x000000ff);
+ aAttr.aLinCol = aAttr.aChrCol = aAttr.aMrkCol = aAttr.aPatCol =
+ aAttr.aImgCol = aCol;
+ }
+ break;
+ }
+
+ case GOrdPBgCol: PushAttr(nOrderID);
+ case GOrdSBgCol: {
+ USHORT nVal;
+ Color aCol;
+ *pOS2MET >> nVal;
+ if (nVal==0x0000 || nVal==0xff00) {
+ aAttr.aLinBgCol=aDefAttr.aLinBgCol;
+ aAttr.aChrBgCol=aDefAttr.aChrBgCol;
+ aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
+ aAttr.aPatBgCol=aDefAttr.aPatBgCol;
+ aAttr.aImgBgCol=aDefAttr.aImgBgCol;
+ }
+ else {
+ if (nVal==0x0007) aCol=Color(COL_WHITE);
+ else if (nVal==0x0008) aCol=Color(COL_BLACK);
+ else if (nVal==0xff08) aCol=GetPaletteColor(0);
+ else aCol=GetPaletteColor(((ULONG)nVal) & 0x000000ff);
+ aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
+ aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
+ }
+ break;
+ }
+ case GOrdPBxCol: PushAttr(nOrderID);
+ case GOrdSBxCol: {
+ BYTE nFlags;
+ ULONG nVal;
+ Color aCol;
+ *pOS2MET >> nFlags;
+ if ((nFlags&0x80)!=0) {
+ aAttr.aLinBgCol=aDefAttr.aLinBgCol;
+ aAttr.aChrBgCol=aDefAttr.aChrBgCol;
+ aAttr.aMrkBgCol=aDefAttr.aMrkBgCol;
+ aAttr.aPatBgCol=aDefAttr.aPatBgCol;
+ aAttr.aImgBgCol=aDefAttr.aImgBgCol;
+ }
+ else {
+ nVal=ReadLittleEndian3BytesLong();
+ if ((nFlags&0x40)!=0 && nVal==1) aCol=Color(COL_BLACK);
+ else if ((nFlags&0x40)!=0 && nVal==2) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==4) aCol=Color(COL_WHITE);
+ else if ((nFlags&0x40)!=0 && nVal==5) aCol=Color(COL_BLACK);
+ else aCol=GetPaletteColor(nVal);
+ aAttr.aLinBgCol = aAttr.aChrBgCol = aAttr.aMrkBgCol =
+ aAttr.aPatBgCol = aAttr.aImgBgCol = aCol;
+ }
+ break;
+ }
+
+ case GOrdPMixMd: PushAttr(nOrderID);
+ case GOrdSMixMd: {
+ BYTE nMix;
+ *pOS2MET >> nMix;
+ if (nMix==0) {
+ aAttr.eLinMix=aDefAttr.eLinMix;
+ aAttr.eChrMix=aDefAttr.eChrMix;
+ aAttr.eMrkMix=aDefAttr.eMrkMix;
+ aAttr.ePatMix=aDefAttr.ePatMix;
+ aAttr.eImgMix=aDefAttr.eImgMix;
+ }
+ else {
+ aAttr.eLinMix = aAttr.eChrMix = aAttr.eMrkMix =
+ aAttr.ePatMix = aAttr.eImgMix = OS2MixToRasterOp(nMix);
+ }
+ break;
+ }
+ case GOrdPBgMix: PushAttr(nOrderID);
+ case GOrdSBgMix: {
+ BYTE nMix;
+ *pOS2MET >> nMix;
+ if (nMix==0) {
+ aAttr.eLinBgMix=aDefAttr.eLinBgMix;
+ aAttr.eChrBgMix=aDefAttr.eChrBgMix;
+ aAttr.eMrkBgMix=aDefAttr.eMrkBgMix;
+ aAttr.ePatBgMix=aDefAttr.ePatBgMix;
+ aAttr.eImgBgMix=aDefAttr.eImgBgMix;
+ }
+ else {
+ aAttr.eLinBgMix = aAttr.eChrBgMix = aAttr.eMrkBgMix =
+ aAttr.ePatBgMix = aAttr.eImgBgMix = OS2MixToRasterOp(nMix);
+ }
+ break;
+ }
+ case GOrdPPtSet: PushAttr(nOrderID);
+ case GOrdSPtSet: OOODEBUG("GOrdSPtSet",0);
+ break;
+
+ case GOrdPPtSym: PushAttr(nOrderID);
+ case GOrdSPtSym: {
+ BYTE nPatt;
+ *pOS2MET >> nPatt;
+ aAttr.bFill = ( nPatt != 0x0f );
+ break;
+ }
+
+ case GOrdPPtRef: PushAttr(nOrderID);
+ case GOrdSPtRef: OOODEBUG("GOrdSPtRef",0);
+ break;
+
+ case GOrdPLnEnd: PushAttr(nOrderID);
+ case GOrdSLnEnd:
+ break;
+
+ case GOrdPLnJoi: PushAttr(nOrderID);
+ case GOrdSLnJoi:
+ break;
+
+ case GOrdPLnTyp: PushAttr(nOrderID);
+ case GOrdSLnTyp: {
+ BYTE nType;
+ *pOS2MET >> nType;
+ switch (nType) {
+ case 0: aAttr.eLinStyle=aDefAttr.eLinStyle; break;
+ case 1: case 4: aAttr.eLinStyle=PEN_DOT; break;
+ case 2: case 5: aAttr.eLinStyle=PEN_DASH; break;
+ case 3: case 6: aAttr.eLinStyle=PEN_DASHDOT; break;
+ case 8: aAttr.eLinStyle=PEN_NULL; break;
+ default: aAttr.eLinStyle=PEN_SOLID;
+ }
+ break;
+ }
+ case GOrdPLnWdt: PushAttr(nOrderID);
+ case GOrdSLnWdt: {
+ BYTE nbyte;
+ *pOS2MET >> nbyte;
+ if (nbyte==0) aAttr.nLinWidth=aDefAttr.nLinWidth;
+ else aAttr.nLinWidth=(USHORT)nbyte-1;
+ break;
+ }
+ case GOrdPFrLWd: PushAttr(nOrderID);
+ case GOrdSFrLWd:
+ break;
+
+ case GOrdPStLWd: PushAttr(nOrderID);
+ case GOrdSStLWd :
+ {
+ BYTE nFlags;
+ long nWd;
+
+ *pOS2MET >> nFlags;
+ if ( nFlags & 0x80 )
+ aAttr.nStrLinWidth = aDefAttr.nStrLinWidth;
+ else
+ {
+ pOS2MET->SeekRel( 1 );
+ nWd = ReadCoord( bCoord32 );
+ if ( nWd < 0 )
+ nWd = -nWd;
+ aAttr.nStrLinWidth = (USHORT)nWd;
+ }
+ break;
+ }
+ case GOrdPChDir: PushAttr(nOrderID);
+ case GOrdSChDir:
+ break;
+
+ case GOrdPChPrc: PushAttr(nOrderID);
+ case GOrdSChPrc:
+ break;
+
+ case GOrdPChSet: PushAttr(nOrderID);
+ case GOrdSChSet: {
+ BYTE nbyte; *pOS2MET >> nbyte;
+ aAttr.nChrSet=((ULONG)nbyte)&0xff;
+ break;
+ }
+ case GOrdPChAng: PushAttr(nOrderID);
+ case GOrdSChAng: {
+ long nX,nY;
+ nX=ReadCoord(bCoord32); nY=ReadCoord(bCoord32);
+ if (nX>=0 && nY==0) aAttr.nChrAng=0;
+ else {
+ aAttr.nChrAng=(short)(atan2((double)nY,(double)nX)/3.1415926539*1800.0);
+ while (aAttr.nChrAng<0) aAttr.nChrAng+=3600;
+ aAttr.nChrAng%=3600;
+ }
+ break;
+ }
+ case GOrdPChBrx: PushAttr(nOrderID);
+ case GOrdSChBrx:
+ break;
+
+ case GOrdPChCel: PushAttr(nOrderID);
+ case GOrdSChCel: {
+ BYTE nbyte;
+ USHORT nLen=nOrderLen;
+ aAttr.aChrCellSize.Width()=ReadCoord(bCoord32);
+ aAttr.aChrCellSize.Height()=ReadCoord(bCoord32);
+ if (bCoord32) nLen-=8; else nLen-=4;
+ if (nLen>=4) {
+ pOS2MET->SeekRel(4); nLen-=4;
+ }
+ if (nLen>=2) {
+ *pOS2MET >> nbyte;
+ if ((nbyte&0x80)==0 && aAttr.aChrCellSize==Size(0,0))
+ aAttr.aChrCellSize=aDefAttr.aChrCellSize;
+ }
+ break;
+ }
+ case GOrdPChXtr: PushAttr(nOrderID);
+ case GOrdSChXtr:
+ break;
+
+ case GOrdPChShr: PushAttr(nOrderID);
+ case GOrdSChShr:
+ break;
+
+ case GOrdPTxAlg: PushAttr(nOrderID);
+ case GOrdSTxAlg: OOODEBUG("GOrdSTxAlg",0);
+ break;
+
+ case GOrdPMkPrc: PushAttr(nOrderID);
+ case GOrdSMkPrc: {
+ BYTE nbyte;
+ *pOS2MET >> nbyte;
+ if (nbyte==0) aAttr.nMrkPrec=aDefAttr.nMrkPrec;
+ else aAttr.nMrkPrec=nbyte;
+ break;
+ }
+
+ case GOrdPMkSet: PushAttr(nOrderID);
+ case GOrdSMkSet: {
+ BYTE nbyte;
+ *pOS2MET >> nbyte;
+ if (nbyte==0) aAttr.nMrkSet=aDefAttr.nMrkSet;
+ else aAttr.nMrkSet=nbyte;
+ break;
+ }
+
+ case GOrdPMkSym: PushAttr(nOrderID);
+ case GOrdSMkSym: {
+ BYTE nbyte;
+ *pOS2MET >> nbyte;
+ if (nbyte==0) aAttr.nMrkSymbol=aDefAttr.nMrkSymbol;
+ else aAttr.nMrkSymbol=nbyte;
+ break;
+ }
+
+ case GOrdPMkCel: PushAttr(nOrderID);
+ case GOrdSMkCel: {
+ BYTE nbyte;
+ USHORT nLen=nOrderLen;
+ aAttr.aMrkCellSize.Width()=ReadCoord(bCoord32);
+ aAttr.aMrkCellSize.Height()=ReadCoord(bCoord32);
+ if (bCoord32) nLen-=8; else nLen-=4;
+ if (nLen>=2) {
+ *pOS2MET >> nbyte;
+ if ((nbyte&0x80)==0 && aAttr.aMrkCellSize==Size(0,0))
+ aAttr.aMrkCellSize=aDefAttr.aMrkCellSize;
+ }
+ break;
+ }
+
+ case GOrdPArcPa: PushAttr(nOrderID);
+ case GOrdSArcPa:
+ aAttr.nArcP=ReadCoord(bCoord32);
+ aAttr.nArcQ=ReadCoord(bCoord32);
+ aAttr.nArcR=ReadCoord(bCoord32);
+ aAttr.nArcS=ReadCoord(bCoord32);
+ break;
+
+ case GOrdPCrPos: PushAttr(nOrderID);
+ case GOrdSCrPos:
+ aAttr.aCurPos=ReadPoint();
+ break;
+
+ case GOrdPMdTrn: PushAttr(nOrderID);
+ case GOrdSMdTrn: OOODEBUG("GOrdSMdTrn",0);
+ break;
+
+ case GOrdPPkIdn: PushAttr(nOrderID);
+ case GOrdSPkIdn: OOODEBUG("GOrdSPkIdn",0);
+ break;
+
+ case GOrdSVwTrn: OOODEBUG("GOrdSVwTrn",0);
+ break;
+
+ case GOrdPVwWin: PushAttr(nOrderID);
+ case GOrdSVwWin: OOODEBUG("GOrdSVwWin",0);
+ break;
+ default: OOODEBUG("Order unbekannt:",nOrderID);
+ }
+}
+
+void OS2METReader::ReadDsc(USHORT nDscID, USHORT /*nDscLen*/)
+{
+ switch (nDscID) {
+ case 0x00f7: { // 'Specify GVM Subset'
+ BYTE nbyte;
+ pOS2MET->SeekRel(6);
+ *pOS2MET >> nbyte;
+ if (nbyte==0x05) bCoord32=TRUE;
+ else if (nbyte==0x04) bCoord32=FALSE;
+ else {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=1;
+ }
+ break;
+ }
+ case 0x00f6:
+ {
+ // 'Set Picture Descriptor'
+ BOOL b32;
+ BYTE nbyte,nUnitType;
+ long x1,y1,x2,y2,nt,xr,yr;
+
+ pOS2MET->SeekRel(2);
+ *pOS2MET >> nbyte;
+
+ if (nbyte==0x05)
+ b32=TRUE;
+ else if(nbyte==0x04)
+ b32=FALSE;
+ else
+ {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=2;
+ }
+
+ *pOS2MET >> nUnitType;
+
+ xr=ReadCoord(b32);
+ yr=ReadCoord(b32);
+
+ ReadCoord(b32);
+
+ if (nUnitType==0x00 && xr>0 && yr>0)
+ aGlobMapMode=MapMode(MAP_INCH,Point(0,0),Fraction(10,xr),Fraction(10,yr));
+ else if (nUnitType==0x01 && xr>0 && yr>0)
+ aGlobMapMode=MapMode(MAP_CM,Point(0,0),Fraction(10,xr),Fraction(10,yr));
+ else
+ aGlobMapMode=MapMode();
+
+ x1=ReadCoord(b32);
+ x2=ReadCoord(b32);
+ y1=ReadCoord(b32);
+ y2=ReadCoord(b32);
+
+ if (x1>x2)
+ {
+ nt=x1;
+ x1=x2;
+ x2=nt;
+ }
+
+ if (y1>y2)
+ {
+ nt=y1;
+ y1=y2;
+ y2=nt;
+ }
+
+ aBoundingRect.Left() = x1;
+ aBoundingRect.Right() = x2;
+ aBoundingRect.Top() = y1;
+ aBoundingRect.Bottom() = y2;
+
+ // no output beside this bounding rect
+ pVirDev->IntersectClipRegion( Rectangle( Point(), aBoundingRect.GetSize() ) );
+
+ break;
+ }
+ case 0x0021: // 'Set Current Defaults'
+ break;
+ }
+}
+
+void OS2METReader::ReadImageData(USHORT nDataID, USHORT nDataLen)
+{
+ OSBitmap * p=pBitmapList; if (p==NULL) return; // Nanu ?
+
+ switch (nDataID) {
+
+ case 0x0070: // Begin Segment
+ break;
+
+ case 0x0091: // Begin Image Content
+ break;
+
+ case 0x0094: // Image Size
+ pOS2MET->SeekRel(5);
+ p->nHeight=ReadBigEndianWord();
+ p->nWidth=ReadBigEndianWord();
+ break;
+
+ case 0x0095: // Image Encoding
+ break;
+
+ case 0x0096: { // Image IDE-Size
+ BYTE nbyte;
+ *pOS2MET >> nbyte; p->nBitsPerPixel=nbyte;
+ break;
+ }
+
+ case 0x0097: // Image LUT-ID
+ break;
+
+ case 0x009b: // IDE Structure
+ break;
+
+ case 0xfe92: { // Image Data
+ // Spaetestens jetzt brauchen wir die temporaere BMP-Datei
+ // und darin mindestens den Header + Palette.
+ if (p->pBMP==NULL) {
+ p->pBMP=new SvMemoryStream();
+ p->pBMP->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ if (p->nWidth==0 || p->nHeight==0 || p->nBitsPerPixel==0) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=3;
+ return;
+ }
+ // Schreibe (Windows-)BITMAPINFOHEADER:
+ *(p->pBMP) << ((ULONG)40) << p->nWidth << p->nHeight;
+ *(p->pBMP) << ((USHORT)1) << p->nBitsPerPixel;
+ *(p->pBMP) << ((ULONG)0) << ((ULONG)0) << ((ULONG)0) << ((ULONG)0);
+ *(p->pBMP) << ((ULONG)0) << ((ULONG)0);
+ // Schreibe Farbtabelle:
+ if (p->nBitsPerPixel<=8) {
+ USHORT i, nColTabSize=1<<(p->nBitsPerPixel);
+ for (i=0; i<nColTabSize; i++) *(p->pBMP) << GetPalette0RGB(i);
+ }
+ }
+ // OK, nun werden die Map-Daten ruebergeschoben. Leider haben OS2 und
+ // BMP eine unterschiedliche Reihenfolge von RGB bei 24-Bit.
+ BYTE * pBuf=new BYTE[nDataLen];
+ pOS2MET->Read(pBuf,nDataLen);
+ if (p->nBitsPerPixel==24) {
+ ULONG i, j, nAlign, nBytesPerLine;
+ BYTE nTemp;
+ nBytesPerLine=(p->nWidth*3+3)&0xfffffffc;
+ nAlign=p->nMapPos-(p->nMapPos % nBytesPerLine);
+ i=0;
+ while (nAlign+i+2<p->nMapPos+nDataLen) {
+ if (nAlign+i>=p->nMapPos) {
+ j=nAlign+i-p->nMapPos;
+ nTemp=pBuf[j]; pBuf[j]=pBuf[j+2]; pBuf[j+2]=nTemp;
+ }
+ i+=3; if (i+2>=nBytesPerLine) {
+ nAlign+=nBytesPerLine;
+ i=0;
+ }
+ }
+ }
+ p->pBMP->Write(pBuf,nDataLen);
+ p->nMapPos+=nDataLen;
+ delete pBuf;
+ break;
+ }
+ case 0x0093: // End Image Content
+ break;
+
+ case 0x0071: // End Segment
+ break;
+ }
+}
+
+void OS2METReader::ReadFont(USHORT nFieldSize)
+{
+ ULONG nPos, nMaxPos;
+ USHORT nLen,i;
+ BYTE nbyte, nTripType, nTripType2;
+ OSFont * pF=new OSFont;
+ pF->pSucc=pFontList; pFontList=pF;
+ pF->nID=0;
+ pF->aFont.SetTransparent(TRUE);
+ pF->aFont.SetAlign(ALIGN_BASELINE);
+
+ nPos=pOS2MET->Tell();
+ nMaxPos=nPos+(ULONG)nFieldSize;
+ pOS2MET->SeekRel(2); nPos+=2;
+ while (nPos<nMaxPos && pOS2MET->GetError()==0) {
+ *pOS2MET >> nbyte; nLen =((USHORT)nbyte) & 0x00ff;
+ *pOS2MET >> nTripType;
+ switch (nTripType) {
+ case 0x02:
+ *pOS2MET >> nTripType2;
+ switch (nTripType2) {
+ case 0x84: // Font name
+ break;
+ case 0x08: { // Font Typeface
+ char str[33];
+ String aStr;
+ pOS2MET->SeekRel(1);
+ for (i=0; i<32; i++) *pOS2MET >> str[i];
+ str[32]=0;
+ aStr = String::CreateFromAscii( str );
+ if ( aStr.CompareIgnoreCaseToAscii( "Helv" ) == COMPARE_EQUAL )
+ aStr = String::CreateFromAscii( "Helvetica" );
+ pF->aFont.SetName( aStr );
+ break;
+ }
+ }
+ break;
+ case 0x24: // Icid
+ *pOS2MET >> nTripType2;
+ switch (nTripType2) {
+ case 0x05: //Icid
+ *pOS2MET >> nbyte;
+ pF->nID=((ULONG)nbyte)&0xff;
+ break;
+ }
+ break;
+ case 0x20: // Font Binary GCID
+ break;
+ case 0x1f: { // Font Attributes
+ FontWeight eWeight;
+ BYTE nbyte;
+ *pOS2MET >> nbyte;
+ switch (nbyte) {
+ case 1: eWeight=WEIGHT_THIN; break;
+ case 2: eWeight=WEIGHT_ULTRALIGHT; break;
+ case 3: eWeight=WEIGHT_LIGHT; break;
+ case 4: eWeight=WEIGHT_SEMILIGHT; break;
+ case 5: eWeight=WEIGHT_NORMAL; break;
+ case 6: eWeight=WEIGHT_SEMIBOLD; break;
+ case 7: eWeight=WEIGHT_BOLD; break;
+ case 8: eWeight=WEIGHT_ULTRABOLD; break;
+ case 9: eWeight=WEIGHT_BLACK; break;
+ default: eWeight=WEIGHT_DONTKNOW;
+ }
+ pF->aFont.SetWeight(eWeight);
+ break;
+ }
+ }
+ nPos+=nLen; pOS2MET->Seek(nPos);
+ }
+}
+
+void OS2METReader::ReadField(USHORT nFieldType, USHORT nFieldSize)
+{
+ switch (nFieldType) {
+ case BegDocumnMagic:
+ break;
+ case EndDocumnMagic:
+ break;
+ case BegResGrpMagic:
+ break;
+ case EndResGrpMagic:
+ break;
+ case BegColAtrMagic:
+ break;
+ case EndColAtrMagic:
+ break;
+ case BlkColAtrMagic: {
+ ULONG nPos, nMaxPos;
+ BYTE nbyte;
+ ULONG nCol;
+ USHORT nStartIndex, nEndIndex, i, nElemLen, nBytesPerCol;
+
+ nPos=pOS2MET->Tell();
+ nMaxPos=nPos+(ULONG)nFieldSize;
+ pOS2MET->SeekRel(3); nPos+=3;
+ while (nPos<nMaxPos && pOS2MET->GetError()==0) {
+ *pOS2MET >> nbyte; nElemLen=((USHORT)nbyte) & 0x00ff;
+ if (nElemLen>11) {
+ pOS2MET->SeekRel(4);
+ nStartIndex=ReadBigEndianWord();
+ pOS2MET->SeekRel(3);
+ *pOS2MET >> nbyte; nBytesPerCol=((USHORT)nbyte) & 0x00ff;
+ nEndIndex=nStartIndex+(nElemLen-11)/nBytesPerCol;
+ for (i=nStartIndex; i<nEndIndex; i++) {
+ if (nBytesPerCol > 3) pOS2MET->SeekRel(nBytesPerCol-3);
+ nCol=ReadBigEndian3BytesLong();
+ SetPalette0RGB(i,nCol);
+ }
+ }
+ else if (nElemLen<10) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=4;
+ }
+ nPos+=(ULONG)nElemLen;
+ pOS2MET->Seek(nPos);
+ }
+ break;
+ }
+ case MapColAtrMagic:
+ break;
+ case BegImgObjMagic: {
+ // neue Bitmap schonmal herstellen: (wird spaeter gefuellt)
+ OSBitmap * pB=new OSBitmap;
+ pB->pSucc=pBitmapList; pBitmapList=pB;
+ pB->pBMP=NULL; pB->nWidth=0; pB->nHeight=0; pB->nBitsPerPixel=0;
+ pB->nMapPos=0;
+ // ID der Bitmap ermitteln:
+ BYTE i,nbyte,nbyte2;
+ pB->nID=0;
+ for (i=0; i<4; i++) {
+ *pOS2MET >> nbyte >> nbyte2;
+ nbyte=((nbyte-0x30)<<4)|(nbyte2-0x30);
+ pB->nID=(pB->nID>>8)|(((ULONG)nbyte)<<24);
+ }
+ // neue Palette auf den Paletten-Stack bringen: (wird spaeter gefuellt)
+ OSPalette * pP=new OSPalette;
+ pP->pSucc=pPaletteStack; pPaletteStack=pP;
+ pP->p0RGB=NULL; pP->nSize=0;
+ break;
+ }
+ case EndImgObjMagic: {
+ // Temporaere Windows-BMP-Datei auslesen:
+ if (pBitmapList==NULL || pBitmapList->pBMP==NULL ||
+ pBitmapList->pBMP->GetError()!=0) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=5;
+ return;
+ }
+ pBitmapList->pBMP->Seek(0);
+
+ pBitmapList->aBitmap.Read( *( pBitmapList->pBMP ), FALSE );
+
+ if (pBitmapList->pBMP->GetError()!=0) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=6;
+ }
+ delete pBitmapList->pBMP; pBitmapList->pBMP=NULL;
+ // Palette vom Stack killen:
+ OSPalette * pP=pPaletteStack;
+ if (pP!=NULL) {
+ pPaletteStack=pP->pSucc;
+ if (pP->p0RGB!=NULL) delete pP->p0RGB;
+ delete pP;
+ }
+ break;
+ }
+ case DscImgObjMagic:
+ break;
+ case DatImgObjMagic: {
+ USHORT nDataID, nDataLen;
+ BYTE nbyte;
+ ULONG nPos, nMaxPos;
+
+ nPos=pOS2MET->Tell();
+ nMaxPos=nPos+(ULONG)nFieldSize;
+ while (nPos<nMaxPos && pOS2MET->GetError()==0) {
+ *pOS2MET >> nbyte; nDataID=((USHORT)nbyte)&0x00ff;
+ if (nDataID==0x00fe) {
+ *pOS2MET >> nbyte;
+ nDataID=(nDataID<<8)|(((USHORT)nbyte)&0x00ff);
+ nDataLen=ReadBigEndianWord();
+ nPos+=4;
+ }
+ else {
+ *pOS2MET >> nbyte; nDataLen=((USHORT)nbyte)&0x00ff;
+ nPos+=2;
+ }
+ ReadImageData(nDataID, nDataLen);
+ nPos+=(ULONG)nDataLen;
+ pOS2MET->Seek(nPos);
+ }
+ break;
+ }
+
+ case BegObEnv1Magic:
+ break;
+ case EndObEnv1Magic:
+ break;
+ case BegGrfObjMagic:
+ break;
+ case EndGrfObjMagic: {
+ SvStream * pSave;
+ ULONG nPos, nMaxPos;
+ USHORT nOrderID, nOrderLen;
+ BYTE nbyte;
+
+ if (pOrdFile==NULL) break;
+
+ // in pOrdFile wurden alle "DatGrfObj"-Felder gesammelt, so
+ // dass die darin enthaltnen "Orders" zusammenhangend und nicht durch
+ // "Fields" segmentiert sind. Um sie aus dem MemoryStream auszulesen,
+ // ohne grosse Umstaende deswegen zu haben (frueher wurden die "Orders"
+ // direkt aus pOS2MET gelesen), hier ein kleiner Trick:
+ pSave=pOS2MET;
+ pOS2MET=pOrdFile; //(!)
+ nMaxPos=pOS2MET->Tell();
+ pOS2MET->Seek(0);
+
+ // "Segmentheader":
+ *pOS2MET >> nbyte;
+ if (nbyte==0x70) { // Header vorhanden
+ pOS2MET->SeekRel(15); // brauchen wir aber nicht
+ }
+ else pOS2MET->SeekRel(-1); // Kein Header, Byte zurueck
+
+ // Schleife ueber Order:
+ while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
+ *pOS2MET >> nbyte; nOrderID=((USHORT)nbyte) & 0x00ff;
+ if (nOrderID==0x00fe) {
+ *pOS2MET >> nbyte;
+ nOrderID=(nOrderID << 8) | (((USHORT)nbyte) & 0x00ff);
+ }
+ if (nOrderID>0x00ff || nOrderID==GOrdPolygn) {
+ // ooo: Laut OS2-Doku sollte die Orderlaenge nun als Big-Endian-Word
+ // gegeben sein (Zitat: "Highorder byte precedes loworder byte").
+ // Tatsaechlich gibt es aber Dateien, die die Laenge als
+ // Little-Endian-Word angeben (zu mindestens fuer nOrderID==GOrdPolygn).
+ // Also werfen wir eine Muenze oder was ?
+ *pOS2MET >> nbyte; nOrderLen=(USHORT)nbyte&0x00ff;
+ *pOS2MET >> nbyte; if (nbyte!=0) nOrderLen=nOrderLen<<8|(((USHORT)nbyte)&0x00ff);
+ }
+ else if (nOrderID==GOrdSTxAlg || nOrderID==GOrdPTxAlg) nOrderLen=2;
+ else if ((nOrderID&0xff88)==0x0008) nOrderLen=1;
+ else if (nOrderID==0x0000 || nOrderID==0x00ff) nOrderLen=0;
+ else { *pOS2MET >> nbyte; nOrderLen=((USHORT)nbyte) & 0x00ff; }
+ nPos=pOS2MET->Tell();
+ ReadOrder(nOrderID, nOrderLen);
+ if (nPos+nOrderLen < pOS2MET->Tell()) {
+ OOODEBUG("Order kuerzer als er denkt! OrderID:",nOrderID);
+ OOODEBUG("...und zwar bei Position (Parameteranfang):",nPos);
+ }
+ else if (nPos+nOrderLen != pOS2MET->Tell()) {
+ OOODEBUG(String(nOrderID)+String(" Order nicht alles gelesen! bei:"),nPos);
+ }
+ pOS2MET->Seek(nPos+nOrderLen);
+ }
+
+ pOS2MET=pSave;
+ if (pOrdFile->GetError()) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=10;
+ }
+ delete pOrdFile; pOrdFile=NULL;
+ break;
+ }
+ case DscGrfObjMagic: {
+ ULONG nPos, nMaxPos;
+ USHORT nDscID, nDscLen;
+ BYTE nbyte;
+
+ nMaxPos=pOS2MET->Tell()+(ULONG)nFieldSize;
+ while (pOS2MET->Tell()<nMaxPos && pOS2MET->GetError()==0) {
+ *pOS2MET >> nbyte; nDscID =((USHORT)nbyte) & 0x00ff;
+ *pOS2MET >> nbyte; nDscLen=((USHORT)nbyte) & 0x00ff;
+ nPos=pOS2MET->Tell();
+ ReadDsc(nDscID, nDscLen);
+ pOS2MET->Seek(nPos+nDscLen);
+ }
+ break;
+ }
+ case DatGrfObjMagic: {
+ if (pOrdFile==NULL) {
+ pOrdFile = new SvMemoryStream;
+ pOrdFile->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ }
+ BYTE * pBuf; pBuf = new BYTE[nFieldSize];
+ pOS2MET->Read(pBuf,nFieldSize);
+ pOrdFile->Write(pBuf,nFieldSize);
+ delete pBuf;
+ break;
+ }
+ case MapCodFntMagic:
+ ReadFont(nFieldSize);
+ break;
+
+ case MapDatResMagic:
+ break;
+ }
+}
+
+void OS2METReader::ReadOS2MET( SvStream & rStreamOS2MET, GDIMetaFile & rGDIMetaFile, PFilterCallback pcallback, void * pcallerdata)
+{
+ USHORT nFieldSize;
+ USHORT nFieldType;
+ ULONG nPos, nStartPos, nEndPos, nPercent, nLastPercent;
+ BYTE nMagicByte;
+
+ ErrorCode=0;
+
+ pCallback=pcallback; pCallerData=pcallerdata;
+
+ pOS2MET = &rStreamOS2MET;
+ nOrigPos = pOS2MET->Tell();
+ nOrigNumberFormat = pOS2MET->GetNumberFormatInt();
+
+ bCoord32 = TRUE;
+ pPaletteStack=NULL;
+ pAreaStack=NULL;
+ pPathStack=NULL;
+ pPathList=NULL;
+ pFontList=NULL;
+ pBitmapList=NULL;
+ pAttrStack=NULL;
+
+ aDefAttr.aLinCol =Color(COL_BLACK);
+ aDefAttr.aLinBgCol =Color(COL_WHITE);
+ aDefAttr.eLinMix =ROP_OVERPAINT;
+ aDefAttr.eLinBgMix =ROP_OVERPAINT;
+ aDefAttr.aChrCol =Color(COL_BLACK);
+ aDefAttr.aChrBgCol =Color(COL_WHITE);
+ aDefAttr.eChrMix =ROP_OVERPAINT;
+ aDefAttr.eChrBgMix =ROP_OVERPAINT;
+ aDefAttr.aMrkCol =Color(COL_BLACK);
+ aDefAttr.aMrkBgCol =Color(COL_WHITE);
+ aDefAttr.eMrkMix =ROP_OVERPAINT;
+ aDefAttr.eMrkBgMix =ROP_OVERPAINT;
+ aDefAttr.aPatCol =Color(COL_BLACK);
+ aDefAttr.aPatBgCol =Color(COL_WHITE);
+ aDefAttr.ePatMix =ROP_OVERPAINT;
+ aDefAttr.ePatBgMix =ROP_OVERPAINT;
+ aDefAttr.aImgCol =Color(COL_BLACK);
+ aDefAttr.aImgBgCol =Color(COL_WHITE);
+ aDefAttr.eImgMix =ROP_OVERPAINT;
+ aDefAttr.eImgBgMix =ROP_OVERPAINT;
+ aDefAttr.nArcP =1;
+ aDefAttr.nArcQ =1;
+ aDefAttr.nArcR =0;
+ aDefAttr.nArcS =0;
+ aDefAttr.nChrAng =0;
+ aDefAttr.aChrCellSize=Size(12,12);
+ aDefAttr.nChrSet =0;
+ aDefAttr.aCurPos =Point(0,0);
+ aDefAttr.eLinStyle =PEN_SOLID;
+ aDefAttr.nLinWidth =0;
+ aDefAttr.aMrkCellSize=Size(10,10);
+ aDefAttr.nMrkPrec =0x01;
+ aDefAttr.nMrkSet =0xff;
+ aDefAttr.nMrkSymbol =0x01;
+ aDefAttr.bFill =TRUE;
+ aDefAttr.nStrLinWidth=0;
+
+ aAttr=aDefAttr;
+
+ pOrdFile=NULL;
+
+ pVirDev = new VirtualDevice();
+ pVirDev->EnableOutput(FALSE);
+ rGDIMetaFile.Record(pVirDev);
+
+ pOS2MET->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+
+ nStartPos=pOS2MET->Tell();
+ nEndPos=pOS2MET->Seek(STREAM_SEEK_TO_END); pOS2MET->Seek(nStartPos);
+ Callback(0); nLastPercent=0;
+
+ nPos=pOS2MET->Tell();
+ if ( nStartPos == nEndPos )
+ {
+ nEndPos = 100;
+ nStartPos = 0;
+ }
+
+ for (;;) {
+
+ nPercent=(nPos-nStartPos)*100/(nEndPos-nStartPos);
+ if (nLastPercent+4<=nPercent) {
+ if (Callback((USHORT)nPercent)==TRUE) break;
+ nLastPercent=nPercent;
+ }
+
+ nFieldSize=ReadBigEndianWord();
+
+ *pOS2MET >> nMagicByte;
+ if (nMagicByte!=0xd3) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=7;
+ break;
+ }
+ *pOS2MET >> nFieldType;
+
+ pOS2MET->SeekRel(3);
+ nPos+=8; nFieldSize-=8;
+
+ if (pOS2MET->GetError()) break;
+ if (pOS2MET->IsEof()) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=8;
+ break;
+ }
+
+ if (nFieldType==EndDocumnMagic) break;
+
+ ReadField(nFieldType, nFieldSize);
+
+ nPos+=(ULONG)nFieldSize;
+ if (pOS2MET->Tell()>nPos) {
+ pOS2MET->SetError(SVSTREAM_FILEFORMAT_ERROR);
+ ErrorCode=9;
+ break;
+ }
+ pOS2MET->Seek(nPos);
+ }
+
+ rGDIMetaFile.Stop();
+ delete pVirDev;
+
+ rGDIMetaFile.SetPrefMapMode( aGlobMapMode );
+
+ if( aBoundingRect.GetWidth() && aBoundingRect.GetHeight() )
+ rGDIMetaFile.SetPrefSize( aBoundingRect.GetSize() );
+ else
+ {
+ if( aCalcBndRect.Left() || aCalcBndRect.Top() )
+ rGDIMetaFile.Move( -aCalcBndRect.Left(), -aCalcBndRect.Top() );
+
+ rGDIMetaFile.SetPrefSize( aCalcBndRect.GetSize() );
+ }
+
+ if (pOrdFile!=NULL) delete pOrdFile;
+
+ while (pAreaStack!=NULL) {
+ OSArea * p=pAreaStack;
+ pAreaStack=p->pSucc;
+ delete p;
+ }
+
+ while (pPathStack!=NULL) {
+ OSPath * p=pPathStack;
+ pPathStack=p->pSucc;
+ delete p;
+ }
+
+ while (pPathList!=NULL) {
+ OSPath * p=pPathList;
+ pPathList=p->pSucc;
+ delete p;
+ }
+
+ while (pFontList!=NULL) {
+ OSFont * p=pFontList;
+ pFontList=p->pSucc;
+ delete p;
+ }
+
+ while (pBitmapList!=NULL) {
+ OSBitmap * p=pBitmapList;
+ pBitmapList=p->pSucc;
+ if (p->pBMP!=NULL) delete p->pBMP;
+ delete p;
+ }
+
+ while (pAttrStack!=NULL) {
+ OSAttr * p=pAttrStack;
+ pAttrStack=p->pSucc;
+ delete p;
+ }
+
+ while (pPaletteStack!=NULL) {
+ OSPalette * p=pPaletteStack;
+ pPaletteStack=p->pSucc;
+ if (p->p0RGB!=NULL) delete p->p0RGB;
+ delete p;
+ }
+
+ pOS2MET->SetNumberFormatInt(nOrigNumberFormat);
+
+ if (pOS2MET->GetError()) {
+ OOODEBUG("Fehler Nr.:",ErrorCode);
+ pOS2MET->Seek(nOrigPos);
+ }
+}
+
+//================== GraphicImport - die exportierte Funktion ================
+
+#ifdef WNT
+extern "C" BOOL _cdecl GraphicImport(SvStream & rStream, Graphic & rGraphic,
+ PFilterCallback pCallback, void * pCallerData,
+ Config *, BOOL)
+#else
+extern "C" BOOL GraphicImport(SvStream & rStream, Graphic & rGraphic,
+ PFilterCallback pCallback, void * pCallerData,
+ Config *, BOOL)
+#endif
+{
+ OS2METReader aOS2METReader;
+ GDIMetaFile aMTF;
+ BOOL bRet = FALSE;
+
+ if ( &rStream == NULL && pCallerData )
+ {
+ SvMemoryStream aMemStm;
+
+ aMemStm << *(GDIMetaFile*) pCallerData;
+ aMemStm.Seek( 0 );
+ pCallerData = NULL;
+
+ aOS2METReader.ReadOS2MET( aMemStm, aMTF, NULL, NULL );
+
+ if ( !aMemStm.GetError() )
+ {
+ rGraphic = Graphic(aMTF);
+ bRet = TRUE;
+ }
+ }
+ else
+ {
+ aOS2METReader.ReadOS2MET(rStream,aMTF,pCallback,pCallerData);
+
+ if ( !rStream.GetError() )
+ {
+ rGraphic=Graphic(aMTF);
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
+//================== ein bischen Muell fuer Windows ==========================
+
+#pragma hdrstop
+
+#ifdef WIN
+
+static HINSTANCE hDLLInst = 0; // HANDLE der DLL
+
+extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
+{
+#ifndef WNT
+ if ( nHeap )
+ UnlockData( 0 );
+#endif
+
+ hDLLInst = hDLL;
+
+ return TRUE;
+}
+
+extern "C" int CALLBACK WEP( int )
+{
+ return 1;
+}
+
+#endif
+