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 // formating 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# explicitely 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