1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include <vcl/sv.h>
28 #include <tools/stream.hxx>
29 #include <tools/bigint.hxx>
30 #include <tools/poly.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/metaact.hxx>
33 #include <vcl/graph.hxx>
34 #include <vcl/bmpacc.hxx>
35 #include <vcl/region.hxx>
36 #include <vcl/metric.hxx>
37 #include <vcl/font.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/msgbox.hxx>
40 #include <vcl/cvtgrf.hxx>
41 #include <vcl/gradient.hxx>
42 #include <svl/solar.hrc>
43 #include <svtools/fltcall.hxx>
44 #include <svtools/FilterConfigItem.hxx>
45 #include <vcl/graphictools.hxx>
46 #include "strings.hrc"
47 
48 #include <math.h>
49 
50 #define POSTSCRIPT_BOUNDINGSEARCH	0x1000	// we only try to get the BoundingBox
51 											// in the first 4096 bytes
52 
53 #define EPS_PREVIEW_TIFF	1
54 #define EPS_PREVIEW_EPSI	2
55 
56 #define PS_LINESIZE 		70		// maximum number of characters a line in the output
57 
58 #define PS_NONE 			0		// formatting mode: action which is inserted behind the output
59 #define PS_SPACE			1
60 #define PS_RET				2
61 #define PS_WRAP 			4
62 
63 // -----------------------------Feld-Typen-------------------------------
64 
65 struct ChrSet
66 {
67 	struct ChrSet * pSucc;
68 	sal_uInt8 nSet;
69 	String aName;
70 	FontWeight eWeight;
71 };
72 
73 struct StackMember
74 {
75 	struct		StackMember * pSucc;
76 	Color		aGlobalCol;
77 	sal_Bool		bLineCol;
78 	Color		aLineCol;
79 	sal_Bool		bFillCol;
80 	Color		aFillCol;
81 	Color		aTextCol;
82 	sal_Bool		bTextFillCol;
83 	Color		aTextFillCol;
84 	Color		aBackgroundCol;
85 	Font		aFont;
86 	TextAlign	eTextAlign;
87 
88 	double						fLineWidth;
89 	double						fMiterLimit;
90 	SvtGraphicStroke::CapType	eLineCap;
91 	SvtGraphicStroke::JoinType	eJoinType;
92 	SvtGraphicStroke::DashArray aDashArray;
93 };
94 
95 struct PSLZWCTreeNode
96 {
97 
98 	PSLZWCTreeNode* 	pBrother;		// naechster Knoten, der den selben Vater hat
99 	PSLZWCTreeNode* 	pFirstChild;	// erster Sohn
100 	sal_uInt16				nCode;			// Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
101 	sal_uInt16				nValue; 		// Der Pixelwert
102 };
103 
104 class PSWriter
105 {
106 private:
107 	sal_Bool				mbStatus;
108 	sal_uLong				mnLevelWarning; 	// number of embedded eps files which was not exported
109 	sal_uLong				mnLastPercent;		// Mit welcher Zahl pCallback zuletzt aufgerufen wurde.
110 	sal_uInt32				mnLatestPush;		// offset auf streamposition, an der zuletzt gepusht wurde
111 
112 	long				mnLevel;			// dialog options
113 	sal_Bool			mbGrayScale;
114 	sal_Bool			mbCompression;
115 	sal_Int32			mnPreview;
116 	sal_Int32			mnTextMode;
117 
118 	SvStream*			mpPS;
119 	const GDIMetaFile*	pMTF;
120 	GDIMetaFile*		pAMTF;				// only created if Graphics is not a Metafile
121 	VirtualDevice		aVDev;
122 
123 	double				nBoundingX1;		// this represents the bounding box
124 	double				nBoundingY1;
125 	double				nBoundingX2;
126 	double				nBoundingY2;
127 											//
128 	StackMember*		pGDIStack;
129 	sal_uLong				mnCursorPos;		// aktuelle Cursorposition im Output
130 	Color				aColor; 			// aktuelle Farbe die fuer den Output benutzt wird
131 	sal_Bool				bLineColor;
132 	Color				aLineColor; 		// aktuelle GDIMetafile Farbeinstellungen
133 	sal_Bool				bFillColor; 		//
134 	Color				aFillColor; 		//
135 	Color				aTextColor; 		//
136 	sal_Bool				bTextFillColor; 	//
137 	Color				aTextFillColor; 	//
138 	Color				aBackgroundColor;	//
139 	sal_Bool				bRegionChanged;
140 	TextAlign			eTextAlign;			//
141 
142 	double						fLineWidth;
143 	double						fMiterLimit;
144 	SvtGraphicStroke::CapType	eLineCap;
145 	SvtGraphicStroke::JoinType	eJoinType;
146 	SvtGraphicStroke::DashArray aDashArray;
147 
148 	Font				maFont;
149 	Font				maLastFont;
150 	sal_uInt8				nChrSet;
151 	ChrSet* 			pChrSetList;		// Liste der Character-Sets
152 	sal_uInt8				nNextChrSetId;		// die erste unbenutzte ChrSet-Id
153 
154 	PSLZWCTreeNode* 	pTable; 			// LZW compression data
155 	PSLZWCTreeNode* 	pPrefix;			// the compression is as same as the TIFF compression
156 	sal_uInt16				nDataSize;
157 	sal_uInt16				nClearCode;
158 	sal_uInt16				nEOICode;
159 	sal_uInt16				nTableSize;
160 	sal_uInt16				nCodeSize;
161 	sal_uLong				nOffset;
162 	sal_uLong				dwShift;
163 
164 	com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
165 
166 	void				ImplWriteProlog( const Graphic* pPreviewEPSI = NULL );
167 	void				ImplWriteEpilog();
168 	void				ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev );
169 
170 						// this method makes LF's, space inserting and word wrapping as used in all nMode
171 						// parameters
172 	inline void 		ImplExecMode( sal_uLong nMode );
173 
174 						// writes char[] + LF to stream
175 	inline void 		ImplWriteLine( const char*, sal_uLong nMode = PS_RET );
176 
177 						// writes ( nNumb / 10^nCount ) in ASCII format to stream
178 	void				ImplWriteF( sal_Int32 nNumb, sal_uLong nCount = 3, sal_uLong nMode = PS_SPACE );
179 
180 						// writes a double in ASCII format to stream
181 	void				ImplWriteDouble( double, sal_uLong nMode = PS_SPACE );
182 
183 						// writes a long in ASCII format to stream
184 	void				ImplWriteLong( sal_Int32 nNumb, sal_uLong nMode = PS_SPACE );
185 
186 						// writes a byte in ASCII format to stream
187 	void				ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE );
188 
189 						// writes a byte in ASCII (hex) format to stream
190 	void				ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode = PS_WRAP );
191 
192 						// writes nNumb as number from 0.000 till 1.000 in ASCII format to stream
193 	void				ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE );
194 
195 	inline void 		ImplWritePoint( const Point&, sal_uInt32 nMode = PS_SPACE );
196 	void				ImplMoveTo( const Point&, sal_uInt32 nMode = PS_SPACE );
197 	void				ImplLineTo( const Point&, sal_uInt32 nMode = PS_SPACE );
198 	void				ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode = PS_SPACE );
199 	void				ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET );
200 	void				ImplScale( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET );
201 
202 	void				ImplWriteLine( const Polygon & rPolygon );
203 	void				ImplAddPath( const Polygon & rPolygon );
204 	void				ImplWriteLineInfo( double fLineWidth, double fMiterLimit, SvtGraphicStroke::CapType eLineCap,
205 									SvtGraphicStroke::JoinType eJoinType, SvtGraphicStroke::DashArray& rDashArray );
206 	void				ImplWriteLineInfo( const LineInfo& rLineInfo );
207 	void				ImplRect( const Rectangle & rRectangle );
208 	void				ImplRectFill ( const Rectangle & rRectangle );
209 	void				ImplWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev );
210 	void				ImplIntersect( const PolyPolygon& rPolyPoly );
211 	void				ImplPolyPoly( const PolyPolygon & rPolyPolygon, sal_Bool bTextOutline = sal_False );
212 	void				ImplPolyLine( const Polygon & rPolygon );
213 
214 	void				ImplSetClipRegion( Region& rRegion );
215 	void				ImplBmp( Bitmap*, Bitmap*, const Point &, double nWidth, double nHeight );
216 	void				ImplText( const String& rUniString, const Point& rPos, const sal_Int32* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev );
217 	void				ImplSetAttrForText( const Point & rPoint );
218 	void				ImplWriteCharacter( sal_Char );
219 	void				ImplWriteString( const ByteString&, VirtualDevice& rVDev, const sal_Int32* pDXArry = NULL, sal_Bool bStretch = sal_False );
220 	void				ImplDefineFont( const char*, const char* );
221 
222 	void				ImplClosePathDraw( sal_uLong nMode = PS_RET );
223 	void				ImplPathDraw();
224 
225 	inline void 		ImplWriteLineColor( sal_uLong nMode = PS_RET );
226 	inline void 		ImplWriteFillColor( sal_uLong nMode = PS_RET );
227 	inline void 		ImplWriteTextColor( sal_uLong nMode = PS_RET );
228 	inline void 		ImplWriteTextFillColor( sal_uLong nMode = PS_RET );
229 	void				ImplWriteColor( sal_uLong nMode );
230 
231 	double				ImplGetScaling( const MapMode& );
232 	void				ImplGetMapMode( const MapMode& );
233 	sal_Bool				ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize );
234 	sal_uInt8*				ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize );
235 						// LZW methods
236 	void				StartCompression();
237 	void				Compress( sal_uInt8 nSrc );
238 	void				EndCompression();
239 	inline void 		WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
240 
241 public:
242 	sal_Bool				WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* );
243 	PSWriter();
244 	~PSWriter();
245 };
246 
247 //========================== Methoden von PSWriter ==========================
248 
249 //---------------------------------------------------------------------------------
250 
PSWriter()251 PSWriter::PSWriter()
252 {
253 	pAMTF = NULL;
254 }
255 
256 
~PSWriter()257 PSWriter::~PSWriter()
258 {
259 	delete pAMTF;
260 }
261 
262 //---------------------------------------------------------------------------------
263 
WritePS(const Graphic & rGraphic,SvStream & rTargetStream,FilterConfigItem * pFilterConfigItem)264 sal_Bool PSWriter::WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem )
265 {
266 	sal_uInt32 nStreamPosition = 0, nPSPosition = 0; // -Wall warning, unset, check
267 
268 	mbStatus = sal_True;
269 	mnPreview = 0;
270 	mnLevelWarning = 0;
271 	mnLastPercent = 0;
272 	mnLatestPush = 0xEFFFFFFE;
273 
274 	if ( pFilterConfigItem )
275 	{
276 		xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
277 		if ( xStatusIndicator.is() )
278 		{
279 			rtl::OUString aMsg;
280 			xStatusIndicator->start( aMsg, 100 );
281 		}
282 	}
283 
284 	mpPS = &rTargetStream;
285 	mpPS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
286 
287 	// default values for the dialog options
288 	mnLevel = 2;
289 	mbGrayScale = sal_False;
290 	mbCompression = sal_True;
291 	mnTextMode = 0;			// default0 : export glyph outlines
292 
293 	// try to get the dialog selection
294 	if ( pFilterConfigItem )
295 	{
296 		ByteString	aResMgrName( "eps" );
297 		ResMgr*		pResMgr;
298 
299 		pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
300 
301 		if( pResMgr )
302 		{
303         	String aPreviewStr( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) );
304 	        String aVersionStr( RTL_CONSTASCII_USTRINGPARAM( "Version" ) );
305         	String aColorStr( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) );
306 	        String aComprStr( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) );
307 			mnPreview = pFilterConfigItem->ReadInt32( aPreviewStr, 1 );
308 			mnLevel = pFilterConfigItem->ReadInt32( aVersionStr, 2 );
309 			if ( mnLevel != 1 )
310 				mnLevel = 2;
311 			mbGrayScale = pFilterConfigItem->ReadInt32( aColorStr, 1 ) == 2;
312 			mbCompression = pFilterConfigItem->ReadInt32( aComprStr, 1 ) == 1;
313         	String sTextMode( RTL_CONSTASCII_USTRINGPARAM( "TextMode" ) );
314 			mnTextMode = pFilterConfigItem->ReadInt32( sTextMode, 0 );
315 			if ( mnTextMode > 2 )
316 				mnTextMode = 0;
317 			delete pResMgr;
318 		}
319 	}
320 
321 	// compression is not available for Level 1
322 	if ( mnLevel == 1 )
323 	{
324 		mbGrayScale = sal_True;
325 		mbCompression = sal_False;
326 	}
327 
328 	if ( mnPreview & EPS_PREVIEW_TIFF )
329 	{
330 		rTargetStream << (sal_uInt32)0xC6D3D0C5;
331 		nStreamPosition = rTargetStream.Tell();
332 		rTargetStream << (sal_uInt32)0 << (sal_uInt32)0 << (sal_uInt32)0 << (sal_uInt32)0
333 			<< nStreamPosition + 26 << (sal_uInt32)0 << (sal_uInt16)0xffff;
334 
335 		sal_uInt32 nErrCode;
336 		if ( mbGrayScale )
337 		{
338 			BitmapEx aTempBitmapEx( rGraphic.GetBitmapEx() );
339 			aTempBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS );
340 			nErrCode = GraphicConverter::Export( rTargetStream, aTempBitmapEx, CVT_TIF ) ;
341 		}
342 		else
343 			nErrCode = GraphicConverter::Export( rTargetStream, rGraphic, CVT_TIF ) ;
344 
345 		if ( nErrCode == ERRCODE_NONE )
346 		{
347 			rTargetStream.Seek( STREAM_SEEK_TO_END );
348 			nPSPosition = rTargetStream.Tell();
349 			rTargetStream.Seek( nStreamPosition + 20 );
350 			rTargetStream << nPSPosition - 30;	// size of tiff gfx
351 			rTargetStream.Seek( nPSPosition );
352 		}
353 		else
354 		{
355 			mnPreview &=~ EPS_PREVIEW_TIFF;
356 			rTargetStream.Seek( nStreamPosition - 4 );
357 		}
358 	}
359 
360 	// global default value setting
361 	ChrSet* 		pCS;
362 	StackMember*	pGS;
363 
364 	if ( rGraphic.GetType() == GRAPHIC_GDIMETAFILE )
365 		pMTF = &rGraphic.GetGDIMetaFile();
366 	else
367 		pMTF = pAMTF = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
368 	aVDev.SetMapMode( pMTF->GetPrefMapMode() );
369 	nBoundingX1 = nBoundingY1 = 0;
370 	nBoundingX2 = pMTF->GetPrefSize().Width();
371 	nBoundingY2 = pMTF->GetPrefSize().Height();
372 
373 	pGDIStack = NULL;
374 	aColor = Color( COL_TRANSPARENT );
375 	bLineColor = sal_True;
376 	aLineColor = Color( COL_BLACK );
377 	bFillColor = sal_True;
378 	aFillColor = Color( COL_WHITE );
379 	bTextFillColor = sal_True;
380 	aTextFillColor = Color( COL_BLACK );
381 	fLineWidth = 1;
382 	fMiterLimit = 15; // use same limit as most graphic systems and basegfx
383 	eLineCap = SvtGraphicStroke::capButt;
384 	eJoinType = SvtGraphicStroke::joinMiter;
385 	aBackgroundColor = Color( COL_WHITE );
386 	eTextAlign = ALIGN_BASELINE;
387 	bRegionChanged = sal_False;
388 
389 	nChrSet = 0x00;
390 	pChrSetList = NULL;
391 	nNextChrSetId = 1;
392 
393 	if( pMTF->GetActionCount() )
394 	{
395 		ImplWriteProlog( ( mnPreview & EPS_PREVIEW_EPSI ) ? &rGraphic : NULL );
396 		mnCursorPos = 0;
397 		ImplWriteActions( *pMTF, aVDev );
398 		ImplWriteEpilog();
399 		if ( mnPreview & EPS_PREVIEW_TIFF )
400 		{
401 			sal_uInt32 nPosition = rTargetStream.Tell();
402 			rTargetStream.Seek( nStreamPosition );
403 			rTargetStream << nPSPosition;
404 			rTargetStream << nPosition - nPSPosition;
405 			rTargetStream.Seek( nPosition );
406 		}
407 		while( pChrSetList )
408 		{
409 			pCS=pChrSetList;
410 			pChrSetList=pCS->pSucc;
411 			delete pCS;
412 		}
413 		while( pGDIStack )
414 		{
415 			pGS=pGDIStack;
416 			pGDIStack=pGS->pSucc;
417 			delete pGS;
418 		}
419 	}
420 	else
421 		mbStatus = sal_False;
422 
423 	if ( mbStatus && mnLevelWarning && pFilterConfigItem )
424 	{
425 		ByteString	aResMgrName( "eps" );
426 		ResMgr* pResMgr;
427 		pResMgr = ResMgr::CreateResMgr( aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
428 		if( pResMgr )
429 		{
430 			InfoBox aInfoBox( NULL, String( ResId( KEY_VERSION_CHECK, *pResMgr ) ) );
431 			aInfoBox.Execute();
432 			delete pResMgr;
433 		}
434 	}
435 
436 	if ( xStatusIndicator.is() )
437 		xStatusIndicator->end();
438 
439 	return mbStatus;
440 }
441 
442 //---------------------------------------------------------------------------------
443 
ImplWriteProlog(const Graphic * pPreview)444 void PSWriter::ImplWriteProlog( const Graphic* pPreview )
445 {
446 	ImplWriteLine( "%!PS-Adobe-3.0 EPSF-3.0 " );
447 	*mpPS << "%%BoundingBox: ";                         // BoundingBox
448 	ImplWriteLong( 0 );
449 	ImplWriteLong( 0 );
450 	Size aSizePoint = Application::GetDefaultDevice()->LogicToLogic( pMTF->GetPrefSize(),
451 						pMTF->GetPrefMapMode(), MAP_POINT );
452 	ImplWriteLong( aSizePoint.Width() );
453 	ImplWriteLong( aSizePoint.Height() ,PS_RET );
454 	ImplWriteLine( "%%Pages: 0" );
455 	ImplWriteLine( "%%Creator: Sun Microsystems, Inc." );
456 	ImplWriteLine( "%%Title: none" );
457 	ImplWriteLine( "%%CreationDate: none" );
458 
459 // defaults
460 
461 	*mpPS << "%%LanguageLevel: ";                       // Language level
462 	ImplWriteLong( mnLevel, PS_RET );
463 	if ( !mbGrayScale && mnLevel == 1 )
464 		ImplWriteLine( "%%Extensions: CMYK" );          // CMYK extension is to set in color mode in level 1
465 	ImplWriteLine( "%%EndComments" );
466 	if ( pPreview && aSizePoint.Width() && aSizePoint.Height() )
467 	{
468 		Size aSizeBitmap( ( aSizePoint.Width() + 7 ) & ~7, aSizePoint.Height() );
469 		Bitmap aTmpBitmap( pPreview->GetBitmap() );
470 		aTmpBitmap.Scale( aSizeBitmap, BMP_SCALE_INTERPOLATE );
471 		aTmpBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
472 		BitmapReadAccess* pAcc = aTmpBitmap.AcquireReadAccess();
473 		if ( pAcc )
474 		{
475 			*mpPS << "%%BeginPreview: ";					// BoundingBox
476 			ImplWriteLong( aSizeBitmap.Width() );
477 			ImplWriteLong( aSizeBitmap.Height() );
478 			*mpPS << "1 ";
479 			sal_Int32 nLines = aSizeBitmap.Width() / 312;
480 			if ( ( nLines * 312 ) != aSizeBitmap.Width() )
481 				nLines++;
482 			nLines *= aSizeBitmap.Height();
483 			ImplWriteLong( nLines );
484 			char  nVal;
485 			sal_Int32 nX, nY, nCount2, nCount = 4;
486 			const BitmapColor aBlack( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
487 			for ( nY = 0; nY < aSizeBitmap.Height(); nY++ )
488 			{
489 				nCount2 = 0;
490 				nVal = 0;
491 				for ( nX = 0; nX < aSizeBitmap.Width(); nX++ )
492 				{
493 					if ( !nCount2 )
494 					{
495 						ImplExecMode( PS_RET );
496 						*mpPS << "%";
497 						nCount2 = 312;
498 					}
499 					nVal <<= 1;
500 					if ( pAcc->GetPixel( nY, nX ) == aBlack )
501 						nVal |= 1;
502 					if ( ! ( --nCount ) )
503 					{
504 						if ( nVal > 9 )
505 							nVal += 'A' - 10;
506 						else
507 							nVal += '0';
508 						*mpPS << nVal;
509 						nVal = 0;
510 						nCount += 4;
511 					}
512 					nCount2--;
513 				}
514 			}
515 			aTmpBitmap.ReleaseAccess( pAcc );
516 			ImplExecMode( PS_RET );
517 			ImplWriteLine( "%%EndPreview" );
518 		}
519 	}
520 	ImplWriteLine( "%%BeginProlog" );
521 	ImplWriteLine( "%%BeginResource: procset SDRes-Prolog 1.0 0" );
522 
523 //	BEGIN EPSF
524 	ImplWriteLine( "/b4_inc_state save def\n/dict_count countdictstack def\n/op_count count 1 sub def\nuserdict begin" );
525 	ImplWriteLine( "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath" );
526 	ImplWriteLine( "/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if" );
527 
528 	ImplWriteLine( "/bdef {bind def} bind def" );       // der neue operator bdef wird erzeugt
529 	if ( mbGrayScale )
530 		ImplWriteLine( "/c {setgray} bdef" );
531 	else
532 		ImplWriteLine( "/c {setrgbcolor} bdef" );
533 	ImplWriteLine( "/l {neg lineto} bdef" );
534 	ImplWriteLine( "/rl {neg rlineto} bdef" );
535 	ImplWriteLine( "/lc {setlinecap} bdef" );
536 	ImplWriteLine( "/lj {setlinejoin} bdef" );
537 	ImplWriteLine( "/lw {setlinewidth} bdef" );
538 	ImplWriteLine( "/ml {setmiterlimit} bdef" );
539 	ImplWriteLine( "/ld {setdash} bdef" );
540 	ImplWriteLine( "/m {neg moveto} bdef" );
541 	ImplWriteLine( "/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef" );
542 	ImplWriteLine( "/r {rotate} bdef" );
543 	ImplWriteLine( "/t {neg translate} bdef" );
544 	ImplWriteLine( "/s {scale} bdef" );
545 	ImplWriteLine( "/sw {show} bdef" );
546 	ImplWriteLine( "/gs {gsave} bdef" );
547 	ImplWriteLine( "/gr {grestore} bdef" );
548 
549 	ImplWriteLine( "/f {findfont dup length dict begin" );  // Setfont
550 	ImplWriteLine( "{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def" );
551 	ImplWriteLine( "currentdict end /NFont exch definefont pop /NFont findfont} bdef" );
552 
553 	ImplWriteLine( "/p {closepath} bdef" );
554 	ImplWriteLine( "/sf {scalefont setfont} bdef" );
555 
556 	ImplWriteLine( "/ef {eofill}bdef"			);      // close path and fill
557 	ImplWriteLine( "/pc {closepath stroke}bdef" );      // close path and draw
558 	ImplWriteLine( "/ps {stroke}bdef" );                // draw current path
559 	ImplWriteLine( "/pum {matrix currentmatrix}bdef" ); // pushes the current matrix
560 	ImplWriteLine( "/pom {setmatrix}bdef" );            // pops the matrix
561 	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" );
562 	ImplWriteLine( "%%EndResource" );
563 	ImplWriteLine( "%%EndProlog" );
564 	ImplWriteLine( "%%BeginSetup" );
565 	ImplWriteLine( "%%EndSetup" );
566 	ImplWriteLine( "%%Page: 1 1" );
567 	ImplWriteLine( "%%BeginPageSetup" );
568 	ImplWriteLine( "%%EndPageSetup" );
569 	ImplWriteLine( "pum" );
570 	ImplScale( (double)aSizePoint.Width() / (double)pMTF->GetPrefSize().Width(), (double)aSizePoint.Height() / (double)pMTF->GetPrefSize().Height() );
571 	ImplWriteDouble( 0 );
572 	ImplWriteDouble( -pMTF->GetPrefSize().Height() );
573 	ImplWriteLine( "t" );
574 	ImplWriteLine( "/tm matrix currentmatrix def" );
575 }
576 
577 //---------------------------------------------------------------------------------
578 
ImplWriteEpilog()579 void PSWriter::ImplWriteEpilog()
580 {
581 	ImplTranslate( 0, nBoundingY2 );
582 	ImplWriteLine( "pom" );
583 	ImplWriteLine( "count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore" );
584 
585 	ImplWriteLine( "%%PageTrailer" );
586 	ImplWriteLine( "%%Trailer" );
587 
588 	ImplWriteLine( "%%EOF" );
589 }
590 
591 //---------------------------------------------------------------------------------
592 //---------------------------------------------------------------------------------
593 //---------------------------------------------------------------------------------
594 
ImplWriteActions(const GDIMetaFile & rMtf,VirtualDevice & rVDev)595 void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
596 {
597 	PolyPolygon aFillPath;
598 
599 	for( sal_uLong nCurAction = 0, nCount = rMtf.GetActionCount(); nCurAction < nCount; nCurAction++ )
600 	{
601 		MetaAction* pMA = rMtf.GetAction( nCurAction );
602 
603 		switch( pMA->GetType() )
604 		{
605 			case META_NULL_ACTION :
606 			break;
607 
608 			case META_PIXEL_ACTION :
609 			{
610 				Color aOldLineColor( aLineColor );
611 				aLineColor = ( (const MetaPixelAction*) pMA )->GetColor();
612 				ImplWriteLineColor( PS_SPACE );
613 				ImplMoveTo( ( (const MetaPixelAction*)pMA )->GetPoint() );
614 				ImplLineTo( ( (const MetaPixelAction*)pMA )->GetPoint() );
615 				ImplPathDraw();
616 				aLineColor = aOldLineColor;
617 			}
618 			break;
619 
620 			case META_POINT_ACTION :
621 			{
622 				ImplWriteLineColor( PS_SPACE );
623 				ImplMoveTo( ( (const MetaPointAction*)pMA )->GetPoint() );
624 				ImplLineTo( ( (const MetaPointAction*)pMA )->GetPoint() );
625 				ImplPathDraw();
626 			}
627 			break;
628 
629 			case META_LINE_ACTION :
630 			{
631 				const LineInfo& rLineInfo = ( ( const MetaLineAction*)pMA )->GetLineInfo();
632 				ImplWriteLineInfo( rLineInfo );
633 				if ( bLineColor )
634 				{
635 					ImplWriteLineColor( PS_SPACE );
636 					ImplMoveTo( ( (const MetaLineAction*) pMA )->GetStartPoint() );
637 					ImplLineTo( ( (const MetaLineAction*) pMA )->GetEndPoint() );
638 					ImplPathDraw();
639 				}
640 			}
641 			break;
642 
643 			case META_RECT_ACTION :
644 			{
645 				ImplRect( ( (const MetaRectAction*) pMA )->GetRect() );
646 			}
647 			break;
648 
649 			case META_ROUNDRECT_ACTION :
650 				ImplRect( ( (const MetaRoundRectAction*) pMA )->GetRect() );
651 			break;
652 
653 			case META_ELLIPSE_ACTION :
654 			{
655 				Rectangle	aRect = ( ( (const MetaEllipseAction*) pMA )->GetRect() );
656 				Point		aCenter = aRect.Center();
657 				Polygon		aPoly( aCenter, aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
658 				PolyPolygon aPolyPoly( aPoly );
659 				ImplPolyPoly( aPolyPoly );
660 			}
661 			break;
662 
663 			case META_ARC_ACTION :
664 			{
665 				Polygon aPoly( ( (const MetaArcAction*)pMA )->GetRect(), ( (const MetaArcAction*)pMA )->GetStartPoint(),
666 					( (const MetaArcAction*)pMA )->GetEndPoint(), POLY_ARC );
667 				PolyPolygon	aPolyPoly( aPoly );
668 				ImplPolyPoly( aPolyPoly );
669 			}
670 			break;
671 
672 			case META_PIE_ACTION :
673 			{
674 				Polygon aPoly( ( (const MetaPieAction*)pMA )->GetRect(), ( (const MetaPieAction*)pMA )->GetStartPoint(),
675 					( (const MetaPieAction*)pMA )->GetEndPoint(), POLY_PIE );
676 				PolyPolygon aPolyPoly( aPoly );
677 				ImplPolyPoly( aPolyPoly );
678 			}
679 			break;
680 
681 			case META_CHORD_ACTION :
682 			{
683 				Polygon aPoly( ( (const MetaChordAction*)pMA )->GetRect(), ( (const MetaChordAction*)pMA )->GetStartPoint(),
684 					( (const MetaChordAction*)pMA )->GetEndPoint(), POLY_CHORD );
685 				PolyPolygon aPolyPoly( aPoly );
686 				ImplPolyPoly( aPolyPoly );
687 			}
688 			break;
689 
690 			case META_POLYLINE_ACTION :
691 			{
692 				Polygon aPoly( ( (const MetaPolyLineAction*) pMA )->GetPolygon() );
693 				const LineInfo& rLineInfo = ( ( const MetaPolyLineAction*)pMA )->GetLineInfo();
694                 ImplWriteLineInfo( rLineInfo );
695 
696                 if(basegfx::B2DLINEJOIN_NONE == rLineInfo.GetLineJoin()
697                     && rLineInfo.GetWidth() > 1)
698                 {
699                     // emulate B2DLINEJOIN_NONE by creating single edges
700                     const sal_uInt16 nPoints(aPoly.GetSize());
701                     const bool bCurve(aPoly.HasFlags());
702 
703                     for(sal_uInt16 a(0); a + 1 < nPoints; a++)
704                     {
705                         if(bCurve
706                             && POLY_NORMAL != aPoly.GetFlags(a + 1)
707                             && a + 2 < nPoints
708                             && POLY_NORMAL != aPoly.GetFlags(a + 2)
709                             && a + 3 < nPoints)
710                         {
711 							const Polygon aSnippet(4,
712                                 aPoly.GetConstPointAry() + a,
713                                 aPoly.GetConstFlagAry() + a);
714             				ImplPolyLine(aSnippet);
715                             a += 2;
716                         }
717                         else
718                         {
719 							const Polygon aSnippet(2,
720                                 aPoly.GetConstPointAry() + a);
721             				ImplPolyLine(aSnippet);
722                         }
723                     }
724                 }
725                 else
726                 {
727     				ImplPolyLine( aPoly );
728                 }
729 			}
730 			break;
731 
732 			case META_POLYGON_ACTION :
733 			{
734 				PolyPolygon aPolyPoly( ( (const MetaPolygonAction*) pMA )->GetPolygon() );
735 				ImplPolyPoly( aPolyPoly );
736 			}
737 			break;
738 
739 			case META_POLYPOLYGON_ACTION :
740 			{
741 				ImplPolyPoly( ( (const MetaPolyPolygonAction*) pMA )->GetPolyPolygon() );
742 			}
743 			break;
744 
745 			case META_TEXT_ACTION:
746 			{
747 				const MetaTextAction * pA = (const MetaTextAction*) pMA;
748 
749 				String	aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() );
750 				Point	aPoint( pA->GetPoint() );
751 
752 				ImplText( aUniStr, aPoint, NULL, 0, rVDev );
753 			}
754 			break;
755 
756 			case META_TEXTRECT_ACTION:
757 			{
758 				DBG_ERROR( "Unsupported action: TextRect...Action!" );
759 			}
760 			break;
761 
762 			case META_STRETCHTEXT_ACTION :
763 			{
764 				const MetaStretchTextAction* pA = (const MetaStretchTextAction*)pMA;
765 				String	aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() );
766 				Point	aPoint( pA->GetPoint() );
767 
768 				ImplText( aUniStr, aPoint, NULL, pA->GetWidth(), rVDev );
769 			}
770 			break;
771 
772 			case META_TEXTARRAY_ACTION:
773 			{
774 				const MetaTextArrayAction* pA = (const MetaTextArrayAction*)pMA;
775 				String	aUniStr( pA->GetText(), pA->GetIndex(), pA->GetLen() );
776 				Point	aPoint( pA->GetPoint() );
777 
778 				ImplText( aUniStr, aPoint, pA->GetDXArray(), 0, rVDev );
779 			}
780 			break;
781 
782 			case META_BMP_ACTION :
783 			{
784 				Bitmap aBitmap = ( (const MetaBmpAction*)pMA )->GetBitmap();
785 				if ( mbGrayScale )
786 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
787 				Point aPoint = ( (const MetaBmpAction*) pMA )->GetPoint();
788 				Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) );
789 				ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
790 			}
791 			break;
792 
793 			case META_BMPSCALE_ACTION :
794 			{
795 				Bitmap aBitmap = ( (const MetaBmpScaleAction*)pMA )->GetBitmap();
796 				if ( mbGrayScale )
797 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
798 				Point aPoint = ( (const MetaBmpScaleAction*) pMA )->GetPoint();
799 				Size aSize = ( (const MetaBmpScaleAction*)pMA )->GetSize();
800 				ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
801 			}
802 			break;
803 
804 			case META_BMPSCALEPART_ACTION :
805 			{
806 				Bitmap	aBitmap( ( (const MetaBmpScalePartAction*)pMA )->GetBitmap() );
807 				aBitmap.Crop( Rectangle( ( (const MetaBmpScalePartAction*)pMA )->GetSrcPoint(),
808 					( (const MetaBmpScalePartAction*)pMA )->GetSrcSize() ) );
809 				if ( mbGrayScale )
810 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
811 				Point aPoint = ( (const MetaBmpScalePartAction*) pMA)->GetDestPoint();
812 				Size aSize = ( (const MetaBmpScalePartAction*)pMA )->GetDestSize();
813 				ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
814 			}
815 			break;
816 
817 			case META_BMPEX_ACTION :
818 			{
819 				BitmapEx aBitmapEx( ( (MetaBmpExAction*)pMA)->GetBitmapEx() );
820 				Bitmap aBitmap( aBitmapEx.GetBitmap() );
821 				if ( mbGrayScale )
822 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
823 				Bitmap aMask( aBitmapEx.GetMask() );
824 				Point aPoint( ( (const MetaBmpExAction*) pMA )->GetPoint() );
825 				Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) );
826 				ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
827 			}
828 			break;
829 
830 			case META_BMPEXSCALE_ACTION :
831 			{
832 				BitmapEx aBitmapEx( ( (MetaBmpExScaleAction*)pMA)->GetBitmapEx() );
833 				Bitmap aBitmap( aBitmapEx.GetBitmap() );
834 				if ( mbGrayScale )
835 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
836 				Bitmap aMask( aBitmapEx.GetMask() );
837 				Point aPoint = ( (const MetaBmpExScaleAction*) pMA)->GetPoint();
838 				Size aSize( ( (const MetaBmpExScaleAction*)pMA )->GetSize() );
839 				ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
840 			}
841 			break;
842 
843 			case META_BMPEXSCALEPART_ACTION :
844 			{
845 				BitmapEx	aBitmapEx( ( (const MetaBmpExScalePartAction*)pMA )->GetBitmapEx() );
846 				aBitmapEx.Crop( Rectangle( ( (const MetaBmpExScalePartAction*)pMA )->GetSrcPoint(),
847 					( (const MetaBmpExScalePartAction*)pMA )->GetSrcSize() ) );
848 				Bitmap		aBitmap( aBitmapEx.GetBitmap() );
849 				if ( mbGrayScale )
850 					aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
851 				Bitmap		aMask( aBitmapEx.GetMask() );
852 				Point aPoint = ( (const MetaBmpExScalePartAction*) pMA)->GetDestPoint();
853 				Size aSize = ( (const MetaBmpExScalePartAction*)pMA )->GetDestSize();
854 				ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
855 			}
856 			break;
857 
858 			// Unsupported Actions
859 			case META_MASK_ACTION:
860 			case META_MASKSCALE_ACTION:
861 			case META_MASKSCALEPART_ACTION:
862 			{
863 				DBG_ERROR( "Unsupported action: MetaMask...Action!" );
864 			}
865 			break;
866 
867 			case META_GRADIENT_ACTION :
868 			{
869 				PolyPolygon aPolyPoly( ( (const MetaGradientAction*)pMA)->GetRect() );
870                 ImplWriteGradient( aPolyPoly, ( (const MetaGradientAction*) pMA )->GetGradient(), rVDev );
871 			}
872 			break;
873 
874 			case META_GRADIENTEX_ACTION :
875 			{
876 				PolyPolygon aPolyPoly( ( (const MetaGradientExAction*)pMA)->GetPolyPolygon() );
877                 ImplWriteGradient( aPolyPoly, ( (const MetaGradientExAction*) pMA )->GetGradient(), rVDev );
878 			}
879 			break;
880 
881 			case META_HATCH_ACTION :
882 			{
883 				VirtualDevice	l_aVDev;
884 				GDIMetaFile 	aTmpMtf;
885 
886 				l_aVDev.SetMapMode( rVDev.GetMapMode() );
887 				l_aVDev.AddHatchActions( ( (const MetaHatchAction*)pMA)->GetPolyPolygon(),
888 									     ( (const MetaHatchAction*)pMA )->GetHatch(), aTmpMtf );
889 				ImplWriteActions( aTmpMtf, rVDev );
890 			}
891 			break;
892 
893 			case META_WALLPAPER_ACTION :
894 			{
895 				const MetaWallpaperAction* pA = (const MetaWallpaperAction*)pMA;
896 				Rectangle	aRect = pA->GetRect();
897 				Wallpaper	aWallpaper = pA->GetWallpaper();
898 
899 				if ( aWallpaper.IsBitmap() )
900 				{
901 					BitmapEx aBitmapEx = aWallpaper.GetBitmap();
902 					Bitmap aBitmap( aBitmapEx.GetBitmap() );
903 					if ( aBitmapEx.IsTransparent() )
904 					{
905 						if ( aWallpaper.IsGradient() )
906 						{
907 
908 						// gradient action
909 
910 						}
911 						Bitmap aMask( aBitmapEx.GetMask() );
912 						ImplBmp( &aBitmap, &aMask, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() );
913 					}
914 					else
915 						ImplBmp( &aBitmap, NULL, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() );
916 
917 						// wallpaper Style
918 
919 				}
920 				else if ( aWallpaper.IsGradient() )
921 				{
922 
923 				// gradient action
924 
925 				}
926 				else
927 				{
928 					aColor = aWallpaper.GetColor();
929 					ImplRectFill( aRect );
930 				}
931 			}
932 			break;
933 
934 			case META_ISECTRECTCLIPREGION_ACTION:
935 			{
936 				const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
937 				Region aRegion( pA->GetRect() );
938 				ImplSetClipRegion( aRegion );
939 			}
940 			break;
941 
942 			case META_CLIPREGION_ACTION:
943 			{
944 				const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pMA;
945 				Region aRegion( pA->GetRegion() );
946 				ImplSetClipRegion( aRegion );
947 			}
948 			break;
949 
950 			case META_ISECTREGIONCLIPREGION_ACTION:
951 			{
952 				const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pMA;
953 				Region aRegion( pA->GetRegion() );
954 				ImplSetClipRegion( aRegion );
955 			}
956 			break;
957 
958 			case META_MOVECLIPREGION_ACTION:
959 			{
960 /*
961 				if ( !aClipRegion.IsEmpty() )
962 				{
963 					const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pMA;
964 					aClipRegion.Move( pA->GetHorzMove(), pA->GetVertMove() );
965 					ImplSetClipRegion();
966 				}
967 */
968 			}
969 			break;
970 
971 			case META_LINECOLOR_ACTION :
972 			{
973 				if ( ( (const MetaLineColorAction*) pMA)->IsSetting() )
974 				{
975 					bLineColor = sal_True;
976 					aLineColor = ( (const MetaLineColorAction*) pMA )->GetColor();
977 				}
978 				else
979 					bLineColor = sal_False;
980 			}
981 			break;
982 
983 			case META_FILLCOLOR_ACTION :
984 			{
985 				if ( ( (const MetaFillColorAction*) pMA )->IsSetting() )
986 				{
987 					bFillColor = sal_True;
988 					aFillColor =  ( (const MetaFillColorAction*) pMA )->GetColor();
989 				}
990 				else
991 					bFillColor = sal_False;
992 			}
993 			break;
994 
995 			case META_TEXTCOLOR_ACTION :
996 			{
997 				aTextColor = ( (const MetaTextColorAction*) pMA )->GetColor();
998 			}
999 			break;
1000 
1001 			case META_TEXTFILLCOLOR_ACTION :
1002 			{
1003 				if ( ( (const MetaTextFillColorAction*) pMA )->IsSetting() )
1004 				{
1005 					bTextFillColor = sal_True;
1006 					aTextFillColor = ( (const MetaTextFillColorAction*) pMA )->GetColor();
1007 				}
1008 				else
1009 					bTextFillColor = sal_False;
1010 			}
1011 			break;
1012 
1013 			case META_TEXTALIGN_ACTION :
1014 			{
1015 				eTextAlign = ( (const MetaTextAlignAction*) pMA )->GetTextAlign();
1016 			}
1017 			break;
1018 
1019 			case META_MAPMODE_ACTION :
1020 			{
1021                 pMA->Execute( &rVDev );
1022 				ImplGetMapMode( rVDev.GetMapMode() );
1023 			}
1024 			break;
1025 
1026 			case META_FONT_ACTION :
1027 			{
1028 				maFont = ((const MetaFontAction*)pMA)->GetFont();
1029 				rVDev.SetFont( maFont );
1030 			}
1031 			break;
1032 
1033 			case META_PUSH_ACTION :
1034 			{
1035                 rVDev.Push(((const MetaPushAction*)pMA)->GetFlags() );
1036 				StackMember* pGS = new StackMember;
1037 				pGS->pSucc = pGDIStack;
1038 				pGDIStack = pGS;
1039 				pGS->aDashArray = aDashArray;
1040 				pGS->eJoinType = eJoinType;
1041 				pGS->eLineCap = eLineCap;
1042 				pGS->fLineWidth = fLineWidth;
1043 				pGS->fMiterLimit = fMiterLimit;
1044 				pGS->eTextAlign = eTextAlign;
1045 				pGS->aGlobalCol = aColor;
1046 				pGS->bLineCol = bLineColor;
1047 				pGS->aLineCol = aLineColor;
1048 				pGS->bFillCol = bFillColor;
1049 				pGS->aFillCol = aFillColor;
1050 				pGS->aTextCol = aTextColor;
1051 				pGS->bTextFillCol = bTextFillColor;
1052 				pGS->aTextFillCol = aTextFillColor;
1053 				pGS->aBackgroundCol = aBackgroundColor;
1054 				bRegionChanged = sal_False;
1055 				pGS->aFont = maFont;
1056 				mnLatestPush = mpPS->Tell();
1057 				ImplWriteLine( "gs" );
1058 			}
1059 			break;
1060 
1061 			case META_POP_ACTION :
1062 			{
1063                 rVDev.Pop();
1064 				StackMember* pGS;
1065 				if( pGDIStack )
1066 				{
1067 					pGS = pGDIStack;
1068 					pGDIStack = pGS->pSucc;
1069 					aDashArray = pGS->aDashArray;
1070 				    eJoinType = pGS->eJoinType;
1071 					eLineCap = pGS->eLineCap;
1072 					fLineWidth = pGS->fLineWidth;
1073 					fMiterLimit = pGS->fMiterLimit;
1074 					eTextAlign = pGS->eTextAlign;
1075 					aColor = pGS->aGlobalCol;
1076 					bLineColor = pGS->bLineCol;
1077 					aLineColor = pGS->aLineCol;
1078 					bFillColor = pGS->bFillCol;
1079 					aFillColor = pGS->aFillCol;
1080 					aTextColor = pGS->aTextCol;
1081 					bTextFillColor = pGS->bTextFillCol;
1082 					aTextFillColor = pGS->aTextFillCol;
1083 					aBackgroundColor = pGS->aBackgroundCol;
1084 					maFont = pGS->aFont;
1085 					maLastFont = Font();				// set maLastFont != maFont -> so that
1086 					delete pGS;
1087 					sal_uInt32 nCurrentPos = mpPS->Tell();
1088 					if ( nCurrentPos - 3 == mnLatestPush )
1089 					{
1090 						mpPS->Seek( mnLatestPush );
1091 						ImplWriteLine( "  " );
1092 						mpPS->Seek( mnLatestPush );
1093 					}
1094 					else
1095 						ImplWriteLine( "gr" );
1096 				}
1097 			}
1098 			break;
1099 
1100 			case META_EPS_ACTION :
1101 			{
1102 				GfxLink aGfxLink = ( (const MetaEPSAction*) pMA )->GetLink();
1103 				const GDIMetaFile aSubstitute( ( ( const MetaEPSAction*) pMA )->GetSubstitute() );
1104 
1105 				sal_Bool	bLevelConflict = sal_False;
1106 				sal_uInt8*	pSource = (sal_uInt8*) aGfxLink.GetData();
1107 				sal_uLong	nSize = aGfxLink.GetDataSize();
1108 				sal_uLong	nParseThis = POSTSCRIPT_BOUNDINGSEARCH;
1109 				if ( nSize < 64 )						// assuming eps is larger than 64 bytes
1110 					pSource = NULL;
1111 				if ( nParseThis > nSize )
1112 					nParseThis = nSize;
1113 
1114 				if ( pSource && ( mnLevel == 1 ) )
1115 				{
1116 					sal_uInt8* pFound = ImplSearchEntry( pSource, (sal_uInt8*)"%%LanguageLevel:", nParseThis - 10, 16 );
1117 					if ( pFound )
1118 					{
1119 						sal_uInt8	k, i = 10;
1120 						pFound += 16;
1121 						while ( --i )
1122 						{
1123 							k = *pFound++;
1124 							if ( ( k > '0' ) && ( k <= '9' ) )
1125 							{
1126 								if ( k != '1' )
1127 								{
1128 									bLevelConflict = sal_True;
1129 									mnLevelWarning++;
1130 								}
1131 								break;
1132 							}
1133 						}
1134 					}
1135 				}
1136 				if ( !bLevelConflict )
1137 				{
1138 					double	nBoundingBox[4];
1139 					if ( pSource && ImplGetBoundingBox( nBoundingBox, pSource, nParseThis ) )
1140 					{
1141 						Point	aPoint = ( (const MetaEPSAction*) pMA )->GetPoint();
1142 						Size	aSize = ( (const MetaEPSAction*) pMA )->GetSize();
1143 
1144 						MapMode	aMapMode( aSubstitute.GetPrefMapMode() );
1145 						Size aOutSize( rVDev.LogicToLogic( aSize, rVDev.GetMapMode(), aMapMode ) );
1146 						Point aOrigin( rVDev.LogicToLogic( aPoint, rVDev.GetMapMode(), aMapMode ) );
1147 						aOrigin.Y() += aOutSize.Height();
1148 						aMapMode.SetOrigin( aOrigin );
1149 						aMapMode.SetScaleX( aOutSize.Width() / ( nBoundingBox[ 2 ] - nBoundingBox[ 0 ] ) );
1150 						aMapMode.SetScaleY( aOutSize.Height() / ( nBoundingBox[ 3 ] - nBoundingBox[ 1 ] ) );
1151 						ImplWriteLine( "gs" );
1152 						ImplGetMapMode( aMapMode );
1153 						ImplWriteLine( "%%BeginDocument:" );
1154 						mpPS->Write( pSource, aGfxLink.GetDataSize() );
1155 						ImplWriteLine( "%%EndDocument\ngr" );
1156 					}
1157 				}
1158 			}
1159 			break;
1160 
1161 			case META_TRANSPARENT_ACTION:
1162 			{
1163 //				ImplLine( ( (const MetaTransparentAction*) pMA )->GetPolyPolygon() );
1164 			}
1165 			break;
1166 
1167 			case META_RASTEROP_ACTION:
1168 			{
1169                 pMA->Execute( &rVDev );
1170             }
1171 			break;
1172 
1173 			case META_FLOATTRANSPARENT_ACTION:
1174 			{
1175 				const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
1176 
1177 				GDIMetaFile		aTmpMtf( pA->GetGDIMetaFile() );
1178 				Point			aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1179 				const Size		aSrcSize( aTmpMtf.GetPrefSize() );
1180 				const Point		aDestPt( pA->GetPoint() );
1181 				const Size		aDestSize( pA->GetSize() );
1182 				const double	fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1183 				const double	fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1184 				long			nMoveX, nMoveY;
1185 
1186 				if( fScaleX != 1.0 || fScaleY != 1.0 )
1187 				{
1188 					aTmpMtf.Scale( fScaleX, fScaleY );
1189 					aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1190 				}
1191 
1192 				nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1193 
1194 				if( nMoveX || nMoveY )
1195 					aTmpMtf.Move( nMoveX, nMoveY );
1196 
1197 				ImplWriteActions( aTmpMtf, rVDev );
1198 			}
1199 			break;
1200 
1201 			case META_COMMENT_ACTION:
1202 			{
1203 				const MetaCommentAction* pA = (const MetaCommentAction*) pMA;
1204 				if ( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1205 				{
1206 					const MetaGradientExAction*	pGradAction = NULL;
1207 					while( ++nCurAction < nCount )
1208 					{
1209 						MetaAction* pAction = rMtf.GetAction( nCurAction );
1210 						if( pAction->GetType() == META_GRADIENTEX_ACTION )
1211 							pGradAction = (const MetaGradientExAction*) pAction;
1212 						else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
1213 								 ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
1214 						{
1215 							break;
1216 						}
1217 					}
1218 					if( pGradAction )
1219 						ImplWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), rVDev );
1220 				}
1221 				else if ( pA->GetComment().Equals( "XPATHFILL_SEQ_END" ) )
1222 				{
1223 					if ( aFillPath.Count() )
1224 					{
1225 						aFillPath = PolyPolygon();
1226 						ImplWriteLine( "gr" );
1227 					}
1228 				}
1229 				else
1230 				{
1231 					const sal_uInt8* pData = pA->GetData();
1232 					if ( pData )
1233 					{
1234 						SvMemoryStream	aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
1235 						sal_Bool		bSkipSequence = sal_False;
1236 						ByteString		sSeqEnd;
1237 
1238 						if( pA->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ) )
1239 						{
1240 							sSeqEnd = ByteString( "XPATHSTROKE_SEQ_END" );
1241 							SvtGraphicStroke aStroke;
1242 							aMemStm >> aStroke;
1243 
1244 							Polygon aPath;
1245 							aStroke.getPath( aPath );
1246 
1247 							PolyPolygon aStartArrow;
1248 							PolyPolygon aEndArrow;
1249 //							double fTransparency( aStroke.getTransparency() );
1250 							double fStrokeWidth( aStroke.getStrokeWidth() );
1251 							SvtGraphicStroke::JoinType eJT( aStroke.getJoinType() );
1252 							SvtGraphicStroke::DashArray l_aDashArray;
1253 
1254 							aStroke.getStartArrow( aStartArrow );
1255 							aStroke.getEndArrow( aEndArrow );
1256 							aStroke.getDashArray( l_aDashArray );
1257 
1258 							bSkipSequence = sal_True;
1259 							if ( l_aDashArray.size() > 11 )	// ps dasharray limit is 11
1260 								bSkipSequence = sal_False;
1261 							if ( aStartArrow.Count() || aEndArrow.Count() )
1262 								bSkipSequence = sal_False;
1263 							if ( (sal_uInt32)eJT > 2 )
1264 								bSkipSequence = sal_False;
1265 							if ( l_aDashArray.size() && ( fStrokeWidth != 0.0 ) )
1266 								bSkipSequence = sal_False;
1267 							if ( bSkipSequence )
1268 							{
1269 								ImplWriteLineInfo( fStrokeWidth, aStroke.getMiterLimit(),
1270 													aStroke.getCapType(), eJT, l_aDashArray );
1271 								ImplPolyLine( aPath );
1272 							}
1273 						}
1274 						else if( pA->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
1275 						{
1276 							sSeqEnd = ByteString( "XPATHFILL_SEQ_END" );
1277 							SvtGraphicFill aFill;
1278 							aMemStm >> aFill;
1279 							switch( aFill.getFillType() )
1280 							{
1281 								case SvtGraphicFill::fillSolid :
1282 								{
1283 									bSkipSequence = sal_True;
1284 									PolyPolygon aPolyPoly;
1285 									aFill.getPath( aPolyPoly );
1286 									sal_uInt16 i, nPolyCount = aPolyPoly.Count();
1287 									if ( nPolyCount )
1288 									{
1289 										aFillColor = aFill.getFillColor();
1290 										ImplWriteFillColor( PS_SPACE );
1291 										for ( i = 0; i < nPolyCount; )
1292 										{
1293 											ImplAddPath( aPolyPoly.GetObject( i ) );
1294 											if ( ++i < nPolyCount )
1295 											{
1296 												*mpPS << "p";
1297 												mnCursorPos += 2;
1298 												ImplExecMode( PS_RET );
1299 											}
1300 										}
1301 										*mpPS << "p ef";
1302 										mnCursorPos += 4;
1303 										ImplExecMode( PS_RET );
1304 									}
1305 								}
1306 								break;
1307 
1308 								case SvtGraphicFill::fillTexture :
1309 								{
1310 									aFill.getPath( aFillPath );
1311 
1312 									/* normally an object filling is consisting of three MetaActions:
1313 										MetaBitmapAction		using RasterOp xor,
1314 										MetaPolyPolygonAction	using RasterOp rop_0
1315 										MetaBitmapAction		using RasterOp xor
1316 
1317 										Because RasterOps cannot been used in Postscript, we have to
1318 										replace these actions. The MetaComment "XPATHFILL_SEQ_BEGIN" is
1319 										providing the clippath of the object. The following loop is
1320 										trying to find the bitmap that is matching the clippath, so that
1321 										only one bitmap is exported, otherwise if the bitmap is not
1322 										locatable, all metaactions are played normally.
1323 									*/
1324 									sal_uInt32 nCommentStartAction = nCurAction;
1325 									sal_uInt32 nBitmapCount = 0;
1326 									sal_uInt32 nBitmapAction = 0;
1327 
1328 									sal_Bool bOk = sal_True;
1329 									while( bOk && ( ++nCurAction < nCount ) )
1330 									{
1331 										MetaAction* pAction = rMtf.GetAction( nCurAction );
1332 										switch( pAction->GetType() )
1333 										{
1334 											case META_BMPSCALE_ACTION :
1335 											case META_BMPSCALEPART_ACTION :
1336 											case META_BMPEXSCALE_ACTION :
1337 											case META_BMPEXSCALEPART_ACTION :
1338 											{
1339 												nBitmapCount++;
1340 												nBitmapAction = nCurAction;
1341 											}
1342 											break;
1343 											case META_COMMENT_ACTION :
1344 											{
1345 												if (((const MetaCommentAction*)pAction)->GetComment().Equals( "XPATHFILL_SEQ_END" ))
1346 													bOk = sal_False;
1347 											}
1348 											break;
1349 										}
1350 									}
1351 									if( nBitmapCount == 2 )
1352 									{
1353 										ImplWriteLine( "gs" );
1354 										ImplIntersect( aFillPath );
1355 										GDIMetaFile aTempMtf;
1356 										aTempMtf.AddAction( rMtf.GetAction( nBitmapAction )->Clone() );
1357 										ImplWriteActions( aTempMtf, rVDev );
1358 										ImplWriteLine( "gr" );
1359 										aFillPath = PolyPolygon();
1360 									}
1361 									else
1362 										nCurAction = nCommentStartAction + 1;
1363 								}
1364 								break;
1365 
1366 								case SvtGraphicFill::fillGradient :
1367 									aFill.getPath( aFillPath );
1368 								break;
1369 
1370 								case SvtGraphicFill::fillHatch :
1371 								break;
1372 							}
1373 							if ( aFillPath.Count() )
1374 							{
1375 								ImplWriteLine( "gs" );
1376 								ImplIntersect( aFillPath );
1377 							}
1378 						}
1379 						if ( bSkipSequence )
1380 						{
1381 							while( ++nCurAction < nCount )
1382 							{
1383 								pMA = rMtf.GetAction( nCurAction );
1384 								if ( pMA->GetType() == META_COMMENT_ACTION )
1385 								{
1386 									ByteString sComment( ((MetaCommentAction*)pMA)->GetComment() );
1387 									if ( sComment.Equals( sSeqEnd ) )
1388 										break;
1389 								}
1390 							}
1391 						}
1392 					}
1393 				}
1394 			}
1395 			break;
1396 
1397 		}
1398 	}
1399 }
1400 
1401 
1402 
1403 //---------------------------------------------------------------------------------
1404 
ImplWritePoint(const Point & rPoint,sal_uInt32 nMode)1405 inline void PSWriter::ImplWritePoint( const Point& rPoint, sal_uInt32 nMode )
1406 {
1407 	ImplWriteDouble( rPoint.X() );
1408 	ImplWriteDouble( rPoint.Y(), nMode );
1409 }
1410 
1411 //---------------------------------------------------------------------------------
1412 
ImplMoveTo(const Point & rPoint,sal_uInt32 nMode)1413 void PSWriter::ImplMoveTo( const Point& rPoint, sal_uInt32 nMode )
1414 {
1415 	ImplWritePoint( rPoint );
1416 	ImplWriteByte( 'm' );
1417 	ImplExecMode( nMode );
1418 }
1419 
1420 //---------------------------------------------------------------------------------
1421 
ImplLineTo(const Point & rPoint,sal_uInt32 nMode)1422 void PSWriter::ImplLineTo( const Point& rPoint, sal_uInt32 nMode )
1423 {
1424 	ImplWritePoint( rPoint );
1425 	ImplWriteByte( 'l' );
1426 	ImplExecMode( nMode );
1427 }
1428 
1429 //---------------------------------------------------------------------------------
1430 
ImplCurveTo(const Point & rP1,const Point & rP2,const Point & rP3,sal_uInt32 nMode)1431 void PSWriter::ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode )
1432 {
1433 	ImplWritePoint( rP1 );
1434 	ImplWritePoint( rP2 );
1435 	ImplWritePoint( rP3 );
1436 	*mpPS << "ct ";
1437 	ImplExecMode( nMode );
1438 }
1439 
1440 //---------------------------------------------------------------------------------
1441 
ImplTranslate(const double & fX,const double & fY,sal_uInt32 nMode)1442 void PSWriter::ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode )
1443 {
1444 	ImplWriteDouble( fX );
1445 	ImplWriteDouble( fY );
1446 	ImplWriteByte( 't' );
1447 	ImplExecMode( nMode );
1448 }
1449 
1450 //---------------------------------------------------------------------------------
1451 
ImplScale(const double & fX,const double & fY,sal_uInt32 nMode)1452 void PSWriter::ImplScale( const double& fX, const double& fY, sal_uInt32 nMode )
1453 {
1454 	ImplWriteDouble( fX );
1455 	ImplWriteDouble( fY );
1456 	ImplWriteByte( 's' );
1457 	ImplExecMode( nMode );
1458 }
1459 
1460 //---------------------------------------------------------------------------------
1461 
ImplRect(const Rectangle & rRect)1462 void PSWriter::ImplRect( const Rectangle & rRect )
1463 {
1464 	if ( bFillColor )
1465 		ImplRectFill( rRect );
1466 	if ( bLineColor )
1467 	{
1468 		double nWidth = rRect.GetWidth();
1469 		double nHeight = rRect.GetHeight();
1470 
1471 		ImplWriteLineColor( PS_SPACE );
1472 		ImplMoveTo( rRect.TopLeft() );
1473 		ImplWriteDouble( nWidth );
1474 		*mpPS << "0 rl 0 ";
1475 		ImplWriteDouble( nHeight );
1476 		*mpPS << "rl ";
1477 		ImplWriteDouble( nWidth );
1478 		*mpPS << "neg 0 rl ";
1479 		ImplClosePathDraw();
1480 	}
1481 	*mpPS << (sal_uInt8)10;
1482 	mnCursorPos = 0;
1483 }
1484 
1485 //---------------------------------------------------------------------------------
1486 
ImplRectFill(const Rectangle & rRect)1487 void PSWriter::ImplRectFill( const Rectangle & rRect )
1488 {
1489 	double nWidth = rRect.GetWidth();
1490 	double nHeight = rRect.GetHeight();
1491 
1492 	ImplWriteFillColor( PS_SPACE );
1493 	ImplMoveTo( rRect.TopLeft() );
1494 	ImplWriteDouble( nWidth );
1495 	*mpPS << "0 rl 0 ";
1496 	ImplWriteDouble( nHeight );
1497 	*mpPS << "rl ";
1498 	ImplWriteDouble( nWidth );
1499 	*mpPS << "neg 0 rl ef ";
1500 	*mpPS << "p ef";
1501 	mnCursorPos += 2;
1502 	ImplExecMode( PS_RET );
1503 }
1504 
1505 //---------------------------------------------------------------------------------
1506 
ImplAddPath(const Polygon & rPolygon)1507 void PSWriter::ImplAddPath( const Polygon & rPolygon )
1508 {
1509 	sal_uInt16 i = 1;
1510 	sal_uInt16 nPointCount = rPolygon.GetSize();
1511 	if ( nPointCount > 1 )
1512 	{
1513 		ImplMoveTo( rPolygon.GetPoint( 0 ) );
1514 		while ( i < nPointCount )
1515 		{
1516 			if ( ( rPolygon.GetFlags( i ) == POLY_CONTROL )
1517 					&& ( ( i + 2 ) < nPointCount )
1518 						&& ( rPolygon.GetFlags( i + 1 ) == POLY_CONTROL )
1519 							&& ( rPolygon.GetFlags( i + 2 ) != POLY_CONTROL ) )
1520 			{
1521 				ImplCurveTo( rPolygon[ i ], rPolygon[ i + 1 ], rPolygon[ i + 2 ], PS_WRAP );
1522 				i += 3;
1523 			}
1524 			else
1525 				ImplLineTo( rPolygon.GetPoint( i++ ), PS_SPACE | PS_WRAP );
1526 		}
1527 	}
1528 }
1529 
1530 //---------------------------------------------------------------------------------
1531 
ImplIntersect(const PolyPolygon & rPolyPoly)1532 void PSWriter::ImplIntersect( const PolyPolygon& rPolyPoly )
1533 {
1534 	sal_uInt16 i, nPolyCount = rPolyPoly.Count();
1535 	for ( i = 0; i < nPolyCount; )
1536 	{
1537 		ImplAddPath( rPolyPoly.GetObject( i ) );
1538 		if ( ++i < nPolyCount )
1539 		{
1540 			*mpPS << "p";
1541 			mnCursorPos += 2;
1542 			ImplExecMode( PS_RET );
1543 		}
1544 	}
1545 	ImplWriteLine( "eoclip newpath" );
1546 }
1547 
1548 //---------------------------------------------------------------------------------
1549 
ImplWriteGradient(const PolyPolygon & rPolyPoly,const Gradient & rGradient,VirtualDevice & rVDev)1550 void PSWriter::ImplWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev )
1551 {
1552 	VirtualDevice	l_aVDev;
1553 	GDIMetaFile 	aTmpMtf;
1554 	l_aVDev.SetMapMode( rVDev.GetMapMode() );
1555 	l_aVDev.AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
1556 	ImplWriteActions( aTmpMtf, rVDev );
1557 }
1558 
1559 //---------------------------------------------------------------------------------
1560 
ImplPolyPoly(const PolyPolygon & rPolyPoly,sal_Bool bTextOutline)1561 void PSWriter::ImplPolyPoly( const PolyPolygon & rPolyPoly, sal_Bool bTextOutline )
1562 {
1563 	sal_uInt16 i, nPolyCount = rPolyPoly.Count();
1564 	if ( nPolyCount )
1565 	{
1566 		if ( bFillColor || bTextOutline )
1567 		{
1568 			if ( bTextOutline )
1569 				ImplWriteTextColor( PS_SPACE );
1570 			else
1571 				ImplWriteFillColor( PS_SPACE );
1572 			for ( i = 0; i < nPolyCount; )
1573 			{
1574 				ImplAddPath( rPolyPoly.GetObject( i ) );
1575 				if ( ++i < nPolyCount )
1576 				{
1577 					*mpPS << "p";
1578 					mnCursorPos += 2;
1579 					ImplExecMode( PS_RET );
1580 				}
1581 			}
1582 			*mpPS << "p ef";
1583 			mnCursorPos += 4;
1584 			ImplExecMode( PS_RET );
1585 		}
1586 		if ( bLineColor )
1587 		{
1588 			ImplWriteLineColor( PS_SPACE );
1589 			for ( i = 0; i < nPolyCount; i++ )
1590 				ImplAddPath( rPolyPoly.GetObject( i ) );
1591 			ImplClosePathDraw( PS_RET );
1592 		}
1593 	}
1594 }
1595 
1596 //---------------------------------------------------------------------------------
1597 
ImplPolyLine(const Polygon & rPoly)1598 void PSWriter::ImplPolyLine( const Polygon & rPoly )
1599 {
1600 	if ( bLineColor )
1601 	{
1602 		ImplWriteLineColor( PS_SPACE );
1603 		sal_uInt16 i, nPointCount = rPoly.GetSize();
1604 		if ( nPointCount )
1605 		{
1606 			if ( nPointCount > 1 )
1607 			{
1608 				ImplMoveTo( rPoly.GetPoint( 0 ) );
1609 				i = 1;
1610 				while ( i < nPointCount )
1611 				{
1612 					if ( ( rPoly.GetFlags( i ) == POLY_CONTROL )
1613 							&& ( ( i + 2 ) < nPointCount )
1614 								&& ( rPoly.GetFlags( i + 1 ) == POLY_CONTROL )
1615 									&& ( rPoly.GetFlags( i + 2 ) != POLY_CONTROL ) )
1616 					{
1617 						ImplCurveTo( rPoly[ i ], rPoly[ i + 1 ], rPoly[ i + 2 ], PS_WRAP );
1618 						i += 3;
1619 					}
1620 					else
1621 						ImplLineTo( rPoly.GetPoint( i++ ), PS_SPACE | PS_WRAP );
1622 				}
1623 			}
1624 
1625             // #104645# explicitly close path if polygon is closed
1626             if( rPoly[ 0 ] == rPoly[ nPointCount-1 ] )
1627                 ImplClosePathDraw( PS_RET );
1628             else
1629                 ImplPathDraw();
1630 		}
1631 	}
1632 }
1633 
1634 //---------------------------------------------------------------------------------
1635 
ImplSetClipRegion(Region & rClipRegion)1636 void PSWriter::ImplSetClipRegion( Region& rClipRegion )
1637 {
1638 	if ( !rClipRegion.IsEmpty() )
1639 	{
1640         RectangleVector aRectangles;
1641         rClipRegion.GetRegionRectangles(aRectangles);
1642 
1643         for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
1644         {
1645             double nX1(aRectIter->Left());
1646             double nY1(aRectIter->Top());
1647             double nX2(aRectIter->Right());
1648             double nY2(aRectIter->Bottom());
1649 
1650             ImplWriteDouble( nX1 );
1651             ImplWriteDouble( nY1 );
1652             ImplWriteByte( 'm' );
1653             ImplWriteDouble( nX2 );
1654             ImplWriteDouble( nY1 );
1655             ImplWriteByte( 'l' );
1656             ImplWriteDouble( nX2 );
1657             ImplWriteDouble( nY2 );
1658             ImplWriteByte( 'l' );
1659             ImplWriteDouble( nX1 );
1660             ImplWriteDouble( nY2 );
1661             ImplWriteByte( 'l' );
1662             ImplWriteDouble( nX1 );
1663             ImplWriteDouble( nY1 );
1664             ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
1665         }
1666 
1667 		//Rectangle		aRect;
1668 		//RegionHandle	hRegionHandle = rClipRegion.BeginEnumRects();
1669         //
1670 		//while ( rClipRegion.GetEnumRects( hRegionHandle, aRect ) )
1671 		//{
1672 		//	double nX1 = aRect.Left();
1673 		//	double nY1 = aRect.Top();
1674 		//	double nX2 = aRect.Right();
1675 		//	double nY2 = aRect.Bottom();
1676 		//	ImplWriteDouble( nX1 );
1677 		//	ImplWriteDouble( nY1 );
1678 		//	ImplWriteByte( 'm' );
1679 		//	ImplWriteDouble( nX2 );
1680 		//	ImplWriteDouble( nY1 );
1681 		//	ImplWriteByte( 'l' );
1682 		//	ImplWriteDouble( nX2 );
1683 		//	ImplWriteDouble( nY2 );
1684 		//	ImplWriteByte( 'l' );
1685 		//	ImplWriteDouble( nX1 );
1686 		//	ImplWriteDouble( nY2 );
1687 		//	ImplWriteByte( 'l' );
1688 		//	ImplWriteDouble( nX1 );
1689 		//	ImplWriteDouble( nY1 );
1690 		//	ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
1691 		//};
1692 		//rClipRegion.EndEnumRects( hRegionHandle );
1693 		ImplWriteLine( "eoclip newpath" );
1694 	}
1695 }
1696 
1697 //---------------------------------------------------------------------------------
1698 // possible gfx formats:
1699 //
1700 // level 1: grayscale	8 bit
1701 //			color	   24 bit
1702 //
1703 // level 2: grayscale	8 bit
1704 //			color		1(pal), 4(pal), 8(pal), 24 Bit
1705 //
1706 
ImplBmp(Bitmap * pBitmap,Bitmap * pMaskBitmap,const Point & rPoint,double nXWidth,double nYHeightOrg)1707 void PSWriter::ImplBmp( Bitmap* pBitmap, Bitmap* pMaskBitmap, const Point & rPoint, double nXWidth, double nYHeightOrg )
1708 {
1709 	if ( !pBitmap )
1710 		return;
1711 
1712 	sal_Int32	nHeightOrg = pBitmap->GetSizePixel().Height();
1713 	sal_Int32	nHeightLeft = nHeightOrg;
1714 	long	nWidth = pBitmap->GetSizePixel().Width();
1715 	Point	aSourcePos( rPoint );
1716 
1717 	while ( nHeightLeft )
1718 	{
1719 		Bitmap	aTileBitmap( *pBitmap );
1720 		long	nHeight = nHeightLeft;
1721 		double	nYHeight = nYHeightOrg;
1722 
1723 		sal_Bool	bDoTrans = sal_False;
1724 
1725 		Rectangle	aRect;
1726 		Region		aRegion;
1727 
1728 		if ( pMaskBitmap )
1729 		{
1730 			bDoTrans = sal_True;
1731 			while (sal_True)
1732 			{
1733 				if ( mnLevel == 1 )
1734 				{
1735 					if ( nHeight > 10 )
1736 						nHeight = 8;
1737 				}
1738 				aRect = Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( (long)nWidth, (long)nHeight ) );
1739 				aRegion = Region( pMaskBitmap->CreateRegion( COL_BLACK, aRect ) );
1740 
1741 				if( mnLevel == 1 )
1742 				{
1743                     RectangleVector aRectangleVector;
1744                     aRegion.GetRegionRectangles(aRectangleVector);
1745 
1746                     if ( aRectangleVector.size() * 5 > 1000 )
1747 				    {
1748 					    nHeight >>= 1;
1749 					    if ( nHeight < 2 )
1750 						    return;
1751                         continue;
1752                     }
1753 				}
1754 				break;
1755 			}
1756 		}
1757 		if ( nHeight != nHeightOrg )
1758 		{
1759 			nYHeight = nYHeightOrg * nHeight / nHeightOrg;
1760 			aTileBitmap.Crop( Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( nWidth, nHeight ) ) );
1761 		}
1762 		if ( bDoTrans )
1763 		{
1764 			ImplWriteLine( "gs\npum" );
1765 			ImplTranslate( aSourcePos.X(), aSourcePos.Y() );
1766 			ImplScale( nXWidth / nWidth,  nYHeight / nHeight );
1767 
1768             RectangleVector aRectangles;
1769             aRegion.GetRegionRectangles(aRectangles);
1770             const long nMoveVertical(nHeightLeft - nHeightOrg);
1771 
1772             for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
1773             {
1774                 aRectIter->Move(0, nMoveVertical);
1775 
1776                 ImplWriteLong( aRectIter->Left() );
1777                 ImplWriteLong( aRectIter->Top() );
1778                 ImplWriteByte( 'm' );
1779                 ImplWriteLong( aRectIter->Right() + 1 );
1780                 ImplWriteLong( aRectIter->Top() );
1781                 ImplWriteByte( 'l' );
1782                 ImplWriteLong( aRectIter->Right() + 1 );
1783                 ImplWriteLong( aRectIter->Bottom() + 1 );
1784                 ImplWriteByte( 'l' );
1785                 ImplWriteLong( aRectIter->Left() );
1786                 ImplWriteLong( aRectIter->Bottom() + 1 );
1787                 ImplWriteByte( 'l' );
1788                 ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
1789             }
1790 
1791             //RegionHandle	hRegionHandle = aRegion.BeginEnumRects();
1792             //
1793 			//while ( aRegion.GetEnumRects( hRegionHandle, aRect ) )
1794 			//{
1795 			//	aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) );
1796 			//	ImplWriteLong( aRect.Left() );
1797 			//	ImplWriteLong( aRect.Top() );
1798 			//	ImplWriteByte( 'm' );
1799 			//	ImplWriteLong( aRect.Right() + 1 );
1800 			//	ImplWriteLong( aRect.Top() );
1801 			//	ImplWriteByte( 'l' );
1802 			//	ImplWriteLong( aRect.Right() + 1 );
1803 			//	ImplWriteLong( aRect.Bottom() + 1 );
1804 			//	ImplWriteByte( 'l' );
1805 			//	ImplWriteLong( aRect.Left() );
1806 			//	ImplWriteLong( aRect.Bottom() + 1 );
1807 			//	ImplWriteByte( 'l' );
1808 			//	ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
1809 			//};
1810 			//aRegion.EndEnumRects( hRegionHandle );
1811 			ImplWriteLine( "eoclip newpath" );
1812 			ImplWriteLine( "pom" );
1813 		}
1814 		BitmapReadAccess* pAcc = aTileBitmap.AcquireReadAccess();
1815 
1816 		if (!bDoTrans )
1817 			ImplWriteLine( "pum" );
1818 
1819 		ImplTranslate( aSourcePos.X(), aSourcePos.Y() + nYHeight );
1820 		ImplScale( nXWidth, nYHeight );
1821 		if ( mnLevel == 1 ) 				// level 1 is always grayscale !!!
1822 		{
1823 			ImplWriteLong( nWidth );
1824 			ImplWriteLong( nHeight );
1825 			*mpPS << "8 [";
1826 			ImplWriteLong( nWidth );
1827 			*mpPS << "0 0 ";
1828 			ImplWriteLong( -nHeight );
1829 			ImplWriteLong( 0 );
1830 			ImplWriteLong( nHeight );
1831 			ImplWriteLine( "]" );
1832 			*mpPS << "{currentfile ";
1833 			ImplWriteLong( nWidth );
1834 			ImplWriteLine( "string readhexstring pop}" );
1835 			ImplWriteLine( "image" );
1836 			for ( long y = 0; y < nHeight; y++ )
1837 			{
1838 				for ( long x = 0; x < nWidth; x++ )
1839 				{
1840 					ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
1841 				}
1842 			}
1843 			*mpPS << (sal_uInt8)10;
1844 		}
1845 		else	// Level 2
1846 		{
1847 			if ( mbGrayScale )
1848 			{
1849 				ImplWriteLine( "/DeviceGray setcolorspace" );
1850 				ImplWriteLine( "<<" );
1851 				ImplWriteLine( "/ImageType 1" );
1852 				*mpPS << "/Width ";
1853 				ImplWriteLong( nWidth, PS_RET );
1854 				*mpPS << "/Height ";
1855 				ImplWriteLong( nHeight, PS_RET );
1856 				ImplWriteLine( "/BitsPerComponent 8" );
1857 				ImplWriteLine( "/Decode[0 1]" );
1858 				*mpPS << "/ImageMatrix[";
1859 				ImplWriteLong( nWidth );
1860 				*mpPS << "0 0 ";
1861 				ImplWriteLong( -nHeight );
1862 				ImplWriteLong( 0 );
1863 				ImplWriteLong( nHeight, PS_NONE );
1864 				ImplWriteByte( ']', PS_RET );
1865 				ImplWriteLine( "/DataSource currentfile" );
1866 				ImplWriteLine( "/ASCIIHexDecode filter" );
1867 				if ( mbCompression )
1868 					ImplWriteLine( "/LZWDecode filter" );
1869 				ImplWriteLine( ">>" );
1870 				ImplWriteLine( "image" );
1871 				if ( mbCompression )
1872 				{
1873 					StartCompression();
1874 					for ( long y = 0; y < nHeight; y++ )
1875 					{
1876 						for ( long x = 0; x < nWidth; x++ )
1877 						{
1878 							Compress( pAcc->GetPixelIndex( y, x ) );
1879 						}
1880 					}
1881 					EndCompression();
1882 				}
1883 				else
1884 				{
1885 					for ( long y = 0; y < nHeight; y++ )
1886 					{
1887 						for ( long x = 0; x < nWidth; x++ )
1888 						{
1889 							ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
1890 						}
1891 					}
1892 				}
1893 			}
1894 			else
1895 			{
1896 				// have we to write a palette ?
1897 
1898 				if ( pAcc->HasPalette() )
1899 				{
1900 					ImplWriteLine( "[/Indexed /DeviceRGB " );
1901 					ImplWriteLong( pAcc->GetPaletteEntryCount() - 1, PS_RET );
1902 					ImplWriteByte( '<', PS_NONE );
1903 					for ( sal_uInt16 i = 0; i < pAcc->GetPaletteEntryCount(); i++ )
1904 					{
1905 						BitmapColor aBitmapColor = pAcc->GetPaletteColor( i );
1906 						ImplWriteHexByte( aBitmapColor.GetRed(), PS_NONE );
1907 						ImplWriteHexByte( aBitmapColor.GetGreen(), PS_NONE );
1908 						ImplWriteHexByte( aBitmapColor.GetBlue(), PS_SPACE | PS_WRAP );
1909 					}
1910 					ImplWriteByte( '>', PS_RET );
1911 
1912 					ImplWriteLine( "] setcolorspace" );
1913 					ImplWriteLine( "<<" );
1914 					ImplWriteLine( "/ImageType 1" );
1915 					*mpPS << "/Width ";
1916 					ImplWriteLong( nWidth, PS_RET );
1917 					*mpPS << "/Height ";
1918 					ImplWriteLong( nHeight, PS_RET );
1919 					ImplWriteLine( "/BitsPerComponent 8" );
1920 					ImplWriteLine( "/Decode[0 255]" );
1921 					*mpPS << "/ImageMatrix[";
1922 					ImplWriteLong( nWidth );
1923 					*mpPS << "0 0 ";
1924 					ImplWriteLong( -nHeight );
1925 					ImplWriteLong( 0);
1926 					ImplWriteLong( nHeight, PS_NONE );
1927 					ImplWriteByte( ']', PS_RET );
1928 					ImplWriteLine( "/DataSource currentfile" );
1929 					ImplWriteLine( "/ASCIIHexDecode filter" );
1930 					if ( mbCompression )
1931 						ImplWriteLine( "/LZWDecode filter" );
1932 					ImplWriteLine( ">>" );
1933 					ImplWriteLine( "image" );
1934 					if ( mbCompression )
1935 					{
1936 						StartCompression();
1937 						for ( long y = 0; y < nHeight; y++ )
1938 						{
1939 							for ( long x = 0; x < nWidth; x++ )
1940 							{
1941 								Compress( pAcc->GetPixelIndex( y, x ) );
1942 							}
1943 						}
1944 						EndCompression();
1945 					}
1946 					else
1947 					{
1948 						for ( long y = 0; y < nHeight; y++ )
1949 						{
1950 							for ( long x = 0; x < nWidth; x++ )
1951 							{
1952 								ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
1953 							}
1954 						}
1955 					}
1956 				}
1957 				else // 24 bit color
1958 				{
1959 					ImplWriteLine( "/DeviceRGB setcolorspace" );
1960 					ImplWriteLine( "<<" );
1961 					ImplWriteLine( "/ImageType 1" );
1962 					*mpPS << "/Width ";
1963 					ImplWriteLong( nWidth, PS_RET );
1964 					*mpPS << "/Height ";
1965 					ImplWriteLong( nHeight, PS_RET );
1966 					ImplWriteLine( "/BitsPerComponent 8" );
1967 					ImplWriteLine( "/Decode[0 1 0 1 0 1]" );
1968 					*mpPS << "/ImageMatrix[";
1969 					ImplWriteLong( nWidth );
1970 					*mpPS << "0 0 ";
1971 					ImplWriteLong( -nHeight );
1972 					ImplWriteLong( 0 );
1973 					ImplWriteLong( nHeight, PS_NONE );
1974 					ImplWriteByte( ']', PS_RET );
1975 					ImplWriteLine( "/DataSource currentfile" );
1976 					ImplWriteLine( "/ASCIIHexDecode filter" );
1977 					if ( mbCompression )
1978 						ImplWriteLine( "/LZWDecode filter" );
1979 					ImplWriteLine( ">>" );
1980 					ImplWriteLine( "image" );
1981 					if ( mbCompression )
1982 					{
1983 						StartCompression();
1984 						for ( long y = 0; y < nHeight; y++ )
1985 						{
1986 							for ( long x = 0; x < nWidth; x++ )
1987 							{
1988 								const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) );
1989 								Compress( aBitmapColor.GetRed() );
1990 								Compress( aBitmapColor.GetGreen() );
1991 								Compress( aBitmapColor.GetBlue() );
1992 							}
1993 						}
1994 						EndCompression();
1995 					}
1996 					else
1997 					{
1998 						for ( long y = 0; y < nHeight; y++ )
1999 						{
2000 							for ( long x = 0; x < nWidth; x++ )
2001 							{
2002 								const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) );
2003 								ImplWriteHexByte( aBitmapColor.GetRed() );
2004 								ImplWriteHexByte( aBitmapColor.GetGreen() );
2005 								ImplWriteHexByte( aBitmapColor.GetBlue() );
2006 							}
2007 						}
2008 					}
2009 				}
2010 			}
2011 			ImplWriteLine( ">" );       // in Level 2 the dictionary needs to be closed (eod)
2012 		}
2013 		if ( bDoTrans )
2014 			ImplWriteLine( "gr" );
2015 		else
2016 			ImplWriteLine( "pom" );
2017 
2018 		aTileBitmap.ReleaseAccess( pAcc );
2019 		nHeightLeft -= nHeight;
2020 		if ( nHeightLeft )
2021 		{
2022 			nHeightLeft++;
2023 			aSourcePos.Y() = (long) ( rPoint.Y() + ( nYHeightOrg * ( nHeightOrg - nHeightLeft ) ) / nHeightOrg );
2024 		}
2025 	}
2026 }
2027 
2028 //---------------------------------------------------------------------------------
2029 
ImplWriteCharacter(sal_Char nChar)2030 void PSWriter::ImplWriteCharacter( sal_Char nChar )
2031 {
2032 	switch( nChar )
2033 	{
2034 		case '(' :
2035 		case ')' :
2036 		case '\\' :
2037 			ImplWriteByte( (sal_uInt8)'\\', PS_NONE );
2038 	}
2039 	ImplWriteByte( (sal_uInt8)nChar, PS_NONE );
2040 }
2041 
2042 //---------------------------------------------------------------------------------
2043 
ImplWriteString(const ByteString & rString,VirtualDevice & rVDev,const sal_Int32 * pDXArry,sal_Bool bStretch)2044 void PSWriter::ImplWriteString( const ByteString& rString, VirtualDevice& rVDev, const sal_Int32* pDXArry, sal_Bool bStretch )
2045 {
2046 	sal_uInt16 nLen = rString.Len();
2047 	if ( nLen )
2048 	{
2049 		sal_uInt16 i;
2050 		if ( pDXArry )
2051 		{
2052 			double nx = 0;
2053 
2054 			for( i = 0; i < nLen; i++ )
2055 			{
2056 				if ( i > 0 )
2057 					nx = pDXArry[ i - 1 ];
2058 				ImplWriteDouble( ( bStretch ) ? nx : rVDev.GetTextWidth( rString.GetChar( i ) ) );
2059 				ImplWriteDouble( nx );
2060 				ImplWriteLine( "(", PS_NONE );
2061 				ImplWriteCharacter( rString.GetChar( i ) );
2062 				ImplWriteLine( ") bs" );
2063 			}
2064 		}
2065 		else
2066 		{
2067 			ImplWriteByte( '(', PS_NONE );
2068 			for ( i = 0; i < nLen; i++ )
2069 				ImplWriteCharacter( rString.GetChar( i ) );
2070 			ImplWriteLine( ") sw" );
2071 		}
2072 	}
2073 }
2074 
2075 // ------------------------------------------------------------------------
2076 
ImplText(const String & rUniString,const Point & rPos,const sal_Int32 * pDXArry,sal_Int32 nWidth,VirtualDevice & rVDev)2077 void PSWriter::ImplText( const String& rUniString, const Point& rPos, const sal_Int32* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev )
2078 {
2079 	sal_uInt16 nLen = rUniString.Len();
2080 	if ( !nLen )
2081 		return;
2082 	if ( mnTextMode == 0 )	// using glpyh outlines
2083 	{
2084 		Font	aNotRotatedFont( maFont );
2085 		aNotRotatedFont.SetOrientation( 0 );
2086 
2087 		VirtualDevice aVirDev( 1 );
2088 		aVirDev.SetMapMode( rVDev.GetMapMode() );
2089 		aVirDev.SetFont( aNotRotatedFont );
2090 		aVirDev.SetTextAlign( eTextAlign );
2091 
2092 		sal_Int16 nRotation = maFont.GetOrientation();
2093 		Polygon	aPolyDummy( 1 );
2094 
2095 		PolyPolygon aPolyPoly;
2096 		Point aPos( rPos );
2097         if ( nRotation )
2098         {
2099 			aPolyDummy.SetPoint( aPos, 0 );
2100 			aPolyDummy.Rotate( rPos, nRotation );
2101 			aPos = aPolyDummy.GetPoint( 0 );
2102         }
2103 		sal_Bool bOldLineColor = bLineColor;
2104 		bLineColor = sal_False;
2105 		std::vector<PolyPolygon> aPolyPolyVec;
2106 		if ( aVirDev.GetTextOutlines( aPolyPolyVec, rUniString, 0, 0, STRING_LEN, sal_True, nWidth, pDXArry ) )
2107 		{
2108 		    // always adjust text position to match baseline alignment
2109 			ImplWriteLine( "pum" );
2110 			ImplWriteDouble( aPos.X() );
2111 			ImplWriteDouble( aPos.Y() );
2112 			ImplWriteLine( "t" );
2113 			if ( nRotation )
2114 			{
2115 				ImplWriteF( nRotation, 1 );
2116 				*mpPS << "r ";
2117 			}
2118 			std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
2119 			while ( aIter != aPolyPolyVec.end() )
2120 				ImplPolyPoly( *aIter++, sal_True );
2121 			ImplWriteLine( "pom" );
2122 		}
2123 		bLineColor = bOldLineColor;
2124 	}
2125 	else if ( ( mnTextMode == 1 ) || ( mnTextMode == 2 ) )	// normal text output
2126 	{
2127 		if ( mnTextMode == 2 )	// forcing output one complete text packet, by
2128 			pDXArry = NULL;		// ignoring the kerning array
2129 		ImplSetAttrForText( rPos );
2130 		ByteString aStr( rUniString, maFont.GetCharSet() );
2131 		ImplWriteString( aStr, rVDev, pDXArry, nWidth != 0 );
2132 		if ( maFont.GetOrientation() )
2133 			ImplWriteLine( "gr" );
2134 	}
2135 }
2136 
2137 // ------------------------------------------------------------------------
2138 
ImplSetAttrForText(const Point & rPoint)2139 void PSWriter::ImplSetAttrForText( const Point& rPoint )
2140 {
2141 	Point aPoint( rPoint );
2142 
2143 	long nRotation = maFont.GetOrientation();
2144 	ImplWriteTextColor();
2145 
2146 	Size aSize = maFont.GetSize();
2147 
2148 	if ( maLastFont != maFont )
2149 	{
2150 		if ( maFont.GetPitch() == PITCH_FIXED ) 		// a little bit font selection
2151 			ImplDefineFont( "Courier", "Oblique" );
2152 		else if ( maFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
2153 			ImplWriteLine( "/Symbol findfont" );
2154 		else if ( maFont.GetFamily() == FAMILY_SWISS )
2155 			ImplDefineFont( "Helvetica", "Oblique" );
2156 		else
2157 			ImplDefineFont( "Times", "Italic" );
2158 
2159 		maLastFont = maFont;
2160 		aSize = maFont.GetSize();
2161 		ImplWriteDouble( aSize.Height() );
2162 		*mpPS << "sf ";
2163 	}
2164 	if ( eTextAlign != ALIGN_BASELINE )
2165 	{														// PostScript kennt kein FontAlignment
2166 		if ( eTextAlign == ALIGN_TOP )						// -> ich gehe daher davon aus, dass
2167 			aPoint.Y() += ( aSize.Height() * 4 / 5 );		// der Bereich unter der Baseline
2168 		else if ( eTextAlign == ALIGN_BOTTOM )				// in etwa 20% der Fontsize ausmacht
2169 			aPoint.Y() -= ( aSize.Height() / 5 );
2170 	}
2171 	ImplMoveTo( aPoint );
2172 	if ( nRotation )
2173 	{
2174 		*mpPS << "gs ";
2175 		ImplWriteF( nRotation, 1 );
2176 		*mpPS << "r ";
2177 	}
2178 }
2179 
2180 //---------------------------------------------------------------------------------
2181 
ImplDefineFont(const char * pOriginalName,const char * pItalic)2182 void PSWriter::ImplDefineFont( const char* pOriginalName, const char* pItalic )
2183 {
2184 	*mpPS << (sal_uInt8)'/';             //convert the font pOriginalName using ISOLatin1Encoding
2185 	*mpPS << pOriginalName;
2186 	switch ( maFont.GetWeight() )
2187 	{
2188 		case WEIGHT_SEMIBOLD :
2189 		case WEIGHT_BOLD :
2190 		case WEIGHT_ULTRABOLD :
2191 		case WEIGHT_BLACK :
2192 			*mpPS << "-Bold";
2193 			if ( maFont.GetItalic() != ITALIC_NONE )
2194 				*mpPS << pItalic;
2195 			break;
2196 		default:
2197 			if ( maFont.GetItalic() != ITALIC_NONE )
2198 				*mpPS << pItalic;
2199 			break;
2200 	}
2201 	ImplWriteLine( " f" );
2202 }
2203 
2204 //---------------------------------------------------------------------------------
2205 //---------------------------------------------------------------------------------
2206 //---------------------------------------------------------------------------------
2207 
ImplClosePathDraw(sal_uLong nMode)2208 void PSWriter::ImplClosePathDraw( sal_uLong nMode )
2209 {
2210 	*mpPS << "pc";
2211 	mnCursorPos += 2;
2212 	ImplExecMode( nMode );
2213 }
2214 
ImplPathDraw()2215 void PSWriter::ImplPathDraw()
2216 {
2217 	*mpPS << "ps";
2218 	mnCursorPos += 2;
2219 	ImplExecMode( PS_RET );
2220 }
2221 
2222 //---------------------------------------------------------------------------------
2223 
ImplWriteLineColor(sal_uLong nMode)2224 inline void PSWriter::ImplWriteLineColor( sal_uLong nMode )
2225 {
2226 	if ( aColor != aLineColor )
2227 	{
2228 		aColor = aLineColor;
2229 		ImplWriteColor( nMode );
2230 	}
2231 }
ImplWriteFillColor(sal_uLong nMode)2232 inline void PSWriter::ImplWriteFillColor( sal_uLong nMode )
2233 {
2234 	if ( aColor != aFillColor )
2235 	{
2236 		aColor = aFillColor;
2237 		ImplWriteColor( nMode );
2238 	}
2239 }
ImplWriteTextColor(sal_uLong nMode)2240 inline void PSWriter::ImplWriteTextColor( sal_uLong nMode )
2241 {
2242 	if ( aColor != aTextColor )
2243 	{
2244 		aColor = aTextColor;
2245 		ImplWriteColor( nMode );
2246 	}
2247 }
ImplWriteTextFillColor(sal_uLong nMode)2248 inline void PSWriter::ImplWriteTextFillColor( sal_uLong nMode )
2249 {
2250 	if ( aColor != aTextFillColor )
2251 	{
2252 		aColor = aTextFillColor;
2253 		ImplWriteColor( nMode );
2254 	}
2255 }
2256 
2257 //---------------------------------------------------------------------------------
2258 
ImplWriteColor(sal_uLong nMode)2259 void PSWriter::ImplWriteColor( sal_uLong nMode )
2260 {
2261 	if ( mbGrayScale )
2262 	{
2263 		// writes the Color (grayscale) as a Number from 0.000 up to 1.000
2264 
2265 		ImplWriteF( 1000 * ( (sal_uInt8)aColor.GetRed() * 77 + (sal_uInt8)aColor.GetGreen() * 151 +
2266 			(sal_uInt8)aColor.GetBlue() * 28 + 1 ) / 65536, 3, nMode );
2267 	}
2268 	else
2269 	{
2270 		ImplWriteB1 ( (sal_uInt8)aColor.GetRed() );
2271 		ImplWriteB1 ( (sal_uInt8)aColor.GetGreen() );
2272 		ImplWriteB1 ( (sal_uInt8)aColor.GetBlue() );
2273 	}
2274 	*mpPS << "c";                               // ( c is defined as setrgbcolor or setgray )
2275 	ImplExecMode( nMode );
2276 }
2277 
2278 //---------------------------------------------------------------------------------
2279 
ImplGetScaling(const MapMode & rMapMode)2280 double PSWriter::ImplGetScaling( const MapMode& rMapMode )
2281 {
2282 	double	nMul;
2283 	switch ( rMapMode.GetMapUnit() )
2284 	{
2285 		case MAP_PIXEL :
2286 		case MAP_SYSFONT :
2287 		case MAP_APPFONT :
2288 
2289 		case MAP_100TH_MM :
2290 			nMul = 1;
2291 			break;
2292 		case MAP_10TH_MM :
2293 			nMul = 10;
2294 			break;
2295 		case MAP_MM :
2296 			nMul = 100;
2297 			break;
2298 		case MAP_CM :
2299 			nMul = 1000;
2300 			break;
2301 		case MAP_1000TH_INCH :
2302 			nMul = 2.54;
2303 			break;
2304 		case MAP_100TH_INCH :
2305 			nMul = 25.4;
2306 			break;
2307 		case MAP_10TH_INCH :
2308 			nMul = 254;
2309 			break;
2310 		case MAP_INCH :
2311 			nMul = 2540;
2312 			break;
2313 		case MAP_TWIP :
2314 			nMul = 1.76388889;
2315 			break;
2316 		case MAP_POINT :
2317 			nMul = 35.27777778;
2318 			break;
2319 		default:
2320 			nMul = 1.0;
2321 			break;
2322 	}
2323 	return nMul;
2324 }
2325 
2326 //---------------------------------------------------------------------------------
2327 
ImplGetMapMode(const MapMode & rMapMode)2328 void PSWriter::ImplGetMapMode( const MapMode& rMapMode )
2329 {
2330 	ImplWriteLine( "tm setmatrix" );
2331 	double fMul = ImplGetScaling( rMapMode );
2332 	double fScaleX = (double)rMapMode.GetScaleX() * fMul;
2333 	double fScaleY = (double)rMapMode.GetScaleY() * fMul;
2334     ImplTranslate( rMapMode.GetOrigin().X() * fScaleX, rMapMode.GetOrigin().Y() * fScaleY );
2335 	ImplScale( fScaleX, fScaleY );
2336 }
2337 
2338 //---------------------------------------------------------------------------------
2339 
ImplExecMode(sal_uLong nMode)2340 inline void PSWriter::ImplExecMode( sal_uLong nMode )
2341 {
2342 	if ( nMode & PS_WRAP )
2343 	{
2344 		if ( mnCursorPos >= PS_LINESIZE )
2345 		{
2346 			mnCursorPos = 0;
2347 			*mpPS << (sal_uInt8)0xa;
2348 			return;
2349 		}
2350 	}
2351 	if ( nMode & PS_SPACE )
2352 	{
2353 			*mpPS << (sal_uInt8)32;
2354 			mnCursorPos++;
2355 	}
2356 	if ( nMode & PS_RET )
2357 	{
2358 		*mpPS << (sal_uInt8)0xa;
2359 		mnCursorPos = 0;
2360 	}
2361 }
2362 
2363 //---------------------------------------------------------------------------------
2364 
ImplWriteLine(const char * pString,sal_uLong nMode)2365 inline void PSWriter::ImplWriteLine( const char* pString, sal_uLong nMode )
2366 {
2367 	sal_uLong i = 0;
2368 	while ( pString[ i ] )
2369 	{
2370 		*mpPS << (sal_uInt8)pString[ i++ ];
2371 	}
2372 	mnCursorPos += i;
2373 	ImplExecMode( nMode );
2374 }
2375 
2376 //---------------------------------------------------------------------------------
2377 
ImplWriteLineInfo(double fLWidth,double fMLimit,SvtGraphicStroke::CapType eLCap,SvtGraphicStroke::JoinType eJoin,SvtGraphicStroke::DashArray & rLDash)2378 void PSWriter::ImplWriteLineInfo( double fLWidth, double fMLimit,
2379 									SvtGraphicStroke::CapType eLCap,
2380 										SvtGraphicStroke::JoinType eJoin,
2381 											SvtGraphicStroke::DashArray& rLDash )
2382 {
2383 	if ( fLineWidth != fLWidth )
2384 	{
2385 		fLineWidth = fLWidth;
2386 		ImplWriteDouble( fLineWidth );
2387 		ImplWriteLine( "lw", PS_SPACE );
2388 	}
2389 	if ( eLineCap != eLCap )
2390 	{
2391 		eLineCap = eLCap;
2392 		ImplWriteLong( (sal_Int32)eLineCap, PS_SPACE );
2393 		ImplWriteLine( "lc", PS_SPACE );
2394 	}
2395 	if ( eJoinType != eJoin )
2396 	{
2397 		eJoinType = eJoin;
2398 		ImplWriteLong( (sal_Int32)eJoinType, PS_SPACE );
2399 		ImplWriteLine( "lj", PS_SPACE );
2400 	}
2401 	if ( eJoinType == SvtGraphicStroke::joinMiter )
2402 	{
2403 		if ( fMiterLimit != fMLimit )
2404 		{
2405 			fMiterLimit = fMLimit;
2406 			ImplWriteDouble( fMiterLimit );
2407 			ImplWriteLine( "ml", PS_SPACE );
2408 		}
2409 	}
2410 	if ( aDashArray != rLDash )
2411 	{
2412 		aDashArray = rLDash;
2413 		sal_uInt32 j, i = aDashArray.size();
2414 		ImplWriteLine( "[", PS_SPACE );
2415 		for ( j = 0; j < i; j++ )
2416 			ImplWriteDouble( aDashArray[ j ] );
2417 		ImplWriteLine( "] 0 ld" );
2418 	}
2419 }
2420 
2421 //---------------------------------------------------------------------------------
2422 
ImplWriteLineInfo(const LineInfo & rLineInfo)2423 void PSWriter::ImplWriteLineInfo( const LineInfo& rLineInfo )
2424 {
2425 	SvtGraphicStroke::DashArray l_aDashArray;
2426 	if ( rLineInfo.GetStyle() == LINE_DASH )
2427 		l_aDashArray.push_back( 2 );
2428 	const double fLWidth(( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5);
2429     SvtGraphicStroke::JoinType aJoinType(SvtGraphicStroke::joinMiter);
2430     SvtGraphicStroke::CapType aCapType(SvtGraphicStroke::capButt);
2431 
2432     switch(rLineInfo.GetLineJoin())
2433     {
2434         default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
2435             // do NOT use SvtGraphicStroke::joinNone here
2436             // since it will be written as numerical value directly
2437             // and is NOT a valid EPS value
2438             break;
2439         case basegfx::B2DLINEJOIN_MITER:
2440             aJoinType = SvtGraphicStroke::joinMiter;
2441             break;
2442         case basegfx::B2DLINEJOIN_BEVEL:
2443             aJoinType = SvtGraphicStroke::joinBevel;
2444             break;
2445         case basegfx::B2DLINEJOIN_ROUND:
2446             aJoinType = SvtGraphicStroke::joinRound;
2447             break;
2448     }
2449 
2450     switch(rLineInfo.GetLineCap())
2451     {
2452         default: /* com::sun::star::drawing::LineCap_BUTT */
2453         {
2454             aCapType = SvtGraphicStroke::capButt;
2455             break;
2456         }
2457         case com::sun::star::drawing::LineCap_ROUND:
2458         {
2459             aCapType = SvtGraphicStroke::capRound;
2460             break;
2461         }
2462         case com::sun::star::drawing::LineCap_SQUARE:
2463         {
2464             aCapType = SvtGraphicStroke::capSquare;
2465             break;
2466         }
2467     }
2468 
2469 	ImplWriteLineInfo( fLWidth, fMiterLimit, aCapType, aJoinType, l_aDashArray );
2470 }
2471 
2472 //---------------------------------------------------------------------------------
2473 
ImplWriteLong(sal_Int32 nNumber,sal_uLong nMode)2474 void PSWriter::ImplWriteLong( sal_Int32 nNumber, sal_uLong nMode )
2475 {
2476 	const ByteString aNumber( ByteString::CreateFromInt32( nNumber ) );
2477 	sal_uLong nLen = aNumber.Len();
2478 	mnCursorPos += nLen;
2479 	for ( sal_uInt16 n = 0; n < nLen; n++ )
2480 		*mpPS << aNumber.GetChar( n );
2481 	ImplExecMode( nMode );
2482 }
2483 
2484 //---------------------------------------------------------------------------------
2485 
ImplWriteDouble(double fNumber,sal_uLong nMode)2486 void PSWriter::ImplWriteDouble( double fNumber, sal_uLong nMode )
2487 {
2488 	sal_Int32 nLength;
2489 
2490 	sal_Int32	nPTemp = (sal_Int32)fNumber;
2491 	sal_Int32	nATemp = labs( (sal_Int32)( ( fNumber - nPTemp ) * 100000 ) );
2492 
2493 	if ( !nPTemp && nATemp && ( fNumber < 0.0 ) )
2494 		*mpPS << (sal_Char)'-';
2495 
2496 	ByteString aNumber1( ByteString::CreateFromInt32( nPTemp ) );
2497 	nLength = aNumber1.Len();
2498 	mnCursorPos += nLength;
2499 	for ( sal_Int32 n = 0; n < nLength; n++ )
2500 		*mpPS << aNumber1.GetChar( (sal_uInt16)n );
2501 
2502 	int zCount = 0;
2503 	if ( nATemp )
2504 	{
2505 		*mpPS << (sal_uInt8)'.';
2506 		mnCursorPos++;
2507 		const ByteString aNumber2( ByteString::CreateFromInt32( nATemp ) );
2508 
2509 		sal_Int16 n, nLen = aNumber2.Len();
2510 		if ( nLen < 8 )
2511 		{
2512 			mnCursorPos += 6 - nLen;
2513 			for ( n = 0; n < ( 5 - nLen ); n++ )
2514 			{
2515 				*mpPS << (sal_uInt8)'0';
2516 			}
2517 		}
2518 		mnCursorPos += nLen;
2519 		for ( n = 0; n < nLen; n++ )
2520 		{
2521 			*mpPS << aNumber2.GetChar( n );
2522 			zCount--;
2523 			if ( aNumber2.GetChar( n ) != '0' )
2524 				zCount = 0;
2525 		}
2526 		if ( zCount )
2527 			mpPS->SeekRel( zCount );
2528 	}
2529 	ImplExecMode( nMode );
2530 }
2531 
2532 //---------------------------------------------------------------------------------
2533 
2534 // writes the number to stream: nNumber / ( 10^nCount )
2535 
ImplWriteF(sal_Int32 nNumber,sal_uLong nCount,sal_uLong nMode)2536 void PSWriter::ImplWriteF( sal_Int32 nNumber, sal_uLong nCount, sal_uLong nMode )
2537 {
2538 	if ( nNumber < 0 )
2539 	{
2540 		*mpPS << (sal_uInt8)'-';
2541 		nNumber = -nNumber;
2542 		mnCursorPos++;
2543 	}
2544 	const ByteString aScaleFactor( ByteString::CreateFromInt32( nNumber ) );
2545 	sal_uLong nLen = aScaleFactor.Len();
2546 	long nStSize =	( nCount + 1 ) - nLen;
2547 	if ( nStSize >= 1 )
2548 	{
2549 		*mpPS << (sal_uInt8)'0';
2550 		mnCursorPos++;
2551 	}
2552 	if ( nStSize >= 2 )
2553 	{
2554 		*mpPS << (sal_uInt8)'.';
2555 		for ( long i = 1; i < nStSize; i++ )
2556 		{
2557 			*mpPS << (sal_uInt8)'0';
2558 			mnCursorPos++;
2559 		}
2560 	}
2561 	mnCursorPos += nLen;
2562 	for( sal_uInt16 n = 0UL; n < nLen; n++	)
2563 	{
2564 		if ( n == nLen - nCount )
2565 		{
2566 			*mpPS << (sal_uInt8)'.';
2567 			mnCursorPos++;
2568 		}
2569 		*mpPS << aScaleFactor.GetChar( n );
2570 	}
2571 	ImplExecMode( nMode );
2572 }
2573 
2574 //---------------------------------------------------------------------------------
2575 
ImplWriteByte(sal_uInt8 nNumb,sal_uLong nMode)2576 void PSWriter::ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode )
2577 {
2578 	*mpPS << ( nNumb );
2579 	mnCursorPos++;
2580 	ImplExecMode( nMode );
2581 }
2582 
2583 //---------------------------------------------------------------------------------
2584 
ImplWriteHexByte(sal_uInt8 nNumb,sal_uLong nMode)2585 void PSWriter::ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode )
2586 {
2587 	if ( ( nNumb >> 4 ) > 9 )
2588 		*mpPS << (sal_uInt8)( ( nNumb >> 4 ) + 'A' - 10 );
2589 	else
2590 		*mpPS << (sal_uInt8)( ( nNumb >> 4 ) + '0' );
2591 
2592 	if ( ( nNumb & 0xf ) > 9 )
2593 		*mpPS << (sal_uInt8)( ( nNumb & 0xf ) + 'A' - 10 );
2594 	else
2595 		*mpPS << (sal_uInt8)( ( nNumb & 0xf ) + '0' );
2596 	mnCursorPos += 2;
2597 	ImplExecMode( nMode );
2598 }
2599 
2600 //---------------------------------------------------------------------------------
2601 
2602 // writes the sal_uInt8 nNumb as a Number from 0.000 up to 1.000
2603 
ImplWriteB1(sal_uInt8 nNumb,sal_uLong nMode)2604 void PSWriter::ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode )
2605 {
2606 	ImplWriteF( 1000 * ( nNumb + 1 ) / 256 , 3, nMode );
2607 }
2608 
2609 
2610 // ------------------------------------------------------------------------
2611 
WriteBits(sal_uInt16 nCode,sal_uInt16 nCodeLen)2612 inline void PSWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
2613 {
2614 	dwShift |= ( nCode << ( nOffset - nCodeLen ) );
2615 	nOffset -= nCodeLen;
2616 	while ( nOffset < 24 )
2617 	{
2618 		ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2619 		dwShift <<= 8;
2620 		nOffset += 8;
2621 	}
2622 	if ( nCode == 257 && nOffset != 32 )
2623 		ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2624 }
2625 
2626 // ------------------------------------------------------------------------
2627 
StartCompression()2628 void PSWriter::StartCompression()
2629 {
2630 	sal_uInt16 i;
2631 	nDataSize = 8;
2632 
2633 	nClearCode = 1 << nDataSize;
2634 	nEOICode = nClearCode + 1;
2635 	nTableSize = nEOICode + 1;
2636 	nCodeSize = nDataSize + 1;
2637 
2638 	nOffset = 32;						// anzahl freier bits in dwShift
2639 	dwShift = 0;
2640 
2641 	pTable = new PSLZWCTreeNode[ 4096 ];
2642 
2643 	for ( i = 0; i < 4096; i++ )
2644 	{
2645 		pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL;
2646 		pTable[ i ].nValue = (sal_uInt8)( pTable[ i ].nCode = i );
2647 	}
2648 	pPrefix = NULL;
2649 	WriteBits( nClearCode, nCodeSize );
2650 }
2651 
2652 // ------------------------------------------------------------------------
2653 
Compress(sal_uInt8 nCompThis)2654 void PSWriter::Compress( sal_uInt8 nCompThis )
2655 {
2656 	PSLZWCTreeNode* 	p;
2657 	sal_uInt16				i;
2658 	sal_uInt8				nV;
2659 
2660 	if( !pPrefix )
2661 	{
2662 		pPrefix = pTable + nCompThis;
2663 	}
2664 	else
2665 	{
2666 		nV = nCompThis;
2667 		for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother )
2668 		{
2669 			if ( p->nValue == nV )
2670 				break;
2671 		}
2672 
2673 		if( p )
2674 			pPrefix = p;
2675 		else
2676 		{
2677 			WriteBits( pPrefix->nCode, nCodeSize );
2678 
2679 			if ( nTableSize == 409 )
2680 			{
2681 				WriteBits( nClearCode, nCodeSize );
2682 
2683 				for ( i = 0; i < nClearCode; i++ )
2684 					pTable[ i ].pFirstChild = NULL;
2685 
2686 				nCodeSize = nDataSize + 1;
2687 				nTableSize = nEOICode + 1;
2688 			}
2689 			else
2690 			{
2691 				if( nTableSize == (sal_uInt16)( ( 1 << nCodeSize ) - 1 ) )
2692 					nCodeSize++;
2693 
2694 				p = pTable + ( nTableSize++ );
2695 				p->pBrother = pPrefix->pFirstChild;
2696 				pPrefix->pFirstChild = p;
2697 				p->nValue = nV;
2698 				p->pFirstChild = NULL;
2699 			}
2700 
2701 			pPrefix = pTable + nV;
2702 		}
2703 	}
2704 }
2705 
2706 // ------------------------------------------------------------------------
2707 
EndCompression()2708 void PSWriter::EndCompression()
2709 {
2710 	if( pPrefix )
2711 		WriteBits( pPrefix->nCode, nCodeSize );
2712 
2713 	WriteBits( nEOICode, nCodeSize );
2714 	delete[] pTable;
2715 }
2716 
2717 // ------------------------------------------------------------------------
2718 
ImplSearchEntry(sal_uInt8 * pSource,sal_uInt8 * pDest,sal_uLong nComp,sal_uLong nSize)2719 sal_uInt8* PSWriter::ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize )
2720 {
2721 	while ( nComp-- >= nSize )
2722 	{
2723 		sal_uLong i;
2724 		for ( i = 0; i < nSize; i++ )
2725 		{
2726 			if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
2727 				break;
2728 		}
2729 		if ( i == nSize )
2730 			return pSource;
2731 		pSource++;
2732 	}
2733 	return NULL;
2734 }
2735 
2736 // ------------------------------------------------------------------------
2737 
ImplGetBoundingBox(double * nNumb,sal_uInt8 * pSource,sal_uLong nSize)2738 sal_Bool PSWriter::ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize )
2739 {
2740 	sal_Bool	bRetValue = sal_False;
2741 	sal_uLong	nBytesRead;
2742 
2743 	if ( nSize < 256 )		// we assume that the file is greater than 256 bytes
2744 		return sal_False;
2745 
2746 	if ( nSize < POSTSCRIPT_BOUNDINGSEARCH )
2747 		nBytesRead = nSize;
2748 	else
2749 		nBytesRead = POSTSCRIPT_BOUNDINGSEARCH;
2750 
2751 	sal_uInt8* pDest = ImplSearchEntry( pSource, (sal_uInt8*)"%%BoundingBox:", nBytesRead, 14 );
2752 	if ( pDest )
2753 	{
2754 		int 	nSecurityCount = 100;	// only 100 bytes following the bounding box will be checked
2755 		nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
2756 		pDest += 14;
2757 		for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
2758 		{
2759 			int 	nDivision = 1;
2760 			sal_Bool	bDivision = sal_False;
2761 			sal_Bool	bNegative = sal_False;
2762 			sal_Bool	bValid = sal_True;
2763 
2764 			while ( ( --nSecurityCount ) && ( ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) )
2765 				pDest++;
2766 			sal_uInt8 nByte = *pDest;
2767 			while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
2768 			{
2769 				switch ( nByte )
2770 				{
2771 					case '.' :
2772 						if ( bDivision )
2773 							bValid = sal_False;
2774 						else
2775 							bDivision = sal_True;
2776 						break;
2777 					case '-' :
2778 						bNegative = sal_True;
2779 						break;
2780 					default :
2781 						if ( ( nByte < '0' ) || ( nByte > '9' ) )
2782 							nSecurityCount = 1; 	// error parsing the bounding box values
2783 						else if ( bValid )
2784 						{
2785 							if ( bDivision )
2786 								nDivision*=10;
2787 							nNumb[i] *= 10;
2788 							nNumb[i] += nByte - '0';
2789 						}
2790 						break;
2791 				}
2792 				nSecurityCount--;
2793 				nByte = *(++pDest);
2794 			}
2795 			if ( bNegative )
2796 				nNumb[i] = -nNumb[i];
2797 			if ( bDivision && ( nDivision != 1 ) )
2798 				nNumb[i] /= nDivision;
2799 		}
2800 		if ( nSecurityCount)
2801 			bRetValue = sal_True;
2802 	}
2803 	return bRetValue;
2804 }
2805 
2806 //================== GraphicExport - die exportierte Funktion ================
2807 
GraphicExport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem * pFilterConfigItem,sal_Bool)2808 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool)
2809 {
2810 	PSWriter aPSWriter;
2811 	return aPSWriter.WritePS( rGraphic, rStream, pFilterConfigItem );
2812 }
2813 
2814