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