| /************************************************************** |
| * |
| * 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/sv.h> |
| #include <tools/stream.hxx> |
| #include <tools/bigint.hxx> |
| #include <tools/poly.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/metaact.hxx> |
| #include <vcl/graph.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <vcl/region.hxx> |
| #include <vcl/metric.hxx> |
| #include <vcl/font.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/cvtgrf.hxx> |
| #include <vcl/gradient.hxx> |
| #include <svl/solar.hrc> |
| #include <svtools/fltcall.hxx> |
| #include <svtools/FilterConfigItem.hxx> |
| #include <vcl/graphictools.hxx> |
| #include "strings.hrc" |
| |
| #include <math.h> |
| |
| #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox |
| // in the first 4096 bytes |
| |
| #define EPS_PREVIEW_TIFF 1 |
| #define EPS_PREVIEW_EPSI 2 |
| |
| #define PS_LINESIZE 70 // maximum number of characters a line in the output |
| |
| #define PS_NONE 0 // formating mode: action which is inserted behind the output |
| #define PS_SPACE 1 |
| #define PS_RET 2 |
| #define PS_WRAP 4 |
| |
| // -----------------------------Feld-Typen------------------------------- |
| |
| struct ChrSet |
| { |
| struct ChrSet * pSucc; |
| sal_uInt8 nSet; |
| String aName; |
| FontWeight eWeight; |
| }; |
| |
| struct StackMember |
| { |
| struct StackMember * pSucc; |
| Color aGlobalCol; |
| sal_Bool bLineCol; |
| Color aLineCol; |
| sal_Bool bFillCol; |
| Color aFillCol; |
| Color aTextCol; |
| sal_Bool bTextFillCol; |
| Color aTextFillCol; |
| Color aBackgroundCol; |
| Font aFont; |
| TextAlign eTextAlign; |
| |
| double fLineWidth; |
| double fMiterLimit; |
| SvtGraphicStroke::CapType eLineCap; |
| SvtGraphicStroke::JoinType eJoinType; |
| SvtGraphicStroke::DashArray aDashArray; |
| }; |
| |
| struct PSLZWCTreeNode |
| { |
| |
| PSLZWCTreeNode* pBrother; // naechster Knoten, der den selben Vater hat |
| PSLZWCTreeNode* pFirstChild; // erster Sohn |
| sal_uInt16 nCode; // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn |
| sal_uInt16 nValue; // Der Pixelwert |
| }; |
| |
| class PSWriter |
| { |
| private: |
| sal_Bool mbStatus; |
| sal_uLong mnLevelWarning; // number of embedded eps files which was not exported |
| sal_uLong mnLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde. |
| sal_uInt32 mnLatestPush; // offset auf streamposition, an der zuletzt gepusht wurde |
| |
| long mnLevel; // dialog options |
| sal_Bool mbGrayScale; |
| sal_Bool mbCompression; |
| sal_Int32 mnPreview; |
| sal_Int32 mnTextMode; |
| |
| SvStream* mpPS; |
| const GDIMetaFile* pMTF; |
| GDIMetaFile* pAMTF; // only created if Graphics is not a Metafile |
| VirtualDevice aVDev; |
| |
| double nBoundingX1; // this represents the bounding box |
| double nBoundingY1; |
| double nBoundingX2; |
| double nBoundingY2; |
| // |
| StackMember* pGDIStack; |
| sal_uLong mnCursorPos; // aktuelle Cursorposition im Output |
| Color aColor; // aktuelle Farbe die fuer den Output benutzt wird |
| sal_Bool bLineColor; |
| Color aLineColor; // aktuelle GDIMetafile Farbeinstellungen |
| sal_Bool bFillColor; // |
| Color aFillColor; // |
| Color aTextColor; // |
| sal_Bool bTextFillColor; // |
| Color aTextFillColor; // |
| Color aBackgroundColor; // |
| sal_Bool bRegionChanged; |
| TextAlign eTextAlign; // |
| |
| double fLineWidth; |
| double fMiterLimit; |
| SvtGraphicStroke::CapType eLineCap; |
| SvtGraphicStroke::JoinType eJoinType; |
| SvtGraphicStroke::DashArray aDashArray; |
| |
| Font maFont; |
| Font maLastFont; |
| sal_uInt8 nChrSet; |
| ChrSet* pChrSetList; // Liste der Character-Sets |
| sal_uInt8 nNextChrSetId; // die erste unbenutzte ChrSet-Id |
| |
| PSLZWCTreeNode* pTable; // LZW compression data |
| PSLZWCTreeNode* pPrefix; // the compression is as same as the TIFF compression |
| sal_uInt16 nDataSize; |
| sal_uInt16 nClearCode; |
| sal_uInt16 nEOICode; |
| sal_uInt16 nTableSize; |
| sal_uInt16 nCodeSize; |
| sal_uLong nOffset; |
| sal_uLong dwShift; |
| |
| com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator; |
| |
| void ImplWriteProlog( const Graphic* pPreviewEPSI = NULL ); |
| void ImplWriteEpilog(); |
| void ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev ); |
| |
| // this method makes LF's, space inserting and word wrapping as used in all nMode |
| // parameters |
| inline void ImplExecMode( sal_uLong nMode ); |
| |
| // writes char[] + LF to stream |
| inline void ImplWriteLine( const char*, sal_uLong nMode = PS_RET ); |
| |
| // writes ( nNumb / 10^nCount ) in ASCII format to stream |
| void ImplWriteF( sal_Int32 nNumb, sal_uLong nCount = 3, sal_uLong nMode = PS_SPACE ); |
| |
| // writes a double in ASCII format to stream |
| void ImplWriteDouble( double, sal_uLong nMode = PS_SPACE ); |
| |
| // writes a long in ASCII format to stream |
| void ImplWriteLong( sal_Int32 nNumb, sal_uLong nMode = PS_SPACE ); |
| |
| // writes a byte in ASCII format to stream |
| void ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE ); |
| |
| // writes a byte in ASCII (hex) format to stream |
| void ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode = PS_WRAP ); |
| |
| // writes nNumb as number from 0.000 till 1.000 in ASCII format to stream |
| void ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE ); |
| |
| inline void ImplWritePoint( const Point&, sal_uInt32 nMode = PS_SPACE ); |
| void ImplMoveTo( const Point&, sal_uInt32 nMode = PS_SPACE ); |
| void ImplLineTo( const Point&, sal_uInt32 nMode = PS_SPACE ); |
| void ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode = PS_SPACE ); |
| void ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET ); |
| void ImplScale( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET ); |
| |
| void ImplWriteLine( const Polygon & rPolygon ); |
| void ImplAddPath( const Polygon & rPolygon ); |
| void ImplWriteLineInfo( double fLineWidth, double fMiterLimit, SvtGraphicStroke::CapType eLineCap, |
| SvtGraphicStroke::JoinType eJoinType, SvtGraphicStroke::DashArray& rDashArray ); |
| void ImplWriteLineInfo( const LineInfo& rLineInfo ); |
| void ImplRect( const Rectangle & rRectangle ); |
| void ImplRectFill ( const Rectangle & rRectangle ); |
| void ImplWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev ); |
| void ImplIntersect( const PolyPolygon& rPolyPoly ); |
| void ImplPolyPoly( const PolyPolygon & rPolyPolygon, sal_Bool bTextOutline = sal_False ); |
| void ImplPolyLine( const Polygon & rPolygon ); |
| |
| void ImplSetClipRegion( Region& rRegion ); |
| void ImplBmp( Bitmap*, Bitmap*, const Point &, double nWidth, double nHeight ); |
| void ImplText( const String& rUniString, const Point& rPos, const sal_Int32* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev ); |
| void ImplSetAttrForText( const Point & rPoint ); |
| void ImplWriteCharacter( sal_Char ); |
| void ImplWriteString( const ByteString&, VirtualDevice& rVDev, const sal_Int32* pDXArry = NULL, sal_Bool bStretch = sal_False ); |
| void ImplDefineFont( const char*, const char* ); |
| |
| void ImplClosePathDraw( sal_uLong nMode = PS_RET ); |
| void ImplPathDraw(); |
| |
| inline void ImplWriteLineColor( sal_uLong nMode = PS_RET ); |
| inline void ImplWriteFillColor( sal_uLong nMode = PS_RET ); |
| inline void ImplWriteTextColor( sal_uLong nMode = PS_RET ); |
| inline void ImplWriteTextFillColor( sal_uLong nMode = PS_RET ); |
| void ImplWriteColor( sal_uLong nMode ); |
| |
| double ImplGetScaling( const MapMode& ); |
| void ImplGetMapMode( const MapMode& ); |
| sal_Bool ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize ); |
| sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize ); |
| // LZW methods |
| void StartCompression(); |
| void Compress( sal_uInt8 nSrc ); |
| void EndCompression(); |
| inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen ); |
| |
| public: |
| sal_Bool WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* ); |
| PSWriter(); |
| ~PSWriter(); |
| }; |
| |
| //========================== Methoden von PSWriter ========================== |
| |
| //--------------------------------------------------------------------------------- |
| |
| PSWriter::PSWriter() |
| { |
| pAMTF = NULL; |
| } |
| |
| |
| PSWriter::~PSWriter() |
| { |
| delete pAMTF; |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| sal_Bool PSWriter::WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem ) |
| { |
| sal_uInt32 nStreamPosition = 0, nPSPosition = 0; // -Wall warning, unset, check |
| |
| mbStatus = sal_True; |
| mnPreview = 0; |
| mnLevelWarning = 0; |
| mnLastPercent = 0; |
| mnLatestPush = 0xEFFFFFFE; |
| |
| if ( pFilterConfigItem ) |
| { |
| xStatusIndicator = pFilterConfigItem->GetStatusIndicator(); |
| if ( xStatusIndicator.is() ) |
| { |
| rtl::OUString aMsg; |
| xStatusIndicator->start( aMsg, 100 ); |
| } |
| } |
| |
| mpPS = &rTargetStream; |
| mpPS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); |
| |
| // default values for the dialog options |
| mnLevel = 2; |
| mbGrayScale = sal_False; |
| mbCompression = sal_True; |
| mnTextMode = 0; // default0 : export glyph outlines |
| |
| // try to get the dialog selection |
| if ( pFilterConfigItem ) |
| { |
| ByteString aResMgrName( "eps" ); |
| ResMgr* pResMgr; |
| |
| pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() ); |
| |
| if( pResMgr ) |
| { |
| String aPreviewStr( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) ); |
| String aVersionStr( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ); |
| String aColorStr( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) ); |
| String aComprStr( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) ); |
| mnPreview = pFilterConfigItem->ReadInt32( aPreviewStr, 1 ); |
| mnLevel = pFilterConfigItem->ReadInt32( aVersionStr, 2 ); |
| if ( mnLevel != 1 ) |
| mnLevel = 2; |
| mbGrayScale = pFilterConfigItem->ReadInt32( aColorStr, 1 ) == 2; |
| mbCompression = pFilterConfigItem->ReadInt32( aComprStr, 1 ) == 1; |
| String sTextMode( RTL_CONSTASCII_USTRINGPARAM( "TextMode" ) ); |
| mnTextMode = pFilterConfigItem->ReadInt32( sTextMode, 0 ); |
| if ( mnTextMode > 2 ) |
| mnTextMode = 0; |
| delete pResMgr; |
| } |
| } |
| |
| // compression is not available for Level 1 |
| if ( mnLevel == 1 ) |
| { |
| mbGrayScale = sal_True; |
| mbCompression = sal_False; |
| } |
| |
| if ( mnPreview & EPS_PREVIEW_TIFF ) |
| { |
| rTargetStream << (sal_uInt32)0xC6D3D0C5; |
| nStreamPosition = rTargetStream.Tell(); |
| rTargetStream << (sal_uInt32)0 << (sal_uInt32)0 << (sal_uInt32)0 << (sal_uInt32)0 |
| << nStreamPosition + 26 << (sal_uInt32)0 << (sal_uInt16)0xffff; |
| |
| sal_uInt32 nErrCode; |
| if ( mbGrayScale ) |
| { |
| BitmapEx aTempBitmapEx( rGraphic.GetBitmapEx() ); |
| aTempBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| nErrCode = GraphicConverter::Export( rTargetStream, aTempBitmapEx, CVT_TIF ) ; |
| } |
| else |
| nErrCode = GraphicConverter::Export( rTargetStream, rGraphic, CVT_TIF ) ; |
| |
| if ( nErrCode == ERRCODE_NONE ) |
| { |
| rTargetStream.Seek( STREAM_SEEK_TO_END ); |
| nPSPosition = rTargetStream.Tell(); |
| rTargetStream.Seek( nStreamPosition + 20 ); |
| rTargetStream << nPSPosition - 30; // size of tiff gfx |
| rTargetStream.Seek( nPSPosition ); |
| } |
| else |
| { |
| mnPreview &=~ EPS_PREVIEW_TIFF; |
| rTargetStream.Seek( nStreamPosition - 4 ); |
| } |
| } |
| |
| // global default value setting |
| ChrSet* pCS; |
| StackMember* pGS; |
| |
| if ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE ) |
| pMTF = &rGraphic.GetGDIMetaFile(); |
| else |
| pMTF = pAMTF = new GDIMetaFile( rGraphic.GetGDIMetaFile() ); |
| aVDev.SetMapMode( pMTF->GetPrefMapMode() ); |
| nBoundingX1 = nBoundingY1 = 0; |
| nBoundingX2 = pMTF->GetPrefSize().Width(); |
| nBoundingY2 = pMTF->GetPrefSize().Height(); |
| |
| pGDIStack = NULL; |
| aColor = Color( COL_TRANSPARENT ); |
| bLineColor = sal_True; |
| aLineColor = Color( COL_BLACK ); |
| bFillColor = sal_True; |
| aFillColor = Color( COL_WHITE ); |
| bTextFillColor = sal_True; |
| aTextFillColor = Color( COL_BLACK ); |
| fLineWidth = 1; |
| fMiterLimit = 15; // use same limit as most graphic systems and basegfx |
| eLineCap = SvtGraphicStroke::capButt; |
| eJoinType = SvtGraphicStroke::joinMiter; |
| aBackgroundColor = Color( COL_WHITE ); |
| eTextAlign = ALIGN_BASELINE; |
| bRegionChanged = sal_False; |
| |
| nChrSet = 0x00; |
| pChrSetList = NULL; |
| nNextChrSetId = 1; |
| |
| if( pMTF->GetActionCount() ) |
| { |
| ImplWriteProlog( ( mnPreview & EPS_PREVIEW_EPSI ) ? &rGraphic : NULL ); |
| mnCursorPos = 0; |
| ImplWriteActions( *pMTF, aVDev ); |
| ImplWriteEpilog(); |
| if ( mnPreview & EPS_PREVIEW_TIFF ) |
| { |
| sal_uInt32 nPosition = rTargetStream.Tell(); |
| rTargetStream.Seek( nStreamPosition ); |
| rTargetStream << nPSPosition; |
| rTargetStream << nPosition - nPSPosition; |
| rTargetStream.Seek( nPosition ); |
| } |
| while( pChrSetList ) |
| { |
| pCS=pChrSetList; |
| pChrSetList=pCS->pSucc; |
| delete pCS; |
| } |
| while( pGDIStack ) |
| { |
| pGS=pGDIStack; |
| pGDIStack=pGS->pSucc; |
| delete pGS; |
| } |
| } |
| else |
| mbStatus = sal_False; |
| |
| if ( mbStatus && mnLevelWarning && pFilterConfigItem ) |
| { |
| ByteString aResMgrName( "eps" ); |
| ResMgr* pResMgr; |
| pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() ); |
| if( pResMgr ) |
| { |
| InfoBox aInfoBox( NULL, String( ResId( KEY_VERSION_CHECK, *pResMgr ) ) ); |
| aInfoBox.Execute(); |
| delete pResMgr; |
| } |
| } |
| |
| if ( xStatusIndicator.is() ) |
| xStatusIndicator->end(); |
| |
| return mbStatus; |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteProlog( const Graphic* pPreview ) |
| { |
| ImplWriteLine( "%!PS-Adobe-3.0 EPSF-3.0 " ); |
| *mpPS << "%%BoundingBox: "; // BoundingBox |
| ImplWriteLong( 0 ); |
| ImplWriteLong( 0 ); |
| Size aSizePoint = Application::GetDefaultDevice()->LogicToLogic( pMTF->GetPrefSize(), |
| pMTF->GetPrefMapMode(), MAP_POINT ); |
| ImplWriteLong( aSizePoint.Width() ); |
| ImplWriteLong( aSizePoint.Height() ,PS_RET ); |
| ImplWriteLine( "%%Pages: 0" ); |
| ImplWriteLine( "%%Creator: Sun Microsystems, Inc." ); |
| ImplWriteLine( "%%Title: none" ); |
| ImplWriteLine( "%%CreationDate: none" ); |
| |
| // defaults |
| |
| *mpPS << "%%LanguageLevel: "; // Language level |
| ImplWriteLong( mnLevel, PS_RET ); |
| if ( !mbGrayScale && mnLevel == 1 ) |
| ImplWriteLine( "%%Extensions: CMYK" ); // CMYK extension is to set in color mode in level 1 |
| ImplWriteLine( "%%EndComments" ); |
| if ( pPreview && aSizePoint.Width() && aSizePoint.Height() ) |
| { |
| Size aSizeBitmap( ( aSizePoint.Width() + 7 ) & ~7, aSizePoint.Height() ); |
| Bitmap aTmpBitmap( pPreview->GetBitmap() ); |
| aTmpBitmap.Scale( aSizeBitmap, BMP_SCALE_INTERPOLATE ); |
| aTmpBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD ); |
| BitmapReadAccess* pAcc = aTmpBitmap.AcquireReadAccess(); |
| if ( pAcc ) |
| { |
| *mpPS << "%%BeginPreview: "; // BoundingBox |
| ImplWriteLong( aSizeBitmap.Width() ); |
| ImplWriteLong( aSizeBitmap.Height() ); |
| *mpPS << "1 "; |
| sal_Int32 nLines = aSizeBitmap.Width() / 312; |
| if ( ( nLines * 312 ) != aSizeBitmap.Width() ) |
| nLines++; |
| nLines *= aSizeBitmap.Height(); |
| ImplWriteLong( nLines ); |
| char nVal; |
| sal_Int32 nX, nY, nCount2, nCount = 4; |
| const BitmapColor aBlack( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) ); |
| for ( nY = 0; nY < aSizeBitmap.Height(); nY++ ) |
| { |
| nCount2 = 0; |
| nVal = 0; |
| for ( nX = 0; nX < aSizeBitmap.Width(); nX++ ) |
| { |
| if ( !nCount2 ) |
| { |
| ImplExecMode( PS_RET ); |
| *mpPS << "%"; |
| nCount2 = 312; |
| } |
| nVal <<= 1; |
| if ( pAcc->GetPixel( nY, nX ) == aBlack ) |
| nVal |= 1; |
| if ( ! ( --nCount ) ) |
| { |
| if ( nVal > 9 ) |
| nVal += 'A' - 10; |
| else |
| nVal += '0'; |
| *mpPS << nVal; |
| nVal = 0; |
| nCount += 4; |
| } |
| nCount2--; |
| } |
| } |
| aTmpBitmap.ReleaseAccess( pAcc ); |
| ImplExecMode( PS_RET ); |
| ImplWriteLine( "%%EndPreview" ); |
| } |
| } |
| ImplWriteLine( "%%BeginProlog" ); |
| ImplWriteLine( "%%BeginResource: procset SDRes-Prolog 1.0 0" ); |
| |
| // BEGIN EPSF |
| ImplWriteLine( "/b4_inc_state save def\n/dict_count countdictstack def\n/op_count count 1 sub def\nuserdict begin" ); |
| ImplWriteLine( "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath" ); |
| ImplWriteLine( "/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if" ); |
| |
| ImplWriteLine( "/bdef {bind def} bind def" ); // der neue operator bdef wird erzeugt |
| if ( mbGrayScale ) |
| ImplWriteLine( "/c {setgray} bdef" ); |
| else |
| ImplWriteLine( "/c {setrgbcolor} bdef" ); |
| ImplWriteLine( "/l {neg lineto} bdef" ); |
| ImplWriteLine( "/rl {neg rlineto} bdef" ); |
| ImplWriteLine( "/lc {setlinecap} bdef" ); |
| ImplWriteLine( "/lj {setlinejoin} bdef" ); |
| ImplWriteLine( "/lw {setlinewidth} bdef" ); |
| ImplWriteLine( "/ml {setmiterlimit} bdef" ); |
| ImplWriteLine( "/ld {setdash} bdef" ); |
| ImplWriteLine( "/m {neg moveto} bdef" ); |
| ImplWriteLine( "/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef" ); |
| ImplWriteLine( "/r {rotate} bdef" ); |
| ImplWriteLine( "/t {neg translate} bdef" ); |
| ImplWriteLine( "/s {scale} bdef" ); |
| ImplWriteLine( "/sw {show} bdef" ); |
| ImplWriteLine( "/gs {gsave} bdef" ); |
| ImplWriteLine( "/gr {grestore} bdef" ); |
| |
| ImplWriteLine( "/f {findfont dup length dict begin" ); // Setfont |
| ImplWriteLine( "{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def" ); |
| ImplWriteLine( "currentdict end /NFont exch definefont pop /NFont findfont} bdef" ); |
| |
| ImplWriteLine( "/p {closepath} bdef" ); |
| ImplWriteLine( "/sf {scalefont setfont} bdef" ); |
| |
| ImplWriteLine( "/ef {eofill}bdef" ); // close path and fill |
| ImplWriteLine( "/pc {closepath stroke}bdef" ); // close path and draw |
| ImplWriteLine( "/ps {stroke}bdef" ); // draw current path |
| ImplWriteLine( "/pum {matrix currentmatrix}bdef" ); // pushes the current matrix |
| ImplWriteLine( "/pom {setmatrix}bdef" ); // pops the matrix |
| ImplWriteLine( "/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef" ); |
| ImplWriteLine( "%%EndResource" ); |
| ImplWriteLine( "%%EndProlog" ); |
| ImplWriteLine( "%%BeginSetup" ); |
| ImplWriteLine( "%%EndSetup" ); |
| ImplWriteLine( "%%Page: 1 1" ); |
| ImplWriteLine( "%%BeginPageSetup" ); |
| ImplWriteLine( "%%EndPageSetup" ); |
| ImplWriteLine( "pum" ); |
| ImplScale( (double)aSizePoint.Width() / (double)pMTF->GetPrefSize().Width(), (double)aSizePoint.Height() / (double)pMTF->GetPrefSize().Height() ); |
| ImplWriteDouble( 0 ); |
| ImplWriteDouble( -pMTF->GetPrefSize().Height() ); |
| ImplWriteLine( "t" ); |
| ImplWriteLine( "/tm matrix currentmatrix def" ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteEpilog() |
| { |
| ImplTranslate( 0, nBoundingY2 ); |
| ImplWriteLine( "pom" ); |
| ImplWriteLine( "count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore" ); |
| |
| ImplWriteLine( "%%PageTrailer" ); |
| ImplWriteLine( "%%Trailer" ); |
| |
| ImplWriteLine( "%%EOF" ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| //--------------------------------------------------------------------------------- |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev ) |
| { |
| PolyPolygon aFillPath; |
| |
| for( sal_uLong nCurAction = 0, nCount = rMtf.GetActionCount(); nCurAction < nCount; nCurAction++ ) |
| { |
| MetaAction* pMA = rMtf.GetAction( nCurAction ); |
| |
| switch( pMA->GetType() ) |
| { |
| case META_NULL_ACTION : |
| break; |
| |
| case META_PIXEL_ACTION : |
| { |
| Color aOldLineColor( aLineColor ); |
| aLineColor = ( (const MetaPixelAction*) pMA )->GetColor(); |
| ImplWriteLineColor( PS_SPACE ); |
| ImplMoveTo( ( (const MetaPixelAction*)pMA )->GetPoint() ); |
| ImplLineTo( ( (const MetaPixelAction*)pMA )->GetPoint() ); |
| ImplPathDraw(); |
| aLineColor = aOldLineColor; |
| } |
| break; |
| |
| case META_POINT_ACTION : |
| { |
| ImplWriteLineColor( PS_SPACE ); |
| ImplMoveTo( ( (const MetaPointAction*)pMA )->GetPoint() ); |
| ImplLineTo( ( (const MetaPointAction*)pMA )->GetPoint() ); |
| ImplPathDraw(); |
| } |
| break; |
| |
| case META_LINE_ACTION : |
| { |
| const LineInfo& rLineInfo = ( ( const MetaLineAction*)pMA )->GetLineInfo(); |
| ImplWriteLineInfo( rLineInfo ); |
| if ( bLineColor ) |
| { |
| ImplWriteLineColor( PS_SPACE ); |
| ImplMoveTo( ( (const MetaLineAction*) pMA )->GetStartPoint() ); |
| ImplLineTo( ( (const MetaLineAction*) pMA )->GetEndPoint() ); |
| ImplPathDraw(); |
| } |
| } |
| break; |
| |
| case META_RECT_ACTION : |
| { |
| ImplRect( ( (const MetaRectAction*) pMA )->GetRect() ); |
| } |
| break; |
| |
| case META_ROUNDRECT_ACTION : |
| ImplRect( ( (const MetaRoundRectAction*) pMA )->GetRect() ); |
| break; |
| |
| case META_ELLIPSE_ACTION : |
| { |
| Rectangle aRect = ( ( (const MetaEllipseAction*) pMA )->GetRect() ); |
| Point aCenter = aRect.Center(); |
| Polygon aPoly( aCenter, aRect.GetWidth() / 2, aRect.GetHeight() / 2 ); |
| PolyPolygon aPolyPoly( aPoly ); |
| ImplPolyPoly( aPolyPoly ); |
| } |
| break; |
| |
| case META_ARC_ACTION : |
| { |
| Polygon aPoly( ( (const MetaArcAction*)pMA )->GetRect(), ( (const MetaArcAction*)pMA )->GetStartPoint(), |
| ( (const MetaArcAction*)pMA )->GetEndPoint(), POLY_ARC ); |
| PolyPolygon aPolyPoly( aPoly ); |
| ImplPolyPoly( aPolyPoly ); |
| } |
| break; |
| |
| case META_PIE_ACTION : |
| { |
| Polygon aPoly( ( (const MetaPieAction*)pMA )->GetRect(), ( (const MetaPieAction*)pMA )->GetStartPoint(), |
| ( (const MetaPieAction*)pMA )->GetEndPoint(), POLY_PIE ); |
| PolyPolygon aPolyPoly( aPoly ); |
| ImplPolyPoly( aPolyPoly ); |
| } |
| break; |
| |
| case META_CHORD_ACTION : |
| { |
| Polygon aPoly( ( (const MetaChordAction*)pMA )->GetRect(), ( (const MetaChordAction*)pMA )->GetStartPoint(), |
| ( (const MetaChordAction*)pMA )->GetEndPoint(), POLY_CHORD ); |
| PolyPolygon aPolyPoly( aPoly ); |
| ImplPolyPoly( aPolyPoly ); |
| } |
| break; |
| |
| case META_POLYLINE_ACTION : |
| { |
| Polygon aPoly( ( (const MetaPolyLineAction*) pMA )->GetPolygon() ); |
| const LineInfo& rLineInfo = ( ( const MetaPolyLineAction*)pMA )->GetLineInfo(); |
| ImplWriteLineInfo( rLineInfo ); |
| |
| if(basegfx::B2DLINEJOIN_NONE == rLineInfo.GetLineJoin() |
| && rLineInfo.GetWidth() > 1) |
| { |
| // emulate B2DLINEJOIN_NONE by creating single edges |
| const sal_uInt16 nPoints(aPoly.GetSize()); |
| const bool bCurve(aPoly.HasFlags()); |
| |
| for(sal_uInt16 a(0); a + 1 < nPoints; a++) |
| { |
| if(bCurve |
| && POLY_NORMAL != aPoly.GetFlags(a + 1) |
| && a + 2 < nPoints |
| && POLY_NORMAL != aPoly.GetFlags(a + 2) |
| && a + 3 < nPoints) |
| { |
| const Polygon aSnippet(4, |
| aPoly.GetConstPointAry() + a, |
| aPoly.GetConstFlagAry() + a); |
| ImplPolyLine(aSnippet); |
| a += 2; |
| } |
| else |
| { |
| const Polygon aSnippet(2, |
| aPoly.GetConstPointAry() + a); |
| ImplPolyLine(aSnippet); |
| } |
| } |
| } |
| else |
| { |
| ImplPolyLine( aPoly ); |
| } |
| } |
| break; |
| |
| case META_POLYGON_ACTION : |
| { |
| PolyPolygon aPolyPoly( ( (const MetaPolygonAction*) pMA )->GetPolygon() ); |
| ImplPolyPoly( aPolyPoly ); |
| } |
| break; |
| |
| case META_POLYPOLYGON_ACTION : |
| { |
| ImplPolyPoly( ( (const MetaPolyPolygonAction*) pMA )->GetPolyPolygon() ); |
| } |
| break; |
| |
| case META_TEXT_ACTION: |
| { |
| const MetaTextAction * pA = (const MetaTextAction*) pMA; |
| |
| String aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| Point aPoint( pA->GetPoint() ); |
| |
| ImplText( aUniStr, aPoint, NULL, 0, rVDev ); |
| } |
| break; |
| |
| case META_TEXTRECT_ACTION: |
| { |
| DBG_ERROR( "Unsupported action: TextRect...Action!" ); |
| } |
| break; |
| |
| case META_STRETCHTEXT_ACTION : |
| { |
| const MetaStretchTextAction* pA = (const MetaStretchTextAction*)pMA; |
| String aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| Point aPoint( pA->GetPoint() ); |
| |
| ImplText( aUniStr, aPoint, NULL, pA->GetWidth(), rVDev ); |
| } |
| break; |
| |
| case META_TEXTARRAY_ACTION: |
| { |
| const MetaTextArrayAction* pA = (const MetaTextArrayAction*)pMA; |
| String aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| Point aPoint( pA->GetPoint() ); |
| |
| ImplText( aUniStr, aPoint, pA->GetDXArray(), 0, rVDev ); |
| } |
| break; |
| |
| case META_BMP_ACTION : |
| { |
| Bitmap aBitmap = ( (const MetaBmpAction*)pMA )->GetBitmap(); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Point aPoint = ( (const MetaBmpAction*) pMA )->GetPoint(); |
| Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) ); |
| ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| case META_BMPSCALE_ACTION : |
| { |
| Bitmap aBitmap = ( (const MetaBmpScaleAction*)pMA )->GetBitmap(); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Point aPoint = ( (const MetaBmpScaleAction*) pMA )->GetPoint(); |
| Size aSize = ( (const MetaBmpScaleAction*)pMA )->GetSize(); |
| ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| case META_BMPSCALEPART_ACTION : |
| { |
| Bitmap aBitmap( ( (const MetaBmpScalePartAction*)pMA )->GetBitmap() ); |
| aBitmap.Crop( Rectangle( ( (const MetaBmpScalePartAction*)pMA )->GetSrcPoint(), |
| ( (const MetaBmpScalePartAction*)pMA )->GetSrcSize() ) ); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Point aPoint = ( (const MetaBmpScalePartAction*) pMA)->GetDestPoint(); |
| Size aSize = ( (const MetaBmpScalePartAction*)pMA )->GetDestSize(); |
| ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| case META_BMPEX_ACTION : |
| { |
| BitmapEx aBitmapEx( ( (MetaBmpExAction*)pMA)->GetBitmapEx() ); |
| Bitmap aBitmap( aBitmapEx.GetBitmap() ); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Bitmap aMask( aBitmapEx.GetMask() ); |
| Point aPoint( ( (const MetaBmpExAction*) pMA )->GetPoint() ); |
| Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) ); |
| ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| case META_BMPEXSCALE_ACTION : |
| { |
| BitmapEx aBitmapEx( ( (MetaBmpExScaleAction*)pMA)->GetBitmapEx() ); |
| Bitmap aBitmap( aBitmapEx.GetBitmap() ); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Bitmap aMask( aBitmapEx.GetMask() ); |
| Point aPoint = ( (const MetaBmpExScaleAction*) pMA)->GetPoint(); |
| Size aSize( ( (const MetaBmpExScaleAction*)pMA )->GetSize() ); |
| ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| case META_BMPEXSCALEPART_ACTION : |
| { |
| BitmapEx aBitmapEx( ( (const MetaBmpExScalePartAction*)pMA )->GetBitmapEx() ); |
| aBitmapEx.Crop( Rectangle( ( (const MetaBmpExScalePartAction*)pMA )->GetSrcPoint(), |
| ( (const MetaBmpExScalePartAction*)pMA )->GetSrcSize() ) ); |
| Bitmap aBitmap( aBitmapEx.GetBitmap() ); |
| if ( mbGrayScale ) |
| aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS ); |
| Bitmap aMask( aBitmapEx.GetMask() ); |
| Point aPoint = ( (const MetaBmpExScalePartAction*) pMA)->GetDestPoint(); |
| Size aSize = ( (const MetaBmpExScalePartAction*)pMA )->GetDestSize(); |
| ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() ); |
| } |
| break; |
| |
| // Unsupported Actions |
| case META_MASK_ACTION: |
| case META_MASKSCALE_ACTION: |
| case META_MASKSCALEPART_ACTION: |
| { |
| DBG_ERROR( "Unsupported action: MetaMask...Action!" ); |
| } |
| break; |
| |
| case META_GRADIENT_ACTION : |
| { |
| PolyPolygon aPolyPoly( ( (const MetaGradientAction*)pMA)->GetRect() ); |
| ImplWriteGradient( aPolyPoly, ( (const MetaGradientAction*) pMA )->GetGradient(), rVDev ); |
| } |
| break; |
| |
| case META_GRADIENTEX_ACTION : |
| { |
| PolyPolygon aPolyPoly( ( (const MetaGradientExAction*)pMA)->GetPolyPolygon() ); |
| ImplWriteGradient( aPolyPoly, ( (const MetaGradientExAction*) pMA )->GetGradient(), rVDev ); |
| } |
| break; |
| |
| case META_HATCH_ACTION : |
| { |
| VirtualDevice l_aVDev; |
| GDIMetaFile aTmpMtf; |
| |
| l_aVDev.SetMapMode( rVDev.GetMapMode() ); |
| l_aVDev.AddHatchActions( ( (const MetaHatchAction*)pMA)->GetPolyPolygon(), |
| ( (const MetaHatchAction*)pMA )->GetHatch(), aTmpMtf ); |
| ImplWriteActions( aTmpMtf, rVDev ); |
| } |
| break; |
| |
| case META_WALLPAPER_ACTION : |
| { |
| const MetaWallpaperAction* pA = (const MetaWallpaperAction*)pMA; |
| Rectangle aRect = pA->GetRect(); |
| Wallpaper aWallpaper = pA->GetWallpaper(); |
| |
| if ( aWallpaper.IsBitmap() ) |
| { |
| BitmapEx aBitmapEx = aWallpaper.GetBitmap(); |
| Bitmap aBitmap( aBitmapEx.GetBitmap() ); |
| if ( aBitmapEx.IsTransparent() ) |
| { |
| if ( aWallpaper.IsGradient() ) |
| { |
| |
| // gradient action |
| |
| } |
| Bitmap aMask( aBitmapEx.GetMask() ); |
| ImplBmp( &aBitmap, &aMask, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() ); |
| } |
| else |
| ImplBmp( &aBitmap, NULL, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() ); |
| |
| // wallpaper Style |
| |
| } |
| else if ( aWallpaper.IsGradient() ) |
| { |
| |
| // gradient action |
| |
| } |
| else |
| { |
| aColor = aWallpaper.GetColor(); |
| ImplRectFill( aRect ); |
| } |
| } |
| break; |
| |
| case META_ISECTRECTCLIPREGION_ACTION: |
| { |
| const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA; |
| Region aRegion( pA->GetRect() ); |
| ImplSetClipRegion( aRegion ); |
| } |
| break; |
| |
| case META_CLIPREGION_ACTION: |
| { |
| const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pMA; |
| Region aRegion( pA->GetRegion() ); |
| ImplSetClipRegion( aRegion ); |
| } |
| break; |
| |
| case META_ISECTREGIONCLIPREGION_ACTION: |
| { |
| const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pMA; |
| Region aRegion( pA->GetRegion() ); |
| ImplSetClipRegion( aRegion ); |
| } |
| break; |
| |
| case META_MOVECLIPREGION_ACTION: |
| { |
| /* |
| if ( !aClipRegion.IsEmpty() ) |
| { |
| const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pMA; |
| aClipRegion.Move( pA->GetHorzMove(), pA->GetVertMove() ); |
| ImplSetClipRegion(); |
| } |
| */ |
| } |
| break; |
| |
| case META_LINECOLOR_ACTION : |
| { |
| if ( ( (const MetaLineColorAction*) pMA)->IsSetting() ) |
| { |
| bLineColor = sal_True; |
| aLineColor = ( (const MetaLineColorAction*) pMA )->GetColor(); |
| } |
| else |
| bLineColor = sal_False; |
| } |
| break; |
| |
| case META_FILLCOLOR_ACTION : |
| { |
| if ( ( (const MetaFillColorAction*) pMA )->IsSetting() ) |
| { |
| bFillColor = sal_True; |
| aFillColor = ( (const MetaFillColorAction*) pMA )->GetColor(); |
| } |
| else |
| bFillColor = sal_False; |
| } |
| break; |
| |
| case META_TEXTCOLOR_ACTION : |
| { |
| aTextColor = ( (const MetaTextColorAction*) pMA )->GetColor(); |
| } |
| break; |
| |
| case META_TEXTFILLCOLOR_ACTION : |
| { |
| if ( ( (const MetaTextFillColorAction*) pMA )->IsSetting() ) |
| { |
| bTextFillColor = sal_True; |
| aTextFillColor = ( (const MetaTextFillColorAction*) pMA )->GetColor(); |
| } |
| else |
| bTextFillColor = sal_False; |
| } |
| break; |
| |
| case META_TEXTALIGN_ACTION : |
| { |
| eTextAlign = ( (const MetaTextAlignAction*) pMA )->GetTextAlign(); |
| } |
| break; |
| |
| case META_MAPMODE_ACTION : |
| { |
| pMA->Execute( &rVDev ); |
| ImplGetMapMode( rVDev.GetMapMode() ); |
| } |
| break; |
| |
| case META_FONT_ACTION : |
| { |
| maFont = ((const MetaFontAction*)pMA)->GetFont(); |
| rVDev.SetFont( maFont ); |
| } |
| break; |
| |
| case META_PUSH_ACTION : |
| { |
| rVDev.Push(((const MetaPushAction*)pMA)->GetFlags() ); |
| StackMember* pGS = new StackMember; |
| pGS->pSucc = pGDIStack; |
| pGDIStack = pGS; |
| pGS->aDashArray = aDashArray; |
| pGS->eJoinType = eJoinType; |
| pGS->eLineCap = eLineCap; |
| pGS->fLineWidth = fLineWidth; |
| pGS->fMiterLimit = fMiterLimit; |
| pGS->eTextAlign = eTextAlign; |
| pGS->aGlobalCol = aColor; |
| pGS->bLineCol = bLineColor; |
| pGS->aLineCol = aLineColor; |
| pGS->bFillCol = bFillColor; |
| pGS->aFillCol = aFillColor; |
| pGS->aTextCol = aTextColor; |
| pGS->bTextFillCol = bTextFillColor; |
| pGS->aTextFillCol = aTextFillColor; |
| pGS->aBackgroundCol = aBackgroundColor; |
| bRegionChanged = sal_False; |
| pGS->aFont = maFont; |
| mnLatestPush = mpPS->Tell(); |
| ImplWriteLine( "gs" ); |
| } |
| break; |
| |
| case META_POP_ACTION : |
| { |
| rVDev.Pop(); |
| StackMember* pGS; |
| if( pGDIStack ) |
| { |
| pGS = pGDIStack; |
| pGDIStack = pGS->pSucc; |
| aDashArray = pGS->aDashArray; |
| eJoinType = pGS->eJoinType; |
| eLineCap = pGS->eLineCap; |
| fLineWidth = pGS->fLineWidth; |
| fMiterLimit = pGS->fMiterLimit; |
| eTextAlign = pGS->eTextAlign; |
| aColor = pGS->aGlobalCol; |
| bLineColor = pGS->bLineCol; |
| aLineColor = pGS->aLineCol; |
| bFillColor = pGS->bFillCol; |
| aFillColor = pGS->aFillCol; |
| aTextColor = pGS->aTextCol; |
| bTextFillColor = pGS->bTextFillCol; |
| aTextFillColor = pGS->aTextFillCol; |
| aBackgroundColor = pGS->aBackgroundCol; |
| maFont = pGS->aFont; |
| maLastFont = Font(); // set maLastFont != maFont -> so that |
| delete pGS; |
| sal_uInt32 nCurrentPos = mpPS->Tell(); |
| if ( nCurrentPos - 3 == mnLatestPush ) |
| { |
| mpPS->Seek( mnLatestPush ); |
| ImplWriteLine( " " ); |
| mpPS->Seek( mnLatestPush ); |
| } |
| else |
| ImplWriteLine( "gr" ); |
| } |
| } |
| break; |
| |
| case META_EPS_ACTION : |
| { |
| GfxLink aGfxLink = ( (const MetaEPSAction*) pMA )->GetLink(); |
| const GDIMetaFile aSubstitute( ( ( const MetaEPSAction*) pMA )->GetSubstitute() ); |
| |
| sal_Bool bLevelConflict = sal_False; |
| sal_uInt8* pSource = (sal_uInt8*) aGfxLink.GetData(); |
| sal_uLong nSize = aGfxLink.GetDataSize(); |
| sal_uLong nParseThis = POSTSCRIPT_BOUNDINGSEARCH; |
| if ( nSize < 64 ) // assuming eps is larger than 64 bytes |
| pSource = NULL; |
| if ( nParseThis > nSize ) |
| nParseThis = nSize; |
| |
| if ( pSource && ( mnLevel == 1 ) ) |
| { |
| sal_uInt8* pFound = ImplSearchEntry( pSource, (sal_uInt8*)"%%LanguageLevel:", nParseThis - 10, 16 ); |
| if ( pFound ) |
| { |
| sal_uInt8 k, i = 10; |
| pFound += 16; |
| while ( --i ) |
| { |
| k = *pFound++; |
| if ( ( k > '0' ) && ( k <= '9' ) ) |
| { |
| if ( k != '1' ) |
| { |
| bLevelConflict = sal_True; |
| mnLevelWarning++; |
| } |
| break; |
| } |
| } |
| } |
| } |
| if ( !bLevelConflict ) |
| { |
| double nBoundingBox[4]; |
| if ( pSource && ImplGetBoundingBox( nBoundingBox, pSource, nParseThis ) ) |
| { |
| Point aPoint = ( (const MetaEPSAction*) pMA )->GetPoint(); |
| Size aSize = ( (const MetaEPSAction*) pMA )->GetSize(); |
| |
| MapMode aMapMode( aSubstitute.GetPrefMapMode() ); |
| Size aOutSize( rVDev.LogicToLogic( aSize, rVDev.GetMapMode(), aMapMode ) ); |
| Point aOrigin( rVDev.LogicToLogic( aPoint, rVDev.GetMapMode(), aMapMode ) ); |
| aOrigin.Y() += aOutSize.Height(); |
| aMapMode.SetOrigin( aOrigin ); |
| aMapMode.SetScaleX( aOutSize.Width() / ( nBoundingBox[ 2 ] - nBoundingBox[ 0 ] ) ); |
| aMapMode.SetScaleY( aOutSize.Height() / ( nBoundingBox[ 3 ] - nBoundingBox[ 1 ] ) ); |
| ImplWriteLine( "gs" ); |
| ImplGetMapMode( aMapMode ); |
| ImplWriteLine( "%%BeginDocument:" ); |
| mpPS->Write( pSource, aGfxLink.GetDataSize() ); |
| ImplWriteLine( "%%EndDocument\ngr" ); |
| } |
| } |
| } |
| break; |
| |
| case META_TRANSPARENT_ACTION: |
| { |
| // ImplLine( ( (const MetaTransparentAction*) pMA )->GetPolyPolygon() ); |
| } |
| break; |
| |
| case META_RASTEROP_ACTION: |
| { |
| pMA->Execute( &rVDev ); |
| } |
| 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 ); |
| |
| ImplWriteActions( aTmpMtf, rVDev ); |
| } |
| break; |
| |
| case META_COMMENT_ACTION: |
| { |
| const MetaCommentAction* pA = (const MetaCommentAction*) pMA; |
| if ( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL ) |
| { |
| const MetaGradientExAction* pGradAction = NULL; |
| while( ++nCurAction < nCount ) |
| { |
| MetaAction* pAction = rMtf.GetAction( nCurAction ); |
| if( pAction->GetType() == META_GRADIENTEX_ACTION ) |
| pGradAction = (const MetaGradientExAction*) pAction; |
| else if( ( pAction->GetType() == META_COMMENT_ACTION ) && |
| ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) ) |
| { |
| break; |
| } |
| } |
| if( pGradAction ) |
| ImplWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), rVDev ); |
| } |
| else if ( pA->GetComment().Equals( "XPATHFILL_SEQ_END" ) ) |
| { |
| if ( aFillPath.Count() ) |
| { |
| aFillPath = PolyPolygon(); |
| ImplWriteLine( "gr" ); |
| } |
| } |
| else |
| { |
| const sal_uInt8* pData = pA->GetData(); |
| if ( pData ) |
| { |
| SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ ); |
| sal_Bool bSkipSequence = sal_False; |
| ByteString sSeqEnd; |
| |
| if( pA->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ) ) |
| { |
| sSeqEnd = ByteString( "XPATHSTROKE_SEQ_END" ); |
| SvtGraphicStroke aStroke; |
| aMemStm >> aStroke; |
| |
| Polygon aPath; |
| aStroke.getPath( aPath ); |
| |
| PolyPolygon aStartArrow; |
| PolyPolygon aEndArrow; |
| // double fTransparency( aStroke.getTransparency() ); |
| double fStrokeWidth( aStroke.getStrokeWidth() ); |
| SvtGraphicStroke::JoinType eJT( aStroke.getJoinType() ); |
| SvtGraphicStroke::DashArray l_aDashArray; |
| |
| aStroke.getStartArrow( aStartArrow ); |
| aStroke.getEndArrow( aEndArrow ); |
| aStroke.getDashArray( l_aDashArray ); |
| |
| bSkipSequence = sal_True; |
| if ( l_aDashArray.size() > 11 ) // ps dasharray limit is 11 |
| bSkipSequence = sal_False; |
| if ( aStartArrow.Count() || aEndArrow.Count() ) |
| bSkipSequence = sal_False; |
| if ( (sal_uInt32)eJT > 2 ) |
| bSkipSequence = sal_False; |
| if ( l_aDashArray.size() && ( fStrokeWidth != 0.0 ) ) |
| bSkipSequence = sal_False; |
| if ( bSkipSequence ) |
| { |
| ImplWriteLineInfo( fStrokeWidth, aStroke.getMiterLimit(), |
| aStroke.getCapType(), eJT, l_aDashArray ); |
| ImplPolyLine( aPath ); |
| } |
| } |
| else if( pA->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) ) |
| { |
| sSeqEnd = ByteString( "XPATHFILL_SEQ_END" ); |
| SvtGraphicFill aFill; |
| aMemStm >> aFill; |
| switch( aFill.getFillType() ) |
| { |
| case SvtGraphicFill::fillSolid : |
| { |
| bSkipSequence = sal_True; |
| PolyPolygon aPolyPoly; |
| aFill.getPath( aPolyPoly ); |
| sal_uInt16 i, nPolyCount = aPolyPoly.Count(); |
| if ( nPolyCount ) |
| { |
| aFillColor = aFill.getFillColor(); |
| ImplWriteFillColor( PS_SPACE ); |
| for ( i = 0; i < nPolyCount; ) |
| { |
| ImplAddPath( aPolyPoly.GetObject( i ) ); |
| if ( ++i < nPolyCount ) |
| { |
| *mpPS << "p"; |
| mnCursorPos += 2; |
| ImplExecMode( PS_RET ); |
| } |
| } |
| *mpPS << "p ef"; |
| mnCursorPos += 4; |
| ImplExecMode( PS_RET ); |
| } |
| } |
| break; |
| |
| case SvtGraphicFill::fillTexture : |
| { |
| aFill.getPath( aFillPath ); |
| |
| /* normally an object filling is consisting of three MetaActions: |
| MetaBitmapAction using RasterOp xor, |
| MetaPolyPolygonAction using RasterOp rop_0 |
| MetaBitmapAction using RasterOp xor |
| |
| Because RasterOps cannot been used in Postscript, we have to |
| replace these actions. The MetaComment "XPATHFILL_SEQ_BEGIN" is |
| providing the clippath of the object. The following loop is |
| trying to find the bitmap that is matching the clippath, so that |
| only one bitmap is exported, otherwise if the bitmap is not |
| locatable, all metaactions are played normally. |
| */ |
| sal_uInt32 nCommentStartAction = nCurAction; |
| sal_uInt32 nBitmapCount = 0; |
| sal_uInt32 nBitmapAction = 0; |
| |
| sal_Bool bOk = sal_True; |
| while( bOk && ( ++nCurAction < nCount ) ) |
| { |
| MetaAction* pAction = rMtf.GetAction( nCurAction ); |
| switch( pAction->GetType() ) |
| { |
| case META_BMPSCALE_ACTION : |
| case META_BMPSCALEPART_ACTION : |
| case META_BMPEXSCALE_ACTION : |
| case META_BMPEXSCALEPART_ACTION : |
| { |
| nBitmapCount++; |
| nBitmapAction = nCurAction; |
| } |
| break; |
| case META_COMMENT_ACTION : |
| { |
| if (((const MetaCommentAction*)pAction)->GetComment().Equals( "XPATHFILL_SEQ_END" )) |
| bOk = sal_False; |
| } |
| break; |
| } |
| } |
| if( nBitmapCount == 2 ) |
| { |
| ImplWriteLine( "gs" ); |
| ImplIntersect( aFillPath ); |
| GDIMetaFile aTempMtf; |
| aTempMtf.AddAction( rMtf.GetAction( nBitmapAction )->Clone() ); |
| ImplWriteActions( aTempMtf, rVDev ); |
| ImplWriteLine( "gr" ); |
| aFillPath = PolyPolygon(); |
| } |
| else |
| nCurAction = nCommentStartAction + 1; |
| } |
| break; |
| |
| case SvtGraphicFill::fillGradient : |
| aFill.getPath( aFillPath ); |
| break; |
| |
| case SvtGraphicFill::fillHatch : |
| break; |
| } |
| if ( aFillPath.Count() ) |
| { |
| ImplWriteLine( "gs" ); |
| ImplIntersect( aFillPath ); |
| } |
| } |
| if ( bSkipSequence ) |
| { |
| while( ++nCurAction < nCount ) |
| { |
| pMA = rMtf.GetAction( nCurAction ); |
| if ( pMA->GetType() == META_COMMENT_ACTION ) |
| { |
| ByteString sComment( ((MetaCommentAction*)pMA)->GetComment() ); |
| if ( sComment.Equals( sSeqEnd ) ) |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| break; |
| |
| } |
| } |
| } |
| |
| |
| |
| //--------------------------------------------------------------------------------- |
| |
| inline void PSWriter::ImplWritePoint( const Point& rPoint, sal_uInt32 nMode ) |
| { |
| ImplWriteDouble( rPoint.X() ); |
| ImplWriteDouble( rPoint.Y(), nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplMoveTo( const Point& rPoint, sal_uInt32 nMode ) |
| { |
| ImplWritePoint( rPoint ); |
| ImplWriteByte( 'm' ); |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplLineTo( const Point& rPoint, sal_uInt32 nMode ) |
| { |
| ImplWritePoint( rPoint ); |
| ImplWriteByte( 'l' ); |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode ) |
| { |
| ImplWritePoint( rP1 ); |
| ImplWritePoint( rP2 ); |
| ImplWritePoint( rP3 ); |
| *mpPS << "ct "; |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode ) |
| { |
| ImplWriteDouble( fX ); |
| ImplWriteDouble( fY ); |
| ImplWriteByte( 't' ); |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplScale( const double& fX, const double& fY, sal_uInt32 nMode ) |
| { |
| ImplWriteDouble( fX ); |
| ImplWriteDouble( fY ); |
| ImplWriteByte( 's' ); |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplRect( const Rectangle & rRect ) |
| { |
| if ( bFillColor ) |
| ImplRectFill( rRect ); |
| if ( bLineColor ) |
| { |
| double nWidth = rRect.GetWidth(); |
| double nHeight = rRect.GetHeight(); |
| |
| ImplWriteLineColor( PS_SPACE ); |
| ImplMoveTo( rRect.TopLeft() ); |
| ImplWriteDouble( nWidth ); |
| *mpPS << "0 rl 0 "; |
| ImplWriteDouble( nHeight ); |
| *mpPS << "rl "; |
| ImplWriteDouble( nWidth ); |
| *mpPS << "neg 0 rl "; |
| ImplClosePathDraw(); |
| } |
| *mpPS << (sal_uInt8)10; |
| mnCursorPos = 0; |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplRectFill( const Rectangle & rRect ) |
| { |
| double nWidth = rRect.GetWidth(); |
| double nHeight = rRect.GetHeight(); |
| |
| ImplWriteFillColor( PS_SPACE ); |
| ImplMoveTo( rRect.TopLeft() ); |
| ImplWriteDouble( nWidth ); |
| *mpPS << "0 rl 0 "; |
| ImplWriteDouble( nHeight ); |
| *mpPS << "rl "; |
| ImplWriteDouble( nWidth ); |
| *mpPS << "neg 0 rl ef "; |
| *mpPS << "p ef"; |
| mnCursorPos += 2; |
| ImplExecMode( PS_RET ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplAddPath( const Polygon & rPolygon ) |
| { |
| sal_uInt16 i = 1; |
| sal_uInt16 nPointCount = rPolygon.GetSize(); |
| if ( nPointCount > 1 ) |
| { |
| ImplMoveTo( rPolygon.GetPoint( 0 ) ); |
| while ( i < nPointCount ) |
| { |
| if ( ( rPolygon.GetFlags( i ) == POLY_CONTROL ) |
| && ( ( i + 2 ) < nPointCount ) |
| && ( rPolygon.GetFlags( i + 1 ) == POLY_CONTROL ) |
| && ( rPolygon.GetFlags( i + 2 ) != POLY_CONTROL ) ) |
| { |
| ImplCurveTo( rPolygon[ i ], rPolygon[ i + 1 ], rPolygon[ i + 2 ], PS_WRAP ); |
| i += 3; |
| } |
| else |
| ImplLineTo( rPolygon.GetPoint( i++ ), PS_SPACE | PS_WRAP ); |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplIntersect( const PolyPolygon& rPolyPoly ) |
| { |
| sal_uInt16 i, nPolyCount = rPolyPoly.Count(); |
| for ( i = 0; i < nPolyCount; ) |
| { |
| ImplAddPath( rPolyPoly.GetObject( i ) ); |
| if ( ++i < nPolyCount ) |
| { |
| *mpPS << "p"; |
| mnCursorPos += 2; |
| ImplExecMode( PS_RET ); |
| } |
| } |
| ImplWriteLine( "eoclip newpath" ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev ) |
| { |
| VirtualDevice l_aVDev; |
| GDIMetaFile aTmpMtf; |
| l_aVDev.SetMapMode( rVDev.GetMapMode() ); |
| l_aVDev.AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf ); |
| ImplWriteActions( aTmpMtf, rVDev ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplPolyPoly( const PolyPolygon & rPolyPoly, sal_Bool bTextOutline ) |
| { |
| sal_uInt16 i, nPolyCount = rPolyPoly.Count(); |
| if ( nPolyCount ) |
| { |
| if ( bFillColor || bTextOutline ) |
| { |
| if ( bTextOutline ) |
| ImplWriteTextColor( PS_SPACE ); |
| else |
| ImplWriteFillColor( PS_SPACE ); |
| for ( i = 0; i < nPolyCount; ) |
| { |
| ImplAddPath( rPolyPoly.GetObject( i ) ); |
| if ( ++i < nPolyCount ) |
| { |
| *mpPS << "p"; |
| mnCursorPos += 2; |
| ImplExecMode( PS_RET ); |
| } |
| } |
| *mpPS << "p ef"; |
| mnCursorPos += 4; |
| ImplExecMode( PS_RET ); |
| } |
| if ( bLineColor ) |
| { |
| ImplWriteLineColor( PS_SPACE ); |
| for ( i = 0; i < nPolyCount; i++ ) |
| ImplAddPath( rPolyPoly.GetObject( i ) ); |
| ImplClosePathDraw( PS_RET ); |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplPolyLine( const Polygon & rPoly ) |
| { |
| if ( bLineColor ) |
| { |
| ImplWriteLineColor( PS_SPACE ); |
| sal_uInt16 i, nPointCount = rPoly.GetSize(); |
| if ( nPointCount ) |
| { |
| if ( nPointCount > 1 ) |
| { |
| ImplMoveTo( rPoly.GetPoint( 0 ) ); |
| i = 1; |
| while ( i < nPointCount ) |
| { |
| if ( ( rPoly.GetFlags( i ) == POLY_CONTROL ) |
| && ( ( i + 2 ) < nPointCount ) |
| && ( rPoly.GetFlags( i + 1 ) == POLY_CONTROL ) |
| && ( rPoly.GetFlags( i + 2 ) != POLY_CONTROL ) ) |
| { |
| ImplCurveTo( rPoly[ i ], rPoly[ i + 1 ], rPoly[ i + 2 ], PS_WRAP ); |
| i += 3; |
| } |
| else |
| ImplLineTo( rPoly.GetPoint( i++ ), PS_SPACE | PS_WRAP ); |
| } |
| } |
| |
| // #104645# explicitely close path if polygon is closed |
| if( rPoly[ 0 ] == rPoly[ nPointCount-1 ] ) |
| ImplClosePathDraw( PS_RET ); |
| else |
| ImplPathDraw(); |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplSetClipRegion( Region& rClipRegion ) |
| { |
| if ( !rClipRegion.IsEmpty() ) |
| { |
| RectangleVector aRectangles; |
| rClipRegion.GetRegionRectangles(aRectangles); |
| |
| for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) |
| { |
| double nX1(aRectIter->Left()); |
| double nY1(aRectIter->Top()); |
| double nX2(aRectIter->Right()); |
| double nY2(aRectIter->Bottom()); |
| |
| ImplWriteDouble( nX1 ); |
| ImplWriteDouble( nY1 ); |
| ImplWriteByte( 'm' ); |
| ImplWriteDouble( nX2 ); |
| ImplWriteDouble( nY1 ); |
| ImplWriteByte( 'l' ); |
| ImplWriteDouble( nX2 ); |
| ImplWriteDouble( nY2 ); |
| ImplWriteByte( 'l' ); |
| ImplWriteDouble( nX1 ); |
| ImplWriteDouble( nY2 ); |
| ImplWriteByte( 'l' ); |
| ImplWriteDouble( nX1 ); |
| ImplWriteDouble( nY1 ); |
| ImplWriteByte( 'l', PS_SPACE | PS_WRAP ); |
| } |
| |
| //Rectangle aRect; |
| //RegionHandle hRegionHandle = rClipRegion.BeginEnumRects(); |
| // |
| //while ( rClipRegion.GetEnumRects( hRegionHandle, aRect ) ) |
| //{ |
| // double nX1 = aRect.Left(); |
| // double nY1 = aRect.Top(); |
| // double nX2 = aRect.Right(); |
| // double nY2 = aRect.Bottom(); |
| // ImplWriteDouble( nX1 ); |
| // ImplWriteDouble( nY1 ); |
| // ImplWriteByte( 'm' ); |
| // ImplWriteDouble( nX2 ); |
| // ImplWriteDouble( nY1 ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteDouble( nX2 ); |
| // ImplWriteDouble( nY2 ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteDouble( nX1 ); |
| // ImplWriteDouble( nY2 ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteDouble( nX1 ); |
| // ImplWriteDouble( nY1 ); |
| // ImplWriteByte( 'l', PS_SPACE | PS_WRAP ); |
| //}; |
| //rClipRegion.EndEnumRects( hRegionHandle ); |
| ImplWriteLine( "eoclip newpath" ); |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| // possible gfx formats: |
| // |
| // level 1: grayscale 8 bit |
| // color 24 bit |
| // |
| // level 2: grayscale 8 bit |
| // color 1(pal), 4(pal), 8(pal), 24 Bit |
| // |
| |
| void PSWriter::ImplBmp( Bitmap* pBitmap, Bitmap* pMaskBitmap, const Point & rPoint, double nXWidth, double nYHeightOrg ) |
| { |
| if ( !pBitmap ) |
| return; |
| |
| sal_Int32 nHeightOrg = pBitmap->GetSizePixel().Height(); |
| sal_Int32 nHeightLeft = nHeightOrg; |
| long nWidth = pBitmap->GetSizePixel().Width(); |
| Point aSourcePos( rPoint ); |
| |
| while ( nHeightLeft ) |
| { |
| Bitmap aTileBitmap( *pBitmap ); |
| long nHeight = nHeightLeft; |
| double nYHeight = nYHeightOrg; |
| |
| sal_Bool bDoTrans = sal_False; |
| |
| Rectangle aRect; |
| Region aRegion; |
| |
| if ( pMaskBitmap ) |
| { |
| bDoTrans = sal_True; |
| while (sal_True) |
| { |
| if ( mnLevel == 1 ) |
| { |
| if ( nHeight > 10 ) |
| nHeight = 8; |
| } |
| aRect = Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( (long)nWidth, (long)nHeight ) ); |
| aRegion = Region( pMaskBitmap->CreateRegion( COL_BLACK, aRect ) ); |
| |
| if( mnLevel == 1 ) |
| { |
| RectangleVector aRectangleVector; |
| aRegion.GetRegionRectangles(aRectangleVector); |
| |
| if ( aRectangleVector.size() * 5 > 1000 ) |
| { |
| nHeight >>= 1; |
| if ( nHeight < 2 ) |
| return; |
| continue; |
| } |
| } |
| break; |
| } |
| } |
| if ( nHeight != nHeightOrg ) |
| { |
| nYHeight = nYHeightOrg * nHeight / nHeightOrg; |
| aTileBitmap.Crop( Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( nWidth, nHeight ) ) ); |
| } |
| if ( bDoTrans ) |
| { |
| ImplWriteLine( "gs\npum" ); |
| ImplTranslate( aSourcePos.X(), aSourcePos.Y() ); |
| ImplScale( nXWidth / nWidth, nYHeight / nHeight ); |
| |
| RectangleVector aRectangles; |
| aRegion.GetRegionRectangles(aRectangles); |
| const long nMoveVertical(nHeightLeft - nHeightOrg); |
| |
| for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) |
| { |
| aRectIter->Move(0, nMoveVertical); |
| |
| ImplWriteLong( aRectIter->Left() ); |
| ImplWriteLong( aRectIter->Top() ); |
| ImplWriteByte( 'm' ); |
| ImplWriteLong( aRectIter->Right() + 1 ); |
| ImplWriteLong( aRectIter->Top() ); |
| ImplWriteByte( 'l' ); |
| ImplWriteLong( aRectIter->Right() + 1 ); |
| ImplWriteLong( aRectIter->Bottom() + 1 ); |
| ImplWriteByte( 'l' ); |
| ImplWriteLong( aRectIter->Left() ); |
| ImplWriteLong( aRectIter->Bottom() + 1 ); |
| ImplWriteByte( 'l' ); |
| ImplWriteByte( 'p', PS_SPACE | PS_WRAP ); |
| } |
| |
| //RegionHandle hRegionHandle = aRegion.BeginEnumRects(); |
| // |
| //while ( aRegion.GetEnumRects( hRegionHandle, aRect ) ) |
| //{ |
| // aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) ); |
| // ImplWriteLong( aRect.Left() ); |
| // ImplWriteLong( aRect.Top() ); |
| // ImplWriteByte( 'm' ); |
| // ImplWriteLong( aRect.Right() + 1 ); |
| // ImplWriteLong( aRect.Top() ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteLong( aRect.Right() + 1 ); |
| // ImplWriteLong( aRect.Bottom() + 1 ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteLong( aRect.Left() ); |
| // ImplWriteLong( aRect.Bottom() + 1 ); |
| // ImplWriteByte( 'l' ); |
| // ImplWriteByte( 'p', PS_SPACE | PS_WRAP ); |
| //}; |
| //aRegion.EndEnumRects( hRegionHandle ); |
| ImplWriteLine( "eoclip newpath" ); |
| ImplWriteLine( "pom" ); |
| } |
| BitmapReadAccess* pAcc = aTileBitmap.AcquireReadAccess(); |
| |
| if (!bDoTrans ) |
| ImplWriteLine( "pum" ); |
| |
| ImplTranslate( aSourcePos.X(), aSourcePos.Y() + nYHeight ); |
| ImplScale( nXWidth, nYHeight ); |
| if ( mnLevel == 1 ) // level 1 is always grayscale !!! |
| { |
| ImplWriteLong( nWidth ); |
| ImplWriteLong( nHeight ); |
| *mpPS << "8 ["; |
| ImplWriteLong( nWidth ); |
| *mpPS << "0 0 "; |
| ImplWriteLong( -nHeight ); |
| ImplWriteLong( 0 ); |
| ImplWriteLong( nHeight ); |
| ImplWriteLine( "]" ); |
| *mpPS << "{currentfile "; |
| ImplWriteLong( nWidth ); |
| ImplWriteLine( "string readhexstring pop}" ); |
| ImplWriteLine( "image" ); |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) ); |
| } |
| } |
| *mpPS << (sal_uInt8)10; |
| } |
| else // Level 2 |
| { |
| if ( mbGrayScale ) |
| { |
| ImplWriteLine( "/DeviceGray setcolorspace" ); |
| ImplWriteLine( "<<" ); |
| ImplWriteLine( "/ImageType 1" ); |
| *mpPS << "/Width "; |
| ImplWriteLong( nWidth, PS_RET ); |
| *mpPS << "/Height "; |
| ImplWriteLong( nHeight, PS_RET ); |
| ImplWriteLine( "/BitsPerComponent 8" ); |
| ImplWriteLine( "/Decode[0 1]" ); |
| *mpPS << "/ImageMatrix["; |
| ImplWriteLong( nWidth ); |
| *mpPS << "0 0 "; |
| ImplWriteLong( -nHeight ); |
| ImplWriteLong( 0 ); |
| ImplWriteLong( nHeight, PS_NONE ); |
| ImplWriteByte( ']', PS_RET ); |
| ImplWriteLine( "/DataSource currentfile" ); |
| ImplWriteLine( "/ASCIIHexDecode filter" ); |
| if ( mbCompression ) |
| ImplWriteLine( "/LZWDecode filter" ); |
| ImplWriteLine( ">>" ); |
| ImplWriteLine( "image" ); |
| if ( mbCompression ) |
| { |
| StartCompression(); |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| Compress( pAcc->GetPixelIndex( y, x ) ); |
| } |
| } |
| EndCompression(); |
| } |
| else |
| { |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) ); |
| } |
| } |
| } |
| } |
| else |
| { |
| // have we to write a palette ? |
| |
| if ( pAcc->HasPalette() ) |
| { |
| ImplWriteLine( "[/Indexed /DeviceRGB " ); |
| ImplWriteLong( pAcc->GetPaletteEntryCount() - 1, PS_RET ); |
| ImplWriteByte( '<', PS_NONE ); |
| for ( sal_uInt16 i = 0; i < pAcc->GetPaletteEntryCount(); i++ ) |
| { |
| BitmapColor aBitmapColor = pAcc->GetPaletteColor( i ); |
| ImplWriteHexByte( aBitmapColor.GetRed(), PS_NONE ); |
| ImplWriteHexByte( aBitmapColor.GetGreen(), PS_NONE ); |
| ImplWriteHexByte( aBitmapColor.GetBlue(), PS_SPACE | PS_WRAP ); |
| } |
| ImplWriteByte( '>', PS_RET ); |
| |
| ImplWriteLine( "] setcolorspace" ); |
| ImplWriteLine( "<<" ); |
| ImplWriteLine( "/ImageType 1" ); |
| *mpPS << "/Width "; |
| ImplWriteLong( nWidth, PS_RET ); |
| *mpPS << "/Height "; |
| ImplWriteLong( nHeight, PS_RET ); |
| ImplWriteLine( "/BitsPerComponent 8" ); |
| ImplWriteLine( "/Decode[0 255]" ); |
| *mpPS << "/ImageMatrix["; |
| ImplWriteLong( nWidth ); |
| *mpPS << "0 0 "; |
| ImplWriteLong( -nHeight ); |
| ImplWriteLong( 0); |
| ImplWriteLong( nHeight, PS_NONE ); |
| ImplWriteByte( ']', PS_RET ); |
| ImplWriteLine( "/DataSource currentfile" ); |
| ImplWriteLine( "/ASCIIHexDecode filter" ); |
| if ( mbCompression ) |
| ImplWriteLine( "/LZWDecode filter" ); |
| ImplWriteLine( ">>" ); |
| ImplWriteLine( "image" ); |
| if ( mbCompression ) |
| { |
| StartCompression(); |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| Compress( pAcc->GetPixelIndex( y, x ) ); |
| } |
| } |
| EndCompression(); |
| } |
| else |
| { |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) ); |
| } |
| } |
| } |
| } |
| else // 24 bit color |
| { |
| ImplWriteLine( "/DeviceRGB setcolorspace" ); |
| ImplWriteLine( "<<" ); |
| ImplWriteLine( "/ImageType 1" ); |
| *mpPS << "/Width "; |
| ImplWriteLong( nWidth, PS_RET ); |
| *mpPS << "/Height "; |
| ImplWriteLong( nHeight, PS_RET ); |
| ImplWriteLine( "/BitsPerComponent 8" ); |
| ImplWriteLine( "/Decode[0 1 0 1 0 1]" ); |
| *mpPS << "/ImageMatrix["; |
| ImplWriteLong( nWidth ); |
| *mpPS << "0 0 "; |
| ImplWriteLong( -nHeight ); |
| ImplWriteLong( 0 ); |
| ImplWriteLong( nHeight, PS_NONE ); |
| ImplWriteByte( ']', PS_RET ); |
| ImplWriteLine( "/DataSource currentfile" ); |
| ImplWriteLine( "/ASCIIHexDecode filter" ); |
| if ( mbCompression ) |
| ImplWriteLine( "/LZWDecode filter" ); |
| ImplWriteLine( ">>" ); |
| ImplWriteLine( "image" ); |
| if ( mbCompression ) |
| { |
| StartCompression(); |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) ); |
| Compress( aBitmapColor.GetRed() ); |
| Compress( aBitmapColor.GetGreen() ); |
| Compress( aBitmapColor.GetBlue() ); |
| } |
| } |
| EndCompression(); |
| } |
| else |
| { |
| for ( long y = 0; y < nHeight; y++ ) |
| { |
| for ( long x = 0; x < nWidth; x++ ) |
| { |
| const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) ); |
| ImplWriteHexByte( aBitmapColor.GetRed() ); |
| ImplWriteHexByte( aBitmapColor.GetGreen() ); |
| ImplWriteHexByte( aBitmapColor.GetBlue() ); |
| } |
| } |
| } |
| } |
| } |
| ImplWriteLine( ">" ); // in Level 2 the dictionary needs to be closed (eod) |
| } |
| if ( bDoTrans ) |
| ImplWriteLine( "gr" ); |
| else |
| ImplWriteLine( "pom" ); |
| |
| aTileBitmap.ReleaseAccess( pAcc ); |
| nHeightLeft -= nHeight; |
| if ( nHeightLeft ) |
| { |
| nHeightLeft++; |
| aSourcePos.Y() = (long) ( rPoint.Y() + ( nYHeightOrg * ( nHeightOrg - nHeightLeft ) ) / nHeightOrg ); |
| } |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteCharacter( sal_Char nChar ) |
| { |
| switch( nChar ) |
| { |
| case '(' : |
| case ')' : |
| case '\\' : |
| ImplWriteByte( (sal_uInt8)'\\', PS_NONE ); |
| } |
| ImplWriteByte( (sal_uInt8)nChar, PS_NONE ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteString( const ByteString& rString, VirtualDevice& rVDev, const sal_Int32* pDXArry, sal_Bool bStretch ) |
| { |
| sal_uInt16 nLen = rString.Len(); |
| if ( nLen ) |
| { |
| sal_uInt16 i; |
| if ( pDXArry ) |
| { |
| double nx = 0; |
| |
| for( i = 0; i < nLen; i++ ) |
| { |
| if ( i > 0 ) |
| nx = pDXArry[ i - 1 ]; |
| ImplWriteDouble( ( bStretch ) ? nx : rVDev.GetTextWidth( rString.GetChar( i ) ) ); |
| ImplWriteDouble( nx ); |
| ImplWriteLine( "(", PS_NONE ); |
| ImplWriteCharacter( rString.GetChar( i ) ); |
| ImplWriteLine( ") bs" ); |
| } |
| } |
| else |
| { |
| ImplWriteByte( '(', PS_NONE ); |
| for ( i = 0; i < nLen; i++ ) |
| ImplWriteCharacter( rString.GetChar( i ) ); |
| ImplWriteLine( ") sw" ); |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void PSWriter::ImplText( const String& rUniString, const Point& rPos, const sal_Int32* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev ) |
| { |
| sal_uInt16 nLen = rUniString.Len(); |
| if ( !nLen ) |
| return; |
| if ( mnTextMode == 0 ) // using glpyh outlines |
| { |
| Font aNotRotatedFont( maFont ); |
| aNotRotatedFont.SetOrientation( 0 ); |
| |
| VirtualDevice aVirDev( 1 ); |
| aVirDev.SetMapMode( rVDev.GetMapMode() ); |
| aVirDev.SetFont( aNotRotatedFont ); |
| aVirDev.SetTextAlign( eTextAlign ); |
| |
| sal_Int16 nRotation = maFont.GetOrientation(); |
| Polygon aPolyDummy( 1 ); |
| |
| PolyPolygon aPolyPoly; |
| Point aPos( rPos ); |
| if ( nRotation ) |
| { |
| aPolyDummy.SetPoint( aPos, 0 ); |
| aPolyDummy.Rotate( rPos, nRotation ); |
| aPos = aPolyDummy.GetPoint( 0 ); |
| } |
| sal_Bool bOldLineColor = bLineColor; |
| bLineColor = sal_False; |
| std::vector<PolyPolygon> aPolyPolyVec; |
| if ( aVirDev.GetTextOutlines( aPolyPolyVec, rUniString, 0, 0, STRING_LEN, sal_True, nWidth, pDXArry ) ) |
| { |
| // always adjust text position to match baseline alignment |
| ImplWriteLine( "pum" ); |
| ImplWriteDouble( aPos.X() ); |
| ImplWriteDouble( aPos.Y() ); |
| ImplWriteLine( "t" ); |
| if ( nRotation ) |
| { |
| ImplWriteF( nRotation, 1 ); |
| *mpPS << "r "; |
| } |
| std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() ); |
| while ( aIter != aPolyPolyVec.end() ) |
| ImplPolyPoly( *aIter++, sal_True ); |
| ImplWriteLine( "pom" ); |
| } |
| bLineColor = bOldLineColor; |
| } |
| else if ( ( mnTextMode == 1 ) || ( mnTextMode == 2 ) ) // normal text output |
| { |
| if ( mnTextMode == 2 ) // forcing output one complete text packet, by |
| pDXArry = NULL; // ignoring the kerning array |
| ImplSetAttrForText( rPos ); |
| ByteString aStr( rUniString, maFont.GetCharSet() ); |
| ImplWriteString( aStr, rVDev, pDXArry, nWidth != 0 ); |
| if ( maFont.GetOrientation() ) |
| ImplWriteLine( "gr" ); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void PSWriter::ImplSetAttrForText( const Point& rPoint ) |
| { |
| Point aPoint( rPoint ); |
| |
| long nRotation = maFont.GetOrientation(); |
| ImplWriteTextColor(); |
| |
| Size aSize = maFont.GetSize(); |
| |
| if ( maLastFont != maFont ) |
| { |
| if ( maFont.GetPitch() == PITCH_FIXED ) // a little bit font selection |
| ImplDefineFont( "Courier", "Oblique" ); |
| else if ( maFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) |
| ImplWriteLine( "/Symbol findfont" ); |
| else if ( maFont.GetFamily() == FAMILY_SWISS ) |
| ImplDefineFont( "Helvetica", "Oblique" ); |
| else |
| ImplDefineFont( "Times", "Italic" ); |
| |
| maLastFont = maFont; |
| aSize = maFont.GetSize(); |
| ImplWriteDouble( aSize.Height() ); |
| *mpPS << "sf "; |
| } |
| if ( eTextAlign != ALIGN_BASELINE ) |
| { // PostScript kennt kein FontAlignment |
| if ( eTextAlign == ALIGN_TOP ) // -> ich gehe daher davon aus, dass |
| aPoint.Y() += ( aSize.Height() * 4 / 5 ); // der Bereich unter der Baseline |
| else if ( eTextAlign == ALIGN_BOTTOM ) // in etwa 20% der Fontsize ausmacht |
| aPoint.Y() -= ( aSize.Height() / 5 ); |
| } |
| ImplMoveTo( aPoint ); |
| if ( nRotation ) |
| { |
| *mpPS << "gs "; |
| ImplWriteF( nRotation, 1 ); |
| *mpPS << "r "; |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplDefineFont( const char* pOriginalName, const char* pItalic ) |
| { |
| *mpPS << (sal_uInt8)'/'; //convert the font pOriginalName using ISOLatin1Encoding |
| *mpPS << pOriginalName; |
| switch ( maFont.GetWeight() ) |
| { |
| case WEIGHT_SEMIBOLD : |
| case WEIGHT_BOLD : |
| case WEIGHT_ULTRABOLD : |
| case WEIGHT_BLACK : |
| *mpPS << "-Bold"; |
| if ( maFont.GetItalic() != ITALIC_NONE ) |
| *mpPS << pItalic; |
| break; |
| default: |
| if ( maFont.GetItalic() != ITALIC_NONE ) |
| *mpPS << pItalic; |
| break; |
| } |
| ImplWriteLine( " f" ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| //--------------------------------------------------------------------------------- |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplClosePathDraw( sal_uLong nMode ) |
| { |
| *mpPS << "pc"; |
| mnCursorPos += 2; |
| ImplExecMode( nMode ); |
| } |
| |
| void PSWriter::ImplPathDraw() |
| { |
| *mpPS << "ps"; |
| mnCursorPos += 2; |
| ImplExecMode( PS_RET ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| inline void PSWriter::ImplWriteLineColor( sal_uLong nMode ) |
| { |
| if ( aColor != aLineColor ) |
| { |
| aColor = aLineColor; |
| ImplWriteColor( nMode ); |
| } |
| } |
| inline void PSWriter::ImplWriteFillColor( sal_uLong nMode ) |
| { |
| if ( aColor != aFillColor ) |
| { |
| aColor = aFillColor; |
| ImplWriteColor( nMode ); |
| } |
| } |
| inline void PSWriter::ImplWriteTextColor( sal_uLong nMode ) |
| { |
| if ( aColor != aTextColor ) |
| { |
| aColor = aTextColor; |
| ImplWriteColor( nMode ); |
| } |
| } |
| inline void PSWriter::ImplWriteTextFillColor( sal_uLong nMode ) |
| { |
| if ( aColor != aTextFillColor ) |
| { |
| aColor = aTextFillColor; |
| ImplWriteColor( nMode ); |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteColor( sal_uLong nMode ) |
| { |
| if ( mbGrayScale ) |
| { |
| // writes the Color (grayscale) as a Number from 0.000 up to 1.000 |
| |
| ImplWriteF( 1000 * ( (sal_uInt8)aColor.GetRed() * 77 + (sal_uInt8)aColor.GetGreen() * 151 + |
| (sal_uInt8)aColor.GetBlue() * 28 + 1 ) / 65536, 3, nMode ); |
| } |
| else |
| { |
| ImplWriteB1 ( (sal_uInt8)aColor.GetRed() ); |
| ImplWriteB1 ( (sal_uInt8)aColor.GetGreen() ); |
| ImplWriteB1 ( (sal_uInt8)aColor.GetBlue() ); |
| } |
| *mpPS << "c"; // ( c is defined as setrgbcolor or setgray ) |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| double PSWriter::ImplGetScaling( const MapMode& rMapMode ) |
| { |
| double nMul; |
| switch ( rMapMode.GetMapUnit() ) |
| { |
| case MAP_PIXEL : |
| case MAP_SYSFONT : |
| case MAP_APPFONT : |
| |
| case MAP_100TH_MM : |
| nMul = 1; |
| break; |
| case MAP_10TH_MM : |
| nMul = 10; |
| break; |
| case MAP_MM : |
| nMul = 100; |
| break; |
| case MAP_CM : |
| nMul = 1000; |
| break; |
| case MAP_1000TH_INCH : |
| nMul = 2.54; |
| break; |
| case MAP_100TH_INCH : |
| nMul = 25.4; |
| break; |
| case MAP_10TH_INCH : |
| nMul = 254; |
| break; |
| case MAP_INCH : |
| nMul = 2540; |
| break; |
| case MAP_TWIP : |
| nMul = 1.76388889; |
| break; |
| case MAP_POINT : |
| nMul = 35.27777778; |
| break; |
| default: |
| nMul = 1.0; |
| break; |
| } |
| return nMul; |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplGetMapMode( const MapMode& rMapMode ) |
| { |
| ImplWriteLine( "tm setmatrix" ); |
| double fMul = ImplGetScaling( rMapMode ); |
| double fScaleX = (double)rMapMode.GetScaleX() * fMul; |
| double fScaleY = (double)rMapMode.GetScaleY() * fMul; |
| ImplTranslate( rMapMode.GetOrigin().X() * fScaleX, rMapMode.GetOrigin().Y() * fScaleY ); |
| ImplScale( fScaleX, fScaleY ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| inline void PSWriter::ImplExecMode( sal_uLong nMode ) |
| { |
| if ( nMode & PS_WRAP ) |
| { |
| if ( mnCursorPos >= PS_LINESIZE ) |
| { |
| mnCursorPos = 0; |
| *mpPS << (sal_uInt8)0xa; |
| return; |
| } |
| } |
| if ( nMode & PS_SPACE ) |
| { |
| *mpPS << (sal_uInt8)32; |
| mnCursorPos++; |
| } |
| if ( nMode & PS_RET ) |
| { |
| *mpPS << (sal_uInt8)0xa; |
| mnCursorPos = 0; |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| inline void PSWriter::ImplWriteLine( const char* pString, sal_uLong nMode ) |
| { |
| sal_uLong i = 0; |
| while ( pString[ i ] ) |
| { |
| *mpPS << (sal_uInt8)pString[ i++ ]; |
| } |
| mnCursorPos += i; |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteLineInfo( double fLWidth, double fMLimit, |
| SvtGraphicStroke::CapType eLCap, |
| SvtGraphicStroke::JoinType eJoin, |
| SvtGraphicStroke::DashArray& rLDash ) |
| { |
| if ( fLineWidth != fLWidth ) |
| { |
| fLineWidth = fLWidth; |
| ImplWriteDouble( fLineWidth ); |
| ImplWriteLine( "lw", PS_SPACE ); |
| } |
| if ( eLineCap != eLCap ) |
| { |
| eLineCap = eLCap; |
| ImplWriteLong( (sal_Int32)eLineCap, PS_SPACE ); |
| ImplWriteLine( "lc", PS_SPACE ); |
| } |
| if ( eJoinType != eJoin ) |
| { |
| eJoinType = eJoin; |
| ImplWriteLong( (sal_Int32)eJoinType, PS_SPACE ); |
| ImplWriteLine( "lj", PS_SPACE ); |
| } |
| if ( eJoinType == SvtGraphicStroke::joinMiter ) |
| { |
| if ( fMiterLimit != fMLimit ) |
| { |
| fMiterLimit = fMLimit; |
| ImplWriteDouble( fMiterLimit ); |
| ImplWriteLine( "ml", PS_SPACE ); |
| } |
| } |
| if ( aDashArray != rLDash ) |
| { |
| aDashArray = rLDash; |
| sal_uInt32 j, i = aDashArray.size(); |
| ImplWriteLine( "[", PS_SPACE ); |
| for ( j = 0; j < i; j++ ) |
| ImplWriteDouble( aDashArray[ j ] ); |
| ImplWriteLine( "] 0 ld" ); |
| } |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteLineInfo( const LineInfo& rLineInfo ) |
| { |
| SvtGraphicStroke::DashArray l_aDashArray; |
| if ( rLineInfo.GetStyle() == LINE_DASH ) |
| l_aDashArray.push_back( 2 ); |
| const double fLWidth(( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5); |
| SvtGraphicStroke::JoinType aJoinType(SvtGraphicStroke::joinMiter); |
| SvtGraphicStroke::CapType aCapType(SvtGraphicStroke::capButt); |
| |
| switch(rLineInfo.GetLineJoin()) |
| { |
| default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE |
| // do NOT use SvtGraphicStroke::joinNone here |
| // since it will be written as numerical value directly |
| // and is NOT a valid EPS value |
| break; |
| case basegfx::B2DLINEJOIN_MITER: |
| aJoinType = SvtGraphicStroke::joinMiter; |
| break; |
| case basegfx::B2DLINEJOIN_BEVEL: |
| aJoinType = SvtGraphicStroke::joinBevel; |
| break; |
| case basegfx::B2DLINEJOIN_ROUND: |
| aJoinType = SvtGraphicStroke::joinRound; |
| break; |
| } |
| |
| switch(rLineInfo.GetLineCap()) |
| { |
| default: /* com::sun::star::drawing::LineCap_BUTT */ |
| { |
| aCapType = SvtGraphicStroke::capButt; |
| break; |
| } |
| case com::sun::star::drawing::LineCap_ROUND: |
| { |
| aCapType = SvtGraphicStroke::capRound; |
| break; |
| } |
| case com::sun::star::drawing::LineCap_SQUARE: |
| { |
| aCapType = SvtGraphicStroke::capSquare; |
| break; |
| } |
| } |
| |
| ImplWriteLineInfo( fLWidth, fMiterLimit, aCapType, aJoinType, l_aDashArray ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteLong( sal_Int32 nNumber, sal_uLong nMode ) |
| { |
| const ByteString aNumber( ByteString::CreateFromInt32( nNumber ) ); |
| sal_uLong nLen = aNumber.Len(); |
| mnCursorPos += nLen; |
| for ( sal_uInt16 n = 0; n < nLen; n++ ) |
| *mpPS << aNumber.GetChar( n ); |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteDouble( double fNumber, sal_uLong nMode ) |
| { |
| sal_Int32 nLength; |
| |
| sal_Int32 nPTemp = (sal_Int32)fNumber; |
| sal_Int32 nATemp = labs( (sal_Int32)( ( fNumber - nPTemp ) * 100000 ) ); |
| |
| if ( !nPTemp && nATemp && ( fNumber < 0.0 ) ) |
| *mpPS << (sal_Char)'-'; |
| |
| ByteString aNumber1( ByteString::CreateFromInt32( nPTemp ) ); |
| nLength = aNumber1.Len(); |
| mnCursorPos += nLength; |
| for ( sal_Int32 n = 0; n < nLength; n++ ) |
| *mpPS << aNumber1.GetChar( (sal_uInt16)n ); |
| |
| int zCount = 0; |
| if ( nATemp ) |
| { |
| *mpPS << (sal_uInt8)'.'; |
| mnCursorPos++; |
| const ByteString aNumber2( ByteString::CreateFromInt32( nATemp ) ); |
| |
| sal_Int16 n, nLen = aNumber2.Len(); |
| if ( nLen < 8 ) |
| { |
| mnCursorPos += 6 - nLen; |
| for ( n = 0; n < ( 5 - nLen ); n++ ) |
| { |
| *mpPS << (sal_uInt8)'0'; |
| } |
| } |
| mnCursorPos += nLen; |
| for ( n = 0; n < nLen; n++ ) |
| { |
| *mpPS << aNumber2.GetChar( n ); |
| zCount--; |
| if ( aNumber2.GetChar( n ) != '0' ) |
| zCount = 0; |
| } |
| if ( zCount ) |
| mpPS->SeekRel( zCount ); |
| } |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| // writes the number to stream: nNumber / ( 10^nCount ) |
| |
| void PSWriter::ImplWriteF( sal_Int32 nNumber, sal_uLong nCount, sal_uLong nMode ) |
| { |
| if ( nNumber < 0 ) |
| { |
| *mpPS << (sal_uInt8)'-'; |
| nNumber = -nNumber; |
| mnCursorPos++; |
| } |
| const ByteString aScaleFactor( ByteString::CreateFromInt32( nNumber ) ); |
| sal_uLong nLen = aScaleFactor.Len(); |
| long nStSize = ( nCount + 1 ) - nLen; |
| if ( nStSize >= 1 ) |
| { |
| *mpPS << (sal_uInt8)'0'; |
| mnCursorPos++; |
| } |
| if ( nStSize >= 2 ) |
| { |
| *mpPS << (sal_uInt8)'.'; |
| for ( long i = 1; i < nStSize; i++ ) |
| { |
| *mpPS << (sal_uInt8)'0'; |
| mnCursorPos++; |
| } |
| } |
| mnCursorPos += nLen; |
| for( sal_uInt16 n = 0UL; n < nLen; n++ ) |
| { |
| if ( n == nLen - nCount ) |
| { |
| *mpPS << (sal_uInt8)'.'; |
| mnCursorPos++; |
| } |
| *mpPS << aScaleFactor.GetChar( n ); |
| } |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode ) |
| { |
| *mpPS << ( nNumb ); |
| mnCursorPos++; |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| void PSWriter::ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode ) |
| { |
| if ( ( nNumb >> 4 ) > 9 ) |
| *mpPS << (sal_uInt8)( ( nNumb >> 4 ) + 'A' - 10 ); |
| else |
| *mpPS << (sal_uInt8)( ( nNumb >> 4 ) + '0' ); |
| |
| if ( ( nNumb & 0xf ) > 9 ) |
| *mpPS << (sal_uInt8)( ( nNumb & 0xf ) + 'A' - 10 ); |
| else |
| *mpPS << (sal_uInt8)( ( nNumb & 0xf ) + '0' ); |
| mnCursorPos += 2; |
| ImplExecMode( nMode ); |
| } |
| |
| //--------------------------------------------------------------------------------- |
| |
| // writes the sal_uInt8 nNumb as a Number from 0.000 up to 1.000 |
| |
| void PSWriter::ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode ) |
| { |
| ImplWriteF( 1000 * ( nNumb + 1 ) / 256 , 3, nMode ); |
| } |
| |
| |
| // ------------------------------------------------------------------------ |
| |
| inline void PSWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen ) |
| { |
| dwShift |= ( nCode << ( nOffset - nCodeLen ) ); |
| nOffset -= nCodeLen; |
| while ( nOffset < 24 ) |
| { |
| ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) ); |
| dwShift <<= 8; |
| nOffset += 8; |
| } |
| if ( nCode == 257 && nOffset != 32 ) |
| ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) ); |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void PSWriter::StartCompression() |
| { |
| sal_uInt16 i; |
| nDataSize = 8; |
| |
| nClearCode = 1 << nDataSize; |
| nEOICode = nClearCode + 1; |
| nTableSize = nEOICode + 1; |
| nCodeSize = nDataSize + 1; |
| |
| nOffset = 32; // anzahl freier bits in dwShift |
| dwShift = 0; |
| |
| pTable = new PSLZWCTreeNode[ 4096 ]; |
| |
| for ( i = 0; i < 4096; i++ ) |
| { |
| pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL; |
| pTable[ i ].nValue = (sal_uInt8)( pTable[ i ].nCode = i ); |
| } |
| pPrefix = NULL; |
| WriteBits( nClearCode, nCodeSize ); |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void PSWriter::Compress( sal_uInt8 nCompThis ) |
| { |
| PSLZWCTreeNode* p; |
| sal_uInt16 i; |
| sal_uInt8 nV; |
| |
| if( !pPrefix ) |
| { |
| pPrefix = pTable + nCompThis; |
| } |
| else |
| { |
| nV = nCompThis; |
| for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother ) |
| { |
| if ( p->nValue == nV ) |
| break; |
| } |
| |
| if( p ) |
| pPrefix = p; |
| else |
| { |
| WriteBits( pPrefix->nCode, nCodeSize ); |
| |
| if ( nTableSize == 409 ) |
| { |
| WriteBits( nClearCode, nCodeSize ); |
| |
| for ( i = 0; i < nClearCode; i++ ) |
| pTable[ i ].pFirstChild = NULL; |
| |
| nCodeSize = nDataSize + 1; |
| nTableSize = nEOICode + 1; |
| } |
| else |
| { |
| if( nTableSize == (sal_uInt16)( ( 1 << nCodeSize ) - 1 ) ) |
| nCodeSize++; |
| |
| p = pTable + ( nTableSize++ ); |
| p->pBrother = pPrefix->pFirstChild; |
| pPrefix->pFirstChild = p; |
| p->nValue = nV; |
| p->pFirstChild = NULL; |
| } |
| |
| pPrefix = pTable + nV; |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void PSWriter::EndCompression() |
| { |
| if( pPrefix ) |
| WriteBits( pPrefix->nCode, nCodeSize ); |
| |
| WriteBits( nEOICode, nCodeSize ); |
| delete[] pTable; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_uInt8* PSWriter::ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize ) |
| { |
| while ( nComp-- >= nSize ) |
| { |
| sal_uLong i; |
| for ( i = 0; i < nSize; i++ ) |
| { |
| if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) ) |
| break; |
| } |
| if ( i == nSize ) |
| return pSource; |
| pSource++; |
| } |
| return NULL; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| sal_Bool PSWriter::ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize ) |
| { |
| sal_Bool bRetValue = sal_False; |
| sal_uLong nBytesRead; |
| |
| if ( nSize < 256 ) // we assume that the file is greater than 256 bytes |
| return sal_False; |
| |
| if ( nSize < POSTSCRIPT_BOUNDINGSEARCH ) |
| nBytesRead = nSize; |
| else |
| nBytesRead = POSTSCRIPT_BOUNDINGSEARCH; |
| |
| sal_uInt8* pDest = ImplSearchEntry( pSource, (sal_uInt8*)"%%BoundingBox:", nBytesRead, 14 ); |
| if ( pDest ) |
| { |
| int nSecurityCount = 100; // only 100 bytes following the bounding box will be checked |
| nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; |
| pDest += 14; |
| for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ ) |
| { |
| int nDivision = 1; |
| sal_Bool bDivision = sal_False; |
| sal_Bool bNegative = sal_False; |
| sal_Bool bValid = sal_True; |
| |
| while ( ( --nSecurityCount ) && ( ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) ) |
| pDest++; |
| sal_uInt8 nByte = *pDest; |
| while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) |
| { |
| switch ( nByte ) |
| { |
| case '.' : |
| if ( bDivision ) |
| bValid = sal_False; |
| else |
| bDivision = sal_True; |
| break; |
| case '-' : |
| bNegative = sal_True; |
| break; |
| default : |
| if ( ( nByte < '0' ) || ( nByte > '9' ) ) |
| nSecurityCount = 1; // error parsing the bounding box values |
| else if ( bValid ) |
| { |
| if ( bDivision ) |
| nDivision*=10; |
| nNumb[i] *= 10; |
| nNumb[i] += nByte - '0'; |
| } |
| break; |
| } |
| nSecurityCount--; |
| nByte = *(++pDest); |
| } |
| if ( bNegative ) |
| nNumb[i] = -nNumb[i]; |
| if ( bDivision && ( nDivision != 1 ) ) |
| nNumb[i] /= nDivision; |
| } |
| if ( nSecurityCount) |
| bRetValue = sal_True; |
| } |
| return bRetValue; |
| } |
| |
| //================== GraphicExport - die exportierte Funktion ================ |
| |
| extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool) |
| { |
| PSWriter aPSWriter; |
| return aPSWriter.WritePS( rGraphic, rStream, pFilterConfigItem ); |
| } |
| |