| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 ) ] |= (pAcc->GetPixelIndex( 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 ) ] |= (pAcc->GetPixelIndex( ny, i ) & 15) << ((i & 1) << 2); |
| break; |
| case 8 : |
| for ( i = 0; i < nWidth; i++ ) |
| pPix[ i ] = pAcc->GetPixelIndex( 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: |
| { |
| // DBG_ERROR( "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: |
| { |
| // DBG_ERROR( "Unsupported PICT-Action: META_TEXTRECT_ACTION!" ); |
| } |
| break; |
| |
| case META_BMP_ACTION: |
| { |
| const MetaBmpAction* pA = (const MetaBmpAction*) pMA; |
| const Bitmap aBmp( pA->GetBitmap() ); |
| VirtualDevice aVirDev; |
| |
| WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), aBmp ); |
| } |
| 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() ); |
| VirtualDevice aVirDev; |
| |
| WriteOpcode_BitsRect( pA->GetPoint(), aVirDev.PixelToLogic( aBmp.GetSizePixel(), aSrcMapMode ), 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: |
| { |
| // DBG_ERROR( "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: |
| { |
| // DBG_ERROR( "Unsupported PICT-Action: META_WALLPAPER_ACTION!" ); |
| } |
| break; |
| |
| case META_CLIPREGION_ACTION: |
| { |
| // DBG_ERROR( "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: |
| { |
| // DBG_ERROR( "Unsupported PICT-Action: META_ISECTREGIONCLIPREGION_ACTION!" ); |
| } |
| break; |
| |
| case META_MOVECLIPREGION_ACTION: |
| { |
| // DBG_ERROR( "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: |
| { |
| // DBG_ERROR( "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; |
| |
| // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically |
| GDIMetaFile aScaledMtf( rGraphic.GetGDIMetaFile() ); |
| |
| return aPictWriter.WritePict( aScaledMtf, rStream, pFilterConfigItem ); |
| } |
| |