/************************************************************** * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "strings.hrc" #include #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 // formatting 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# explicitly 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 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::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 ); }