diff options
Diffstat (limited to 'filter/source/graphicfilter/epict/epict.cxx')
-rw-r--r-- | filter/source/graphicfilter/epict/epict.cxx | 2332 |
1 files changed, 2332 insertions, 0 deletions
diff --git a/filter/source/graphicfilter/epict/epict.cxx b/filter/source/graphicfilter/epict/epict.cxx new file mode 100644 index 000000000000..53da35e677f7 --- /dev/null +++ b/filter/source/graphicfilter/epict/epict.cxx @@ -0,0 +1,2332 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_filter.hxx" + +#include <vcl/metaact.hxx> +#include <svtools/filter.hxx> +#include <svl/solar.hrc> +#include <svtools/fltcall.hxx> + +#include <math.h> +#include <vcl/bmpacc.hxx> +#include <vcl/metaact.hxx> +#include <vcl/graph.hxx> +#include <vcl/bmpacc.hxx> +#include <vcl/gradient.hxx> +#include <vcl/hatch.hxx> +#include <vcl/metric.hxx> +#include <vcl/font.hxx> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/gdimtf.hxx> + +#include <tools/bigint.hxx> + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> + +//============================== PictWriter =================================== + +struct PictWriterAttrStackMember { + struct PictWriterAttrStackMember * pSucc; + Color aLineColor; + Color aFillColor; + RasterOp eRasterOp; + Font aFont; + MapMode aMapMode; + Rectangle aClipRect; +}; + + +enum PictDrawingMethod { + PDM_FRAME, PDM_PAINT, PDM_ERASE, PDM_INVERT, PDM_FILL +}; + + +struct PictPattern { + sal_uInt32 nLo, nHi; +}; + +class PictWriter { + +private: + + sal_Bool bStatus; + sal_uLong nLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde. + com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator; + + SvStream * pPict; + + // Aktuelle Attribute im Quell-Metafile: + Color aLineColor; + Color aFillColor; + RasterOp eSrcRasterOp; + Font aSrcFont; + MapMode aSrcMapMode; + MapMode aTargetMapMode; + Rectangle aClipRect; + PictWriterAttrStackMember * pAttrStack; + + // Aktuelle Attribute im Ziel-Metafile, und ob sie gueltig sind + sal_Bool bDstBkPatVisible; sal_Bool bDstBkPatValid; + sal_uInt8 nDstTxFace; sal_Bool bDstTxFaceValid; + RasterOp eDstTxMode; sal_Bool bDstTxModeValid; + sal_uInt16 nDstPnSize; sal_Bool bDstPnSizeValid; + RasterOp eDstPnMode; sal_Bool bDstPnModeValid; + PictPattern aDstPnPat; sal_Bool bDstPnPatValid; + sal_Bool bDstFillPatVisible; sal_Bool bDstFillPatValid; + sal_uInt16 nDstTxSize; sal_Bool bDstTxSizeValid; + Color aDstFgCol; sal_Bool bDstFgColValid; + Color aDstBkCol; sal_Bool bDstBkColValid; + Point aDstPenPosition; sal_Bool bDstPenPositionValid; + Point aDstTextPosition; sal_Bool bDstTextPositionValid; + String aDstFontName; sal_uInt16 nDstFontNameId; sal_Bool bDstFontNameValid; + + sal_uLong nNumberOfActions; // Anzahl der Actions im GDIMetafile + sal_uLong nNumberOfBitmaps; // Anzahl der Bitmaps + sal_uLong nWrittenActions; // Anzahl der bereits verarbeiteten Actions beim Schreiben der Opcodes + sal_uLong nWrittenBitmaps; // Anzahl der bereits geschriebenen Bitmaps + sal_uLong nActBitmapPercent; // Wieviel Prozent die naechste Bitmap schon geschrieben ist. + + void MayCallback(); + // Berechnet anhand der obigen 5 Parameter eine Prozentzahl + // und macht dann ggf. einen Callback. Setzt bStatus auf sal_False wenn User abbrechen + // moechte. + + void CountActionsAndBitmaps(const GDIMetaFile & rMTF); + // Zaehlt die Bitmaps und Actions (nNumberOfActions und nNumberOfBitmaps muessen + // zu Anfang auf 0 gesetzt werden, weil diese Methode rekursiv ist) + + Polygon PolyPolygonToPolygon(const PolyPolygon & rPoly); + // Macht aus einem PolyPolygon ein halbwegs vernuenftiges Polygon + + Rectangle MapRectangle( const Rectangle& rRect ); + void WritePoint(const Point & rPoint); + void WriteSize(const Size & rSize); + void WriteRGBColor(const Color & rColor); + void WriteString( const String & rString ); + void WriteRectangle(const Rectangle & rRect); + void WritePolygon(const Polygon & rPoly); + void WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt); + + void ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible); + void ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible); + + void WriteOpcode_TxFace(const Font & rFont); + void WriteOpcode_TxMode(RasterOp eMode); + void WriteOpcode_PnSize(sal_uInt16 nSize); + void WriteOpcode_PnMode(RasterOp eMode); + void WriteOpcode_PnLinePat(sal_Bool bVisible); + void WriteOpcode_PnFillPat(sal_Bool bVisible); + void WriteOpcode_OvSize(const Size & rSize); + void WriteOpcode_TxSize(sal_uInt16 nSize); + void WriteOpcode_RGBFgCol(const Color & rColor); + void WriteOpcode_RGBBkCol(const Color & rColor); + void WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt); + void WriteOpcode_LineFrom(const Point & rNewPt); + void WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta); + void WriteOpcode_FontName(const Font & rFont); + void WriteOpcode_ClipRect( const Rectangle& rRect ); + void WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect); + void WriteOpcode_SameRect(PictDrawingMethod eMethod); + void WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect); + void WriteOpcode_SameRRect(PictDrawingMethod eMethod); + void WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect); + void WriteOpcode_SameOval(PictDrawingMethod eMethod); + void WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect, + const Point & rStartPt, const Point & rEndPt); + void WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect, + const Point & rStartPt, const Point & rEndPt); + void WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly); + void WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap); + void WriteOpcode_EndOfFile(); + + void SetAttrForPaint(); + void SetAttrForFrame(); + void SetAttrForText(); + + void WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry); + + void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon); + void WriteOpcodes(const GDIMetaFile & rMTF); + + void WriteHeader(const GDIMetaFile & rMTF); + void UpdateHeader(); + +public: + + sal_Bool WritePict( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem ); +}; + + +//========================== Methoden von PictWriter ========================== + + +void PictWriter::MayCallback() +{ + if ( xStatusIndicator.is() ) + { + sal_uLong nPercent; + nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions) + *100 + /((nNumberOfBitmaps<<14)+nNumberOfActions); + + if (nPercent>=nLastPercent+3) + { + nLastPercent=nPercent; + if( nPercent<=100 ) + xStatusIndicator->setValue( nPercent ); + } + } +} + +void PictWriter::CountActionsAndBitmaps(const GDIMetaFile & rMTF) +{ + sal_uLong nAction, nActionCount; + const MetaAction* pMA; + + nActionCount = rMTF.GetActionCount(); + + for (nAction=0; nAction<nActionCount; nAction++) + { + pMA = rMTF.GetAction( nAction ); + + switch( pMA->GetType() ) + { + case META_BMP_ACTION: + case META_BMPSCALE_ACTION: + case META_BMPSCALEPART_ACTION: + case META_BMPEX_ACTION: + case META_BMPEXSCALE_ACTION: + case META_BMPEXSCALEPART_ACTION: + nNumberOfBitmaps++; + break; + } + + nNumberOfActions++; + } +} + + +Polygon PictWriter::PolyPolygonToPolygon(const PolyPolygon & rPolyPoly) +{ + sal_uInt16 nCount,nSize1,nSize2,np,i1,i2,i3,nBestIdx1,nBestIdx2; + long nDistSqr,nBestDistSqr, nCountdownTests; + Point aP1,aPRel; + Polygon aPoly1, aPoly2, aPoly3; + + nCount=rPolyPoly.Count(); + if (nCount==0) return Polygon(0); + + aPoly1=rPolyPoly.GetObject(0); + for (np=1; np<nCount; np++) { + aPoly2=rPolyPoly.GetObject(np); + + //-----------------Folgendes verschmilzt aPoly1 und aPoly2 zu aPoly1----------------- + + nSize1=aPoly1.GetSize(); + nSize2=aPoly2.GetSize(); + + // Zunaechst werden ein Punkt in aPoly1 (referenziert durch nBestIdx1) und ein + // Punkt in aPoly2 (referenziert durch nBestIdx2) gesucht, die moeglichst dicht + // beieinander liegen. Da dies mit quadratischem Aufwand einher geht, und somit + // manche Bilder Ewigkeiten benoetigen, um exportiert zu werden, begrenzen wir + // die Anzahl der Tests auf 1000, und brechen die Suche ggf. schon vorher ab. + // Dadruch wird das Ergebnis nicht falsch, sondern eventuell nicht so schoen. + nCountdownTests=1000; + nBestDistSqr=0x7fffffff; + nBestIdx1=0; + nBestIdx2=0; + for (i1=0; i1<nSize1; i1++) { + aP1=aPoly1.GetPoint(i1); + for (i2=0; i2<nSize2; i2++) { + aPRel=aPoly2.GetPoint(i2); aPRel-=aP1; + nDistSqr=aPRel.X()*aPRel.X()+aPRel.Y()*aPRel.Y(); + if (nDistSqr<nBestDistSqr) { + nBestIdx1=i1; + nBestIdx2=i2; + nBestDistSqr=nDistSqr; + } + if (nCountdownTests<=0) break; + nCountdownTests--; + } + if (nCountdownTests<=0) break; + } + + // Nun werden aPoly1 und aPoly2 zu einem Polygon aPoly3 (spaeter aPoly1) zusammengefuegt. + // Die beiden Polygone werden verbunden durch zwei zusaetzliche Kanten zwischen den oben + // gefundenen Punkten. + aPoly3.Clear(); + aPoly3.SetSize(nSize1+nSize2+2); + i3=0; + for (i1=nBestIdx1; i1<nSize1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++); + for (i1=0; i1<=nBestIdx1; i1++) aPoly3.SetPoint(aPoly1.GetPoint(i1),i3++); + for (i2=nBestIdx2; i2<nSize2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++); + for (i2=0; i2<=nBestIdx2; i2++) aPoly3.SetPoint(aPoly2.GetPoint(i2),i3++); + + aPoly1=aPoly3; + + //----------------------------------------------------------------------------------- + + } + return aPoly1; +} + + +void PictWriter::WritePoint(const Point & rPoint) +{ + Point aPoint = OutputDevice::LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ); + *pPict << ((short)aPoint.Y()) << ((short)aPoint.X()); +} + + +void PictWriter::WriteSize(const Size & rSize) +{ + OutputDevice::LogicToLogic( rSize, aSrcMapMode, aTargetMapMode ); // -Wall is this needed. + *pPict << ((short)rSize.Height()) << ((short)rSize.Width()); +} + + +void PictWriter::WriteRGBColor(const Color & rColor) +{ + const sal_uInt16 nR = ( (sal_uInt16) rColor.GetRed() << 8 ) | (sal_uInt16) rColor.GetRed(); + const sal_uInt16 nG = ( (sal_uInt16) rColor.GetGreen() << 8 ) | (sal_uInt16) rColor.GetGreen(); + const sal_uInt16 nB = ( (sal_uInt16) rColor.GetBlue() << 8 ) | (sal_uInt16) rColor.GetBlue(); + + *pPict << nR << nG << nB; +} + + +void PictWriter::WriteString( const String & rString ) +{ + sal_uInt16 i,nLen; + + ByteString aByteString( rString, gsl_getSystemTextEncoding() ); + nLen = aByteString.Len(); + if ( nLen > 255 ) + nLen = 255; + *pPict << ( (sal_uInt8)nLen ); + for ( i = 0; i < nLen; i++ ) + *pPict << aByteString.GetChar( i ); +} + +Rectangle PictWriter::MapRectangle( const Rectangle& rRect ) +{ + Point aPoint = OutputDevice::LogicToLogic( rRect.TopLeft(), aSrcMapMode, aTargetMapMode ); + Size aSize = OutputDevice::LogicToLogic( rRect.GetSize(), aSrcMapMode, aTargetMapMode ); + Rectangle aRect( aPoint, aSize ); + aRect.Justify(); + aRect.nBottom++; + aRect.nRight++; + return aRect; +} + +void PictWriter::WriteRectangle(const Rectangle & rRect) +{ + Rectangle aRect( MapRectangle( rRect ) ); + *pPict << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left() + << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right(); +} + +void PictWriter::WritePolygon(const Polygon & rPoly) +{ + sal_uInt16 nDataSize,i,nSize; + short nMinX = 0, nMinY = 0, nMaxX = 0, nMaxY = 0; + short nx,ny; + Polygon aPoly(rPoly); + + nSize=aPoly.GetSize(); + + if (aPoly.GetPoint(0) != aPoly.GetPoint(nSize-1)) + { + nSize++; + aPoly.SetSize(nSize); + aPoly.SetPoint(aPoly.GetPoint(0),nSize-1); + } + + nDataSize=nSize*4+10; + for (i=0; i<nSize; i++) + { + Point aPoint = OutputDevice::LogicToLogic( aPoly.GetPoint( i ), + aSrcMapMode, + aTargetMapMode ); + + nx = (short) aPoint.X(); + ny = (short) aPoint.Y(); + + if ( i==0 || nMinX>nx ) + nMinX=nx; + if ( i==0 || nMinY>ny ) + nMinY=ny; + if ( i==0 || nMaxX<nx ) + nMaxX=nx; + if ( i==0 || nMaxY<ny ) + nMaxY=ny; + } + + *pPict << nDataSize << nMinY << nMinX << nMaxY << nMaxX; + + for (i=0; i<nSize; i++) + WritePoint( aPoly.GetPoint(i) ); +} + + +void PictWriter::WriteArcAngles(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt) +{ + Point aStartPt = OutputDevice::LogicToLogic( rStartPt, + aSrcMapMode, + aTargetMapMode ); + Point aEndPt = OutputDevice::LogicToLogic( rEndPt, + aSrcMapMode, + aTargetMapMode ); + Rectangle aRect( OutputDevice::LogicToLogic( rRect.TopLeft(), + aSrcMapMode, + aTargetMapMode ), + OutputDevice::LogicToLogic( rRect.GetSize(), + aSrcMapMode, + aTargetMapMode ) ); + Point aCenter; + double fAngS, fAngE, fdx, fdy; + short nStartAngle, nArcAngle; + + + aCenter=Point( ( aRect.Left() + aRect.Right() ) >> 1, + ( aRect.Top() + aRect.Bottom() ) >> 1 ); + + fdx=(double)(aStartPt.X()-aCenter.X()); + fdy=(double)(aStartPt.Y()-aCenter.Y()); + if ( fdx==0.0 && fdy==0.0 ) + fdx=1.0; + fAngE=atan2(fdx,-fdy); + + fdx=(double)(aEndPt.X()-aCenter.X()); + fdy=(double)(aEndPt.Y()-aCenter.Y()); + if ( fdx==0.0 && fdy==0.0 ) + fdx=1.0; + fAngS=atan2(fdx,-fdy); + + nStartAngle=(short)(fAngS*180.0/3.14159265359); + nArcAngle=((short)(fAngE*180.0/3.14159265359))-nStartAngle; + if (nArcAngle<0) + nArcAngle += 360; + *pPict << nStartAngle << nArcAngle; +} + + +void PictWriter::ConvertLinePattern(PictPattern & rPat, sal_Bool bVisible) +{ + if( bVisible ) + { + rPat.nHi=0xffffffff; + rPat.nLo=0xffffffff; + } + else + { + rPat.nHi=0x00000000; + rPat.nLo=0x00000000; + } +} + +void PictWriter::ConvertFillPattern(PictPattern & rPat, sal_Bool bVisible) +{ + if( bVisible ) + { + rPat.nHi=0xffffffff; + rPat.nLo=0xffffffff; + } + else + { + rPat.nHi=0x00000000; + rPat.nLo=0x00000000; + } +} + + +void PictWriter::WriteOpcode_TxFace(const Font & rFont) +{ + sal_uInt8 nFace; + FontWeight eWeight; + + nFace=0; + eWeight=rFont.GetWeight(); + if (eWeight==WEIGHT_BOLD || + eWeight==WEIGHT_SEMIBOLD || + eWeight==WEIGHT_ULTRABOLD || + eWeight==WEIGHT_BLACK) nFace|=0x01; + if (rFont.GetItalic()!=ITALIC_NONE) nFace|=0x02; + if (rFont.GetUnderline()!=UNDERLINE_NONE) nFace|=0x04; + if (rFont.IsOutline()==sal_True) nFace|=0x08; + if (rFont.IsShadow()==sal_True) nFace|=0x10; + + if (bDstTxFaceValid==sal_False || nDstTxFace!=nFace) { + *pPict << (sal_uInt16)0x0004 << nFace << (sal_uInt8)0; + nDstTxFace=nFace; + bDstTxFaceValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_TxMode(RasterOp eMode) +{ + sal_uInt16 nVal; + + if (bDstTxModeValid==sal_False || eDstTxMode!=eMode) { + switch (eMode) { + case ROP_INVERT: nVal=0x000c; break; + case ROP_XOR: nVal=0x000a; break; + default: nVal=0x0008; + } + *pPict << (sal_uInt16)0x0005 << nVal; + eDstTxMode=eMode; + bDstTxModeValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_PnSize(sal_uInt16 nSize) +{ + if (nSize==0) nSize=1; + if (bDstPnSizeValid==sal_False || nDstPnSize!=nSize) { + *pPict << (sal_uInt16)0x0007 << nSize << nSize; + nDstPnSize=nSize; + bDstPnSizeValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_PnMode(RasterOp eMode) +{ + sal_uInt16 nVal; + + if (bDstPnModeValid==sal_False || eDstPnMode!=eMode) { + switch (eMode) + { + case ROP_INVERT: nVal=0x000c; break; + case ROP_XOR: nVal=0x000a; break; + default: nVal=0x0008; + } + *pPict << (sal_uInt16)0x0008 << nVal; + eDstPnMode=eMode; + bDstPnModeValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_PnLinePat(sal_Bool bVisible) +{ + PictPattern aPat; + + ConvertLinePattern(aPat,bVisible); + if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) { + *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo; + aDstPnPat=aPat; + bDstPnPatValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_PnFillPat(sal_Bool bVisible) +{ + PictPattern aPat; + + ConvertFillPattern(aPat,bVisible); + if (bDstPnPatValid==sal_False || aDstPnPat.nHi!=aPat.nHi || aDstPnPat.nLo!=aPat.nLo) { + *pPict << (sal_uInt16)0x0009 << aPat.nHi << aPat.nLo; + aDstPnPat=aPat; + bDstPnPatValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_OvSize(const Size & rSize) +{ + *pPict << (sal_uInt16)0x000b; + WriteSize(rSize); +} + + +void PictWriter::WriteOpcode_TxSize(sal_uInt16 nSize) +{ + if (bDstTxSizeValid==sal_False || nDstTxSize!=nSize) { + + nDstTxSize = (sal_uInt16) OutputDevice::LogicToLogic( Size( 0, nSize ), + aSrcMapMode, aTargetMapMode ).Height(); + + *pPict << (sal_uInt16)0x000d << nDstTxSize; + bDstTxSizeValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_RGBFgCol(const Color & rColor) +{ + if (bDstFgColValid==sal_False || aDstFgCol!=rColor) { + *pPict << (sal_uInt16)0x001a; + WriteRGBColor(rColor); + aDstFgCol=rColor; + bDstFgColValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_RGBBkCol(const Color & rColor) +{ + if (bDstBkColValid==sal_False || aDstBkCol!=rColor) { + *pPict << (sal_uInt16)0x001b; + WriteRGBColor(rColor); + aDstBkCol=rColor; + bDstBkColValid=sal_True; + } +} + + +void PictWriter::WriteOpcode_Line(const Point & rLocPt, const Point & rNewPt) +{ + Point aLocPt = OutputDevice::LogicToLogic( rLocPt, + aSrcMapMode, + aTargetMapMode ); + Point aNewPt = OutputDevice::LogicToLogic( rNewPt, + aSrcMapMode, + aTargetMapMode ); + long dh,dv; + + dh=aNewPt.X()-aLocPt.X(); + dv=aNewPt.Y()-aLocPt.Y(); + if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128) + { // ShortLine + *pPict << (sal_uInt16)0x0022; + WritePoint(rLocPt); + *pPict << (char)dh << (char)dv; + } + else + { + *pPict << (sal_uInt16)0x0020; + WritePoint(rLocPt); + WritePoint(rNewPt); + } + aDstPenPosition=rNewPt; + bDstPenPositionValid=sal_True; +} + + +void PictWriter::WriteOpcode_LineFrom(const Point & rNewPt) +{ + Point aNewPt = OutputDevice::LogicToLogic( rNewPt, + aSrcMapMode, + aTargetMapMode ); + long dh,dv; + + dh = aNewPt.X()-aDstPenPosition.X(); + dv = aNewPt.Y()-aDstPenPosition.Y(); + + if (dh<=127 && dh>=-128 && dv<=127 && dv>=-128) + { // ShortLine + *pPict << (sal_uInt16)0x0023; + *pPict << (char)dh << (char)dv; + } + else + { + *pPict << (sal_uInt16)0x0021; + WritePoint(rNewPt); + } + aDstPenPosition=rNewPt; + bDstPenPositionValid=sal_True; +} + + +void PictWriter::WriteOpcode_Text(const Point & rPoint, const String& rString, sal_Bool bDelta) +{ + Point aPoint = OutputDevice::LogicToLogic( rPoint, + aSrcMapMode, + aTargetMapMode ); + long dh,dv; + sal_uLong nPos; + + nPos = pPict->Tell(); + dh = aPoint.X()-aDstTextPosition.X(); + dv = aPoint.Y()-aDstTextPosition.Y(); + + if (bDstTextPositionValid==sal_False || dh<0 || dh>255 || dv<0 || dv>0 || bDelta==sal_False) + { + *pPict << (sal_uInt16)0x0028; + WritePoint(rPoint); + } + else if (dv==0) + { + *pPict << (sal_uInt16)0x0029 << (sal_uInt8)dh; + } + else if (dh==0) + { + *pPict << (sal_uInt16)0x002a << (sal_uInt8)dv; + } + else + { + *pPict << (sal_uInt16)0x002b << (sal_uInt8)dh << (sal_uInt8)dv; + } + + WriteString( rString ); + if (((pPict->Tell()-nPos)&1)!=0) + *pPict << (sal_uInt8)0; + + aDstTextPosition = aPoint; + bDstTextPositionValid=sal_True; +} + + +void PictWriter::WriteOpcode_FontName(const Font & rFont) +{ + sal_uInt16 nDataLen,nFontId; + + switch (rFont.GetFamily()) { + case FAMILY_MODERN: nFontId=22; break; + case FAMILY_ROMAN: nFontId=20; break; + case FAMILY_SWISS: nFontId=21; break; + default: nFontId=1; + } + + if (bDstFontNameValid==sal_False || nDstFontNameId!=nFontId || aDstFontName!=rFont.GetName()) + { + ByteString aByteString( rFont.GetName(), gsl_getSystemTextEncoding() ); + sal_uInt16 nFontNameLen = aByteString.Len(); + if ( nFontNameLen ) + { + nDataLen = 3 + nFontNameLen; + *pPict << (sal_uInt16)0x002c << nDataLen << nFontId; + WriteString( rFont.GetName() ); + if ( ( nFontNameLen & 1 ) == 0 ) + *pPict << (sal_uInt8)0; + } + *pPict << (sal_uInt16)0x0003 << nFontId; + aDstFontName=rFont.GetName(); + nDstFontNameId=nFontId; + bDstFontNameValid=sal_True; + } +} + +void PictWriter::WriteOpcode_ClipRect( const Rectangle& rRect ) +{ + Rectangle aRect( MapRectangle( rRect ) ); + aRect.nBottom++; + aRect.nRight++; + *pPict << (sal_uInt16)1 // opcode 1 + << (sal_uInt16)10 // data size + << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left() + << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right(); + aClipRect = aRect; +} + +void PictWriter::WriteOpcode_Rect(PictDrawingMethod eMethod, const Rectangle & rRect) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0030; break; + case PDM_PAINT: oc=0x0031; break; + case PDM_ERASE: oc=0x0032; break; + case PDM_INVERT: oc=0x0033; break; + case PDM_FILL: oc=0x0034; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WriteRectangle(rRect); +} + + +void PictWriter::WriteOpcode_SameRect(PictDrawingMethod eMethod) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0038; break; + case PDM_PAINT: oc=0x0039; break; + case PDM_ERASE: oc=0x003a; break; + case PDM_INVERT: oc=0x003b; break; + case PDM_FILL: oc=0x003c; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; +} + + +void PictWriter::WriteOpcode_RRect(PictDrawingMethod eMethod, const Rectangle & rRect) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0040; break; + case PDM_PAINT: oc=0x0041; break; + case PDM_ERASE: oc=0x0042; break; + case PDM_INVERT: oc=0x0043; break; + case PDM_FILL: oc=0x0044; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WriteRectangle(rRect); +} + + +void PictWriter::WriteOpcode_SameRRect(PictDrawingMethod eMethod) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0048; break; + case PDM_PAINT: oc=0x0049; break; + case PDM_ERASE: oc=0x004a; break; + case PDM_INVERT: oc=0x004b; break; + case PDM_FILL: oc=0x004c; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; +} + + +void PictWriter::WriteOpcode_Oval(PictDrawingMethod eMethod, const Rectangle & rRect) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0050; break; + case PDM_PAINT: oc=0x0051; break; + case PDM_ERASE: oc=0x0052; break; + case PDM_INVERT: oc=0x0053; break; + case PDM_FILL: oc=0x0054; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WriteRectangle(rRect); +} + + +void PictWriter::WriteOpcode_SameOval(PictDrawingMethod eMethod) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0058; break; + case PDM_PAINT: oc=0x0059; break; + case PDM_ERASE: oc=0x005a; break; + case PDM_INVERT: oc=0x005b; break; + case PDM_FILL: oc=0x005c; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; +} + + +void PictWriter::WriteOpcode_Arc(PictDrawingMethod eMethod, const Rectangle & rRect, + const Point & rStartPt, const Point & rEndPt) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0060; break; + case PDM_PAINT: oc=0x0061; break; + case PDM_ERASE: oc=0x0062; break; + case PDM_INVERT: oc=0x0063; break; + case PDM_FILL: oc=0x0064; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WriteRectangle(rRect); + WriteArcAngles(rRect,rStartPt,rEndPt); +} + + +void PictWriter::WriteOpcode_SameArc(PictDrawingMethod eMethod, const Rectangle & rRect, + const Point & rStartPt, const Point & rEndPt) +{ + sal_uInt16 oc; + switch (eMethod) { + case PDM_FRAME: oc=0x0068; break; + case PDM_PAINT: oc=0x0069; break; + case PDM_ERASE: oc=0x006a; break; + case PDM_INVERT: oc=0x006b; break; + case PDM_FILL: oc=0x006c; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WriteArcAngles(rRect,rStartPt,rEndPt); +} + + +void PictWriter::WriteOpcode_Poly(PictDrawingMethod eMethod, const Polygon & rPoly) +{ + sal_uInt16 oc; + + if (rPoly.GetSize()<3) return; + switch (eMethod) { + case PDM_FRAME: oc=0x0070; break; + case PDM_PAINT: oc=0x0071; break; + case PDM_ERASE: oc=0x0072; break; + case PDM_INVERT: oc=0x0073; break; + case PDM_FILL: oc=0x0074; break; + default: oc=0; break; // -Wall a default for oc... + } + *pPict << oc; + WritePolygon(rPoly); +} + + +void PictWriter::WriteOpcode_BitsRect(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap) +{ + BitmapReadAccess* pAcc = NULL; + Bitmap aBitmap( rBitmap ); + + sal_uLong nWidth, nHeight, nDstRowBytes, nx, nc, ny, nCount, nColTabSize, i; + sal_uLong nDstRowPos, nSrcRowBytes, nEqu3, nPos, nDstMapPos; + sal_uInt16 nBitsPerPixel, nPackType; + sal_uInt8 *pComp[4], *pPix, *pTemp; + sal_uInt8 nEquData = 0; + sal_uInt8 nFlagCounterByte, nRed, nGreen, nBlue; + + SetAttrForPaint(); + + // temopraere Windows-BMP-Datei erzeugen: + nActBitmapPercent=30; + MayCallback(); + + if ( bStatus == sal_False ) + return; + if ( ( pAcc = aBitmap.AcquireReadAccess() ) == NULL ) + return; + + nBitsPerPixel = aBitmap.GetBitCount(); + + // export code below only handles four discrete cases + nBitsPerPixel = + nBitsPerPixel <= 1 ? 1 : nBitsPerPixel <= 4 ? 4 : nBitsPerPixel <= 8 ? 8 : 24; + + nWidth = pAcc->Width(); + nHeight = pAcc->Height(); + + // Wenn 24-Bit, dann den Opcode 'DirectBitsRect' erzeugen: + if ( nBitsPerPixel == 24 ) + { + + // Anzahl Bytes einer (ungepackten) Zeile in Quelle und Ziel berechnen: + nSrcRowBytes =( ( 3 * nWidth ) + 0x0003 ) & 0xfffc; + nDstRowBytes = nWidth * 4; + + // Opcode und BaseAddr (?) schreiben: + *pPict << (sal_uInt16)0x009a << (sal_uInt32)0x000000ff; + + // Normalerweise wollen wir den Packing-Type 4 (Run length encoding + // for 32-Bit Pixels) erzeugen. Wenn aber RowBytes<8 gilt, sind die Daten + // grundsaetzlich ungepackt, auch wenn der Packing-Type 4 angegeben ist, + // was etwas komisch erscheint. Daher wollen wir in so einem Fall lieber + // gleich den Packing-Type 1 (ungepackt) angeben: + + if ( nDstRowBytes < 8 ) + nPackType = 1; + else + nPackType = 4; + + // PixMap-Struktur schreiben: + *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes pro Zeile und dass es eine 'PixMap' ist + << (sal_uInt16)0x0000 // Y1-Position der Bitmap in der Quelle + << (sal_uInt16)0x0000 // X1-Position der Bitmap in der Quelle + << (sal_uInt16)nHeight // Y2-Position der Bitmap in der Quelle + << (sal_uInt16)nWidth // X2-Position der Bitmap in der Quelle + << (sal_uInt16)0x0000 // Version + << (sal_uInt16)nPackType // Packing type + << (sal_uInt32) 0x00000000 // Packing size (?) + << (sal_uInt32) 0x00480000 // H-Res + << (sal_uInt32) 0x00480000 // V-Res + << (sal_uInt16)0x0010 // Pixel type (?) + << (sal_uInt16)0x0020 // Pixel size: 32 bit + << (sal_uInt16)0x0004 // CmpCount: 4 Komponenten + << (sal_uInt16)0x0008 // CmpSize: 8 Bits + << (sal_uInt32) 0x00000000 // PlaneBytes (?) + << (sal_uInt32) 0x00000000 // (?) + << (sal_uInt32) 0x00000000; // (?) + + // Source-Rectangle schreiben: + *pPict << (sal_uInt16)0x0000 // Y1-Position auf der Bitmap + << (sal_uInt16)0x0000 // X1-Position auf der Bitmap + << (sal_uInt16)nHeight // Y2-Position auf der Bitmap + << (sal_uInt16)nWidth; // X2-Position auf der Bitmap + + // Destination-Rectangle schreiben: + WritePoint( rPoint ); + WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) ); + + // Transfer mode schreiben: + *pPict << (sal_uInt16)0x0000; // (?) + + // Position der Map-Daten in Ziel merken: + nDstMapPos=pPict->Tell(); + + if ( nPackType == 1 ) // bei 24 bits nWidth == 1 !! + { // nicht packen + for ( ny = 0; ny < nHeight; ny++ ) + { + *pPict << (sal_uInt8)0; + *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetRed(); + *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetGreen(); + *pPict << (sal_uInt8)pAcc->GetPixel( ny, 0 ).GetBlue(); + // Prozente zaehlen, Callback, Fehler pruefen: + nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus) + MayCallback(); + } + } + else // packen ( PackType == 4 ) + { + // Speicher fuer Zeilen-Zwischen-Datenstruktur allozieren: + for ( nc = 0; nc < 4; nc++ ) + pComp[ nc ] = new sal_uInt8[ nWidth ]; + + // Schleife ueber Zeilen: + for ( ny = 0; ny < nHeight; ny++ ) + { + // Zeil ny der Quelle in die Zwischen-Datenstrktur einlesen: + + for ( nx = 0; nx < nWidth; nx++ ) + { + pComp[ 1 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetRed(); + pComp[ 2 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetGreen(); + pComp[ 3 ][ nx ] = (sal_uInt8)pAcc->GetPixel( ny, nx ) .GetBlue(); + pComp[ 0 ][ nx ] = 0; + } + + // Anfang der Zeile im Ziel merken: + nDstRowPos = pPict->Tell(); + + // ByteCount (das ist die Groesse der gepackten Zeile) zunaechst 0 (wird spaeter berichtigt): + if ( nDstRowBytes > 250 ) + *pPict << (sal_uInt16)0; + else + *pPict << (sal_uInt8)0; + + // Schleife ueber Componenten: + for ( nc = 0; nc < 4; nc++ ) + { + // Schleife ueber x: + nx = 0; + while ( nx < nWidth ) + { + // Die Position von 3 gleichen Bytes suchen und in nEqu3 merken. + // wenn nicht gefunden, dann nEqu3=nWidth setzten. + // Wenn doch gefunden, dann in nEquData den Wert der Bytes merken. + nEqu3 = nx; + for (;;) + { + if ( nEqu3 + 2 >= nWidth ) + { + nEqu3 = nWidth; + break; + } + nEquData = pComp[nc][nEqu3]; + if ( nEquData == pComp[nc][nEqu3+1] && nEquData==pComp[nc][nEqu3+2] ) + break; + nEqu3++; + } + + // Die Daten von nx bis nEqu3 unkomprimiert schreiben (ggf. in mehreren Records): + while ( nEqu3 > nx ) + { + nCount = nEqu3 - nx; + if ( nCount > 128 ) + nCount=128; + nFlagCounterByte = (sal_uInt8)(nCount-1); + *pPict << nFlagCounterByte; + do + { + *pPict << pComp[nc][nx++]; + nCount--; + } + while ( nCount > 0 ); + } + + // Jetzt einen Komprimierungs-Record erzeugen (falls oben mindestens 3 + // gleiche Bytes gefunden): + if ( nx < nWidth ) + { // Hinweis: es gilt nx==nEqu3 (hoffentlich) + nCount=3; // Drei Bytes sind gleich, wie weiter oben herausgefunden. + // Pruefen, ob es weitere gleiche Bytes gibts (dabei Max.-Record-Groesse beachten): + while ( nx + nCount < nWidth && nCount < 128 ) + { + if ( nEquData != pComp[ nc ][ nx + nCount ] ) + break; + nCount++; + } + // nCount gleiche Bytes komprimiert schreiben: + nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount ); + *pPict << nFlagCounterByte << nEquData; + nx += nCount; + } + } + } + // ByteCount berichtigen: + nPos = pPict->Tell(); + pPict->Seek( nDstRowPos ); + if ( nDstRowBytes > 250 ) + *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) ); + else + *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) ); + pPict->Seek( nPos ); + + // Prozente zaehlen, Callback, Fehler pruefen: + nActBitmapPercent = ( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus) + MayCallback(); + } + // Aufraeumen: + for ( nc = 0; nc < 4; nc++ ) + delete pComp[ nc ]; + } + } + else + { // nicht 24-Bit also Opcode 'PackBitsRect' erzeugen: + + // Bei 1-Bit-Bildern ignorieren manche Import-Filter die Palette und nehmen statt + // dessen die Vorder- und Hintergrundfarbe: + if ( nBitsPerPixel == 1 ) + { + WriteOpcode_RGBBkCol( pAcc->GetPaletteColor( 0 ) ); + WriteOpcode_RGBFgCol( pAcc->GetPaletteColor( 1 ) ); + } + else + { + WriteOpcode_RGBBkCol( Color( COL_BLACK ) ); + WriteOpcode_RGBFgCol( Color( COL_WHITE ) ); + } + + // Anzahl Bytes einer (ungepackten) Zeile in Ziel und Quelle berechnen: + nDstRowBytes = ( nWidth * nBitsPerPixel + 7 ) >> 3; + nSrcRowBytes = ( nDstRowBytes + 3 ) & 0xfffffffc; + + // Opcode schreiben: + *pPict << (sal_uInt16)0x0098; + + // Normalerweise wollen wir den Packing-Type 0 (default Packing) erzeugen. + // Wenn aber RowBytes<8 gilt, sind die Daten grundsaetzlich ungepackt, + // auch wenn der Packing-Type 0 angegeben ist, was etwas komisch erscheint. + // Daher wollen wir in so einem Fall lieber gleich den Packing-Type 1 (ungepackt) + // angeben: + if ( nDstRowBytes < 8 ) + nPackType = 1; + else + nPackType = 0; + + // PixMap-Struktur schreiben: + *pPict << (sal_uInt16)(nDstRowBytes|0x8000) // Bytes pro Zeile und dass es eine 'PixMap' ist + << (sal_uInt16)0x0000 // Y1-Position der Bitmap in der Quelle + << (sal_uInt16)0x0000 // X1-Position der Bitmap in der Quelle + << (sal_uInt16)nHeight // Y2-Position der Bitmap in der Quelle + << (sal_uInt16)nWidth // X2-Position der Bitmap in der Quelle + << (sal_uInt16)0x0000 // Version + << (sal_uInt16)nPackType // Packing type + << (sal_uInt32) 0x00000000 // Packing size (?) + << (sal_uInt32) 0x00480000 // H-Res + << (sal_uInt32) 0x00480000 // V-Res + << (sal_uInt16)0x0000 // Pixel type (?) + << (sal_uInt16)nBitsPerPixel // Pixel size + << (sal_uInt16)0x0001 // CmpCount: 1 Komponente + << (sal_uInt16)nBitsPerPixel // CmpSize + << (sal_uInt32) 0x00000000 // PlaneBytes (?) + << (sal_uInt32) 0x00000000 // (?) + << (sal_uInt32) 0x00000000; // (?) + + // Palette lesen und schreiben: + nColTabSize = pAcc->GetPaletteEntryCount(); + *pPict << (sal_uInt32)0 << (sal_uInt16)0x8000 << (sal_uInt16)( nColTabSize - 1 ); + + for ( i = 0; i < nColTabSize; i++ ) + { + nRed = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetRed(); + nGreen = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetGreen(); + nBlue = (sal_uInt8)pAcc->GetPaletteColor( (sal_uInt16)i ).GetBlue(); + *pPict << (sal_uInt16)0 << nRed << nRed << nGreen << nGreen << nBlue << nBlue; + } + + // Source-Rectangle schreiben: + *pPict << (sal_uInt16)0 << (sal_uInt16)0 << (sal_uInt16)nHeight << (sal_uInt16)nWidth; + + // Destination-Rectangle schreiben: + WritePoint( rPoint ); + WritePoint( Point( rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height() ) ); + + // Transfer mode schreiben: + *pPict << (sal_uInt16)0; // (?) + + // Speicher fuer eine Zeile allozieren: + pPix = new sal_uInt8[ nSrcRowBytes ]; + + // Position der Map-Daten in Ziel merken: + nDstMapPos=pPict->Tell(); + + // Schleife ueber Zeilen: + for ( ny = 0; ny < nHeight; ny++ ) + { + + // Zeile ny der Quelle in den Zwischenspeicher einlesen: + + switch ( nBitsPerPixel ) + { + case 1 : + for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ ) + *pTemp++ = (sal_uInt8)0; + for ( i = 0; i < nWidth; i++ ) + pPix[ ( i >> 3 ) ] |= (sal_uInt8)( pAcc->GetPixel( ny, i ) & 1 ) << ( ( i & 7 ) ^ 7 ); + break; + case 4 : + for ( pTemp = pPix, i = 0; i < nSrcRowBytes; i++ ) + *pTemp++ = (sal_uInt8)0; + for ( i = 0; i < nWidth; i++ ) + pPix[ ( i >> 1 ) ] |= (sal_uInt8)( pAcc->GetPixel( ny, i ) & 15 ) << ( ( i & 1 ) << 2 ) ; + break; + case 8 : + for ( i = 0; i < nWidth; i++ ) + pPix[ i ] = (sal_uInt8)pAcc->GetPixel( ny, i ); + break; + } + + if ( nPackType == 1 ) + { // nicht packen + pPict->Write( pPix, nDstRowBytes ); + } + else + { // Packen (nPackType==0) + + // Anfang der Zeile im Ziel merken: + nDstRowPos = pPict->Tell(); + + // ByteCount (das ist die Groesse der gepackten Zeile) zunaechst 0 (wird spaeter berichtigt): + if ( nDstRowBytes > 250 ) + *pPict << (sal_uInt16)0; + else + *pPict << (sal_uInt8)0; + + // Schleife ueber Bytes der Zeile: + nx=0; + while ( nx < nDstRowBytes && bStatus ) + { + // Die Position von 3 gleichen Bytes suchen und in nEqu3 merken. + // wenn nicht gefunden, dann nEqu3=nDstRowBytes setzten. + // Wenn doch gefunden, dann in nEquData den Wert der Bytes merken. + nEqu3 = nx; + for (;;) + { + if ( nEqu3 + 2 >= nDstRowBytes ) + { + nEqu3 = nDstRowBytes; + break; + } + nEquData = pPix[ nEqu3 ]; + if ( nEquData == pPix[ nEqu3 + 1 ] && nEquData == pPix[ nEqu3 + 2 ] ) + break; + nEqu3++; + } + + // Die Daten von nx bis nEqu3 unkomprimiert schreiben (ggf. in mehreren Records): + while ( nEqu3 > nx ) + { + nCount = nEqu3 - nx; + if ( nCount > 128 ) + nCount = 128; + nFlagCounterByte = (sal_uInt8)( nCount - 1 ); + *pPict << nFlagCounterByte; + do + { + *pPict << pPix[ nx++ ]; + nCount--; + } while ( nCount > 0 ); + } + + // Jetzt einen Komprimierungs-Record erzeugen (falls oben mindestens 3 + // gleiche Bytes gefunden): + if ( nx < nDstRowBytes ) + { // Hinweis: es gilt nx==nEqu3 (hoffentlich) + nCount = 3; // Drei Bytes sind gleich, wie weiter oben herausgefunden. + // Pruefen, ob es weitere gleiche Bytes gibts (dabei Max.-Record-Groesse beachten): + while ( nx + nCount < nDstRowBytes && nCount < 128 ) + { + if ( nEquData != pPix[ nx + nCount ] ) + break; + nCount++; + } + // nCount gleiche Bytes komprimiert schreiben: + nFlagCounterByte = (sal_uInt8)( 1 - (long)nCount ); + *pPict << nFlagCounterByte << nEquData; + nx += nCount; + } + } + + // ByteCount berichtigen: + nPos = pPict->Tell(); + pPict->Seek( nDstRowPos ); + if ( nDstRowBytes > 250 ) + *pPict << ( (sal_uInt16)( nPos - nDstRowPos - 2 ) ); + else + *pPict << ( (sal_uInt8)( nPos - nDstRowPos - 1 ) ); + pPict->Seek( nPos ); + } + + // Prozente zaehlen, Callback, Fehler pruefen: + nActBitmapPercent =( ny * 70 / nHeight ) + 30; // (30% machten schon das Schreiben der Win-BMP-Datei aus) + MayCallback(); + if ( pPict->GetError() ) + bStatus = sal_False; + } + // Aufraeumen: + delete[] pPix; + } + + // Map-Daten muessen gerade Anzahl von Bytes sein: + if ( ( ( pPict->Tell() - nDstMapPos ) & 1 ) != 0 ) + *pPict << (sal_uInt8)0; + + // Bitmaps zaehlen: + nWrittenBitmaps++; + nActBitmapPercent = 0; + if ( pAcc ) + aBitmap.ReleaseAccess( pAcc ); +} + +void PictWriter::WriteOpcode_EndOfFile() +{ + *pPict << (sal_uInt16)0x00ff; +} + + +void PictWriter::SetAttrForPaint() +{ + WriteOpcode_PnMode(eSrcRasterOp); + WriteOpcode_RGBFgCol(aFillColor); + WriteOpcode_RGBBkCol(aFillColor); + WriteOpcode_PnFillPat(aFillColor!=Color( COL_TRANSPARENT )); +} + + +void PictWriter::SetAttrForFrame() +{ + WriteOpcode_PnMode(eSrcRasterOp); + WriteOpcode_PnSize(0); + WriteOpcode_RGBFgCol(aLineColor); + WriteOpcode_PnLinePat(aLineColor!=Color( COL_TRANSPARENT )); +} + + +void PictWriter::SetAttrForText() +{ + WriteOpcode_RGBFgCol(aSrcFont.GetColor()); + WriteOpcode_RGBBkCol(aSrcFont.GetFillColor()); + WriteOpcode_PnLinePat(sal_True); + WriteOpcode_FontName(aSrcFont); + WriteOpcode_TxSize((sal_uInt16)(aSrcFont.GetSize().Height())); + WriteOpcode_TxMode(eSrcRasterOp); + WriteOpcode_TxFace(aSrcFont); +} + + +void PictWriter::WriteTextArray(Point & rPoint, const String& rString, const sal_Int32 * pDXAry) +{ + sal_uInt16 i,nLen; + sal_Unicode c; + sal_Bool bDelta; + Point aPt; + + if ( pDXAry == NULL ) + WriteOpcode_Text( rPoint, rString, sal_False ); + else + { + bDelta = sal_False; + nLen = rString.Len(); + for ( i = 0; i < nLen; i++ ) + { + c = rString.GetChar( i ); + if ( c && ( c != 0x20 ) ) + { + aPt = rPoint; + if ( i > 0 ) + aPt.X() += pDXAry[ i - 1 ]; + + WriteOpcode_Text( aPt, String( c ), bDelta ); + bDelta = sal_True; + } + } + } +} + +void PictWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon) +{ + if(rLinePolygon.count()) + { + basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon); + basegfx::B2DPolyPolygon aFillPolyPolygon; + + rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon); + + if(aLinePolyPolygon.count()) + { + aLinePolyPolygon = aLinePolyPolygon.getDefaultAdaptiveSubdivision(); + const sal_uInt32 nPolyCount(aLinePolyPolygon.count()); + SetAttrForFrame(); + + for(sal_uInt32 a(0); a < nPolyCount; a++) + { + const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aCandidate.count()); + + if(nPointCount) + { + const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount); + const basegfx::B2DPoint aCurr(aCandidate.getB2DPoint(0)); + Point nCurr(basegfx::fround(aCurr.getX()), basegfx::fround(aCurr.getY())); + + for(sal_uInt32 b(0); b < nEdgeCount; b++) + { + const sal_uInt32 nNextIndex((b + 1) % nPointCount); + const basegfx::B2DPoint aNext(aCandidate.getB2DPoint(nNextIndex)); + const Point nNext(basegfx::fround(aNext.getX()), basegfx::fround(aNext.getY())); + + WriteOpcode_Line(nCurr, nNext); + nCurr = nNext; + } + } + } + } + + if(aFillPolyPolygon.count()) + { + const Color aOldLineColor(aLineColor); + const Color aOldFillColor(aFillColor); + + aLineColor = Color( COL_TRANSPARENT ); + aFillColor = aOldLineColor; + SetAttrForPaint(); + + for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) + { + const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a).getDefaultAdaptiveSubdivision()); + WriteOpcode_Poly(PDM_PAINT, aPolygon); + } + + aLineColor = aOldLineColor; + aFillColor = aOldFillColor; + } + } +} + +void PictWriter::WriteOpcodes( const GDIMetaFile & rMTF ) +{ + sal_uLong nA, nACount; + const MetaAction* pMA; + + if( !bStatus) + return; + + nACount=rMTF.GetActionCount(); + + for (nA=0; nA<nACount; nA++) + { + pMA = rMTF.GetAction(nA); + + switch (pMA->GetType()) + { + case META_PIXEL_ACTION: + { + const MetaPixelAction* pA = (const MetaPixelAction*) pMA; + WriteOpcode_PnMode(eSrcRasterOp); + WriteOpcode_PnSize(1); + WriteOpcode_RGBFgCol(pA->GetColor()); + WriteOpcode_PnLinePat(sal_True); + WriteOpcode_Line(pA->GetPoint(),pA->GetPoint()); + } + break; + + case META_POINT_ACTION: + { + const MetaPointAction* pA = (const MetaPointAction*) pMA; + + if( aLineColor != Color( COL_TRANSPARENT ) ) + { + SetAttrForFrame(); + WriteOpcode_Line( pA->GetPoint(),pA->GetPoint() ); + } + } + break; + + case META_LINE_ACTION: + { + const MetaLineAction* pA = (const MetaLineAction*) pMA; + + if( aLineColor != Color( COL_TRANSPARENT ) ) + { + if(pA->GetLineInfo().IsDefault()) + { + SetAttrForFrame(); + WriteOpcode_Line( pA->GetStartPoint(),pA->GetEndPoint() ); + } + else + { + // LineInfo used; handle Dash/Dot and fat lines + basegfx::B2DPolygon aPolygon; + aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y())); + aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y())); + HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon); + } + } + break; + } + + case META_RECT_ACTION: + { + const MetaRectAction* pA = (const MetaRectAction*) pMA; + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Rect(PDM_PAINT,pA->GetRect()); + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_SameRect(PDM_FRAME); + } + } + else if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_Rect(PDM_FRAME,pA->GetRect()); + } + } + break; + + case META_ROUNDRECT_ACTION: + { + const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA; + + WriteOpcode_OvSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) ); + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_RRect(PDM_PAINT,pA->GetRect()); + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_SameRRect(PDM_FRAME); + } + } + else if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_RRect(PDM_FRAME,pA->GetRect()); + } + } + break; + + case META_ELLIPSE_ACTION: + { + const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA; + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Oval(PDM_PAINT,pA->GetRect()); + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_SameOval(PDM_FRAME); + } + } + else if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_Oval(PDM_FRAME,pA->GetRect()); + } + } + break; + + case META_ARC_ACTION: + { + const MetaArcAction* pA = (const MetaArcAction*) pMA; + + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint()); + } + } + break; + + case META_PIE_ACTION: + { + const MetaPieAction* pA = (const MetaPieAction *) pMA; + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Arc(PDM_PAINT,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint()); + + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_SameArc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint()); + } + } + else if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_Arc(PDM_FRAME,pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint()); + } + + if (aLineColor!=Color( COL_TRANSPARENT )) + { + double fxc,fyc,fxr,fyr,fx1,fy1,fx2,fy2,l1,l2; + + fxc=((double)(pA->GetRect().Left()+pA->GetRect().Right()))/2.0; + fyc=((double)(pA->GetRect().Top()+pA->GetRect().Bottom()))/2.0; + fxr=((double)pA->GetRect().GetWidth())/2.0; + fyr=((double)pA->GetRect().GetHeight())/2.0; + fx1=((double)pA->GetStartPoint().X())-fxc; + fy1=((double)pA->GetStartPoint().Y())-fyc; + fx2=((double)pA->GetEndPoint().X())-fxc; + fy2=((double)pA->GetEndPoint().Y())-fyc; + l1=sqrt(fx1*fx1+fy1*fy1); + l2=sqrt(fx2*fx2+fy2*fy2); + + if (l1>0) + { + fx1=fx1/l1*fxr; + fy1=fy1/l1*fyr; + } + + if (l2>0) + { + fx2=fx2/l2*fxr; + fy2=fy2/l2*fyr; + } + fx1+=fxc; fy1+=fyc; fx2+=fxc; fy2+=fyc; + WriteOpcode_Line(Point((long)(fx1+0.5),(long)(fy1+0.5)), Point((long)(fxc+0.5),(long)(fyc+0.5))); + WriteOpcode_LineFrom(Point((long)(fx2+0.5),(long)(fy2+0.5))); + } + } + break; + + case META_CHORD_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_CHORD_ACTION!" ); + } + break; + + case META_POLYLINE_ACTION: + { + const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA; + + if( aLineColor!=Color( COL_TRANSPARENT ) ) + { + const Polygon& rPoly = pA->GetPolygon(); + + if( rPoly.GetSize() ) + { + if(pA->GetLineInfo().IsDefault()) + { + Polygon aSimplePoly; + if ( rPoly.HasFlags() ) + rPoly.AdaptiveSubdivide( aSimplePoly ); + else + aSimplePoly = rPoly; + + const sal_uInt16 nSize = aSimplePoly.GetSize(); + Point aLast; + + if ( nSize ) + { + SetAttrForFrame(); + aLast = aSimplePoly[0]; + + for ( sal_uInt16 i = 1; i < nSize; i++ ) + { + WriteOpcode_Line( aLast, aSimplePoly[i] ); + aLast = aSimplePoly[i]; + } + } + } + else + { + // LineInfo used; handle Dash/Dot and fat lines + HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon()); + } + } + } + } + break; + + case META_POLYGON_ACTION: + { + const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA; + + const Polygon& rPoly = pA->GetPolygon(); + + Polygon aSimplePoly; + if ( rPoly.HasFlags() ) + rPoly.AdaptiveSubdivide( aSimplePoly ); + else + aSimplePoly = rPoly; + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Poly( PDM_PAINT, aSimplePoly ); + } + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + WriteOpcode_Poly( PDM_FRAME, aSimplePoly ); + } + } + break; + + case META_POLYPOLYGON_ACTION: + { + const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA; + + const PolyPolygon& rPolyPoly = pA->GetPolyPolygon(); + sal_uInt16 nPolyCount = rPolyPoly.Count(); + PolyPolygon aSimplePolyPoly( rPolyPoly ); + for ( sal_uInt16 i = 0; i < nPolyCount; i++ ) + { + if ( aSimplePolyPoly[ i ].HasFlags() ) + { + Polygon aSimplePoly; + aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly ); + aSimplePolyPoly[ i ] = aSimplePoly; + } + } + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( aSimplePolyPoly )); + } + + if (aLineColor!=Color( COL_TRANSPARENT )) + { + sal_uInt16 nCount,i; + SetAttrForFrame(); + nCount = aSimplePolyPoly.Count(); + for ( i = 0; i < nCount; i++ ) + WriteOpcode_Poly( PDM_FRAME, aSimplePolyPoly.GetObject( i ) ); + } + } + break; + + case META_TEXT_ACTION: + { + const MetaTextAction* pA = (const MetaTextAction*) pMA; + Point aPt( pA->GetPoint() ); + + if ( aSrcFont.GetAlign() != ALIGN_BASELINE ) + { + VirtualDevice aVirDev; + + if (aSrcFont.GetAlign()==ALIGN_TOP) + aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent(); + else + aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent(); + } + + SetAttrForText(); + String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() ); + WriteOpcode_Text( aPt, aStr, sal_False ); + } + break; + + case META_TEXTARRAY_ACTION: + { + const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA; + Point aPt( pA->GetPoint() ); + + if (aSrcFont.GetAlign()!=ALIGN_BASELINE) + { + VirtualDevice aVirDev; + + if (aSrcFont.GetAlign()==ALIGN_TOP) + aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent(); + else + aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent(); + } + SetAttrForText(); + String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() ); + WriteTextArray( aPt, aStr, pA->GetDXArray() ); + break; + } + + case META_STRETCHTEXT_ACTION: + { + const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pMA; + Point aPt( pA->GetPoint() ); + String aStr( pA->GetText(),pA->GetIndex(),pA->GetLen() ); + VirtualDevice aVirDev; + sal_Int32* pDXAry = new sal_Int32[ aStr.Len() ]; + sal_Int32 nNormSize( aVirDev.GetTextArray( aStr,pDXAry ) ); + sal_uInt16 i; + + if (aSrcFont.GetAlign()!=ALIGN_BASELINE) + { + if (aSrcFont.GetAlign()==ALIGN_TOP) + aPt.Y()+=(long)aVirDev.GetFontMetric(aSrcFont).GetAscent(); + else + aPt.Y()-=(long)aVirDev.GetFontMetric(aSrcFont).GetDescent(); + } + + for ( i = 0; i < aStr.Len() - 1; i++ ) + pDXAry[ i ] = pDXAry[ i ] * ( (long)pA->GetWidth() ) / nNormSize; + + SetAttrForText(); + WriteTextArray( aPt, aStr, pDXAry ); + delete[] pDXAry; + } + break; + + case META_TEXTRECT_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_TEXTRECT_ACTION!" ); + } + break; + + case META_BMP_ACTION: + { + const MetaBmpAction* pA = (const MetaBmpAction*) pMA; + WriteOpcode_BitsRect( pA->GetPoint(),pA->GetBitmap().GetSizePixel(), pA->GetBitmap() ); + } + break; + + case META_BMPSCALE_ACTION: + { + const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA; + WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() ); + } + break; + + case META_BMPSCALEPART_ACTION: + { + const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA; + Bitmap aBmp( pA->GetBitmap() ); + + aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ); + WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp ); + } + break; + + case META_BMPEX_ACTION: + { + const MetaBmpExAction* pA = (const MetaBmpExAction*) pMA; + const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() ); + + WriteOpcode_BitsRect( pA->GetPoint(), aBmp.GetSizePixel(), aBmp ); + } + break; + + case META_BMPEXSCALE_ACTION: + { + const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA; + const Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() ); + + WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), aBmp ); + } + break; + + case META_BMPEXSCALEPART_ACTION: + { + const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA; + Bitmap aBmp( Graphic( pA->GetBitmapEx() ).GetBitmap() ); + + aBmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ); + WriteOpcode_BitsRect( pA->GetDestPoint(), pA->GetDestSize(), aBmp ); + } + break; + + case META_EPS_ACTION : + { + const MetaEPSAction* pA = (const MetaEPSAction*)pMA; + const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() ); + + sal_Int32 nCount = aGDIMetaFile.GetActionCount(); + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i ); + if ( pMetaAct->GetType() == META_BMPSCALE_ACTION ) + { + const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct; + WriteOpcode_BitsRect( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() ); + break; + } + } + } + break; + + case META_MASK_ACTION: + case META_MASKSCALE_ACTION: + case META_MASKSCALEPART_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_MASK..._ACTION!" ); + } + break; + + case META_GRADIENT_ACTION: + { + VirtualDevice aVDev; + GDIMetaFile aTmpMtf; + const MetaGradientAction* pA = (const MetaGradientAction*) pMA; + + aVDev.SetMapMode( aTargetMapMode ); + aVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf ); + WriteOpcodes( aTmpMtf ); + } + break; + + case META_HATCH_ACTION: + { + VirtualDevice aVDev; + GDIMetaFile aTmpMtf; + const MetaHatchAction* pA = (const MetaHatchAction*) pMA; + + aVDev.SetMapMode( aTargetMapMode ); + aVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf ); + WriteOpcodes( aTmpMtf ); + } + break; + + case META_WALLPAPER_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_WALLPAPER_ACTION!" ); + } + break; + + case META_CLIPREGION_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_CLIPREGION_ACTION!" ); + } + break; + + case META_ISECTRECTCLIPREGION_ACTION: + { + const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA; + WriteOpcode_ClipRect( pA->GetRect() ); + } + break; + + case META_ISECTREGIONCLIPREGION_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_ISECTREGIONCLIPREGION_ACTION!" ); + } + break; + + case META_MOVECLIPREGION_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_MOVECLIPREGION_ACTION!" ); + } + break; + + case META_LINECOLOR_ACTION: + { + const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA; + + if( pA->IsSetting() ) + aLineColor = pA->GetColor(); + else + aLineColor = Color( COL_TRANSPARENT ); + } + break; + + case META_FILLCOLOR_ACTION: + { + const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA; + + if( pA->IsSetting() ) + aFillColor = pA->GetColor(); + else + aFillColor = Color( COL_TRANSPARENT ); + } + break; + + case META_TEXTCOLOR_ACTION: + { + const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA; + aSrcFont.SetColor( pA->GetColor() ); + } + break; + + case META_TEXTFILLCOLOR_ACTION: + { + const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA; + + if( pA->IsSetting() ) + aSrcFont.SetFillColor( pA->GetColor() ); + else + aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) ); + } + break; + + case META_TEXTALIGN_ACTION: + { +// OSL_FAIL( "Unsupported PICT-Action: META_TEXTALIGN_ACTION!" ); + } + break; + + case META_MAPMODE_ACTION: + { + const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA; + + if (aSrcMapMode!=pA->GetMapMode()) + { + if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE ) + { + MapMode aMM = pA->GetMapMode(); + Fraction aScaleX = aMM.GetScaleX(); + Fraction aScaleY = aMM.GetScaleY(); + + Point aOrigin = aSrcMapMode.GetOrigin(); + BigInt aX( aOrigin.X() ); + aX *= BigInt( aScaleX.GetDenominator() ); + if( aOrigin.X() >= 0 ) + { + if( aScaleX.GetNumerator() >= 0 ) + aX += BigInt( aScaleX.GetNumerator()/2 ); + else + aX -= BigInt( (aScaleX.GetNumerator()+1)/2 ); + } + else + { + if( aScaleX.GetNumerator() >= 0 ) + aX -= BigInt( (aScaleX.GetNumerator()-1)/2 ); + else + aX += BigInt( aScaleX.GetNumerator()/2 ); + } + + aX /= BigInt( aScaleX.GetNumerator() ); + aOrigin.X() = (long)aX + aMM.GetOrigin().X(); + BigInt aY( aOrigin.Y() ); + aY *= BigInt( aScaleY.GetDenominator() ); + + if( aOrigin.Y() >= 0 ) + { + if( aScaleY.GetNumerator() >= 0 ) + aY += BigInt( aScaleY.GetNumerator()/2 ); + else + aY -= BigInt( (aScaleY.GetNumerator()+1)/2 ); + } + else + { + if( aScaleY.GetNumerator() >= 0 ) + aY -= BigInt( (aScaleY.GetNumerator()-1)/2 ); + else + aY += BigInt( aScaleY.GetNumerator()/2 ); + } + + aY /= BigInt( aScaleY.GetNumerator() ); + aOrigin.Y() = (long)aY + aMM.GetOrigin().Y(); + aSrcMapMode.SetOrigin( aOrigin ); + + aScaleX *= aSrcMapMode.GetScaleX(); + aScaleY *= aSrcMapMode.GetScaleY(); + aSrcMapMode.SetScaleX( aScaleX ); + aSrcMapMode.SetScaleY( aScaleY ); + } + else + aSrcMapMode = pA->GetMapMode(); + } + } + break; + + case META_FONT_ACTION: + { + const MetaFontAction* pA = (const MetaFontAction*) pMA; + aSrcFont=pA->GetFont(); + } + break; + + case META_PUSH_ACTION: + { + PictWriterAttrStackMember * pAt = new PictWriterAttrStackMember; + pAt->aLineColor=aLineColor; + pAt->aFillColor=aFillColor; + pAt->eRasterOp=eSrcRasterOp; + pAt->aFont=aSrcFont; + pAt->aMapMode=aSrcMapMode; + pAt->aClipRect=aClipRect; + pAt->pSucc=pAttrStack; + pAttrStack=pAt; + } + break; + + case META_POP_ACTION: + { + PictWriterAttrStackMember* pAt=pAttrStack; + + if( pAt ) + { + aLineColor=pAt->aLineColor; + aFillColor=pAt->aFillColor; + eSrcRasterOp=pAt->eRasterOp; + aSrcFont=pAt->aFont; + aSrcMapMode=pAt->aMapMode; + if ( pAt->aClipRect != aClipRect ) + { + Rectangle aRect( pAt->aClipRect ); + *pPict << (sal_uInt16)1 // opcode 1 + << (sal_uInt16)10 // data size + << (sal_Int16)aRect.Top() << (sal_Int16)aRect.Left() + << (sal_Int16)aRect.Bottom() << (sal_Int16)aRect.Right(); + } + aClipRect=pAt->aClipRect; + pAttrStack=pAt->pSucc; + delete pAt; + } + } + break; + + case META_RASTEROP_ACTION: + { + const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA; + eSrcRasterOp=pA->GetRasterOp(); + } + break; + + case META_TRANSPARENT_ACTION: + { + const PolyPolygon& rPolyPoly = ( (const MetaTransparentAction*) pMA )->GetPolyPolygon(); + + if (aFillColor!=Color( COL_TRANSPARENT )) + { + SetAttrForPaint(); + WriteOpcode_Poly( PDM_PAINT, PolyPolygonToPolygon( rPolyPoly ) ); + } + + if (aLineColor!=Color( COL_TRANSPARENT )) + { + SetAttrForFrame(); + for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ ) + WriteOpcode_Poly( PDM_FRAME, rPolyPoly.GetObject( i ) ); + } + } + break; + + case META_FLOATTRANSPARENT_ACTION: + { + const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA; + + GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() ); + Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() ); + const Size aSrcSize( aTmpMtf.GetPrefSize() ); + const Point aDestPt( pA->GetPoint() ); + const Size aDestSize( pA->GetSize() ); + const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0; + const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0; + long nMoveX, nMoveY; + + if( fScaleX != 1.0 || fScaleY != 1.0 ) + { + aTmpMtf.Scale( fScaleX, fScaleY ); + aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY ); + } + + nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y(); + + if( nMoveX || nMoveY ) + aTmpMtf.Move( nMoveX, nMoveY ); + + WriteOpcodes( aTmpMtf ); + } + break; + } + + nWrittenActions++; + MayCallback(); + + if (pPict->GetError()) + bStatus=sal_False; + + if (bStatus==sal_False) + break; + } +} + + +void PictWriter::WriteHeader(const GDIMetaFile & rMTF) +{ + sal_uInt16 i; + Size aSize( rMTF.GetPrefSize() ); + Point aPoint; + Rectangle aRect( aPoint, aSize ); + + // 512 Bytes "Muell" am Anfang: + for (i=0;i<128;i++) *pPict << (sal_uInt32)0; + + // Lo-16-Bits der Groesse der Datei ohne die 512 Bytes Muell: + *pPict << (sal_uInt16)0; // wird spaeter durch UpdateHeader() berichtigt + + // Das Bounding-Rectangle (y1,x1,y2,x2 !): + WriteRectangle( aRect ); + + // Version 2: + *pPict << (sal_uInt32)0x001102ff; + + // Extended-Version-2-Header: + *pPict << (sal_uInt16)0x0c00 // Opcode + << (sal_uInt16)0xfffe // Version (?) + << (sal_uInt16)0x0000 // Reserved + << (sal_uInt32) 0x00480000 // hRes + << (sal_uInt32) 0x00480000; + WriteRectangle( aRect ); + *pPict << (sal_uInt32)0x00000000; // Reserved + + // viele Import-Filter verlangen die Angabe eines + // Clipping-Bereichs am Anfang + + WriteOpcode_ClipRect( aRect ); +} + + +void PictWriter::UpdateHeader() +{ + sal_uLong nPos; + + // Lo-16-Bits der Groesse der Datei ohne die 512 Bytes Muell berichtigen: + nPos=pPict->Tell(); + pPict->Seek(512); + *pPict << (sal_uInt16)((nPos-512)&0x0000ffff); + pPict->Seek(nPos); +} + + +sal_Bool PictWriter::WritePict(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem ) +{ + PictWriterAttrStackMember* pAt; + MapMode aMap72( MAP_INCH ); + Fraction aDPIFrac( 1, 72 ); + + bStatus=sal_True; + nLastPercent=0; + + if ( pFilterConfigItem ) + { + xStatusIndicator = pFilterConfigItem->GetStatusIndicator(); + if ( xStatusIndicator.is() ) + { + rtl::OUString aMsg; + xStatusIndicator->start( aMsg, 100 ); + } + } + + pPict=&rTargetStream; + pPict->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN); + + aLineColor=Color( COL_BLACK ); + aFillColor=Color( COL_WHITE ); + eSrcRasterOp=ROP_OVERPAINT; + aSrcFont=Font(); + aSrcMapMode = rMTF.GetPrefMapMode(); + + aMap72.SetScaleX( aDPIFrac ); + aMap72.SetScaleY( aDPIFrac ); + aTargetMapMode = aMap72; + + pAttrStack=NULL; + + bDstBkPatValid=sal_False; + bDstTxFaceValid=sal_False; + bDstTxModeValid=sal_False; + bDstPnSizeValid=sal_False; + bDstPnModeValid=sal_False; + bDstPnPatValid=sal_False; + bDstFillPatValid=sal_False; + bDstTxSizeValid=sal_False; + bDstFgColValid=sal_False; + bDstBkColValid=sal_False; + bDstPenPositionValid=sal_False; + bDstTextPositionValid=sal_False; + bDstFontNameValid=sal_False; + + nNumberOfActions=0; + nNumberOfBitmaps=0; + nWrittenActions=0; + nWrittenBitmaps=0; + nActBitmapPercent=0; + + CountActionsAndBitmaps(rMTF); + + WriteHeader(rMTF); + WriteOpcodes(rMTF); + WriteOpcode_EndOfFile(); + UpdateHeader(); + + while (pAttrStack!=NULL) { + pAt=pAttrStack; + pAttrStack=pAt->pSucc; + delete pAt; + } + + if ( xStatusIndicator.is() ) + xStatusIndicator->end(); + + return bStatus; +} + +//================== GraphicExport - die exportierte Funktion ================ + +extern "C" sal_Bool __LOADONCALLAPI GraphicExport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool) +{ + PictWriter aPictWriter; + + if (rGraphic.GetType()==GRAPHIC_GDIMETAFILE) + { + GDIMetaFile aScaledMtf( rGraphic.GetGDIMetaFile() ); + +/* + MapMode aMap72( MAP_INCH ); + Fraction aDPIFrac( 1, 72 ); + Size aOldSize = aScaledMtf.GetPrefSize(); + + aMap72.SetScaleX( aDPIFrac ); + aMap72.SetScaleY( aDPIFrac ); + + Size aNewSize = OutputDevice::LogicToLogic( aOldSize, + aScaledMtf.GetPrefMapMode(), + aMap72 ); + + aScaledMtf.Scale( Fraction( aNewSize.Width(), aOldSize.Width() ), + Fraction( aNewSize.Height(), aOldSize.Height() ) ); + aScaledMtf.SetPrefMapMode( aMap72 ); + aScaledMtf.SetPrefSize( aNewSize ); +*/ + + return aPictWriter.WritePict( aScaledMtf, rStream, pFilterConfigItem ); + } + else + { + Bitmap aBmp=rGraphic.GetBitmap(); + GDIMetaFile aMTF; + VirtualDevice aVirDev; + + aMTF.Record(&aVirDev); + aVirDev.DrawBitmap(Point(),aBmp); + aMTF.Stop(); + aMTF.SetPrefSize(aBmp.GetSizePixel()); + return aPictWriter.WritePict( aMTF, rStream, pFilterConfigItem ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |