1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/solar.h>
21 #include <tools/stream.hxx>
22 #include <tools/poly.hxx>
23 #include <tools/fract.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/metaact.hxx>
26 #include <vcl/graph.hxx>
27 #include <vcl/bmpacc.hxx>
28 #include <vcl/region.hxx>
29 #include <vcl/metric.hxx>
30 #include <vcl/font.hxx>
31 #include <vcl/virdev.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <vcl/cvtgrf.hxx>
34 #include <vcl/gradient.hxx>
35 #include <vcl/settings.hxx>
36 #include <unotools/configmgr.hxx>
37 #include <svl/solar.hrc>
38 #include <vcl/fltcall.hxx>
39 #include <vcl/FilterConfigItem.hxx>
40 #include <vcl/graphictools.hxx>
41 #include "strings.hrc"
44 #include <boost/scoped_ptr.hpp>
46 using namespace ::com::sun::star::uno
;
48 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox
49 // in the first 4096 bytes
51 #define EPS_PREVIEW_TIFF 1
52 #define EPS_PREVIEW_EPSI 2
54 #define PS_LINESIZE 70 // maximum number of characters a line in the output
56 #define PS_NONE 0 // formatting mode: action which is inserted behind the output
61 // -----------------------------Feld-Typen-------------------------------
65 struct ChrSet
* pSucc
;
73 struct StackMember
* pSucc
;
88 SvtGraphicStroke::CapType eLineCap
;
89 SvtGraphicStroke::JoinType eJoinType
;
90 SvtGraphicStroke::DashArray aDashArray
;
96 PSLZWCTreeNode
* pBrother
; // next node who has the same father
97 PSLZWCTreeNode
* pFirstChild
; // first son
98 sal_uInt16 nCode
; // The code for the string of pixel values, which arises if... <missing comment>
99 sal_uInt16 nValue
; // the pixel value
106 sal_uLong mnLevelWarning
; // number of embedded eps files which was not exported
107 sal_uLong mnLastPercent
; // the number with which pCallback was called the last time
108 sal_uInt32 mnLatestPush
; // offset to streamposition, where last push was done
110 long mnLevel
; // dialog options
114 sal_Int32 mnTextMode
;
117 const GDIMetaFile
* pMTF
;
118 GDIMetaFile
* pAMTF
; // only created if Graphics is not a Metafile
119 ScopedVclPtrInstance
<VirtualDevice
> pVDev
;
121 double nBoundingX1
; // this represents the bounding box
126 StackMember
* pGDIStack
;
127 sal_uLong mnCursorPos
; // current cursor position in output
128 Color aColor
; // current color which is used for output
130 Color aLineColor
; // current GDIMetafile color settings
135 Color aTextFillColor
;
136 Color aBackgroundColor
;
138 TextAlign eTextAlign
;
142 SvtGraphicStroke::CapType eLineCap
;
143 SvtGraphicStroke::JoinType eJoinType
;
144 SvtGraphicStroke::DashArray aDashArray
;
147 vcl::Font maLastFont
;
149 ChrSet
* pChrSetList
; // list of character sets
150 sal_uInt8 nNextChrSetId
; // first unused ChrSet-Id
152 PSLZWCTreeNode
* pTable
; // LZW compression data
153 PSLZWCTreeNode
* pPrefix
; // the compression is as same as the TIFF compression
154 sal_uInt16 nDataSize
;
155 sal_uInt16 nClearCode
;
157 sal_uInt16 nTableSize
;
158 sal_uInt16 nCodeSize
;
162 com::sun::star::uno::Reference
< com::sun::star::task::XStatusIndicator
> xStatusIndicator
;
164 void ImplWriteProlog( const Graphic
* pPreviewEPSI
= NULL
);
165 void ImplWriteEpilog();
166 void ImplWriteActions( const GDIMetaFile
& rMtf
, VirtualDevice
& rVDev
);
168 // this method makes LF's, space inserting and word wrapping as used in all nMode
170 inline void ImplExecMode( sal_uLong nMode
);
172 // writes char[] + LF to stream
173 inline void ImplWriteLine( const char*, sal_uLong nMode
= PS_RET
);
175 // writes ( nNumb / 10^nCount ) in ASCII format to stream
176 void ImplWriteF( sal_Int32 nNumb
, sal_uLong nCount
= 3, sal_uLong nMode
= PS_SPACE
);
178 // writes a double in ASCII format to stream
179 void ImplWriteDouble( double, sal_uLong nMode
= PS_SPACE
);
181 // writes a long in ASCII format to stream
182 void ImplWriteLong( sal_Int32 nNumb
, sal_uLong nMode
= PS_SPACE
);
184 // writes a byte in ASCII format to stream
185 void ImplWriteByte( sal_uInt8 nNumb
, sal_uLong nMode
= PS_SPACE
);
187 // writes a byte in ASCII (hex) format to stream
188 void ImplWriteHexByte( sal_uInt8 nNumb
, sal_uLong nMode
= PS_WRAP
);
190 // writes nNumb as number from 0.000 till 1.000 in ASCII format to stream
191 void ImplWriteB1( sal_uInt8 nNumb
, sal_uLong nMode
= PS_SPACE
);
193 inline void ImplWritePoint( const Point
&, sal_uInt32 nMode
= PS_SPACE
);
194 void ImplMoveTo( const Point
&, sal_uInt32 nMode
= PS_SPACE
);
195 void ImplLineTo( const Point
&, sal_uInt32 nMode
= PS_SPACE
);
196 void ImplCurveTo( const Point
& rP1
, const Point
& rP2
, const Point
& rP3
, sal_uInt32 nMode
= PS_SPACE
);
197 void ImplTranslate( const double& fX
, const double& fY
, sal_uInt32 nMode
= PS_RET
);
198 void ImplScale( const double& fX
, const double& fY
, sal_uInt32 nMode
= PS_RET
);
200 void ImplAddPath( const Polygon
& rPolygon
);
201 void ImplWriteLineInfo( double fLineWidth
, double fMiterLimit
, SvtGraphicStroke::CapType eLineCap
,
202 SvtGraphicStroke::JoinType eJoinType
, SvtGraphicStroke::DashArray
& rDashArray
);
203 void ImplWriteLineInfo( const LineInfo
& rLineInfo
);
204 void ImplRect( const Rectangle
& rRectangle
);
205 void ImplRectFill ( const Rectangle
& rRectangle
);
206 void ImplWriteGradient( const tools::PolyPolygon
& rPolyPoly
, const Gradient
& rGradient
, VirtualDevice
& rVDev
);
207 void ImplIntersect( const tools::PolyPolygon
& rPolyPoly
);
208 void ImplPolyPoly( const tools::PolyPolygon
& rPolyPolygon
, bool bTextOutline
= false );
209 void ImplPolyLine( const Polygon
& rPolygon
);
211 void ImplSetClipRegion( vcl::Region
& rRegion
);
212 void ImplBmp( Bitmap
*, Bitmap
*, const Point
&, double nWidth
, double nHeight
);
213 void ImplText( const OUString
& rUniString
, const Point
& rPos
, const long* pDXArry
, sal_Int32 nWidth
, VirtualDevice
& rVDev
);
214 void ImplSetAttrForText( const Point
& rPoint
);
215 void ImplWriteCharacter( sal_Char
);
216 void ImplWriteString( const OString
&, VirtualDevice
& rVDev
, const long* pDXArry
= NULL
, bool bStretch
= false );
217 void ImplDefineFont( const char*, const char* );
219 void ImplClosePathDraw( sal_uLong nMode
= PS_RET
);
222 inline void ImplWriteLineColor( sal_uLong nMode
= PS_RET
);
223 inline void ImplWriteFillColor( sal_uLong nMode
= PS_RET
);
224 inline void ImplWriteTextColor( sal_uLong nMode
= PS_RET
);
225 void ImplWriteColor( sal_uLong nMode
);
227 static double ImplGetScaling( const MapMode
& );
228 void ImplGetMapMode( const MapMode
& );
229 static bool ImplGetBoundingBox( double* nNumb
, sal_uInt8
* pSource
, sal_uLong nSize
);
230 static sal_uInt8
* ImplSearchEntry( sal_uInt8
* pSource
, sal_uInt8
const * pDest
, sal_uLong nComp
, sal_uLong nSize
);
232 void StartCompression();
233 void Compress( sal_uInt8 nSrc
);
234 void EndCompression();
235 inline void WriteBits( sal_uInt16 nCode
, sal_uInt16 nCodeLen
);
238 bool WritePS( const Graphic
& rGraphic
, SvStream
& rTargetStream
, FilterConfigItem
* );
243 //========================== Methoden von PSWriter ==========================
254 , mbCompression(false)
273 , bTextFillColor(false)
276 , bRegionChanged(false)
303 PSWriter::~PSWriter()
310 bool PSWriter::WritePS( const Graphic
& rGraphic
, SvStream
& rTargetStream
, FilterConfigItem
* pFilterConfigItem
)
312 sal_uInt32 nStreamPosition
= 0, nPSPosition
= 0; // -Wall warning, unset, check
318 mnLatestPush
= 0xEFFFFFFE;
320 if ( pFilterConfigItem
)
322 xStatusIndicator
= pFilterConfigItem
->GetStatusIndicator();
323 if ( xStatusIndicator
.is() )
326 xStatusIndicator
->start( aMsg
, 100 );
330 mpPS
= &rTargetStream
;
331 mpPS
->SetEndian( SvStreamEndian::LITTLE
);
333 // default values for the dialog options
336 #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
337 mbCompression
= false;
339 mbCompression
= sal_True
;
341 mnTextMode
= 0; // default0 : export glyph outlines
343 // try to get the dialog selection
344 if ( pFilterConfigItem
)
346 boost::scoped_ptr
<ResMgr
> pResMgr(ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() ));
350 #ifdef UNX // don't put binary tiff preview ahead of postscript code by default on unix as ghostscript is unable to read it
351 mnPreview
= pFilterConfigItem
->ReadInt32( "Preview", 0 );
353 mnPreview
= pFilterConfigItem
->ReadInt32( "Preview", 1 );
355 mnLevel
= pFilterConfigItem
->ReadInt32( "Version", 2 );
358 mbGrayScale
= pFilterConfigItem
->ReadInt32( "ColorFormat", 1 ) == 2;
359 #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
360 mbCompression
= pFilterConfigItem
->ReadInt32( "CompressionMode", 0 ) != 0;
362 mbCompression
= pFilterConfigItem
->ReadInt32( "CompressionMode", 1 ) == 1;
364 mnTextMode
= pFilterConfigItem
->ReadInt32( "TextMode", 0 );
365 if ( mnTextMode
> 2 )
370 // compression is not available for Level 1
374 mbCompression
= false;
377 if ( mnPreview
& EPS_PREVIEW_TIFF
)
379 rTargetStream
.WriteUInt32( 0xC6D3D0C5 );
380 nStreamPosition
= rTargetStream
.Tell();
381 rTargetStream
.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
382 .WriteUInt32( nStreamPosition
+ 26 ).WriteUInt32( 0 ).WriteUInt16( 0xffff );
387 BitmapEx
aTempBitmapEx( rGraphic
.GetBitmapEx() );
388 aTempBitmapEx
.Convert( BMP_CONVERSION_8BIT_GREYS
);
389 nErrCode
= GraphicConverter::Export( rTargetStream
, aTempBitmapEx
, CVT_TIF
) ;
392 nErrCode
= GraphicConverter::Export( rTargetStream
, rGraphic
, CVT_TIF
) ;
394 if ( nErrCode
== ERRCODE_NONE
)
396 rTargetStream
.Seek( STREAM_SEEK_TO_END
);
397 nPSPosition
= rTargetStream
.Tell();
398 rTargetStream
.Seek( nStreamPosition
+ 20 );
399 rTargetStream
.WriteUInt32( nPSPosition
- 30 ); // size of tiff gfx
400 rTargetStream
.Seek( nPSPosition
);
404 mnPreview
&=~ EPS_PREVIEW_TIFF
;
405 rTargetStream
.Seek( nStreamPosition
- 4 );
409 // global default value setting
413 if (rGraphic
.GetType() == GRAPHIC_GDIMETAFILE
)
414 pMTF
= &rGraphic
.GetGDIMetaFile();
415 else if (rGraphic
.GetGDIMetaFile().GetActionSize())
416 pMTF
= pAMTF
= new GDIMetaFile( rGraphic
.GetGDIMetaFile() );
419 Bitmap
aBmp( rGraphic
.GetBitmap() );
420 pAMTF
= new GDIMetaFile();
421 ScopedVclPtrInstance
< VirtualDevice
> pTmpVDev
;
422 pAMTF
->Record( pTmpVDev
);
423 pTmpVDev
->DrawBitmap( Point(), aBmp
);
425 pAMTF
->SetPrefSize( aBmp
.GetSizePixel() );
428 pVDev
->SetMapMode( pMTF
->GetPrefMapMode() );
429 nBoundingX1
= nBoundingY1
= 0;
430 nBoundingX2
= pMTF
->GetPrefSize().Width();
431 nBoundingY2
= pMTF
->GetPrefSize().Height();
434 aColor
= Color( COL_TRANSPARENT
);
436 aLineColor
= Color( COL_BLACK
);
438 aFillColor
= Color( COL_WHITE
);
439 bTextFillColor
= true;
440 aTextFillColor
= Color( COL_BLACK
);
442 fMiterLimit
= 15; // use same limit as most graphic systems and basegfx
443 eLineCap
= SvtGraphicStroke::capButt
;
444 eJoinType
= SvtGraphicStroke::joinMiter
;
445 aBackgroundColor
= Color( COL_WHITE
);
446 eTextAlign
= ALIGN_BASELINE
;
447 bRegionChanged
= false;
453 if( pMTF
->GetActionSize() )
455 ImplWriteProlog( ( mnPreview
& EPS_PREVIEW_EPSI
) ? &rGraphic
: NULL
);
457 ImplWriteActions( *pMTF
, *pVDev
.get() );
459 if ( mnPreview
& EPS_PREVIEW_TIFF
)
461 sal_uInt32 nPosition
= rTargetStream
.Tell();
462 rTargetStream
.Seek( nStreamPosition
);
463 rTargetStream
.WriteUInt32( nPSPosition
);
464 rTargetStream
.WriteUInt32( nPosition
- nPSPosition
);
465 rTargetStream
.Seek( nPosition
);
470 pChrSetList
=pCS
->pSucc
;
476 pGDIStack
=pGS
->pSucc
;
483 if ( mbStatus
&& mnLevelWarning
&& pFilterConfigItem
)
486 pResMgr
= ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() );
489 ScopedVclPtrInstance
< InfoBox
> aInfoBox( nullptr, ResId(KEY_VERSION_CHECK
, *pResMgr
).toString() );
495 if ( xStatusIndicator
.is() )
496 xStatusIndicator
->end();
503 void PSWriter::ImplWriteProlog( const Graphic
* pPreview
)
505 ImplWriteLine( "%!PS-Adobe-3.0 EPSF-3.0 " );
506 mpPS
->WriteCharPtr( "%%BoundingBox: " ); // BoundingBox
509 Size aSizePoint
= OutputDevice::LogicToLogic( pMTF
->GetPrefSize(),
510 pMTF
->GetPrefMapMode(), MAP_POINT
);
511 ImplWriteLong( aSizePoint
.Width() );
512 ImplWriteLong( aSizePoint
.Height() ,PS_RET
);
513 ImplWriteLine( "%%Pages: 0" );
514 OUString
aCreator( "%%Creator: " + utl::ConfigManager::getProductName() + " " +
515 utl::ConfigManager::getProductVersion() );
516 ImplWriteLine( OUStringToOString( aCreator
, RTL_TEXTENCODING_UTF8
).getStr() );
517 ImplWriteLine( "%%Title: none" );
518 ImplWriteLine( "%%CreationDate: none" );
522 mpPS
->WriteCharPtr( "%%LanguageLevel: " ); // Language level
523 ImplWriteLong( mnLevel
, PS_RET
);
524 if ( !mbGrayScale
&& mnLevel
== 1 )
525 ImplWriteLine( "%%Extensions: CMYK" ); // CMYK extension is to set in color mode in level 1
526 ImplWriteLine( "%%EndComments" );
527 if ( pPreview
&& aSizePoint
.Width() && aSizePoint
.Height() )
529 Size
aSizeBitmap( ( aSizePoint
.Width() + 7 ) & ~7, aSizePoint
.Height() );
530 Bitmap
aTmpBitmap( pPreview
->GetBitmap() );
531 aTmpBitmap
.Scale( aSizeBitmap
, BmpScaleFlag::BestQuality
);
532 aTmpBitmap
.Convert( BMP_CONVERSION_1BIT_THRESHOLD
);
533 BitmapReadAccess
* pAcc
= aTmpBitmap
.AcquireReadAccess();
536 mpPS
->WriteCharPtr( "%%BeginPreview: " ); // BoundingBox
537 ImplWriteLong( aSizeBitmap
.Width() );
538 ImplWriteLong( aSizeBitmap
.Height() );
539 mpPS
->WriteCharPtr( "1 " );
540 sal_Int32 nLines
= aSizeBitmap
.Width() / 312;
541 if ( ( nLines
* 312 ) != aSizeBitmap
.Width() )
543 nLines
*= aSizeBitmap
.Height();
544 ImplWriteLong( nLines
);
545 sal_Int32 nX
, nY
, nCount2
, nCount
= 4;
546 const BitmapColor
aBlack( pAcc
->GetBestMatchingColor( Color( COL_BLACK
) ) );
547 for ( nY
= 0; nY
< aSizeBitmap
.Height(); nY
++ )
551 for ( nX
= 0; nX
< aSizeBitmap
.Width(); nX
++ )
555 ImplExecMode( PS_RET
);
556 mpPS
->WriteCharPtr( "%" );
560 if ( pAcc
->GetPixel( nY
, nX
) == aBlack
)
562 if ( ! ( --nCount
) )
568 mpPS
->WriteChar( nVal
);
575 Bitmap::ReleaseAccess( pAcc
);
576 ImplExecMode( PS_RET
);
577 ImplWriteLine( "%%EndPreview" );
580 ImplWriteLine( "%%BeginProlog" );
581 ImplWriteLine( "%%BeginResource: procset SDRes-Prolog 1.0 0" );
584 ImplWriteLine( "/b4_inc_state save def\n/dict_count countdictstack def\n/op_count count 1 sub def\nuserdict begin" );
585 ImplWriteLine( "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath" );
586 ImplWriteLine( "/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if" );
588 ImplWriteLine( "/bdef {bind def} bind def" ); // the new operator bdef is created
590 ImplWriteLine( "/c {setgray} bdef" );
592 ImplWriteLine( "/c {setrgbcolor} bdef" );
593 ImplWriteLine( "/l {neg lineto} bdef" );
594 ImplWriteLine( "/rl {neg rlineto} bdef" );
595 ImplWriteLine( "/lc {setlinecap} bdef" );
596 ImplWriteLine( "/lj {setlinejoin} bdef" );
597 ImplWriteLine( "/lw {setlinewidth} bdef" );
598 ImplWriteLine( "/ml {setmiterlimit} bdef" );
599 ImplWriteLine( "/ld {setdash} bdef" );
600 ImplWriteLine( "/m {neg moveto} bdef" );
601 ImplWriteLine( "/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef" );
602 ImplWriteLine( "/r {rotate} bdef" );
603 ImplWriteLine( "/t {neg translate} bdef" );
604 ImplWriteLine( "/s {scale} bdef" );
605 ImplWriteLine( "/sw {show} bdef" );
606 ImplWriteLine( "/gs {gsave} bdef" );
607 ImplWriteLine( "/gr {grestore} bdef" );
609 ImplWriteLine( "/f {findfont dup length dict begin" ); // Setfont
610 ImplWriteLine( "{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def" );
611 ImplWriteLine( "currentdict end /NFont exch definefont pop /NFont findfont} bdef" );
613 ImplWriteLine( "/p {closepath} bdef" );
614 ImplWriteLine( "/sf {scalefont setfont} bdef" );
616 ImplWriteLine( "/ef {eofill}bdef" ); // close path and fill
617 ImplWriteLine( "/pc {closepath stroke}bdef" ); // close path and draw
618 ImplWriteLine( "/ps {stroke}bdef" ); // draw current path
619 ImplWriteLine( "/pum {matrix currentmatrix}bdef" ); // pushes the current matrix
620 ImplWriteLine( "/pom {setmatrix}bdef" ); // pops the matrix
621 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" );
622 ImplWriteLine( "%%EndResource" );
623 ImplWriteLine( "%%EndProlog" );
624 ImplWriteLine( "%%BeginSetup" );
625 ImplWriteLine( "%%EndSetup" );
626 ImplWriteLine( "%%Page: 1 1" );
627 ImplWriteLine( "%%BeginPageSetup" );
628 ImplWriteLine( "%%EndPageSetup" );
629 ImplWriteLine( "pum" );
630 ImplScale( (double)aSizePoint
.Width() / (double)pMTF
->GetPrefSize().Width(), (double)aSizePoint
.Height() / (double)pMTF
->GetPrefSize().Height() );
631 ImplWriteDouble( 0 );
632 ImplWriteDouble( -pMTF
->GetPrefSize().Height() );
633 ImplWriteLine( "t" );
634 ImplWriteLine( "/tm matrix currentmatrix def" );
639 void PSWriter::ImplWriteEpilog()
641 ImplTranslate( 0, nBoundingY2
);
642 ImplWriteLine( "pom" );
643 ImplWriteLine( "count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore" );
645 ImplWriteLine( "%%PageTrailer" );
646 ImplWriteLine( "%%Trailer" );
648 ImplWriteLine( "%%EOF" );
655 void PSWriter::ImplWriteActions( const GDIMetaFile
& rMtf
, VirtualDevice
& rVDev
)
657 tools::PolyPolygon aFillPath
;
659 for( size_t nCurAction
= 0, nCount
= rMtf
.GetActionSize(); nCurAction
< nCount
; nCurAction
++ )
661 MetaAction
* pMA
= rMtf
.GetAction( nCurAction
);
663 switch( pMA
->GetType() )
665 case MetaActionType::NONE
:
668 case MetaActionType::PIXEL
:
670 Color
aOldLineColor( aLineColor
);
671 aLineColor
= static_cast<const MetaPixelAction
*>(pMA
)->GetColor();
672 ImplWriteLineColor( PS_SPACE
);
673 ImplMoveTo( static_cast<const MetaPixelAction
*>(pMA
)->GetPoint() );
674 ImplLineTo( static_cast<const MetaPixelAction
*>(pMA
)->GetPoint() );
676 aLineColor
= aOldLineColor
;
680 case MetaActionType::POINT
:
682 ImplWriteLineColor( PS_SPACE
);
683 ImplMoveTo( static_cast<const MetaPointAction
*>(pMA
)->GetPoint() );
684 ImplLineTo( static_cast<const MetaPointAction
*>(pMA
)->GetPoint() );
689 case MetaActionType::LINE
:
691 const LineInfo
& rLineInfo
= static_cast<const MetaLineAction
*>(pMA
)->GetLineInfo();
692 ImplWriteLineInfo( rLineInfo
);
695 ImplWriteLineColor( PS_SPACE
);
696 ImplMoveTo( static_cast<const MetaLineAction
*>(pMA
)->GetStartPoint() );
697 ImplLineTo( static_cast<const MetaLineAction
*>(pMA
)->GetEndPoint() );
703 case MetaActionType::RECT
:
705 ImplRect( static_cast<const MetaRectAction
*>(pMA
)->GetRect() );
709 case MetaActionType::ROUNDRECT
:
710 ImplRect( static_cast<const MetaRoundRectAction
*>(pMA
)->GetRect() );
713 case MetaActionType::ELLIPSE
:
715 Rectangle aRect
= static_cast<const MetaEllipseAction
*>(pMA
)->GetRect();
716 Point aCenter
= aRect
.Center();
717 Polygon
aPoly( aCenter
, aRect
.GetWidth() / 2, aRect
.GetHeight() / 2 );
718 tools::PolyPolygon
aPolyPoly( aPoly
);
719 ImplPolyPoly( aPolyPoly
);
723 case MetaActionType::ARC
:
725 Polygon
aPoly( static_cast<const MetaArcAction
*>(pMA
)->GetRect(), static_cast<const MetaArcAction
*>(pMA
)->GetStartPoint(),
726 static_cast<const MetaArcAction
*>(pMA
)->GetEndPoint(), POLY_ARC
);
727 tools::PolyPolygon
aPolyPoly( aPoly
);
728 ImplPolyPoly( aPolyPoly
);
732 case MetaActionType::PIE
:
734 Polygon
aPoly( static_cast<const MetaPieAction
*>(pMA
)->GetRect(), static_cast<const MetaPieAction
*>(pMA
)->GetStartPoint(),
735 static_cast<const MetaPieAction
*>(pMA
)->GetEndPoint(), POLY_PIE
);
736 tools::PolyPolygon
aPolyPoly( aPoly
);
737 ImplPolyPoly( aPolyPoly
);
741 case MetaActionType::CHORD
:
743 Polygon
aPoly( static_cast<const MetaChordAction
*>(pMA
)->GetRect(), static_cast<const MetaChordAction
*>(pMA
)->GetStartPoint(),
744 static_cast<const MetaChordAction
*>(pMA
)->GetEndPoint(), POLY_CHORD
);
745 tools::PolyPolygon
aPolyPoly( aPoly
);
746 ImplPolyPoly( aPolyPoly
);
750 case MetaActionType::POLYLINE
:
752 Polygon
aPoly( static_cast<const MetaPolyLineAction
*>(pMA
)->GetPolygon() );
753 const LineInfo
& rLineInfo
= static_cast<const MetaPolyLineAction
*>(pMA
)->GetLineInfo();
754 ImplWriteLineInfo( rLineInfo
);
756 if(basegfx::B2DLINEJOIN_NONE
== rLineInfo
.GetLineJoin()
757 && rLineInfo
.GetWidth() > 1)
759 // emulate B2DLINEJOIN_NONE by creating single edges
760 const sal_uInt16
nPoints(aPoly
.GetSize());
761 const bool bCurve(aPoly
.HasFlags());
763 for(sal_uInt16
a(0); a
+ 1 < nPoints
; a
++)
766 && POLY_NORMAL
!= aPoly
.GetFlags(a
+ 1)
768 && POLY_NORMAL
!= aPoly
.GetFlags(a
+ 2)
771 const Polygon
aSnippet(4,
772 aPoly
.GetConstPointAry() + a
,
773 aPoly
.GetConstFlagAry() + a
);
774 ImplPolyLine(aSnippet
);
779 const Polygon
aSnippet(2,
780 aPoly
.GetConstPointAry() + a
);
781 ImplPolyLine(aSnippet
);
787 ImplPolyLine( aPoly
);
792 case MetaActionType::POLYGON
:
794 tools::PolyPolygon
aPolyPoly( static_cast<const MetaPolygonAction
*>(pMA
)->GetPolygon() );
795 ImplPolyPoly( aPolyPoly
);
799 case MetaActionType::POLYPOLYGON
:
801 ImplPolyPoly( static_cast<const MetaPolyPolygonAction
*>(pMA
)->GetPolyPolygon() );
805 case MetaActionType::TEXT
:
807 const MetaTextAction
* pA
= static_cast<const MetaTextAction
*>(pMA
);
809 OUString aUniStr
= pA
->GetText().copy( pA
->GetIndex(), pA
->GetLen() );
810 Point
aPoint( pA
->GetPoint() );
812 ImplText( aUniStr
, aPoint
, NULL
, 0, rVDev
);
816 case MetaActionType::TEXTRECT
:
818 OSL_FAIL( "Unsupported action: TextRect...Action!" );
822 case MetaActionType::STRETCHTEXT
:
824 const MetaStretchTextAction
* pA
= static_cast<const MetaStretchTextAction
*>(pMA
);
825 OUString aUniStr
= pA
->GetText().copy( pA
->GetIndex(), pA
->GetLen() );
826 Point
aPoint( pA
->GetPoint() );
828 ImplText( aUniStr
, aPoint
, NULL
, pA
->GetWidth(), rVDev
);
832 case MetaActionType::TEXTARRAY
:
834 const MetaTextArrayAction
* pA
= static_cast<const MetaTextArrayAction
*>(pMA
);
835 OUString aUniStr
= pA
->GetText().copy( pA
->GetIndex(), pA
->GetLen() );
836 Point
aPoint( pA
->GetPoint() );
838 ImplText( aUniStr
, aPoint
, pA
->GetDXArray(), 0, rVDev
);
842 case MetaActionType::BMP
:
844 Bitmap aBitmap
= static_cast<const MetaBmpAction
*>(pMA
)->GetBitmap();
846 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
847 Point aPoint
= static_cast<const MetaBmpAction
*>(pMA
)->GetPoint();
848 Size
aSize( rVDev
.PixelToLogic( aBitmap
.GetSizePixel() ) );
849 ImplBmp( &aBitmap
, NULL
, aPoint
, aSize
.Width(), aSize
.Height() );
853 case MetaActionType::BMPSCALE
:
855 Bitmap aBitmap
= static_cast<const MetaBmpScaleAction
*>(pMA
)->GetBitmap();
857 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
858 Point aPoint
= static_cast<const MetaBmpScaleAction
*>(pMA
)->GetPoint();
859 Size aSize
= static_cast<const MetaBmpScaleAction
*>(pMA
)->GetSize();
860 ImplBmp( &aBitmap
, NULL
, aPoint
, aSize
.Width(), aSize
.Height() );
864 case MetaActionType::BMPSCALEPART
:
866 Bitmap
aBitmap( static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetBitmap() );
867 aBitmap
.Crop( Rectangle( static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetSrcPoint(),
868 static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetSrcSize() ) );
870 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
871 Point aPoint
= static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetDestPoint();
872 Size aSize
= static_cast<const MetaBmpScalePartAction
*>(pMA
)->GetDestSize();
873 ImplBmp( &aBitmap
, NULL
, aPoint
, aSize
.Width(), aSize
.Height() );
877 case MetaActionType::BMPEX
:
879 BitmapEx
aBitmapEx( static_cast<MetaBmpExAction
*>(pMA
)->GetBitmapEx() );
880 Bitmap
aBitmap( aBitmapEx
.GetBitmap() );
882 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
883 Bitmap
aMask( aBitmapEx
.GetMask() );
884 Point
aPoint( static_cast<const MetaBmpExAction
*>(pMA
)->GetPoint() );
885 Size
aSize( rVDev
.PixelToLogic( aBitmap
.GetSizePixel() ) );
886 ImplBmp( &aBitmap
, &aMask
, aPoint
, aSize
.Width(), aSize
.Height() );
890 case MetaActionType::BMPEXSCALE
:
892 BitmapEx
aBitmapEx( static_cast<MetaBmpExScaleAction
*>(pMA
)->GetBitmapEx() );
893 Bitmap
aBitmap( aBitmapEx
.GetBitmap() );
895 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
896 Bitmap
aMask( aBitmapEx
.GetMask() );
897 Point aPoint
= static_cast<const MetaBmpExScaleAction
*>(pMA
)->GetPoint();
898 Size
aSize( static_cast<const MetaBmpExScaleAction
*>(pMA
)->GetSize() );
899 ImplBmp( &aBitmap
, &aMask
, aPoint
, aSize
.Width(), aSize
.Height() );
903 case MetaActionType::BMPEXSCALEPART
:
905 BitmapEx
aBitmapEx( static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetBitmapEx() );
906 aBitmapEx
.Crop( Rectangle( static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetSrcPoint(),
907 static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetSrcSize() ) );
908 Bitmap
aBitmap( aBitmapEx
.GetBitmap() );
910 aBitmap
.Convert( BMP_CONVERSION_8BIT_GREYS
);
911 Bitmap
aMask( aBitmapEx
.GetMask() );
912 Point aPoint
= static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetDestPoint();
913 Size aSize
= static_cast<const MetaBmpExScalePartAction
*>(pMA
)->GetDestSize();
914 ImplBmp( &aBitmap
, &aMask
, aPoint
, aSize
.Width(), aSize
.Height() );
918 // Unsupported Actions
919 case MetaActionType::MASK
:
920 case MetaActionType::MASKSCALE
:
921 case MetaActionType::MASKSCALEPART
:
923 OSL_FAIL( "Unsupported action: MetaMask...Action!" );
927 case MetaActionType::GRADIENT
:
929 tools::PolyPolygon
aPolyPoly( static_cast<const MetaGradientAction
*>(pMA
)->GetRect() );
930 ImplWriteGradient( aPolyPoly
, static_cast<const MetaGradientAction
*>(pMA
)->GetGradient(), rVDev
);
934 case MetaActionType::GRADIENTEX
:
936 tools::PolyPolygon
aPolyPoly( static_cast<const MetaGradientExAction
*>(pMA
)->GetPolyPolygon() );
937 ImplWriteGradient( aPolyPoly
, static_cast<const MetaGradientExAction
*>(pMA
)->GetGradient(), rVDev
);
941 case MetaActionType::HATCH
:
943 ScopedVclPtrInstance
< VirtualDevice
> l_pVirDev
;
946 l_pVirDev
->SetMapMode( rVDev
.GetMapMode() );
947 l_pVirDev
->AddHatchActions( static_cast<const MetaHatchAction
*>(pMA
)->GetPolyPolygon(),
948 static_cast<const MetaHatchAction
*>(pMA
)->GetHatch(), aTmpMtf
);
949 ImplWriteActions( aTmpMtf
, rVDev
);
953 case MetaActionType::WALLPAPER
:
955 const MetaWallpaperAction
* pA
= static_cast<const MetaWallpaperAction
*>(pMA
);
956 Rectangle aRect
= pA
->GetRect();
957 Wallpaper aWallpaper
= pA
->GetWallpaper();
959 if ( aWallpaper
.IsBitmap() )
961 BitmapEx aBitmapEx
= aWallpaper
.GetBitmap();
962 Bitmap
aBitmap( aBitmapEx
.GetBitmap() );
963 if ( aBitmapEx
.IsTransparent() )
965 if ( aWallpaper
.IsGradient() )
971 Bitmap
aMask( aBitmapEx
.GetMask() );
972 ImplBmp( &aBitmap
, &aMask
, Point( aRect
.Left(), aRect
.Top() ), aRect
.GetWidth(), aRect
.GetHeight() );
975 ImplBmp( &aBitmap
, NULL
, Point( aRect
.Left(), aRect
.Top() ), aRect
.GetWidth(), aRect
.GetHeight() );
980 else if ( aWallpaper
.IsGradient() )
988 aColor
= aWallpaper
.GetColor();
989 ImplRectFill( aRect
);
994 case MetaActionType::ISECTRECTCLIPREGION
:
996 const MetaISectRectClipRegionAction
* pA
= static_cast<const MetaISectRectClipRegionAction
*>(pMA
);
997 vcl::Region
aRegion( pA
->GetRect() );
998 ImplSetClipRegion( aRegion
);
1002 case MetaActionType::CLIPREGION
:
1004 const MetaClipRegionAction
* pA
= static_cast<const MetaClipRegionAction
*>(pMA
);
1005 vcl::Region
aRegion( pA
->GetRegion() );
1006 ImplSetClipRegion( aRegion
);
1010 case MetaActionType::ISECTREGIONCLIPREGION
:
1012 const MetaISectRegionClipRegionAction
* pA
= static_cast<const MetaISectRegionClipRegionAction
*>(pMA
);
1013 vcl::Region
aRegion( pA
->GetRegion() );
1014 ImplSetClipRegion( aRegion
);
1018 case MetaActionType::MOVECLIPREGION
:
1021 if ( !aClipRegion.IsEmpty() )
1023 const MetaMoveClipRegionAction* pA = static_cast<const MetaMoveClipRegionAction*>(pMA);
1024 aClipRegion.Move( pA->GetHorzMove(), pA->GetVertMove() );
1025 ImplSetClipRegion();
1031 case MetaActionType::LINECOLOR
:
1033 if ( static_cast<const MetaLineColorAction
*>(pMA
)->IsSetting() )
1036 aLineColor
= static_cast<const MetaLineColorAction
*>(pMA
)->GetColor();
1043 case MetaActionType::FILLCOLOR
:
1045 if ( static_cast<const MetaFillColorAction
*>(pMA
)->IsSetting() )
1048 aFillColor
= static_cast<const MetaFillColorAction
*>(pMA
)->GetColor();
1055 case MetaActionType::TEXTCOLOR
:
1057 aTextColor
= static_cast<const MetaTextColorAction
*>(pMA
)->GetColor();
1061 case MetaActionType::TEXTFILLCOLOR
:
1063 if ( static_cast<const MetaTextFillColorAction
*>(pMA
)->IsSetting() )
1065 bTextFillColor
= true;
1066 aTextFillColor
= static_cast<const MetaTextFillColorAction
*>(pMA
)->GetColor();
1069 bTextFillColor
= false;
1073 case MetaActionType::TEXTALIGN
:
1075 eTextAlign
= static_cast<const MetaTextAlignAction
*>(pMA
)->GetTextAlign();
1079 case MetaActionType::MAPMODE
:
1081 pMA
->Execute( &rVDev
);
1082 ImplGetMapMode( rVDev
.GetMapMode() );
1086 case MetaActionType::FONT
:
1088 maFont
= static_cast<const MetaFontAction
*>(pMA
)->GetFont();
1089 rVDev
.SetFont( maFont
);
1093 case MetaActionType::PUSH
:
1095 rVDev
.Push(static_cast<const MetaPushAction
*>(pMA
)->GetFlags() );
1096 StackMember
* pGS
= new StackMember
;
1097 pGS
->pSucc
= pGDIStack
;
1099 pGS
->aDashArray
= aDashArray
;
1100 pGS
->eJoinType
= eJoinType
;
1101 pGS
->eLineCap
= eLineCap
;
1102 pGS
->fLineWidth
= fLineWidth
;
1103 pGS
->fMiterLimit
= fMiterLimit
;
1104 pGS
->eTextAlign
= eTextAlign
;
1105 pGS
->aGlobalCol
= aColor
;
1106 pGS
->bLineCol
= bLineColor
;
1107 pGS
->aLineCol
= aLineColor
;
1108 pGS
->bFillCol
= bFillColor
;
1109 pGS
->aFillCol
= aFillColor
;
1110 pGS
->aTextCol
= aTextColor
;
1111 pGS
->bTextFillCol
= bTextFillColor
;
1112 pGS
->aTextFillCol
= aTextFillColor
;
1113 pGS
->aBackgroundCol
= aBackgroundColor
;
1114 bRegionChanged
= false;
1115 pGS
->aFont
= maFont
;
1116 mnLatestPush
= mpPS
->Tell();
1117 ImplWriteLine( "gs" );
1121 case MetaActionType::POP
:
1128 pGDIStack
= pGS
->pSucc
;
1129 aDashArray
= pGS
->aDashArray
;
1130 eJoinType
= pGS
->eJoinType
;
1131 eLineCap
= pGS
->eLineCap
;
1132 fLineWidth
= pGS
->fLineWidth
;
1133 fMiterLimit
= pGS
->fMiterLimit
;
1134 eTextAlign
= pGS
->eTextAlign
;
1135 aColor
= pGS
->aGlobalCol
;
1136 bLineColor
= pGS
->bLineCol
;
1137 aLineColor
= pGS
->aLineCol
;
1138 bFillColor
= pGS
->bFillCol
;
1139 aFillColor
= pGS
->aFillCol
;
1140 aTextColor
= pGS
->aTextCol
;
1141 bTextFillColor
= pGS
->bTextFillCol
;
1142 aTextFillColor
= pGS
->aTextFillCol
;
1143 aBackgroundColor
= pGS
->aBackgroundCol
;
1144 maFont
= pGS
->aFont
;
1145 maLastFont
= vcl::Font(); // set maLastFont != maFont -> so that
1147 sal_uInt32 nCurrentPos
= mpPS
->Tell();
1148 if ( nCurrentPos
- 3 == mnLatestPush
)
1150 mpPS
->Seek( mnLatestPush
);
1151 ImplWriteLine( " " );
1152 mpPS
->Seek( mnLatestPush
);
1155 ImplWriteLine( "gr" );
1160 case MetaActionType::EPS
:
1162 GfxLink aGfxLink
= static_cast<const MetaEPSAction
*>(pMA
)->GetLink();
1163 const GDIMetaFile
aSubstitute( static_cast<const MetaEPSAction
*>(pMA
)->GetSubstitute() );
1165 bool bLevelConflict
= false;
1166 sal_uInt8
* pSource
= const_cast<sal_uInt8
*>(aGfxLink
.GetData());
1167 sal_uLong nSize
= aGfxLink
.GetDataSize();
1168 sal_uLong nParseThis
= POSTSCRIPT_BOUNDINGSEARCH
;
1169 if ( nSize
< 64 ) // assuming eps is larger than 64 bytes
1171 if ( nParseThis
> nSize
)
1174 if ( pSource
&& ( mnLevel
== 1 ) )
1176 sal_uInt8
* pFound
= ImplSearchEntry( pSource
, reinterpret_cast<sal_uInt8
const *>("%%LanguageLevel:"), nParseThis
- 10, 16 );
1179 sal_uInt8 k
, i
= 10;
1184 if ( ( k
> '0' ) && ( k
<= '9' ) )
1188 bLevelConflict
= true;
1196 if ( !bLevelConflict
)
1198 double nBoundingBox
[4];
1199 if ( pSource
&& ImplGetBoundingBox( nBoundingBox
, pSource
, nParseThis
) )
1201 Point aPoint
= static_cast<const MetaEPSAction
*>(pMA
)->GetPoint();
1202 Size aSize
= static_cast<const MetaEPSAction
*>(pMA
)->GetSize();
1204 MapMode
aMapMode( aSubstitute
.GetPrefMapMode() );
1205 Size
aOutSize( OutputDevice::LogicToLogic( aSize
, rVDev
.GetMapMode(), aMapMode
) );
1206 Point
aOrigin( OutputDevice::LogicToLogic( aPoint
, rVDev
.GetMapMode(), aMapMode
) );
1207 aOrigin
.Y() += aOutSize
.Height();
1208 aMapMode
.SetOrigin( aOrigin
);
1209 aMapMode
.SetScaleX( aOutSize
.Width() / ( nBoundingBox
[ 2 ] - nBoundingBox
[ 0 ] ) );
1210 aMapMode
.SetScaleY( aOutSize
.Height() / ( nBoundingBox
[ 3 ] - nBoundingBox
[ 1 ] ) );
1211 ImplWriteLine( "gs" );
1212 ImplGetMapMode( aMapMode
);
1213 ImplWriteLine( "%%BeginDocument:" );
1214 mpPS
->Write( pSource
, aGfxLink
.GetDataSize() );
1215 ImplWriteLine( "%%EndDocument\ngr" );
1221 case MetaActionType::Transparent
:
1223 // ImplLine( ( (const MetaTransparentAction*) pMA )->GetPolyPolygon() );
1227 case MetaActionType::RASTEROP
:
1229 pMA
->Execute( &rVDev
);
1233 case MetaActionType::FLOATTRANSPARENT
:
1235 const MetaFloatTransparentAction
* pA
= static_cast<const MetaFloatTransparentAction
*>(pMA
);
1237 GDIMetaFile
aTmpMtf( pA
->GetGDIMetaFile() );
1238 Point
aSrcPt( aTmpMtf
.GetPrefMapMode().GetOrigin() );
1239 const Size
aSrcSize( aTmpMtf
.GetPrefSize() );
1240 const Point
aDestPt( pA
->GetPoint() );
1241 const Size
aDestSize( pA
->GetSize() );
1242 const double fScaleX
= aSrcSize
.Width() ? (double) aDestSize
.Width() / aSrcSize
.Width() : 1.0;
1243 const double fScaleY
= aSrcSize
.Height() ? (double) aDestSize
.Height() / aSrcSize
.Height() : 1.0;
1244 long nMoveX
, nMoveY
;
1246 if( fScaleX
!= 1.0 || fScaleY
!= 1.0 )
1248 aTmpMtf
.Scale( fScaleX
, fScaleY
);
1249 aSrcPt
.X() = FRound( aSrcPt
.X() * fScaleX
), aSrcPt
.Y() = FRound( aSrcPt
.Y() * fScaleY
);
1252 nMoveX
= aDestPt
.X() - aSrcPt
.X(), nMoveY
= aDestPt
.Y() - aSrcPt
.Y();
1254 if( nMoveX
|| nMoveY
)
1255 aTmpMtf
.Move( nMoveX
, nMoveY
);
1257 ImplWriteActions( aTmpMtf
, rVDev
);
1261 case MetaActionType::COMMENT
:
1263 const MetaCommentAction
* pA
= static_cast<const MetaCommentAction
*>(pMA
);
1264 if ( pA
->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") )
1266 const MetaGradientExAction
* pGradAction
= NULL
;
1267 while( ++nCurAction
< nCount
)
1269 MetaAction
* pAction
= rMtf
.GetAction( nCurAction
);
1270 if( pAction
->GetType() == MetaActionType::GRADIENTEX
)
1271 pGradAction
= static_cast<const MetaGradientExAction
*>(pAction
);
1272 else if( ( pAction
->GetType() == MetaActionType::COMMENT
) &&
1273 ( static_cast<const MetaCommentAction
*>(pAction
)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END") ) )
1279 ImplWriteGradient( pGradAction
->GetPolyPolygon(), pGradAction
->GetGradient(), rVDev
);
1281 else if ( pA
->GetComment().equals("XPATHFILL_SEQ_END") )
1283 if ( aFillPath
.Count() )
1285 aFillPath
= tools::PolyPolygon();
1286 ImplWriteLine( "gr" );
1291 const sal_uInt8
* pData
= pA
->GetData();
1294 SvMemoryStream
aMemStm( (void*)pData
, pA
->GetDataSize(), StreamMode::READ
);
1295 bool bSkipSequence
= false;
1298 if( pA
->GetComment().equals( "XPATHSTROKE_SEQ_BEGIN" ) )
1300 sSeqEnd
= "XPATHSTROKE_SEQ_END";
1301 SvtGraphicStroke aStroke
;
1302 ReadSvtGraphicStroke( aMemStm
, aStroke
);
1305 aStroke
.getPath( aPath
);
1307 tools::PolyPolygon aStartArrow
;
1308 tools::PolyPolygon aEndArrow
;
1309 // double fTransparency( aStroke.getTransparency() );
1310 double fStrokeWidth( aStroke
.getStrokeWidth() );
1311 SvtGraphicStroke::JoinType
eJT( aStroke
.getJoinType() );
1312 SvtGraphicStroke::DashArray l_aDashArray
;
1314 aStroke
.getStartArrow( aStartArrow
);
1315 aStroke
.getEndArrow( aEndArrow
);
1316 aStroke
.getDashArray( l_aDashArray
);
1318 bSkipSequence
= true;
1319 if ( l_aDashArray
.size() > 11 ) // ps dasharray limit is 11
1320 bSkipSequence
= false;
1321 if ( aStartArrow
.Count() || aEndArrow
.Count() )
1322 bSkipSequence
= false;
1323 if ( (sal_uInt32
)eJT
> 2 )
1324 bSkipSequence
= false;
1325 if ( l_aDashArray
.size() && ( fStrokeWidth
!= 0.0 ) )
1326 bSkipSequence
= false;
1327 if ( bSkipSequence
)
1329 ImplWriteLineInfo( fStrokeWidth
, aStroke
.getMiterLimit(),
1330 aStroke
.getCapType(), eJT
, l_aDashArray
);
1331 ImplPolyLine( aPath
);
1334 else if (pA
->GetComment().equals("XPATHFILL_SEQ_BEGIN"))
1336 sSeqEnd
= "XPATHFILL_SEQ_END";
1337 SvtGraphicFill aFill
;
1338 ReadSvtGraphicFill( aMemStm
, aFill
);
1339 switch( aFill
.getFillType() )
1341 case SvtGraphicFill::fillSolid
:
1343 bSkipSequence
= true;
1344 tools::PolyPolygon aPolyPoly
;
1345 aFill
.getPath( aPolyPoly
);
1346 sal_uInt16 i
, nPolyCount
= aPolyPoly
.Count();
1349 aFillColor
= aFill
.getFillColor();
1350 ImplWriteFillColor( PS_SPACE
);
1351 for ( i
= 0; i
< nPolyCount
; )
1353 ImplAddPath( aPolyPoly
.GetObject( i
) );
1354 if ( ++i
< nPolyCount
)
1356 mpPS
->WriteCharPtr( "p" );
1358 ImplExecMode( PS_RET
);
1361 mpPS
->WriteCharPtr( "p ef" );
1363 ImplExecMode( PS_RET
);
1368 case SvtGraphicFill::fillTexture
:
1370 aFill
.getPath( aFillPath
);
1372 /* normally an object filling is consisting of three MetaActions:
1373 MetaBitmapAction using RasterOp xor,
1374 MetaPolyPolygonAction using RasterOp rop_0
1375 MetaBitmapAction using RasterOp xor
1377 Because RasterOps cannot been used in Postscript, we have to
1378 replace these actions. The MetaComment "XPATHFILL_SEQ_BEGIN" is
1379 providing the clippath of the object. The following loop is
1380 trying to find the bitmap that is matching the clippath, so that
1381 only one bitmap is exported, otherwise if the bitmap is not
1382 locatable, all metaactions are played normally.
1384 sal_uInt32 nCommentStartAction
= nCurAction
;
1385 sal_uInt32 nBitmapCount
= 0;
1386 sal_uInt32 nBitmapAction
= 0;
1389 while( bOk
&& ( ++nCurAction
< nCount
) )
1391 MetaAction
* pAction
= rMtf
.GetAction( nCurAction
);
1392 switch( pAction
->GetType() )
1394 case MetaActionType::BMPSCALE
:
1395 case MetaActionType::BMPSCALEPART
:
1396 case MetaActionType::BMPEXSCALE
:
1397 case MetaActionType::BMPEXSCALEPART
:
1400 nBitmapAction
= nCurAction
;
1403 case MetaActionType::COMMENT
:
1405 if (static_cast<const MetaCommentAction
*>(pAction
)->GetComment().equals("XPATHFILL_SEQ_END"))
1412 if( nBitmapCount
== 2 )
1414 ImplWriteLine( "gs" );
1415 ImplIntersect( aFillPath
);
1416 GDIMetaFile aTempMtf
;
1417 aTempMtf
.AddAction( rMtf
.GetAction( nBitmapAction
)->Clone() );
1418 ImplWriteActions( aTempMtf
, rVDev
);
1419 ImplWriteLine( "gr" );
1420 aFillPath
= tools::PolyPolygon();
1423 nCurAction
= nCommentStartAction
+ 1;
1427 case SvtGraphicFill::fillGradient
:
1428 aFill
.getPath( aFillPath
);
1431 case SvtGraphicFill::fillHatch
:
1434 if ( aFillPath
.Count() )
1436 ImplWriteLine( "gs" );
1437 ImplIntersect( aFillPath
);
1440 if ( bSkipSequence
)
1442 while( ++nCurAction
< nCount
)
1444 pMA
= rMtf
.GetAction( nCurAction
);
1445 if ( pMA
->GetType() == MetaActionType::COMMENT
)
1447 OString
sComment( static_cast<MetaCommentAction
*>(pMA
)->GetComment() );
1448 if ( sComment
.equals( sSeqEnd
) )
1466 inline void PSWriter::ImplWritePoint( const Point
& rPoint
, sal_uInt32 nMode
)
1468 ImplWriteDouble( rPoint
.X() );
1469 ImplWriteDouble( rPoint
.Y(), nMode
);
1474 void PSWriter::ImplMoveTo( const Point
& rPoint
, sal_uInt32 nMode
)
1476 ImplWritePoint( rPoint
);
1477 ImplWriteByte( 'm' );
1478 ImplExecMode( nMode
);
1483 void PSWriter::ImplLineTo( const Point
& rPoint
, sal_uInt32 nMode
)
1485 ImplWritePoint( rPoint
);
1486 ImplWriteByte( 'l' );
1487 ImplExecMode( nMode
);
1492 void PSWriter::ImplCurveTo( const Point
& rP1
, const Point
& rP2
, const Point
& rP3
, sal_uInt32 nMode
)
1494 ImplWritePoint( rP1
);
1495 ImplWritePoint( rP2
);
1496 ImplWritePoint( rP3
);
1497 mpPS
->WriteCharPtr( "ct " );
1498 ImplExecMode( nMode
);
1503 void PSWriter::ImplTranslate( const double& fX
, const double& fY
, sal_uInt32 nMode
)
1505 ImplWriteDouble( fX
);
1506 ImplWriteDouble( fY
);
1507 ImplWriteByte( 't' );
1508 ImplExecMode( nMode
);
1513 void PSWriter::ImplScale( const double& fX
, const double& fY
, sal_uInt32 nMode
)
1515 ImplWriteDouble( fX
);
1516 ImplWriteDouble( fY
);
1517 ImplWriteByte( 's' );
1518 ImplExecMode( nMode
);
1523 void PSWriter::ImplRect( const Rectangle
& rRect
)
1526 ImplRectFill( rRect
);
1529 double nWidth
= rRect
.GetWidth();
1530 double nHeight
= rRect
.GetHeight();
1532 ImplWriteLineColor( PS_SPACE
);
1533 ImplMoveTo( rRect
.TopLeft() );
1534 ImplWriteDouble( nWidth
);
1535 mpPS
->WriteCharPtr( "0 rl 0 " );
1536 ImplWriteDouble( nHeight
);
1537 mpPS
->WriteCharPtr( "rl " );
1538 ImplWriteDouble( nWidth
);
1539 mpPS
->WriteCharPtr( "neg 0 rl " );
1540 ImplClosePathDraw();
1542 mpPS
->WriteUChar( 10 );
1548 void PSWriter::ImplRectFill( const Rectangle
& rRect
)
1550 double nWidth
= rRect
.GetWidth();
1551 double nHeight
= rRect
.GetHeight();
1553 ImplWriteFillColor( PS_SPACE
);
1554 ImplMoveTo( rRect
.TopLeft() );
1555 ImplWriteDouble( nWidth
);
1556 mpPS
->WriteCharPtr( "0 rl 0 " );
1557 ImplWriteDouble( nHeight
);
1558 mpPS
->WriteCharPtr( "rl " );
1559 ImplWriteDouble( nWidth
);
1560 mpPS
->WriteCharPtr( "neg 0 rl ef " );
1561 mpPS
->WriteCharPtr( "p ef" );
1563 ImplExecMode( PS_RET
);
1568 void PSWriter::ImplAddPath( const Polygon
& rPolygon
)
1570 sal_uInt16 nPointCount
= rPolygon
.GetSize();
1571 if ( nPointCount
> 1 )
1574 ImplMoveTo( rPolygon
.GetPoint( 0 ) );
1575 while ( i
< nPointCount
)
1577 if ( ( rPolygon
.GetFlags( i
) == POLY_CONTROL
)
1578 && ( ( i
+ 2 ) < nPointCount
)
1579 && ( rPolygon
.GetFlags( i
+ 1 ) == POLY_CONTROL
)
1580 && ( rPolygon
.GetFlags( i
+ 2 ) != POLY_CONTROL
) )
1582 ImplCurveTo( rPolygon
[ i
], rPolygon
[ i
+ 1 ], rPolygon
[ i
+ 2 ], PS_WRAP
);
1586 ImplLineTo( rPolygon
.GetPoint( i
++ ), PS_SPACE
| PS_WRAP
);
1593 void PSWriter::ImplIntersect( const tools::PolyPolygon
& rPolyPoly
)
1595 sal_uInt16 i
, nPolyCount
= rPolyPoly
.Count();
1596 for ( i
= 0; i
< nPolyCount
; )
1598 ImplAddPath( rPolyPoly
.GetObject( i
) );
1599 if ( ++i
< nPolyCount
)
1601 mpPS
->WriteCharPtr( "p" );
1603 ImplExecMode( PS_RET
);
1606 ImplWriteLine( "eoclip newpath" );
1611 void PSWriter::ImplWriteGradient( const tools::PolyPolygon
& rPolyPoly
, const Gradient
& rGradient
, VirtualDevice
& rVDev
)
1613 ScopedVclPtrInstance
< VirtualDevice
> l_pVDev
;
1614 GDIMetaFile aTmpMtf
;
1615 l_pVDev
->SetMapMode( rVDev
.GetMapMode() );
1616 l_pVDev
->AddGradientActions( rPolyPoly
.GetBoundRect(), rGradient
, aTmpMtf
);
1617 ImplWriteActions( aTmpMtf
, rVDev
);
1622 void PSWriter::ImplPolyPoly( const tools::PolyPolygon
& rPolyPoly
, bool bTextOutline
)
1624 sal_uInt16 i
, nPolyCount
= rPolyPoly
.Count();
1627 if ( bFillColor
|| bTextOutline
)
1630 ImplWriteTextColor( PS_SPACE
);
1632 ImplWriteFillColor( PS_SPACE
);
1633 for ( i
= 0; i
< nPolyCount
; )
1635 ImplAddPath( rPolyPoly
.GetObject( i
) );
1636 if ( ++i
< nPolyCount
)
1638 mpPS
->WriteCharPtr( "p" );
1640 ImplExecMode( PS_RET
);
1643 mpPS
->WriteCharPtr( "p ef" );
1645 ImplExecMode( PS_RET
);
1649 ImplWriteLineColor( PS_SPACE
);
1650 for ( i
= 0; i
< nPolyCount
; i
++ )
1651 ImplAddPath( rPolyPoly
.GetObject( i
) );
1652 ImplClosePathDraw( PS_RET
);
1659 void PSWriter::ImplPolyLine( const Polygon
& rPoly
)
1663 ImplWriteLineColor( PS_SPACE
);
1664 sal_uInt16 i
, nPointCount
= rPoly
.GetSize();
1667 if ( nPointCount
> 1 )
1669 ImplMoveTo( rPoly
.GetPoint( 0 ) );
1671 while ( i
< nPointCount
)
1673 if ( ( rPoly
.GetFlags( i
) == POLY_CONTROL
)
1674 && ( ( i
+ 2 ) < nPointCount
)
1675 && ( rPoly
.GetFlags( i
+ 1 ) == POLY_CONTROL
)
1676 && ( rPoly
.GetFlags( i
+ 2 ) != POLY_CONTROL
) )
1678 ImplCurveTo( rPoly
[ i
], rPoly
[ i
+ 1 ], rPoly
[ i
+ 2 ], PS_WRAP
);
1682 ImplLineTo( rPoly
.GetPoint( i
++ ), PS_SPACE
| PS_WRAP
);
1686 // #104645# explicitly close path if polygon is closed
1687 if( rPoly
[ 0 ] == rPoly
[ nPointCount
-1 ] )
1688 ImplClosePathDraw( PS_RET
);
1697 void PSWriter::ImplSetClipRegion( vcl::Region
& rClipRegion
)
1699 if ( !rClipRegion
.IsEmpty() )
1701 RectangleVector aRectangles
;
1702 rClipRegion
.GetRegionRectangles(aRectangles
);
1704 for(RectangleVector::const_iterator
aRectIter(aRectangles
.begin()); aRectIter
!= aRectangles
.end(); ++aRectIter
)
1706 double nX1(aRectIter
->Left());
1707 double nY1(aRectIter
->Top());
1708 double nX2(aRectIter
->Right());
1709 double nY2(aRectIter
->Bottom());
1711 ImplWriteDouble( nX1
);
1712 ImplWriteDouble( nY1
);
1713 ImplWriteByte( 'm' );
1714 ImplWriteDouble( nX2
);
1715 ImplWriteDouble( nY1
);
1716 ImplWriteByte( 'l' );
1717 ImplWriteDouble( nX2
);
1718 ImplWriteDouble( nY2
);
1719 ImplWriteByte( 'l' );
1720 ImplWriteDouble( nX1
);
1721 ImplWriteDouble( nY2
);
1722 ImplWriteByte( 'l' );
1723 ImplWriteDouble( nX1
);
1724 ImplWriteDouble( nY1
);
1725 ImplWriteByte( 'l', PS_SPACE
| PS_WRAP
);
1729 //RegionHandle hRegionHandle = rClipRegion.BeginEnumRects();
1731 //while ( rClipRegion.GetEnumRects( hRegionHandle, aRect ) )
1733 // double nX1 = aRect.Left();
1734 // double nY1 = aRect.Top();
1735 // double nX2 = aRect.Right();
1736 // double nY2 = aRect.Bottom();
1737 // ImplWriteDouble( nX1 );
1738 // ImplWriteDouble( nY1 );
1739 // ImplWriteByte( 'm' );
1740 // ImplWriteDouble( nX2 );
1741 // ImplWriteDouble( nY1 );
1742 // ImplWriteByte( 'l' );
1743 // ImplWriteDouble( nX2 );
1744 // ImplWriteDouble( nY2 );
1745 // ImplWriteByte( 'l' );
1746 // ImplWriteDouble( nX1 );
1747 // ImplWriteDouble( nY2 );
1748 // ImplWriteByte( 'l' );
1749 // ImplWriteDouble( nX1 );
1750 // ImplWriteDouble( nY1 );
1751 // ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
1753 //rClipRegion.EndEnumRects( hRegionHandle );
1754 ImplWriteLine( "eoclip newpath" );
1759 // possible gfx formats:
1761 // level 1: grayscale 8 bit
1764 // level 2: grayscale 8 bit
1765 // color 1(pal), 4(pal), 8(pal), 24 Bit
1768 void PSWriter::ImplBmp( Bitmap
* pBitmap
, Bitmap
* pMaskBitmap
, const Point
& rPoint
, double nXWidth
, double nYHeightOrg
)
1773 sal_Int32 nHeightOrg
= pBitmap
->GetSizePixel().Height();
1774 sal_Int32 nHeightLeft
= nHeightOrg
;
1775 long nWidth
= pBitmap
->GetSizePixel().Width();
1776 Point
aSourcePos( rPoint
);
1778 while ( nHeightLeft
)
1780 Bitmap
aTileBitmap( *pBitmap
);
1781 long nHeight
= nHeightLeft
;
1782 double nYHeight
= nYHeightOrg
;
1784 bool bDoTrans
= false;
1787 vcl::Region aRegion
;
1799 aRect
= Rectangle( Point( 0, nHeightOrg
- nHeightLeft
), Size( (long)nWidth
, (long)nHeight
) );
1800 aRegion
= vcl::Region( pMaskBitmap
->CreateRegion( COL_BLACK
, aRect
) );
1804 RectangleVector aRectangleVector
;
1805 aRegion
.GetRegionRectangles(aRectangleVector
);
1807 if ( aRectangleVector
.size() * 5 > 1000 )
1818 if ( nHeight
!= nHeightOrg
)
1820 nYHeight
= nYHeightOrg
* nHeight
/ nHeightOrg
;
1821 aTileBitmap
.Crop( Rectangle( Point( 0, nHeightOrg
- nHeightLeft
), Size( nWidth
, nHeight
) ) );
1825 ImplWriteLine( "gs\npum" );
1826 ImplTranslate( aSourcePos
.X(), aSourcePos
.Y() );
1827 ImplScale( nXWidth
/ nWidth
, nYHeight
/ nHeight
);
1829 RectangleVector aRectangles
;
1830 aRegion
.GetRegionRectangles(aRectangles
);
1831 const long nMoveVertical(nHeightLeft
- nHeightOrg
);
1833 for(RectangleVector::iterator
aRectIter(aRectangles
.begin()); aRectIter
!= aRectangles
.end(); ++aRectIter
)
1835 aRectIter
->Move(0, nMoveVertical
);
1837 ImplWriteLong( aRectIter
->Left() );
1838 ImplWriteLong( aRectIter
->Top() );
1839 ImplWriteByte( 'm' );
1840 ImplWriteLong( aRectIter
->Right() + 1 );
1841 ImplWriteLong( aRectIter
->Top() );
1842 ImplWriteByte( 'l' );
1843 ImplWriteLong( aRectIter
->Right() + 1 );
1844 ImplWriteLong( aRectIter
->Bottom() + 1 );
1845 ImplWriteByte( 'l' );
1846 ImplWriteLong( aRectIter
->Left() );
1847 ImplWriteLong( aRectIter
->Bottom() + 1 );
1848 ImplWriteByte( 'l' );
1849 ImplWriteByte( 'p', PS_SPACE
| PS_WRAP
);
1852 //RegionHandle hRegionHandle = aRegion.BeginEnumRects();
1854 //while ( aRegion.GetEnumRects( hRegionHandle, aRect ) )
1856 // aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) );
1857 // ImplWriteLong( aRect.Left() );
1858 // ImplWriteLong( aRect.Top() );
1859 // ImplWriteByte( 'm' );
1860 // ImplWriteLong( aRect.Right() + 1 );
1861 // ImplWriteLong( aRect.Top() );
1862 // ImplWriteByte( 'l' );
1863 // ImplWriteLong( aRect.Right() + 1 );
1864 // ImplWriteLong( aRect.Bottom() + 1 );
1865 // ImplWriteByte( 'l' );
1866 // ImplWriteLong( aRect.Left() );
1867 // ImplWriteLong( aRect.Bottom() + 1 );
1868 // ImplWriteByte( 'l' );
1869 // ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
1871 //aRegion.EndEnumRects( hRegionHandle );
1872 ImplWriteLine( "eoclip newpath" );
1873 ImplWriteLine( "pom" );
1875 BitmapReadAccess
* pAcc
= aTileBitmap
.AcquireReadAccess();
1878 ImplWriteLine( "pum" );
1880 ImplTranslate( aSourcePos
.X(), aSourcePos
.Y() + nYHeight
);
1881 ImplScale( nXWidth
, nYHeight
);
1882 if ( mnLevel
== 1 ) // level 1 is always grayscale !!!
1884 ImplWriteLong( nWidth
);
1885 ImplWriteLong( nHeight
);
1886 mpPS
->WriteCharPtr( "8 [" );
1887 ImplWriteLong( nWidth
);
1888 mpPS
->WriteCharPtr( "0 0 " );
1889 ImplWriteLong( -nHeight
);
1891 ImplWriteLong( nHeight
);
1892 ImplWriteLine( "]" );
1893 mpPS
->WriteCharPtr( "{currentfile " );
1894 ImplWriteLong( nWidth
);
1895 ImplWriteLine( "string readhexstring pop}" );
1896 ImplWriteLine( "image" );
1897 for ( long y
= 0; y
< nHeight
; y
++ )
1899 for ( long x
= 0; x
< nWidth
; x
++ )
1901 ImplWriteHexByte( pAcc
->GetPixelIndex( y
, x
) );
1904 mpPS
->WriteUChar( 10 );
1910 ImplWriteLine( "/DeviceGray setcolorspace" );
1911 ImplWriteLine( "<<" );
1912 ImplWriteLine( "/ImageType 1" );
1913 mpPS
->WriteCharPtr( "/Width " );
1914 ImplWriteLong( nWidth
, PS_RET
);
1915 mpPS
->WriteCharPtr( "/Height " );
1916 ImplWriteLong( nHeight
, PS_RET
);
1917 ImplWriteLine( "/BitsPerComponent 8" );
1918 ImplWriteLine( "/Decode[0 1]" );
1919 mpPS
->WriteCharPtr( "/ImageMatrix[" );
1920 ImplWriteLong( nWidth
);
1921 mpPS
->WriteCharPtr( "0 0 " );
1922 ImplWriteLong( -nHeight
);
1924 ImplWriteLong( nHeight
, PS_NONE
);
1925 ImplWriteByte( ']', PS_RET
);
1926 ImplWriteLine( "/DataSource currentfile" );
1927 ImplWriteLine( "/ASCIIHexDecode filter" );
1928 if ( mbCompression
)
1929 ImplWriteLine( "/LZWDecode filter" );
1930 ImplWriteLine( ">>" );
1931 ImplWriteLine( "image" );
1932 if ( mbCompression
)
1935 for ( long y
= 0; y
< nHeight
; y
++ )
1937 for ( long x
= 0; x
< nWidth
; x
++ )
1939 Compress( pAcc
->GetPixelIndex( y
, x
) );
1946 for ( long y
= 0; y
< nHeight
; y
++ )
1948 for ( long x
= 0; x
< nWidth
; x
++ )
1950 ImplWriteHexByte( pAcc
->GetPixelIndex( y
, x
) );
1957 // have we to write a palette ?
1959 if ( pAcc
->HasPalette() )
1961 ImplWriteLine( "[/Indexed /DeviceRGB " );
1962 ImplWriteLong( pAcc
->GetPaletteEntryCount() - 1, PS_RET
);
1963 ImplWriteByte( '<', PS_NONE
);
1964 for ( sal_uInt16 i
= 0; i
< pAcc
->GetPaletteEntryCount(); i
++ )
1966 BitmapColor aBitmapColor
= pAcc
->GetPaletteColor( i
);
1967 ImplWriteHexByte( aBitmapColor
.GetRed(), PS_NONE
);
1968 ImplWriteHexByte( aBitmapColor
.GetGreen(), PS_NONE
);
1969 ImplWriteHexByte( aBitmapColor
.GetBlue(), PS_SPACE
| PS_WRAP
);
1971 ImplWriteByte( '>', PS_RET
);
1973 ImplWriteLine( "] setcolorspace" );
1974 ImplWriteLine( "<<" );
1975 ImplWriteLine( "/ImageType 1" );
1976 mpPS
->WriteCharPtr( "/Width " );
1977 ImplWriteLong( nWidth
, PS_RET
);
1978 mpPS
->WriteCharPtr( "/Height " );
1979 ImplWriteLong( nHeight
, PS_RET
);
1980 ImplWriteLine( "/BitsPerComponent 8" );
1981 ImplWriteLine( "/Decode[0 255]" );
1982 mpPS
->WriteCharPtr( "/ImageMatrix[" );
1983 ImplWriteLong( nWidth
);
1984 mpPS
->WriteCharPtr( "0 0 " );
1985 ImplWriteLong( -nHeight
);
1987 ImplWriteLong( nHeight
, PS_NONE
);
1988 ImplWriteByte( ']', PS_RET
);
1989 ImplWriteLine( "/DataSource currentfile" );
1990 ImplWriteLine( "/ASCIIHexDecode filter" );
1991 if ( mbCompression
)
1992 ImplWriteLine( "/LZWDecode filter" );
1993 ImplWriteLine( ">>" );
1994 ImplWriteLine( "image" );
1995 if ( mbCompression
)
1998 for ( long y
= 0; y
< nHeight
; y
++ )
2000 for ( long x
= 0; x
< nWidth
; x
++ )
2002 Compress( pAcc
->GetPixelIndex( y
, x
) );
2009 for ( long y
= 0; y
< nHeight
; y
++ )
2011 for ( long x
= 0; x
< nWidth
; x
++ )
2013 ImplWriteHexByte( pAcc
->GetPixelIndex( y
, x
) );
2018 else // 24 bit color
2020 ImplWriteLine( "/DeviceRGB setcolorspace" );
2021 ImplWriteLine( "<<" );
2022 ImplWriteLine( "/ImageType 1" );
2023 mpPS
->WriteCharPtr( "/Width " );
2024 ImplWriteLong( nWidth
, PS_RET
);
2025 mpPS
->WriteCharPtr( "/Height " );
2026 ImplWriteLong( nHeight
, PS_RET
);
2027 ImplWriteLine( "/BitsPerComponent 8" );
2028 ImplWriteLine( "/Decode[0 1 0 1 0 1]" );
2029 mpPS
->WriteCharPtr( "/ImageMatrix[" );
2030 ImplWriteLong( nWidth
);
2031 mpPS
->WriteCharPtr( "0 0 " );
2032 ImplWriteLong( -nHeight
);
2034 ImplWriteLong( nHeight
, PS_NONE
);
2035 ImplWriteByte( ']', PS_RET
);
2036 ImplWriteLine( "/DataSource currentfile" );
2037 ImplWriteLine( "/ASCIIHexDecode filter" );
2038 if ( mbCompression
)
2039 ImplWriteLine( "/LZWDecode filter" );
2040 ImplWriteLine( ">>" );
2041 ImplWriteLine( "image" );
2042 if ( mbCompression
)
2045 for ( long y
= 0; y
< nHeight
; y
++ )
2047 for ( long x
= 0; x
< nWidth
; x
++ )
2049 const BitmapColor
aBitmapColor( pAcc
->GetPixel( y
, x
) );
2050 Compress( aBitmapColor
.GetRed() );
2051 Compress( aBitmapColor
.GetGreen() );
2052 Compress( aBitmapColor
.GetBlue() );
2059 for ( long y
= 0; y
< nHeight
; y
++ )
2061 for ( long x
= 0; x
< nWidth
; x
++ )
2063 const BitmapColor
aBitmapColor( pAcc
->GetPixel( y
, x
) );
2064 ImplWriteHexByte( aBitmapColor
.GetRed() );
2065 ImplWriteHexByte( aBitmapColor
.GetGreen() );
2066 ImplWriteHexByte( aBitmapColor
.GetBlue() );
2072 ImplWriteLine( ">" ); // in Level 2 the dictionary needs to be closed (eod)
2075 ImplWriteLine( "gr" );
2077 ImplWriteLine( "pom" );
2079 Bitmap::ReleaseAccess( pAcc
);
2080 nHeightLeft
-= nHeight
;
2084 aSourcePos
.Y() = (long) ( rPoint
.Y() + ( nYHeightOrg
* ( nHeightOrg
- nHeightLeft
) ) / nHeightOrg
);
2091 void PSWriter::ImplWriteCharacter( sal_Char nChar
)
2098 ImplWriteByte( (sal_uInt8
)'\\', PS_NONE
);
2100 ImplWriteByte( (sal_uInt8
)nChar
, PS_NONE
);
2105 void PSWriter::ImplWriteString( const OString
& rString
, VirtualDevice
& rVDev
, const long* pDXArry
, bool bStretch
)
2107 sal_Int32 nLen
= rString
.getLength();
2114 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
2117 nx
= pDXArry
[ i
- 1 ];
2118 ImplWriteDouble( ( bStretch
) ? nx
: rVDev
.GetTextWidth( OUString(rString
[i
]) ) );
2119 ImplWriteDouble( nx
);
2120 ImplWriteLine( "(", PS_NONE
);
2121 ImplWriteCharacter( rString
[i
] );
2122 ImplWriteLine( ") bs" );
2127 ImplWriteByte( '(', PS_NONE
);
2128 for (sal_Int32 i
= 0; i
< nLen
; ++i
)
2129 ImplWriteCharacter( rString
[i
] );
2130 ImplWriteLine( ") sw" );
2137 void PSWriter::ImplText( const OUString
& rUniString
, const Point
& rPos
, const long* pDXArry
, sal_Int32 nWidth
, VirtualDevice
& rVDev
)
2139 if ( rUniString
.isEmpty() )
2141 if ( mnTextMode
== 0 ) // using glpyh outlines
2143 vcl::Font
aNotRotatedFont( maFont
);
2144 aNotRotatedFont
.SetOrientation( 0 );
2146 ScopedVclPtrInstance
< VirtualDevice
> pVirDev( 1 );
2147 pVirDev
->SetMapMode( rVDev
.GetMapMode() );
2148 pVirDev
->SetFont( aNotRotatedFont
);
2149 pVirDev
->SetTextAlign( eTextAlign
);
2151 sal_Int16 nRotation
= maFont
.GetOrientation();
2152 Polygon
aPolyDummy( 1 );
2157 aPolyDummy
.SetPoint( aPos
, 0 );
2158 aPolyDummy
.Rotate( rPos
, nRotation
);
2159 aPos
= aPolyDummy
.GetPoint( 0 );
2161 bool bOldLineColor
= bLineColor
;
2163 std::vector
<tools::PolyPolygon
> aPolyPolyVec
;
2164 if ( pVirDev
->GetTextOutlines( aPolyPolyVec
, rUniString
, 0, 0, -1, true, nWidth
, pDXArry
) )
2166 // always adjust text position to match baseline alignment
2167 ImplWriteLine( "pum" );
2168 ImplWriteDouble( aPos
.X() );
2169 ImplWriteDouble( aPos
.Y() );
2170 ImplWriteLine( "t" );
2173 ImplWriteF( nRotation
, 1 );
2174 mpPS
->WriteCharPtr( "r " );
2176 std::vector
<tools::PolyPolygon
>::iterator
aIter( aPolyPolyVec
.begin() );
2177 while ( aIter
!= aPolyPolyVec
.end() )
2178 ImplPolyPoly( *aIter
++, true );
2179 ImplWriteLine( "pom" );
2181 bLineColor
= bOldLineColor
;
2183 else if ( ( mnTextMode
== 1 ) || ( mnTextMode
== 2 ) ) // normal text output
2185 if ( mnTextMode
== 2 ) // forcing output one complete text packet, by
2186 pDXArry
= NULL
; // ignoring the kerning array
2187 ImplSetAttrForText( rPos
);
2188 OString
aStr(OUStringToOString(rUniString
,
2189 maFont
.GetCharSet()));
2190 ImplWriteString( aStr
, rVDev
, pDXArry
, nWidth
!= 0 );
2191 if ( maFont
.GetOrientation() )
2192 ImplWriteLine( "gr" );
2198 void PSWriter::ImplSetAttrForText( const Point
& rPoint
)
2200 Point
aPoint( rPoint
);
2202 long nRotation
= maFont
.GetOrientation();
2203 ImplWriteTextColor();
2205 Size aSize
= maFont
.GetSize();
2207 if ( maLastFont
!= maFont
)
2209 if ( maFont
.GetPitch() == PITCH_FIXED
) // a little bit font selection
2210 ImplDefineFont( "Courier", "Oblique" );
2211 else if ( maFont
.GetCharSet() == RTL_TEXTENCODING_SYMBOL
)
2212 ImplWriteLine( "/Symbol findfont" );
2213 else if ( maFont
.GetFamily() == FAMILY_SWISS
)
2214 ImplDefineFont( "Helvetica", "Oblique" );
2216 ImplDefineFont( "Times", "Italic" );
2218 maLastFont
= maFont
;
2219 aSize
= maFont
.GetSize();
2220 ImplWriteDouble( aSize
.Height() );
2221 mpPS
->WriteCharPtr( "sf " );
2223 if ( eTextAlign
!= ALIGN_BASELINE
)
2224 { // PostScript kennt kein FontAlignment
2225 if ( eTextAlign
== ALIGN_TOP
) // -> so I assume that
2226 aPoint
.Y() += ( aSize
.Height() * 4 / 5 ); // the area under the baseline
2227 else if ( eTextAlign
== ALIGN_BOTTOM
) // is about 20% of the font size
2228 aPoint
.Y() -= ( aSize
.Height() / 5 );
2230 ImplMoveTo( aPoint
);
2233 mpPS
->WriteCharPtr( "gs " );
2234 ImplWriteF( nRotation
, 1 );
2235 mpPS
->WriteCharPtr( "r " );
2241 void PSWriter::ImplDefineFont( const char* pOriginalName
, const char* pItalic
)
2243 mpPS
->WriteUChar( '/' ); //convert the font pOriginalName using ISOLatin1Encoding
2244 mpPS
->WriteCharPtr( pOriginalName
);
2245 switch ( maFont
.GetWeight() )
2247 case WEIGHT_SEMIBOLD
:
2249 case WEIGHT_ULTRABOLD
:
2251 mpPS
->WriteCharPtr( "-Bold" );
2252 if ( maFont
.GetItalic() != ITALIC_NONE
)
2253 mpPS
->WriteCharPtr( pItalic
);
2256 if ( maFont
.GetItalic() != ITALIC_NONE
)
2257 mpPS
->WriteCharPtr( pItalic
);
2260 ImplWriteLine( " f" );
2267 void PSWriter::ImplClosePathDraw( sal_uLong nMode
)
2269 mpPS
->WriteCharPtr( "pc" );
2271 ImplExecMode( nMode
);
2274 void PSWriter::ImplPathDraw()
2276 mpPS
->WriteCharPtr( "ps" );
2278 ImplExecMode( PS_RET
);
2283 inline void PSWriter::ImplWriteLineColor( sal_uLong nMode
)
2285 if ( aColor
!= aLineColor
)
2287 aColor
= aLineColor
;
2288 ImplWriteColor( nMode
);
2291 inline void PSWriter::ImplWriteFillColor( sal_uLong nMode
)
2293 if ( aColor
!= aFillColor
)
2295 aColor
= aFillColor
;
2296 ImplWriteColor( nMode
);
2299 inline void PSWriter::ImplWriteTextColor( sal_uLong nMode
)
2301 if ( aColor
!= aTextColor
)
2303 aColor
= aTextColor
;
2304 ImplWriteColor( nMode
);
2308 void PSWriter::ImplWriteColor( sal_uLong nMode
)
2312 // writes the Color (grayscale) as a Number from 0.000 up to 1.000
2314 ImplWriteF( 1000 * ( (sal_uInt8
)aColor
.GetRed() * 77 + (sal_uInt8
)aColor
.GetGreen() * 151 +
2315 (sal_uInt8
)aColor
.GetBlue() * 28 + 1 ) / 65536, 3, nMode
);
2319 ImplWriteB1 ( (sal_uInt8
)aColor
.GetRed() );
2320 ImplWriteB1 ( (sal_uInt8
)aColor
.GetGreen() );
2321 ImplWriteB1 ( (sal_uInt8
)aColor
.GetBlue() );
2323 mpPS
->WriteCharPtr( "c" ); // ( c is defined as setrgbcolor or setgray )
2324 ImplExecMode( nMode
);
2329 double PSWriter::ImplGetScaling( const MapMode
& rMapMode
)
2332 switch ( rMapMode
.GetMapUnit() )
2350 case MAP_1000TH_INCH
:
2353 case MAP_100TH_INCH
:
2356 case MAP_10TH_INCH
:
2377 void PSWriter::ImplGetMapMode( const MapMode
& rMapMode
)
2379 ImplWriteLine( "tm setmatrix" );
2380 double fMul
= ImplGetScaling( rMapMode
);
2381 double fScaleX
= (double)rMapMode
.GetScaleX() * fMul
;
2382 double fScaleY
= (double)rMapMode
.GetScaleY() * fMul
;
2383 ImplTranslate( rMapMode
.GetOrigin().X() * fScaleX
, rMapMode
.GetOrigin().Y() * fScaleY
);
2384 ImplScale( fScaleX
, fScaleY
);
2389 inline void PSWriter::ImplExecMode( sal_uLong nMode
)
2391 if ( nMode
& PS_WRAP
)
2393 if ( mnCursorPos
>= PS_LINESIZE
)
2396 mpPS
->WriteUChar( 0xa );
2400 if ( nMode
& PS_SPACE
)
2402 mpPS
->WriteUChar( 32 );
2405 if ( nMode
& PS_RET
)
2407 mpPS
->WriteUChar( 0xa );
2414 inline void PSWriter::ImplWriteLine( const char* pString
, sal_uLong nMode
)
2417 while ( pString
[ i
] )
2419 mpPS
->WriteUChar( pString
[ i
++ ] );
2422 ImplExecMode( nMode
);
2427 void PSWriter::ImplWriteLineInfo( double fLWidth
, double fMLimit
,
2428 SvtGraphicStroke::CapType eLCap
,
2429 SvtGraphicStroke::JoinType eJoin
,
2430 SvtGraphicStroke::DashArray
& rLDash
)
2432 if ( fLineWidth
!= fLWidth
)
2434 fLineWidth
= fLWidth
;
2435 ImplWriteDouble( fLineWidth
);
2436 ImplWriteLine( "lw", PS_SPACE
);
2438 if ( eLineCap
!= eLCap
)
2441 ImplWriteLong( (sal_Int32
)eLineCap
, PS_SPACE
);
2442 ImplWriteLine( "lc", PS_SPACE
);
2444 if ( eJoinType
!= eJoin
)
2447 ImplWriteLong( (sal_Int32
)eJoinType
, PS_SPACE
);
2448 ImplWriteLine( "lj", PS_SPACE
);
2450 if ( eJoinType
== SvtGraphicStroke::joinMiter
)
2452 if ( fMiterLimit
!= fMLimit
)
2454 fMiterLimit
= fMLimit
;
2455 ImplWriteDouble( fMiterLimit
);
2456 ImplWriteLine( "ml", PS_SPACE
);
2459 if ( aDashArray
!= rLDash
)
2461 aDashArray
= rLDash
;
2462 sal_uInt32 j
, i
= aDashArray
.size();
2463 ImplWriteLine( "[", PS_SPACE
);
2464 for ( j
= 0; j
< i
; j
++ )
2465 ImplWriteDouble( aDashArray
[ j
] );
2466 ImplWriteLine( "] 0 ld" );
2472 void PSWriter::ImplWriteLineInfo( const LineInfo
& rLineInfo
)
2474 SvtGraphicStroke::DashArray l_aDashArray
;
2475 if ( rLineInfo
.GetStyle() == LINE_DASH
)
2476 l_aDashArray
.push_back( 2 );
2477 const double fLWidth(( ( rLineInfo
.GetWidth() + 1 ) + ( rLineInfo
.GetWidth() + 1 ) ) * 0.5);
2478 SvtGraphicStroke::JoinType
aJoinType(SvtGraphicStroke::joinMiter
);
2479 SvtGraphicStroke::CapType
aCapType(SvtGraphicStroke::capButt
);
2481 switch(rLineInfo
.GetLineJoin())
2483 default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
2484 // do NOT use SvtGraphicStroke::joinNone here
2485 // since it will be written as numerical value directly
2486 // and is NOT a valid EPS value
2488 case basegfx::B2DLINEJOIN_MITER
:
2489 aJoinType
= SvtGraphicStroke::joinMiter
;
2491 case basegfx::B2DLINEJOIN_BEVEL
:
2492 aJoinType
= SvtGraphicStroke::joinBevel
;
2494 case basegfx::B2DLINEJOIN_ROUND
:
2495 aJoinType
= SvtGraphicStroke::joinRound
;
2498 switch(rLineInfo
.GetLineCap())
2500 default: /* com::sun::star::drawing::LineCap_BUTT */
2502 aCapType
= SvtGraphicStroke::capButt
;
2505 case com::sun::star::drawing::LineCap_ROUND
:
2507 aCapType
= SvtGraphicStroke::capRound
;
2510 case com::sun::star::drawing::LineCap_SQUARE
:
2512 aCapType
= SvtGraphicStroke::capSquare
;
2517 ImplWriteLineInfo( fLWidth
, fMiterLimit
, aCapType
, aJoinType
, l_aDashArray
);
2522 void PSWriter::ImplWriteLong(sal_Int32 nNumber
, sal_uLong nMode
)
2524 const OString
aNumber(OString::number(nNumber
));
2525 mnCursorPos
+= aNumber
.getLength();
2526 mpPS
->WriteCharPtr( aNumber
.getStr() );
2527 ImplExecMode(nMode
);
2532 void PSWriter::ImplWriteDouble( double fNumber
, sal_uLong nMode
)
2534 sal_Int32 nPTemp
= (sal_Int32
)fNumber
;
2535 sal_Int32 nATemp
= labs( (sal_Int32
)( ( fNumber
- nPTemp
) * 100000 ) );
2537 if ( !nPTemp
&& nATemp
&& ( fNumber
< 0.0 ) )
2538 mpPS
->WriteChar( '-' );
2540 const OString
aNumber1(OString::number(nPTemp
));
2541 mpPS
->WriteCharPtr( aNumber1
.getStr() );
2542 mnCursorPos
+= aNumber1
.getLength();
2547 mpPS
->WriteUChar( '.' );
2549 const OString
aNumber2(OString::number(nATemp
));
2551 sal_Int16 n
, nLen
= aNumber2
.getLength();
2554 mnCursorPos
+= 6 - nLen
;
2555 for ( n
= 0; n
< ( 5 - nLen
); n
++ )
2557 mpPS
->WriteUChar( '0' );
2560 mnCursorPos
+= nLen
;
2561 for ( n
= 0; n
< nLen
; n
++ )
2563 mpPS
->WriteChar( aNumber2
[n
] );
2565 if ( aNumber2
[n
] != '0' )
2569 mpPS
->SeekRel( zCount
);
2571 ImplExecMode( nMode
);
2576 // writes the number to stream: nNumber / ( 10^nCount )
2578 void PSWriter::ImplWriteF( sal_Int32 nNumber
, sal_uLong nCount
, sal_uLong nMode
)
2582 mpPS
->WriteUChar( '-' );
2586 const OString
aScaleFactor(OString::number(nNumber
));
2587 sal_uLong nLen
= aScaleFactor
.getLength();
2588 long nStSize
= ( nCount
+ 1 ) - nLen
;
2591 mpPS
->WriteUChar( '0' );
2596 mpPS
->WriteUChar( '.' );
2597 for ( long i
= 1; i
< nStSize
; i
++ )
2599 mpPS
->WriteUChar( '0' );
2603 mnCursorPos
+= nLen
;
2604 for( sal_uInt16 n
= 0UL; n
< nLen
; n
++ )
2606 if ( n
== nLen
- nCount
)
2608 mpPS
->WriteUChar( '.' );
2611 mpPS
->WriteChar( aScaleFactor
[n
] );
2613 ImplExecMode( nMode
);
2618 void PSWriter::ImplWriteByte( sal_uInt8 nNumb
, sal_uLong nMode
)
2620 mpPS
->WriteUChar( nNumb
);
2622 ImplExecMode( nMode
);
2627 void PSWriter::ImplWriteHexByte( sal_uInt8 nNumb
, sal_uLong nMode
)
2629 if ( ( nNumb
>> 4 ) > 9 )
2630 mpPS
->WriteUChar( ( nNumb
>> 4 ) + 'A' - 10 );
2632 mpPS
->WriteUChar( ( nNumb
>> 4 ) + '0' );
2634 if ( ( nNumb
& 0xf ) > 9 )
2635 mpPS
->WriteUChar( ( nNumb
& 0xf ) + 'A' - 10 );
2637 mpPS
->WriteUChar( ( nNumb
& 0xf ) + '0' );
2639 ImplExecMode( nMode
);
2644 // writes the sal_uInt8 nNumb as a Number from 0.000 up to 1.000
2646 void PSWriter::ImplWriteB1( sal_uInt8 nNumb
, sal_uLong nMode
)
2648 ImplWriteF( 1000 * ( nNumb
+ 1 ) / 256 , 3, nMode
);
2654 inline void PSWriter::WriteBits( sal_uInt16 nCode
, sal_uInt16 nCodeLen
)
2656 dwShift
|= ( nCode
<< ( nOffset
- nCodeLen
) );
2657 nOffset
-= nCodeLen
;
2658 while ( nOffset
< 24 )
2660 ImplWriteHexByte( (sal_uInt8
)( dwShift
>> 24 ) );
2664 if ( nCode
== 257 && nOffset
!= 32 )
2665 ImplWriteHexByte( (sal_uInt8
)( dwShift
>> 24 ) );
2670 void PSWriter::StartCompression()
2675 nClearCode
= 1 << nDataSize
;
2676 nEOICode
= nClearCode
+ 1;
2677 nTableSize
= nEOICode
+ 1;
2678 nCodeSize
= nDataSize
+ 1;
2680 nOffset
= 32; // number of free unused in dwShift
2683 pTable
= new PSLZWCTreeNode
[ 4096 ];
2685 for ( i
= 0; i
< 4096; i
++ )
2687 pTable
[ i
].pBrother
= pTable
[ i
].pFirstChild
= NULL
;
2688 pTable
[ i
].nValue
= (sal_uInt8
)( pTable
[ i
].nCode
= i
);
2691 WriteBits( nClearCode
, nCodeSize
);
2696 void PSWriter::Compress( sal_uInt8 nCompThis
)
2704 pPrefix
= pTable
+ nCompThis
;
2709 for( p
= pPrefix
->pFirstChild
; p
!= NULL
; p
= p
->pBrother
)
2711 if ( p
->nValue
== nV
)
2719 WriteBits( pPrefix
->nCode
, nCodeSize
);
2721 if ( nTableSize
== 409 )
2723 WriteBits( nClearCode
, nCodeSize
);
2725 for ( i
= 0; i
< nClearCode
; i
++ )
2726 pTable
[ i
].pFirstChild
= NULL
;
2728 nCodeSize
= nDataSize
+ 1;
2729 nTableSize
= nEOICode
+ 1;
2733 if( nTableSize
== (sal_uInt16
)( ( 1 << nCodeSize
) - 1 ) )
2736 p
= pTable
+ ( nTableSize
++ );
2737 p
->pBrother
= pPrefix
->pFirstChild
;
2738 pPrefix
->pFirstChild
= p
;
2740 p
->pFirstChild
= NULL
;
2743 pPrefix
= pTable
+ nV
;
2750 void PSWriter::EndCompression()
2753 WriteBits( pPrefix
->nCode
, nCodeSize
);
2755 WriteBits( nEOICode
, nCodeSize
);
2761 sal_uInt8
* PSWriter::ImplSearchEntry( sal_uInt8
* pSource
, sal_uInt8
const * pDest
, sal_uLong nComp
, sal_uLong nSize
)
2763 while ( nComp
-- >= nSize
)
2766 for ( i
= 0; i
< nSize
; i
++ )
2768 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
2780 bool PSWriter::ImplGetBoundingBox( double* nNumb
, sal_uInt8
* pSource
, sal_uLong nSize
)
2782 bool bRetValue
= false;
2783 sal_uLong nBytesRead
;
2785 if ( nSize
< 256 ) // we assume that the file is greater than 256 bytes
2788 if ( nSize
< POSTSCRIPT_BOUNDINGSEARCH
)
2791 nBytesRead
= POSTSCRIPT_BOUNDINGSEARCH
;
2793 sal_uInt8
* pDest
= ImplSearchEntry( pSource
, reinterpret_cast<sal_uInt8
const *>("%%BoundingBox:"), nBytesRead
, 14 );
2796 int nSecurityCount
= 100; // only 100 bytes following the bounding box will be checked
2797 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
2799 for ( int i
= 0; ( i
< 4 ) && nSecurityCount
; i
++ )
2802 bool bDivision
= false;
2803 bool bNegative
= false;
2806 while ( ( --nSecurityCount
) && ( ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) )
2808 sal_uInt8 nByte
= *pDest
;
2809 while ( nSecurityCount
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
2823 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
2824 nSecurityCount
= 1; // error parsing the bounding box values
2830 nNumb
[i
] += nByte
- '0';
2838 nNumb
[i
] = -nNumb
[i
];
2839 if ( bDivision
&& ( nDivision
!= 1 ) )
2840 nNumb
[i
] /= nDivision
;
2842 if ( nSecurityCount
)
2848 //================== GraphicExport - die exportierte Funktion ================
2850 // this needs to be kept in sync with
2851 // ImpFilterLibCacheEntry::GetImportFunction() from
2852 // vcl/source/filter/graphicfilter.cxx
2853 #if defined(DISABLE_DYNLOADING)
2854 #define GraphicExport epsGraphicExport
2857 extern "C" SAL_DLLPUBLIC_EXPORT
bool SAL_CALL
2858 GraphicExport( SvStream
& rStream
, Graphic
& rGraphic
, FilterConfigItem
* pFilterConfigItem
)
2861 return aPSWriter
.WritePS( rGraphic
, rStream
, pFilterConfigItem
);
2865 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */