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