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 <tools/fract.hxx>
24 : #include <vcl/svapp.hxx>
25 : #include <vcl/metaact.hxx>
26 : #include <vcl/graph.hxx>
27 : #include <vcl/bmpacc.hxx>
28 : #include <vcl/region.hxx>
29 : #include <vcl/metric.hxx>
30 : #include <vcl/font.hxx>
31 : #include <vcl/virdev.hxx>
32 : #include <vcl/msgbox.hxx>
33 : #include <vcl/cvtgrf.hxx>
34 : #include <vcl/gradient.hxx>
35 : #include <vcl/settings.hxx>
36 : #include <unotools/configmgr.hxx>
37 : #include <svl/solar.hrc>
38 : #include <vcl/fltcall.hxx>
39 : #include <vcl/FilterConfigItem.hxx>
40 : #include <vcl/graphictools.hxx>
41 : #include "strings.hrc"
42 :
43 : #include <math.h>
44 : #include <boost/scoped_ptr.hpp>
45 :
46 : using namespace ::com::sun::star::uno;
47 :
48 : #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox
49 : // in the first 4096 bytes
50 :
51 : #define EPS_PREVIEW_TIFF 1
52 : #define EPS_PREVIEW_EPSI 2
53 :
54 : #define PS_LINESIZE 70 // maximum number of characters a line in the output
55 :
56 : #define PS_NONE 0 // formatting mode: action which is inserted behind the output
57 : #define PS_SPACE 1
58 : #define PS_RET 2
59 : #define PS_WRAP 4
60 :
61 : // -----------------------------Feld-Typen-------------------------------
62 :
63 0 : struct ChrSet
64 : {
65 : struct ChrSet * pSucc;
66 : sal_uInt8 nSet;
67 : OUString aName;
68 : FontWeight eWeight;
69 : };
70 :
71 0 : struct StackMember
72 : {
73 : struct StackMember * pSucc;
74 : Color aGlobalCol;
75 : bool bLineCol;
76 : Color aLineCol;
77 : bool bFillCol;
78 : Color aFillCol;
79 : Color aTextCol;
80 : bool bTextFillCol;
81 : Color aTextFillCol;
82 : Color aBackgroundCol;
83 : vcl::Font aFont;
84 : TextAlign eTextAlign;
85 :
86 : double fLineWidth;
87 : double fMiterLimit;
88 : SvtGraphicStroke::CapType eLineCap;
89 : SvtGraphicStroke::JoinType eJoinType;
90 : SvtGraphicStroke::DashArray aDashArray;
91 : };
92 :
93 : struct PSLZWCTreeNode
94 : {
95 :
96 : PSLZWCTreeNode* pBrother; // next node who has the same father
97 : PSLZWCTreeNode* pFirstChild; // first son
98 : sal_uInt16 nCode; // The code for the string of pixel values, which arises if... <missing comment>
99 : sal_uInt16 nValue; // the pixel value
100 : };
101 :
102 : class PSWriter
103 : {
104 : private:
105 : bool mbStatus;
106 : sal_uLong mnLevelWarning; // number of embedded eps files which was not exported
107 : sal_uLong mnLastPercent; // the number with which pCallback was called the last time
108 : sal_uInt32 mnLatestPush; // offset to streamposition, where last push was done
109 :
110 : long mnLevel; // dialog options
111 : bool mbGrayScale;
112 : bool mbCompression;
113 : sal_Int32 mnPreview;
114 : sal_Int32 mnTextMode;
115 :
116 : SvStream* mpPS;
117 : const GDIMetaFile* pMTF;
118 : GDIMetaFile* pAMTF; // only created if Graphics is not a Metafile
119 : ScopedVclPtrInstance<VirtualDevice> pVDev;
120 :
121 : double nBoundingX1; // this represents the bounding box
122 : double nBoundingY1;
123 : double nBoundingX2;
124 : double nBoundingY2;
125 :
126 : StackMember* pGDIStack;
127 : sal_uLong mnCursorPos; // current cursor position in output
128 : Color aColor; // current color which is used for output
129 : bool bLineColor;
130 : Color aLineColor; // current GDIMetafile color settings
131 : bool bFillColor;
132 : Color aFillColor;
133 : Color aTextColor;
134 : bool bTextFillColor;
135 : Color aTextFillColor;
136 : Color aBackgroundColor;
137 : bool bRegionChanged;
138 : TextAlign eTextAlign;
139 :
140 : double fLineWidth;
141 : double fMiterLimit;
142 : SvtGraphicStroke::CapType eLineCap;
143 : SvtGraphicStroke::JoinType eJoinType;
144 : SvtGraphicStroke::DashArray aDashArray;
145 :
146 : vcl::Font maFont;
147 : vcl::Font maLastFont;
148 : sal_uInt8 nChrSet;
149 : ChrSet* pChrSetList; // list of character sets
150 : sal_uInt8 nNextChrSetId; // first unused ChrSet-Id
151 :
152 : PSLZWCTreeNode* pTable; // LZW compression data
153 : PSLZWCTreeNode* pPrefix; // the compression is as same as the TIFF compression
154 : sal_uInt16 nDataSize;
155 : sal_uInt16 nClearCode;
156 : sal_uInt16 nEOICode;
157 : sal_uInt16 nTableSize;
158 : sal_uInt16 nCodeSize;
159 : sal_uInt32 nOffset;
160 : sal_uInt32 dwShift;
161 :
162 : com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
163 :
164 : void ImplWriteProlog( const Graphic* pPreviewEPSI = NULL );
165 : void ImplWriteEpilog();
166 : void ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev );
167 :
168 : // this method makes LF's, space inserting and word wrapping as used in all nMode
169 : // parameters
170 : inline void ImplExecMode( sal_uLong nMode );
171 :
172 : // writes char[] + LF to stream
173 : inline void ImplWriteLine( const char*, sal_uLong nMode = PS_RET );
174 :
175 : // writes ( nNumb / 10^nCount ) in ASCII format to stream
176 : void ImplWriteF( sal_Int32 nNumb, sal_uLong nCount = 3, sal_uLong nMode = PS_SPACE );
177 :
178 : // writes a double in ASCII format to stream
179 : void ImplWriteDouble( double, sal_uLong nMode = PS_SPACE );
180 :
181 : // writes a long in ASCII format to stream
182 : void ImplWriteLong( sal_Int32 nNumb, sal_uLong nMode = PS_SPACE );
183 :
184 : // writes a byte in ASCII format to stream
185 : void ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE );
186 :
187 : // writes a byte in ASCII (hex) format to stream
188 : void ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode = PS_WRAP );
189 :
190 : // writes nNumb as number from 0.000 till 1.000 in ASCII format to stream
191 : void ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode = PS_SPACE );
192 :
193 : inline void ImplWritePoint( const Point&, sal_uInt32 nMode = PS_SPACE );
194 : void ImplMoveTo( const Point&, sal_uInt32 nMode = PS_SPACE );
195 : void ImplLineTo( const Point&, sal_uInt32 nMode = PS_SPACE );
196 : void ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode = PS_SPACE );
197 : void ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET );
198 : void ImplScale( const double& fX, const double& fY, sal_uInt32 nMode = PS_RET );
199 :
200 : void ImplAddPath( const Polygon & rPolygon );
201 : void ImplWriteLineInfo( double fLineWidth, double fMiterLimit, SvtGraphicStroke::CapType eLineCap,
202 : SvtGraphicStroke::JoinType eJoinType, SvtGraphicStroke::DashArray& rDashArray );
203 : void ImplWriteLineInfo( const LineInfo& rLineInfo );
204 : void ImplRect( const Rectangle & rRectangle );
205 : void ImplRectFill ( const Rectangle & rRectangle );
206 : void ImplWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev );
207 : void ImplIntersect( const tools::PolyPolygon& rPolyPoly );
208 : void ImplPolyPoly( const tools::PolyPolygon & rPolyPolygon, bool bTextOutline = false );
209 : void ImplPolyLine( const Polygon & rPolygon );
210 :
211 : void ImplSetClipRegion( vcl::Region& rRegion );
212 : void ImplBmp( Bitmap*, Bitmap*, const Point &, double nWidth, double nHeight );
213 : void ImplText( const OUString& rUniString, const Point& rPos, const long* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev );
214 : void ImplSetAttrForText( const Point & rPoint );
215 : void ImplWriteCharacter( sal_Char );
216 : void ImplWriteString( const OString&, VirtualDevice& rVDev, const long* pDXArry = NULL, bool bStretch = false );
217 : void ImplDefineFont( const char*, const char* );
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 : void ImplWriteColor( sal_uLong nMode );
226 :
227 : static double ImplGetScaling( const MapMode& );
228 : void ImplGetMapMode( const MapMode& );
229 : static bool ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize );
230 : static sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize );
231 : // LZW methods
232 : void StartCompression();
233 : void Compress( sal_uInt8 nSrc );
234 : void EndCompression();
235 : inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
236 :
237 : public:
238 : bool WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* );
239 : PSWriter();
240 : ~PSWriter();
241 : };
242 :
243 : //========================== Methoden von PSWriter ==========================
244 :
245 :
246 :
247 0 : PSWriter::PSWriter()
248 : : mbStatus(false)
249 : , mnLevelWarning(0)
250 : , mnLastPercent(0)
251 : , mnLatestPush(0)
252 : , mnLevel(0)
253 : , mbGrayScale(false)
254 : , mbCompression(false)
255 : , mnPreview(0)
256 : , mnTextMode(0)
257 : , mpPS(NULL)
258 : , pMTF(NULL)
259 : , pAMTF(NULL)
260 : , pVDev()
261 : , nBoundingX1(0)
262 : , nBoundingY1(0)
263 : , nBoundingX2(0)
264 : , nBoundingY2(0)
265 : , pGDIStack(NULL)
266 : , mnCursorPos(0)
267 : , aColor()
268 : , bLineColor(false)
269 : , aLineColor()
270 : , bFillColor(false)
271 : , aFillColor()
272 : , aTextColor()
273 : , bTextFillColor(false)
274 : , aTextFillColor()
275 : , aBackgroundColor()
276 : , bRegionChanged(false)
277 : , eTextAlign()
278 : , fLineWidth(0)
279 : , fMiterLimit(0)
280 : , eLineCap()
281 : , eJoinType()
282 : , aDashArray()
283 : , maFont()
284 : , maLastFont()
285 : , nChrSet(0)
286 : , pChrSetList(NULL)
287 : , nNextChrSetId(0)
288 : , pTable(NULL)
289 : , pPrefix(NULL)
290 : , nDataSize(0)
291 : , nClearCode(0)
292 : , nEOICode(0)
293 : , nTableSize(0)
294 : , nCodeSize(0)
295 : , nOffset(0)
296 : , dwShift(0)
297 0 : , xStatusIndicator()
298 : {
299 0 : pAMTF = NULL;
300 0 : }
301 :
302 :
303 0 : PSWriter::~PSWriter()
304 : {
305 0 : delete pAMTF;
306 0 : }
307 :
308 :
309 :
310 0 : bool PSWriter::WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem )
311 : {
312 0 : sal_uInt32 nStreamPosition = 0, nPSPosition = 0; // -Wall warning, unset, check
313 :
314 0 : mbStatus = true;
315 0 : mnPreview = 0;
316 0 : mnLevelWarning = 0;
317 0 : mnLastPercent = 0;
318 0 : mnLatestPush = 0xEFFFFFFE;
319 :
320 0 : if ( pFilterConfigItem )
321 : {
322 0 : xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
323 0 : if ( xStatusIndicator.is() )
324 : {
325 0 : OUString aMsg;
326 0 : xStatusIndicator->start( aMsg, 100 );
327 : }
328 : }
329 :
330 0 : mpPS = &rTargetStream;
331 0 : mpPS->SetEndian( SvStreamEndian::LITTLE );
332 :
333 : // default values for the dialog options
334 0 : mnLevel = 2;
335 0 : mbGrayScale = false;
336 : #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
337 0 : mbCompression = false;
338 : #else
339 : mbCompression = sal_True;
340 : #endif
341 0 : mnTextMode = 0; // default0 : export glyph outlines
342 :
343 : // try to get the dialog selection
344 0 : if ( pFilterConfigItem )
345 : {
346 0 : boost::scoped_ptr<ResMgr> pResMgr(ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() ));
347 :
348 0 : if( pResMgr )
349 : {
350 : #ifdef UNX // don't put binary tiff preview ahead of postscript code by default on unix as ghostscript is unable to read it
351 0 : mnPreview = pFilterConfigItem->ReadInt32( "Preview", 0 );
352 : #else
353 : mnPreview = pFilterConfigItem->ReadInt32( "Preview", 1 );
354 : #endif
355 0 : mnLevel = pFilterConfigItem->ReadInt32( "Version", 2 );
356 0 : if ( mnLevel != 1 )
357 0 : mnLevel = 2;
358 0 : mbGrayScale = pFilterConfigItem->ReadInt32( "ColorFormat", 1 ) == 2;
359 : #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
360 0 : mbCompression = pFilterConfigItem->ReadInt32( "CompressionMode", 0 ) != 0;
361 : #else
362 : mbCompression = pFilterConfigItem->ReadInt32( "CompressionMode", 1 ) == 1;
363 : #endif
364 0 : mnTextMode = pFilterConfigItem->ReadInt32( "TextMode", 0 );
365 0 : if ( mnTextMode > 2 )
366 0 : mnTextMode = 0;
367 0 : }
368 : }
369 :
370 : // compression is not available for Level 1
371 0 : if ( mnLevel == 1 )
372 : {
373 0 : mbGrayScale = true;
374 0 : mbCompression = false;
375 : }
376 :
377 0 : if ( mnPreview & EPS_PREVIEW_TIFF )
378 : {
379 0 : rTargetStream.WriteUInt32( 0xC6D3D0C5 );
380 0 : nStreamPosition = rTargetStream.Tell();
381 0 : rTargetStream.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
382 0 : .WriteUInt32( nStreamPosition + 26 ).WriteUInt32( 0 ).WriteUInt16( 0xffff );
383 :
384 : sal_uInt32 nErrCode;
385 0 : if ( mbGrayScale )
386 : {
387 0 : BitmapEx aTempBitmapEx( rGraphic.GetBitmapEx() );
388 0 : aTempBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS );
389 0 : nErrCode = GraphicConverter::Export( rTargetStream, aTempBitmapEx, ConvertDataFormat::TIF ) ;
390 : }
391 : else
392 0 : nErrCode = GraphicConverter::Export( rTargetStream, rGraphic, ConvertDataFormat::TIF ) ;
393 :
394 0 : if ( nErrCode == ERRCODE_NONE )
395 : {
396 0 : rTargetStream.Seek( STREAM_SEEK_TO_END );
397 0 : nPSPosition = rTargetStream.Tell();
398 0 : rTargetStream.Seek( nStreamPosition + 20 );
399 0 : rTargetStream.WriteUInt32( nPSPosition - 30 ); // size of tiff gfx
400 0 : rTargetStream.Seek( nPSPosition );
401 : }
402 : else
403 : {
404 0 : mnPreview &=~ EPS_PREVIEW_TIFF;
405 0 : rTargetStream.Seek( nStreamPosition - 4 );
406 : }
407 : }
408 :
409 : // global default value setting
410 : ChrSet* pCS;
411 : StackMember* pGS;
412 :
413 0 : if (rGraphic.GetType() == GRAPHIC_GDIMETAFILE)
414 0 : pMTF = &rGraphic.GetGDIMetaFile();
415 0 : else if (rGraphic.GetGDIMetaFile().GetActionSize())
416 0 : pMTF = pAMTF = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
417 : else
418 : {
419 0 : Bitmap aBmp( rGraphic.GetBitmap() );
420 0 : pAMTF = new GDIMetaFile();
421 0 : ScopedVclPtrInstance< VirtualDevice > pTmpVDev;
422 0 : pAMTF->Record( pTmpVDev );
423 0 : pTmpVDev->DrawBitmap( Point(), aBmp );
424 0 : pAMTF->Stop();
425 0 : pAMTF->SetPrefSize( aBmp.GetSizePixel() );
426 0 : pMTF = pAMTF;
427 : }
428 0 : pVDev->SetMapMode( pMTF->GetPrefMapMode() );
429 0 : nBoundingX1 = nBoundingY1 = 0;
430 0 : nBoundingX2 = pMTF->GetPrefSize().Width();
431 0 : nBoundingY2 = pMTF->GetPrefSize().Height();
432 :
433 0 : pGDIStack = NULL;
434 0 : aColor = Color( COL_TRANSPARENT );
435 0 : bLineColor = true;
436 0 : aLineColor = Color( COL_BLACK );
437 0 : bFillColor = true;
438 0 : aFillColor = Color( COL_WHITE );
439 0 : bTextFillColor = true;
440 0 : aTextFillColor = Color( COL_BLACK );
441 0 : fLineWidth = 1;
442 0 : fMiterLimit = 15; // use same limit as most graphic systems and basegfx
443 0 : eLineCap = SvtGraphicStroke::capButt;
444 0 : eJoinType = SvtGraphicStroke::joinMiter;
445 0 : aBackgroundColor = Color( COL_WHITE );
446 0 : eTextAlign = ALIGN_BASELINE;
447 0 : bRegionChanged = false;
448 :
449 0 : nChrSet = 0x00;
450 0 : pChrSetList = NULL;
451 0 : nNextChrSetId = 1;
452 :
453 0 : if( pMTF->GetActionSize() )
454 : {
455 0 : ImplWriteProlog( ( mnPreview & EPS_PREVIEW_EPSI ) ? &rGraphic : NULL );
456 0 : mnCursorPos = 0;
457 0 : ImplWriteActions( *pMTF, *pVDev.get() );
458 0 : ImplWriteEpilog();
459 0 : if ( mnPreview & EPS_PREVIEW_TIFF )
460 : {
461 0 : sal_uInt32 nPosition = rTargetStream.Tell();
462 0 : rTargetStream.Seek( nStreamPosition );
463 0 : rTargetStream.WriteUInt32( nPSPosition );
464 0 : rTargetStream.WriteUInt32( nPosition - nPSPosition );
465 0 : rTargetStream.Seek( nPosition );
466 : }
467 0 : while( pChrSetList )
468 : {
469 0 : pCS=pChrSetList;
470 0 : pChrSetList=pCS->pSucc;
471 0 : delete pCS;
472 : }
473 0 : while( pGDIStack )
474 : {
475 0 : pGS=pGDIStack;
476 0 : pGDIStack=pGS->pSucc;
477 0 : delete pGS;
478 : }
479 : }
480 : else
481 0 : mbStatus = false;
482 :
483 0 : if ( mbStatus && mnLevelWarning && pFilterConfigItem )
484 : {
485 : ResMgr* pResMgr;
486 0 : pResMgr = ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() );
487 0 : if( pResMgr )
488 : {
489 0 : ScopedVclPtrInstance< InfoBox > aInfoBox( nullptr, ResId(KEY_VERSION_CHECK, *pResMgr).toString() );
490 0 : aInfoBox->Execute();
491 0 : delete pResMgr;
492 : }
493 : }
494 :
495 0 : if ( xStatusIndicator.is() )
496 0 : xStatusIndicator->end();
497 :
498 0 : return mbStatus;
499 : }
500 :
501 :
502 :
503 0 : void PSWriter::ImplWriteProlog( const Graphic* pPreview )
504 : {
505 0 : ImplWriteLine( "%!PS-Adobe-3.0 EPSF-3.0 " );
506 0 : mpPS->WriteCharPtr( "%%BoundingBox: " ); // BoundingBox
507 0 : ImplWriteLong( 0 );
508 0 : ImplWriteLong( 0 );
509 0 : Size aSizePoint = OutputDevice::LogicToLogic( pMTF->GetPrefSize(),
510 0 : pMTF->GetPrefMapMode(), MAP_POINT );
511 0 : ImplWriteLong( aSizePoint.Width() );
512 0 : ImplWriteLong( aSizePoint.Height() ,PS_RET );
513 0 : ImplWriteLine( "%%Pages: 0" );
514 0 : OUString aCreator( "%%Creator: " + utl::ConfigManager::getProductName() + " " +
515 0 : utl::ConfigManager::getProductVersion() );
516 0 : ImplWriteLine( OUStringToOString( aCreator, RTL_TEXTENCODING_UTF8 ).getStr() );
517 0 : ImplWriteLine( "%%Title: none" );
518 0 : ImplWriteLine( "%%CreationDate: none" );
519 :
520 : // defaults
521 :
522 0 : mpPS->WriteCharPtr( "%%LanguageLevel: " ); // Language level
523 0 : ImplWriteLong( mnLevel, PS_RET );
524 0 : if ( !mbGrayScale && mnLevel == 1 )
525 0 : ImplWriteLine( "%%Extensions: CMYK" ); // CMYK extension is to set in color mode in level 1
526 0 : ImplWriteLine( "%%EndComments" );
527 0 : if ( pPreview && aSizePoint.Width() && aSizePoint.Height() )
528 : {
529 0 : Size aSizeBitmap( ( aSizePoint.Width() + 7 ) & ~7, aSizePoint.Height() );
530 0 : Bitmap aTmpBitmap( pPreview->GetBitmap() );
531 0 : aTmpBitmap.Scale( aSizeBitmap, BmpScaleFlag::BestQuality );
532 0 : aTmpBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
533 0 : BitmapReadAccess* pAcc = aTmpBitmap.AcquireReadAccess();
534 0 : if ( pAcc )
535 : {
536 0 : mpPS->WriteCharPtr( "%%BeginPreview: " ); // BoundingBox
537 0 : ImplWriteLong( aSizeBitmap.Width() );
538 0 : ImplWriteLong( aSizeBitmap.Height() );
539 0 : mpPS->WriteCharPtr( "1 " );
540 0 : sal_Int32 nLines = aSizeBitmap.Width() / 312;
541 0 : if ( ( nLines * 312 ) != aSizeBitmap.Width() )
542 0 : nLines++;
543 0 : nLines *= aSizeBitmap.Height();
544 0 : ImplWriteLong( nLines );
545 0 : sal_Int32 nX, nY, nCount2, nCount = 4;
546 0 : const BitmapColor aBlack( pAcc->GetBestMatchingColor( Color( COL_BLACK ) ) );
547 0 : for ( nY = 0; nY < aSizeBitmap.Height(); nY++ )
548 : {
549 0 : nCount2 = 0;
550 0 : char nVal = 0;
551 0 : for ( nX = 0; nX < aSizeBitmap.Width(); nX++ )
552 : {
553 0 : if ( !nCount2 )
554 : {
555 0 : ImplExecMode( PS_RET );
556 0 : mpPS->WriteCharPtr( "%" );
557 0 : nCount2 = 312;
558 : }
559 0 : nVal <<= 1;
560 0 : if ( pAcc->GetPixel( nY, nX ) == aBlack )
561 0 : nVal |= 1;
562 0 : if ( ! ( --nCount ) )
563 : {
564 0 : if ( nVal > 9 )
565 0 : nVal += 'A' - 10;
566 : else
567 0 : nVal += '0';
568 0 : mpPS->WriteChar( nVal );
569 0 : nVal = 0;
570 0 : nCount += 4;
571 : }
572 0 : nCount2--;
573 : }
574 : }
575 0 : Bitmap::ReleaseAccess( pAcc );
576 0 : ImplExecMode( PS_RET );
577 0 : ImplWriteLine( "%%EndPreview" );
578 0 : }
579 : }
580 0 : ImplWriteLine( "%%BeginProlog" );
581 0 : ImplWriteLine( "%%BeginResource: procset SDRes-Prolog 1.0 0" );
582 :
583 : // BEGIN EPSF
584 0 : ImplWriteLine( "/b4_inc_state save def\n/dict_count countdictstack def\n/op_count count 1 sub def\nuserdict begin" );
585 0 : ImplWriteLine( "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath" );
586 0 : ImplWriteLine( "/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if" );
587 :
588 0 : ImplWriteLine( "/bdef {bind def} bind def" ); // the new operator bdef is created
589 0 : if ( mbGrayScale )
590 0 : ImplWriteLine( "/c {setgray} bdef" );
591 : else
592 0 : ImplWriteLine( "/c {setrgbcolor} bdef" );
593 0 : ImplWriteLine( "/l {neg lineto} bdef" );
594 0 : ImplWriteLine( "/rl {neg rlineto} bdef" );
595 0 : ImplWriteLine( "/lc {setlinecap} bdef" );
596 0 : ImplWriteLine( "/lj {setlinejoin} bdef" );
597 0 : ImplWriteLine( "/lw {setlinewidth} bdef" );
598 0 : ImplWriteLine( "/ml {setmiterlimit} bdef" );
599 0 : ImplWriteLine( "/ld {setdash} bdef" );
600 0 : ImplWriteLine( "/m {neg moveto} bdef" );
601 0 : ImplWriteLine( "/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef" );
602 0 : ImplWriteLine( "/r {rotate} bdef" );
603 0 : ImplWriteLine( "/t {neg translate} bdef" );
604 0 : ImplWriteLine( "/s {scale} bdef" );
605 0 : ImplWriteLine( "/sw {show} bdef" );
606 0 : ImplWriteLine( "/gs {gsave} bdef" );
607 0 : ImplWriteLine( "/gr {grestore} bdef" );
608 :
609 0 : ImplWriteLine( "/f {findfont dup length dict begin" ); // Setfont
610 0 : ImplWriteLine( "{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def" );
611 0 : ImplWriteLine( "currentdict end /NFont exch definefont pop /NFont findfont} bdef" );
612 :
613 0 : ImplWriteLine( "/p {closepath} bdef" );
614 0 : ImplWriteLine( "/sf {scalefont setfont} bdef" );
615 :
616 0 : ImplWriteLine( "/ef {eofill}bdef" ); // close path and fill
617 0 : ImplWriteLine( "/pc {closepath stroke}bdef" ); // close path and draw
618 0 : ImplWriteLine( "/ps {stroke}bdef" ); // draw current path
619 0 : ImplWriteLine( "/pum {matrix currentmatrix}bdef" ); // pushes the current matrix
620 0 : ImplWriteLine( "/pom {setmatrix}bdef" ); // pops the matrix
621 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" );
622 0 : ImplWriteLine( "%%EndResource" );
623 0 : ImplWriteLine( "%%EndProlog" );
624 0 : ImplWriteLine( "%%BeginSetup" );
625 0 : ImplWriteLine( "%%EndSetup" );
626 0 : ImplWriteLine( "%%Page: 1 1" );
627 0 : ImplWriteLine( "%%BeginPageSetup" );
628 0 : ImplWriteLine( "%%EndPageSetup" );
629 0 : ImplWriteLine( "pum" );
630 0 : ImplScale( (double)aSizePoint.Width() / (double)pMTF->GetPrefSize().Width(), (double)aSizePoint.Height() / (double)pMTF->GetPrefSize().Height() );
631 0 : ImplWriteDouble( 0 );
632 0 : ImplWriteDouble( -pMTF->GetPrefSize().Height() );
633 0 : ImplWriteLine( "t" );
634 0 : ImplWriteLine( "/tm matrix currentmatrix def" );
635 0 : }
636 :
637 :
638 :
639 0 : void PSWriter::ImplWriteEpilog()
640 : {
641 0 : ImplTranslate( 0, nBoundingY2 );
642 0 : ImplWriteLine( "pom" );
643 0 : ImplWriteLine( "count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore" );
644 :
645 0 : ImplWriteLine( "%%PageTrailer" );
646 0 : ImplWriteLine( "%%Trailer" );
647 :
648 0 : ImplWriteLine( "%%EOF" );
649 0 : }
650 :
651 :
652 :
653 :
654 :
655 0 : void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
656 : {
657 0 : tools::PolyPolygon aFillPath;
658 :
659 0 : for( size_t nCurAction = 0, nCount = rMtf.GetActionSize(); nCurAction < nCount; nCurAction++ )
660 : {
661 0 : MetaAction* pMA = rMtf.GetAction( nCurAction );
662 :
663 0 : switch( pMA->GetType() )
664 : {
665 : case MetaActionType::NONE :
666 0 : break;
667 :
668 : case MetaActionType::PIXEL :
669 : {
670 0 : Color aOldLineColor( aLineColor );
671 0 : aLineColor = static_cast<const MetaPixelAction*>(pMA)->GetColor();
672 0 : ImplWriteLineColor( PS_SPACE );
673 0 : ImplMoveTo( static_cast<const MetaPixelAction*>(pMA)->GetPoint() );
674 0 : ImplLineTo( static_cast<const MetaPixelAction*>(pMA)->GetPoint() );
675 0 : ImplPathDraw();
676 0 : aLineColor = aOldLineColor;
677 : }
678 0 : break;
679 :
680 : case MetaActionType::POINT :
681 : {
682 0 : ImplWriteLineColor( PS_SPACE );
683 0 : ImplMoveTo( static_cast<const MetaPointAction*>(pMA)->GetPoint() );
684 0 : ImplLineTo( static_cast<const MetaPointAction*>(pMA)->GetPoint() );
685 0 : ImplPathDraw();
686 : }
687 0 : break;
688 :
689 : case MetaActionType::LINE :
690 : {
691 0 : const LineInfo& rLineInfo = static_cast<const MetaLineAction*>(pMA)->GetLineInfo();
692 0 : ImplWriteLineInfo( rLineInfo );
693 0 : if ( bLineColor )
694 : {
695 0 : ImplWriteLineColor( PS_SPACE );
696 0 : ImplMoveTo( static_cast<const MetaLineAction*>(pMA)->GetStartPoint() );
697 0 : ImplLineTo( static_cast<const MetaLineAction*>(pMA )->GetEndPoint() );
698 0 : ImplPathDraw();
699 : }
700 : }
701 0 : break;
702 :
703 : case MetaActionType::RECT :
704 : {
705 0 : ImplRect( static_cast<const MetaRectAction*>(pMA)->GetRect() );
706 : }
707 0 : break;
708 :
709 : case MetaActionType::ROUNDRECT :
710 0 : ImplRect( static_cast<const MetaRoundRectAction*>(pMA)->GetRect() );
711 0 : break;
712 :
713 : case MetaActionType::ELLIPSE :
714 : {
715 0 : Rectangle aRect = static_cast<const MetaEllipseAction*>(pMA)->GetRect();
716 0 : Point aCenter = aRect.Center();
717 0 : Polygon aPoly( aCenter, aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
718 0 : tools::PolyPolygon aPolyPoly( aPoly );
719 0 : ImplPolyPoly( aPolyPoly );
720 : }
721 0 : break;
722 :
723 : case MetaActionType::ARC :
724 : {
725 0 : Polygon aPoly( static_cast<const MetaArcAction*>(pMA)->GetRect(), static_cast<const MetaArcAction*>(pMA)->GetStartPoint(),
726 0 : static_cast<const MetaArcAction*>(pMA)->GetEndPoint(), POLY_ARC );
727 0 : tools::PolyPolygon aPolyPoly( aPoly );
728 0 : ImplPolyPoly( aPolyPoly );
729 : }
730 0 : break;
731 :
732 : case MetaActionType::PIE :
733 : {
734 0 : Polygon aPoly( static_cast<const MetaPieAction*>(pMA)->GetRect(), static_cast<const MetaPieAction*>(pMA)->GetStartPoint(),
735 0 : static_cast<const MetaPieAction*>(pMA)->GetEndPoint(), POLY_PIE );
736 0 : tools::PolyPolygon aPolyPoly( aPoly );
737 0 : ImplPolyPoly( aPolyPoly );
738 : }
739 0 : break;
740 :
741 : case MetaActionType::CHORD :
742 : {
743 0 : Polygon aPoly( static_cast<const MetaChordAction*>(pMA)->GetRect(), static_cast<const MetaChordAction*>(pMA)->GetStartPoint(),
744 0 : static_cast<const MetaChordAction*>(pMA)->GetEndPoint(), POLY_CHORD );
745 0 : tools::PolyPolygon aPolyPoly( aPoly );
746 0 : ImplPolyPoly( aPolyPoly );
747 : }
748 0 : break;
749 :
750 : case MetaActionType::POLYLINE :
751 : {
752 0 : Polygon aPoly( static_cast<const MetaPolyLineAction*>(pMA)->GetPolygon() );
753 0 : const LineInfo& rLineInfo = static_cast<const MetaPolyLineAction*>(pMA)->GetLineInfo();
754 0 : ImplWriteLineInfo( rLineInfo );
755 :
756 0 : if(basegfx::B2DLineJoin::NONE == rLineInfo.GetLineJoin()
757 0 : && rLineInfo.GetWidth() > 1)
758 : {
759 : // emulate B2DLineJoin::NONE by creating single edges
760 0 : const sal_uInt16 nPoints(aPoly.GetSize());
761 0 : const bool bCurve(aPoly.HasFlags());
762 :
763 0 : for(sal_uInt16 a(0); a + 1 < nPoints; a++)
764 : {
765 0 : if(bCurve
766 0 : && POLY_NORMAL != aPoly.GetFlags(a + 1)
767 0 : && a + 2 < nPoints
768 0 : && POLY_NORMAL != aPoly.GetFlags(a + 2)
769 0 : && a + 3 < nPoints)
770 : {
771 : const Polygon aSnippet(4,
772 0 : aPoly.GetConstPointAry() + a,
773 0 : aPoly.GetConstFlagAry() + a);
774 0 : ImplPolyLine(aSnippet);
775 0 : a += 2;
776 : }
777 : else
778 : {
779 : const Polygon aSnippet(2,
780 0 : aPoly.GetConstPointAry() + a);
781 0 : ImplPolyLine(aSnippet);
782 : }
783 : }
784 : }
785 : else
786 : {
787 0 : ImplPolyLine( aPoly );
788 0 : }
789 : }
790 0 : break;
791 :
792 : case MetaActionType::POLYGON :
793 : {
794 0 : tools::PolyPolygon aPolyPoly( static_cast<const MetaPolygonAction*>(pMA)->GetPolygon() );
795 0 : ImplPolyPoly( aPolyPoly );
796 : }
797 0 : break;
798 :
799 : case MetaActionType::POLYPOLYGON :
800 : {
801 0 : ImplPolyPoly( static_cast<const MetaPolyPolygonAction*>(pMA)->GetPolyPolygon() );
802 : }
803 0 : break;
804 :
805 : case MetaActionType::TEXT:
806 : {
807 0 : const MetaTextAction * pA = static_cast<const MetaTextAction*>(pMA);
808 :
809 0 : OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
810 0 : Point aPoint( pA->GetPoint() );
811 :
812 0 : ImplText( aUniStr, aPoint, NULL, 0, rVDev );
813 : }
814 0 : break;
815 :
816 : case MetaActionType::TEXTRECT:
817 : {
818 : OSL_FAIL( "Unsupported action: TextRect...Action!" );
819 : }
820 0 : break;
821 :
822 : case MetaActionType::STRETCHTEXT :
823 : {
824 0 : const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pMA);
825 0 : OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
826 0 : Point aPoint( pA->GetPoint() );
827 :
828 0 : ImplText( aUniStr, aPoint, NULL, pA->GetWidth(), rVDev );
829 : }
830 0 : break;
831 :
832 : case MetaActionType::TEXTARRAY:
833 : {
834 0 : const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pMA);
835 0 : OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
836 0 : Point aPoint( pA->GetPoint() );
837 :
838 0 : ImplText( aUniStr, aPoint, pA->GetDXArray(), 0, rVDev );
839 : }
840 0 : break;
841 :
842 : case MetaActionType::BMP :
843 : {
844 0 : Bitmap aBitmap = static_cast<const MetaBmpAction*>(pMA)->GetBitmap();
845 0 : if ( mbGrayScale )
846 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
847 0 : Point aPoint = static_cast<const MetaBmpAction*>(pMA)->GetPoint();
848 0 : Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) );
849 0 : ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
850 : }
851 0 : break;
852 :
853 : case MetaActionType::BMPSCALE :
854 : {
855 0 : Bitmap aBitmap = static_cast<const MetaBmpScaleAction*>(pMA)->GetBitmap();
856 0 : if ( mbGrayScale )
857 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
858 0 : Point aPoint = static_cast<const MetaBmpScaleAction*>(pMA)->GetPoint();
859 0 : Size aSize = static_cast<const MetaBmpScaleAction*>(pMA)->GetSize();
860 0 : ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
861 : }
862 0 : break;
863 :
864 : case MetaActionType::BMPSCALEPART :
865 : {
866 0 : Bitmap aBitmap( static_cast<const MetaBmpScalePartAction*>(pMA)->GetBitmap() );
867 0 : aBitmap.Crop( Rectangle( static_cast<const MetaBmpScalePartAction*>(pMA)->GetSrcPoint(),
868 0 : static_cast<const MetaBmpScalePartAction*>(pMA)->GetSrcSize() ) );
869 0 : if ( mbGrayScale )
870 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
871 0 : Point aPoint = static_cast<const MetaBmpScalePartAction*>(pMA)->GetDestPoint();
872 0 : Size aSize = static_cast<const MetaBmpScalePartAction*>(pMA)->GetDestSize();
873 0 : ImplBmp( &aBitmap, NULL, aPoint, aSize.Width(), aSize.Height() );
874 : }
875 0 : break;
876 :
877 : case MetaActionType::BMPEX :
878 : {
879 0 : BitmapEx aBitmapEx( static_cast<MetaBmpExAction*>(pMA)->GetBitmapEx() );
880 0 : Bitmap aBitmap( aBitmapEx.GetBitmap() );
881 0 : if ( mbGrayScale )
882 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
883 0 : Bitmap aMask( aBitmapEx.GetMask() );
884 0 : Point aPoint( static_cast<const MetaBmpExAction*>(pMA)->GetPoint() );
885 0 : Size aSize( rVDev.PixelToLogic( aBitmap.GetSizePixel() ) );
886 0 : ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
887 : }
888 0 : break;
889 :
890 : case MetaActionType::BMPEXSCALE :
891 : {
892 0 : BitmapEx aBitmapEx( static_cast<MetaBmpExScaleAction*>(pMA)->GetBitmapEx() );
893 0 : Bitmap aBitmap( aBitmapEx.GetBitmap() );
894 0 : if ( mbGrayScale )
895 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
896 0 : Bitmap aMask( aBitmapEx.GetMask() );
897 0 : Point aPoint = static_cast<const MetaBmpExScaleAction*>(pMA)->GetPoint();
898 0 : Size aSize( static_cast<const MetaBmpExScaleAction*>(pMA)->GetSize() );
899 0 : ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
900 : }
901 0 : break;
902 :
903 : case MetaActionType::BMPEXSCALEPART :
904 : {
905 0 : BitmapEx aBitmapEx( static_cast<const MetaBmpExScalePartAction*>(pMA)->GetBitmapEx() );
906 0 : aBitmapEx.Crop( Rectangle( static_cast<const MetaBmpExScalePartAction*>(pMA)->GetSrcPoint(),
907 0 : static_cast<const MetaBmpExScalePartAction*>(pMA)->GetSrcSize() ) );
908 0 : Bitmap aBitmap( aBitmapEx.GetBitmap() );
909 0 : if ( mbGrayScale )
910 0 : aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
911 0 : Bitmap aMask( aBitmapEx.GetMask() );
912 0 : Point aPoint = static_cast<const MetaBmpExScalePartAction*>(pMA)->GetDestPoint();
913 0 : Size aSize = static_cast<const MetaBmpExScalePartAction*>(pMA)->GetDestSize();
914 0 : ImplBmp( &aBitmap, &aMask, aPoint, aSize.Width(), aSize.Height() );
915 : }
916 0 : break;
917 :
918 : // Unsupported Actions
919 : case MetaActionType::MASK:
920 : case MetaActionType::MASKSCALE:
921 : case MetaActionType::MASKSCALEPART:
922 : {
923 : OSL_FAIL( "Unsupported action: MetaMask...Action!" );
924 : }
925 0 : break;
926 :
927 : case MetaActionType::GRADIENT :
928 : {
929 0 : tools::PolyPolygon aPolyPoly( static_cast<const MetaGradientAction*>(pMA)->GetRect() );
930 0 : ImplWriteGradient( aPolyPoly, static_cast<const MetaGradientAction*>(pMA)->GetGradient(), rVDev );
931 : }
932 0 : break;
933 :
934 : case MetaActionType::GRADIENTEX :
935 : {
936 0 : tools::PolyPolygon aPolyPoly( static_cast<const MetaGradientExAction*>(pMA)->GetPolyPolygon() );
937 0 : ImplWriteGradient( aPolyPoly, static_cast<const MetaGradientExAction*>(pMA)->GetGradient(), rVDev );
938 : }
939 0 : break;
940 :
941 : case MetaActionType::HATCH :
942 : {
943 0 : ScopedVclPtrInstance< VirtualDevice > l_pVirDev;
944 0 : GDIMetaFile aTmpMtf;
945 :
946 0 : l_pVirDev->SetMapMode( rVDev.GetMapMode() );
947 0 : l_pVirDev->AddHatchActions( static_cast<const MetaHatchAction*>(pMA)->GetPolyPolygon(),
948 0 : static_cast<const MetaHatchAction*>(pMA)->GetHatch(), aTmpMtf );
949 0 : ImplWriteActions( aTmpMtf, rVDev );
950 : }
951 0 : break;
952 :
953 : case MetaActionType::WALLPAPER :
954 : {
955 0 : const MetaWallpaperAction* pA = static_cast<const MetaWallpaperAction*>(pMA);
956 0 : Rectangle aRect = pA->GetRect();
957 0 : Wallpaper aWallpaper = pA->GetWallpaper();
958 :
959 0 : if ( aWallpaper.IsBitmap() )
960 : {
961 0 : BitmapEx aBitmapEx = aWallpaper.GetBitmap();
962 0 : Bitmap aBitmap( aBitmapEx.GetBitmap() );
963 0 : if ( aBitmapEx.IsTransparent() )
964 : {
965 0 : if ( aWallpaper.IsGradient() )
966 : {
967 :
968 : // gradient action
969 :
970 : }
971 0 : Bitmap aMask( aBitmapEx.GetMask() );
972 0 : ImplBmp( &aBitmap, &aMask, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() );
973 : }
974 : else
975 0 : ImplBmp( &aBitmap, NULL, Point( aRect.Left(), aRect.Top() ), aRect.GetWidth(), aRect.GetHeight() );
976 :
977 : // wallpaper Style
978 :
979 : }
980 0 : else if ( aWallpaper.IsGradient() )
981 : {
982 :
983 : // gradient action
984 :
985 : }
986 : else
987 : {
988 0 : aColor = aWallpaper.GetColor();
989 0 : ImplRectFill( aRect );
990 0 : }
991 : }
992 0 : break;
993 :
994 : case MetaActionType::ISECTRECTCLIPREGION:
995 : {
996 0 : const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pMA);
997 0 : vcl::Region aRegion( pA->GetRect() );
998 0 : ImplSetClipRegion( aRegion );
999 : }
1000 0 : break;
1001 :
1002 : case MetaActionType::CLIPREGION:
1003 : {
1004 0 : const MetaClipRegionAction* pA = static_cast<const MetaClipRegionAction*>(pMA);
1005 0 : vcl::Region aRegion( pA->GetRegion() );
1006 0 : ImplSetClipRegion( aRegion );
1007 : }
1008 0 : break;
1009 :
1010 : case MetaActionType::ISECTREGIONCLIPREGION:
1011 : {
1012 0 : const MetaISectRegionClipRegionAction* pA = static_cast<const MetaISectRegionClipRegionAction*>(pMA);
1013 0 : vcl::Region aRegion( pA->GetRegion() );
1014 0 : ImplSetClipRegion( aRegion );
1015 : }
1016 0 : break;
1017 :
1018 : case MetaActionType::MOVECLIPREGION:
1019 : {
1020 : /*
1021 : if ( !aClipRegion.IsEmpty() )
1022 : {
1023 : const MetaMoveClipRegionAction* pA = static_cast<const MetaMoveClipRegionAction*>(pMA);
1024 : aClipRegion.Move( pA->GetHorzMove(), pA->GetVertMove() );
1025 : ImplSetClipRegion();
1026 : }
1027 : */
1028 : }
1029 0 : break;
1030 :
1031 : case MetaActionType::LINECOLOR :
1032 : {
1033 0 : if ( static_cast<const MetaLineColorAction*>(pMA)->IsSetting() )
1034 : {
1035 0 : bLineColor = true;
1036 0 : aLineColor = static_cast<const MetaLineColorAction*>(pMA)->GetColor();
1037 : }
1038 : else
1039 0 : bLineColor = false;
1040 : }
1041 0 : break;
1042 :
1043 : case MetaActionType::FILLCOLOR :
1044 : {
1045 0 : if ( static_cast<const MetaFillColorAction*>(pMA)->IsSetting() )
1046 : {
1047 0 : bFillColor = true;
1048 0 : aFillColor = static_cast<const MetaFillColorAction*>(pMA)->GetColor();
1049 : }
1050 : else
1051 0 : bFillColor = false;
1052 : }
1053 0 : break;
1054 :
1055 : case MetaActionType::TEXTCOLOR :
1056 : {
1057 0 : aTextColor = static_cast<const MetaTextColorAction*>(pMA)->GetColor();
1058 : }
1059 0 : break;
1060 :
1061 : case MetaActionType::TEXTFILLCOLOR :
1062 : {
1063 0 : if ( static_cast<const MetaTextFillColorAction*>(pMA)->IsSetting() )
1064 : {
1065 0 : bTextFillColor = true;
1066 0 : aTextFillColor = static_cast<const MetaTextFillColorAction*>(pMA)->GetColor();
1067 : }
1068 : else
1069 0 : bTextFillColor = false;
1070 : }
1071 0 : break;
1072 :
1073 : case MetaActionType::TEXTALIGN :
1074 : {
1075 0 : eTextAlign = static_cast<const MetaTextAlignAction*>(pMA)->GetTextAlign();
1076 : }
1077 0 : break;
1078 :
1079 : case MetaActionType::MAPMODE :
1080 : {
1081 0 : pMA->Execute( &rVDev );
1082 0 : ImplGetMapMode( rVDev.GetMapMode() );
1083 : }
1084 0 : break;
1085 :
1086 : case MetaActionType::FONT :
1087 : {
1088 0 : maFont = static_cast<const MetaFontAction*>(pMA)->GetFont();
1089 0 : rVDev.SetFont( maFont );
1090 : }
1091 0 : break;
1092 :
1093 : case MetaActionType::PUSH :
1094 : {
1095 0 : rVDev.Push(static_cast<const MetaPushAction*>(pMA)->GetFlags() );
1096 0 : StackMember* pGS = new StackMember;
1097 0 : pGS->pSucc = pGDIStack;
1098 0 : pGDIStack = pGS;
1099 0 : pGS->aDashArray = aDashArray;
1100 0 : pGS->eJoinType = eJoinType;
1101 0 : pGS->eLineCap = eLineCap;
1102 0 : pGS->fLineWidth = fLineWidth;
1103 0 : pGS->fMiterLimit = fMiterLimit;
1104 0 : pGS->eTextAlign = eTextAlign;
1105 0 : pGS->aGlobalCol = aColor;
1106 0 : pGS->bLineCol = bLineColor;
1107 0 : pGS->aLineCol = aLineColor;
1108 0 : pGS->bFillCol = bFillColor;
1109 0 : pGS->aFillCol = aFillColor;
1110 0 : pGS->aTextCol = aTextColor;
1111 0 : pGS->bTextFillCol = bTextFillColor;
1112 0 : pGS->aTextFillCol = aTextFillColor;
1113 0 : pGS->aBackgroundCol = aBackgroundColor;
1114 0 : bRegionChanged = false;
1115 0 : pGS->aFont = maFont;
1116 0 : mnLatestPush = mpPS->Tell();
1117 0 : ImplWriteLine( "gs" );
1118 : }
1119 0 : break;
1120 :
1121 : case MetaActionType::POP :
1122 : {
1123 0 : rVDev.Pop();
1124 : StackMember* pGS;
1125 0 : if( pGDIStack )
1126 : {
1127 0 : pGS = pGDIStack;
1128 0 : pGDIStack = pGS->pSucc;
1129 0 : aDashArray = pGS->aDashArray;
1130 0 : eJoinType = pGS->eJoinType;
1131 0 : eLineCap = pGS->eLineCap;
1132 0 : fLineWidth = pGS->fLineWidth;
1133 0 : fMiterLimit = pGS->fMiterLimit;
1134 0 : eTextAlign = pGS->eTextAlign;
1135 0 : aColor = pGS->aGlobalCol;
1136 0 : bLineColor = pGS->bLineCol;
1137 0 : aLineColor = pGS->aLineCol;
1138 0 : bFillColor = pGS->bFillCol;
1139 0 : aFillColor = pGS->aFillCol;
1140 0 : aTextColor = pGS->aTextCol;
1141 0 : bTextFillColor = pGS->bTextFillCol;
1142 0 : aTextFillColor = pGS->aTextFillCol;
1143 0 : aBackgroundColor = pGS->aBackgroundCol;
1144 0 : maFont = pGS->aFont;
1145 0 : maLastFont = vcl::Font(); // set maLastFont != maFont -> so that
1146 0 : delete pGS;
1147 0 : sal_uInt32 nCurrentPos = mpPS->Tell();
1148 0 : if ( nCurrentPos - 3 == mnLatestPush )
1149 : {
1150 0 : mpPS->Seek( mnLatestPush );
1151 0 : ImplWriteLine( " " );
1152 0 : mpPS->Seek( mnLatestPush );
1153 : }
1154 : else
1155 0 : ImplWriteLine( "gr" );
1156 : }
1157 : }
1158 0 : break;
1159 :
1160 : case MetaActionType::EPS :
1161 : {
1162 0 : GfxLink aGfxLink = static_cast<const MetaEPSAction*>(pMA)->GetLink();
1163 0 : const GDIMetaFile aSubstitute( static_cast<const MetaEPSAction*>(pMA)->GetSubstitute() );
1164 :
1165 0 : bool bLevelConflict = false;
1166 0 : sal_uInt8* pSource = const_cast<sal_uInt8*>(aGfxLink.GetData());
1167 0 : sal_uLong nSize = aGfxLink.GetDataSize();
1168 0 : sal_uLong nParseThis = POSTSCRIPT_BOUNDINGSEARCH;
1169 0 : if ( nSize < 64 ) // assuming eps is larger than 64 bytes
1170 0 : pSource = NULL;
1171 0 : if ( nParseThis > nSize )
1172 0 : nParseThis = nSize;
1173 :
1174 0 : if ( pSource && ( mnLevel == 1 ) )
1175 : {
1176 0 : sal_uInt8* pFound = ImplSearchEntry( pSource, reinterpret_cast<sal_uInt8 const *>("%%LanguageLevel:"), nParseThis - 10, 16 );
1177 0 : if ( pFound )
1178 : {
1179 0 : sal_uInt8 k, i = 10;
1180 0 : pFound += 16;
1181 0 : while ( --i )
1182 : {
1183 0 : k = *pFound++;
1184 0 : if ( ( k > '0' ) && ( k <= '9' ) )
1185 : {
1186 0 : if ( k != '1' )
1187 : {
1188 0 : bLevelConflict = true;
1189 0 : mnLevelWarning++;
1190 : }
1191 0 : break;
1192 : }
1193 : }
1194 : }
1195 : }
1196 0 : if ( !bLevelConflict )
1197 : {
1198 : double nBoundingBox[4];
1199 0 : if ( pSource && ImplGetBoundingBox( nBoundingBox, pSource, nParseThis ) )
1200 : {
1201 0 : Point aPoint = static_cast<const MetaEPSAction*>(pMA)->GetPoint();
1202 0 : Size aSize = static_cast<const MetaEPSAction*>(pMA)->GetSize();
1203 :
1204 0 : MapMode aMapMode( aSubstitute.GetPrefMapMode() );
1205 0 : Size aOutSize( OutputDevice::LogicToLogic( aSize, rVDev.GetMapMode(), aMapMode ) );
1206 0 : Point aOrigin( OutputDevice::LogicToLogic( aPoint, rVDev.GetMapMode(), aMapMode ) );
1207 0 : aOrigin.Y() += aOutSize.Height();
1208 0 : aMapMode.SetOrigin( aOrigin );
1209 0 : aMapMode.SetScaleX( aOutSize.Width() / ( nBoundingBox[ 2 ] - nBoundingBox[ 0 ] ) );
1210 0 : aMapMode.SetScaleY( aOutSize.Height() / ( nBoundingBox[ 3 ] - nBoundingBox[ 1 ] ) );
1211 0 : ImplWriteLine( "gs" );
1212 0 : ImplGetMapMode( aMapMode );
1213 0 : ImplWriteLine( "%%BeginDocument:" );
1214 0 : mpPS->Write( pSource, aGfxLink.GetDataSize() );
1215 0 : ImplWriteLine( "%%EndDocument\ngr" );
1216 : }
1217 0 : }
1218 : }
1219 0 : break;
1220 :
1221 : case MetaActionType::Transparent:
1222 : {
1223 : // ImplLine( ( (const MetaTransparentAction*) pMA )->GetPolyPolygon() );
1224 : }
1225 0 : break;
1226 :
1227 : case MetaActionType::RASTEROP:
1228 : {
1229 0 : pMA->Execute( &rVDev );
1230 : }
1231 0 : break;
1232 :
1233 : case MetaActionType::FLOATTRANSPARENT:
1234 : {
1235 0 : const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pMA);
1236 :
1237 0 : GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
1238 0 : Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
1239 0 : const Size aSrcSize( aTmpMtf.GetPrefSize() );
1240 0 : const Point aDestPt( pA->GetPoint() );
1241 0 : const Size aDestSize( pA->GetSize() );
1242 0 : const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
1243 0 : const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
1244 : long nMoveX, nMoveY;
1245 :
1246 0 : if( fScaleX != 1.0 || fScaleY != 1.0 )
1247 : {
1248 0 : aTmpMtf.Scale( fScaleX, fScaleY );
1249 0 : aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
1250 : }
1251 :
1252 0 : nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
1253 :
1254 0 : if( nMoveX || nMoveY )
1255 0 : aTmpMtf.Move( nMoveX, nMoveY );
1256 :
1257 0 : ImplWriteActions( aTmpMtf, rVDev );
1258 : }
1259 0 : break;
1260 :
1261 : case MetaActionType::COMMENT:
1262 : {
1263 0 : const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pMA);
1264 0 : if ( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") )
1265 : {
1266 0 : const MetaGradientExAction* pGradAction = NULL;
1267 0 : while( ++nCurAction < nCount )
1268 : {
1269 0 : MetaAction* pAction = rMtf.GetAction( nCurAction );
1270 0 : if( pAction->GetType() == MetaActionType::GRADIENTEX )
1271 0 : pGradAction = static_cast<const MetaGradientExAction*>(pAction);
1272 0 : else if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
1273 0 : ( static_cast<const MetaCommentAction*>(pAction)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END") ) )
1274 : {
1275 0 : break;
1276 : }
1277 : }
1278 0 : if( pGradAction )
1279 0 : ImplWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), rVDev );
1280 : }
1281 0 : else if ( pA->GetComment().equals("XPATHFILL_SEQ_END") )
1282 : {
1283 0 : if ( aFillPath.Count() )
1284 : {
1285 0 : aFillPath = tools::PolyPolygon();
1286 0 : ImplWriteLine( "gr" );
1287 : }
1288 : }
1289 : else
1290 : {
1291 0 : const sal_uInt8* pData = pA->GetData();
1292 0 : if ( pData )
1293 : {
1294 0 : SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pData), pA->GetDataSize(), StreamMode::READ );
1295 0 : bool bSkipSequence = false;
1296 0 : OString sSeqEnd;
1297 :
1298 0 : if( pA->GetComment().equals( "XPATHSTROKE_SEQ_BEGIN" ) )
1299 : {
1300 0 : sSeqEnd = "XPATHSTROKE_SEQ_END";
1301 0 : SvtGraphicStroke aStroke;
1302 0 : ReadSvtGraphicStroke( aMemStm, aStroke );
1303 :
1304 0 : Polygon aPath;
1305 0 : aStroke.getPath( aPath );
1306 :
1307 0 : tools::PolyPolygon aStartArrow;
1308 0 : tools::PolyPolygon aEndArrow;
1309 : // double fTransparency( aStroke.getTransparency() );
1310 0 : double fStrokeWidth( aStroke.getStrokeWidth() );
1311 0 : SvtGraphicStroke::JoinType eJT( aStroke.getJoinType() );
1312 0 : SvtGraphicStroke::DashArray l_aDashArray;
1313 :
1314 0 : aStroke.getStartArrow( aStartArrow );
1315 0 : aStroke.getEndArrow( aEndArrow );
1316 0 : aStroke.getDashArray( l_aDashArray );
1317 :
1318 0 : bSkipSequence = true;
1319 0 : if ( l_aDashArray.size() > 11 ) // ps dasharray limit is 11
1320 0 : bSkipSequence = false;
1321 0 : if ( aStartArrow.Count() || aEndArrow.Count() )
1322 0 : bSkipSequence = false;
1323 0 : if ( (sal_uInt32)eJT > 2 )
1324 0 : bSkipSequence = false;
1325 0 : if ( l_aDashArray.size() && ( fStrokeWidth != 0.0 ) )
1326 0 : bSkipSequence = false;
1327 0 : if ( bSkipSequence )
1328 : {
1329 : ImplWriteLineInfo( fStrokeWidth, aStroke.getMiterLimit(),
1330 0 : aStroke.getCapType(), eJT, l_aDashArray );
1331 0 : ImplPolyLine( aPath );
1332 0 : }
1333 : }
1334 0 : else if (pA->GetComment().equals("XPATHFILL_SEQ_BEGIN"))
1335 : {
1336 0 : sSeqEnd = "XPATHFILL_SEQ_END";
1337 0 : SvtGraphicFill aFill;
1338 0 : ReadSvtGraphicFill( aMemStm, aFill );
1339 0 : switch( aFill.getFillType() )
1340 : {
1341 : case SvtGraphicFill::fillSolid :
1342 : {
1343 0 : bSkipSequence = true;
1344 0 : tools::PolyPolygon aPolyPoly;
1345 0 : aFill.getPath( aPolyPoly );
1346 0 : sal_uInt16 i, nPolyCount = aPolyPoly.Count();
1347 0 : if ( nPolyCount )
1348 : {
1349 0 : aFillColor = aFill.getFillColor();
1350 0 : ImplWriteFillColor( PS_SPACE );
1351 0 : for ( i = 0; i < nPolyCount; )
1352 : {
1353 0 : ImplAddPath( aPolyPoly.GetObject( i ) );
1354 0 : if ( ++i < nPolyCount )
1355 : {
1356 0 : mpPS->WriteCharPtr( "p" );
1357 0 : mnCursorPos += 2;
1358 0 : ImplExecMode( PS_RET );
1359 : }
1360 : }
1361 0 : mpPS->WriteCharPtr( "p ef" );
1362 0 : mnCursorPos += 4;
1363 0 : ImplExecMode( PS_RET );
1364 0 : }
1365 : }
1366 0 : break;
1367 :
1368 : case SvtGraphicFill::fillTexture :
1369 : {
1370 0 : aFill.getPath( aFillPath );
1371 :
1372 : /* normally an object filling is consisting of three MetaActions:
1373 : MetaBitmapAction using RasterOp xor,
1374 : MetaPolyPolygonAction using RasterOp rop_0
1375 : MetaBitmapAction using RasterOp xor
1376 :
1377 : Because RasterOps cannot been used in Postscript, we have to
1378 : replace these actions. The MetaComment "XPATHFILL_SEQ_BEGIN" is
1379 : providing the clippath of the object. The following loop is
1380 : trying to find the bitmap that is matching the clippath, so that
1381 : only one bitmap is exported, otherwise if the bitmap is not
1382 : locatable, all metaactions are played normally.
1383 : */
1384 0 : sal_uInt32 nCommentStartAction = nCurAction;
1385 0 : sal_uInt32 nBitmapCount = 0;
1386 0 : sal_uInt32 nBitmapAction = 0;
1387 :
1388 0 : bool bOk = true;
1389 0 : while( bOk && ( ++nCurAction < nCount ) )
1390 : {
1391 0 : MetaAction* pAction = rMtf.GetAction( nCurAction );
1392 0 : switch( pAction->GetType() )
1393 : {
1394 : case MetaActionType::BMPSCALE :
1395 : case MetaActionType::BMPSCALEPART :
1396 : case MetaActionType::BMPEXSCALE :
1397 : case MetaActionType::BMPEXSCALEPART :
1398 : {
1399 0 : nBitmapCount++;
1400 0 : nBitmapAction = nCurAction;
1401 : }
1402 0 : break;
1403 : case MetaActionType::COMMENT :
1404 : {
1405 0 : if (static_cast<const MetaCommentAction*>(pAction)->GetComment().equals("XPATHFILL_SEQ_END"))
1406 0 : bOk = false;
1407 : }
1408 0 : break;
1409 0 : default: break;
1410 : }
1411 : }
1412 0 : if( nBitmapCount == 2 )
1413 : {
1414 0 : ImplWriteLine( "gs" );
1415 0 : ImplIntersect( aFillPath );
1416 0 : GDIMetaFile aTempMtf;
1417 0 : aTempMtf.AddAction( rMtf.GetAction( nBitmapAction )->Clone() );
1418 0 : ImplWriteActions( aTempMtf, rVDev );
1419 0 : ImplWriteLine( "gr" );
1420 0 : aFillPath = tools::PolyPolygon();
1421 : }
1422 : else
1423 0 : nCurAction = nCommentStartAction + 1;
1424 : }
1425 0 : break;
1426 :
1427 : case SvtGraphicFill::fillGradient :
1428 0 : aFill.getPath( aFillPath );
1429 0 : break;
1430 :
1431 : case SvtGraphicFill::fillHatch :
1432 0 : break;
1433 : }
1434 0 : if ( aFillPath.Count() )
1435 : {
1436 0 : ImplWriteLine( "gs" );
1437 0 : ImplIntersect( aFillPath );
1438 0 : }
1439 : }
1440 0 : if ( bSkipSequence )
1441 : {
1442 0 : while( ++nCurAction < nCount )
1443 : {
1444 0 : pMA = rMtf.GetAction( nCurAction );
1445 0 : if ( pMA->GetType() == MetaActionType::COMMENT )
1446 : {
1447 0 : OString sComment( static_cast<MetaCommentAction*>(pMA)->GetComment() );
1448 0 : if ( sComment.equals( sSeqEnd ) )
1449 0 : break;
1450 : }
1451 : }
1452 0 : }
1453 : }
1454 : }
1455 : }
1456 0 : break;
1457 0 : default: 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( 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 tools::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 tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev )
1612 : {
1613 0 : ScopedVclPtrInstance< VirtualDevice > l_pVDev;
1614 0 : GDIMetaFile aTmpMtf;
1615 0 : l_pVDev->SetMapMode( rVDev.GetMapMode() );
1616 0 : l_pVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
1617 0 : ImplWriteActions( aTmpMtf, rVDev );
1618 0 : }
1619 :
1620 :
1621 :
1622 0 : void PSWriter::ImplPolyPoly( const tools::PolyPolygon & rPolyPoly, 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( vcl::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 : bool bDoTrans = false;
1785 :
1786 0 : Rectangle aRect;
1787 0 : vcl::Region aRegion;
1788 :
1789 0 : if ( pMaskBitmap )
1790 : {
1791 0 : bDoTrans = 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 = vcl::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( 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 : Bitmap::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 long* pDXArry, 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 long* 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 : vcl::Font aNotRotatedFont( maFont );
2144 0 : aNotRotatedFont.SetOrientation( 0 );
2145 :
2146 0 : ScopedVclPtrInstance< VirtualDevice > pVirDev( 1 );
2147 0 : pVirDev->SetMapMode( rVDev.GetMapMode() );
2148 0 : pVirDev->SetFont( aNotRotatedFont );
2149 0 : pVirDev->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 : bool bOldLineColor = bLineColor;
2162 0 : bLineColor = false;
2163 0 : std::vector<tools::PolyPolygon> aPolyPolyVec;
2164 0 : if ( pVirDev->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<tools::PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
2177 0 : while ( aIter != aPolyPolyVec.end() )
2178 0 : ImplPolyPoly( *aIter++, 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( '/' ); //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 :
2308 0 : void PSWriter::ImplWriteColor( sal_uLong nMode )
2309 : {
2310 0 : if ( mbGrayScale )
2311 : {
2312 : // writes the Color (grayscale) as a Number from 0.000 up to 1.000
2313 :
2314 0 : ImplWriteF( 1000 * ( (sal_uInt8)aColor.GetRed() * 77 + (sal_uInt8)aColor.GetGreen() * 151 +
2315 0 : (sal_uInt8)aColor.GetBlue() * 28 + 1 ) / 65536, 3, nMode );
2316 : }
2317 : else
2318 : {
2319 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetRed() );
2320 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetGreen() );
2321 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetBlue() );
2322 : }
2323 0 : mpPS->WriteCharPtr( "c" ); // ( c is defined as setrgbcolor or setgray )
2324 0 : ImplExecMode( nMode );
2325 0 : }
2326 :
2327 :
2328 :
2329 0 : double PSWriter::ImplGetScaling( const MapMode& rMapMode )
2330 : {
2331 : double nMul;
2332 0 : switch ( rMapMode.GetMapUnit() )
2333 : {
2334 : case MAP_PIXEL :
2335 : case MAP_SYSFONT :
2336 : case MAP_APPFONT :
2337 :
2338 : case MAP_100TH_MM :
2339 0 : nMul = 1;
2340 0 : break;
2341 : case MAP_10TH_MM :
2342 0 : nMul = 10;
2343 0 : break;
2344 : case MAP_MM :
2345 0 : nMul = 100;
2346 0 : break;
2347 : case MAP_CM :
2348 0 : nMul = 1000;
2349 0 : break;
2350 : case MAP_1000TH_INCH :
2351 0 : nMul = 2.54;
2352 0 : break;
2353 : case MAP_100TH_INCH :
2354 0 : nMul = 25.4;
2355 0 : break;
2356 : case MAP_10TH_INCH :
2357 0 : nMul = 254;
2358 0 : break;
2359 : case MAP_INCH :
2360 0 : nMul = 2540;
2361 0 : break;
2362 : case MAP_TWIP :
2363 0 : nMul = 1.76388889;
2364 0 : break;
2365 : case MAP_POINT :
2366 0 : nMul = 35.27777778;
2367 0 : break;
2368 : default:
2369 0 : nMul = 1.0;
2370 0 : break;
2371 : }
2372 0 : return nMul;
2373 : }
2374 :
2375 :
2376 :
2377 0 : void PSWriter::ImplGetMapMode( const MapMode& rMapMode )
2378 : {
2379 0 : ImplWriteLine( "tm setmatrix" );
2380 0 : double fMul = ImplGetScaling( rMapMode );
2381 0 : double fScaleX = (double)rMapMode.GetScaleX() * fMul;
2382 0 : double fScaleY = (double)rMapMode.GetScaleY() * fMul;
2383 0 : ImplTranslate( rMapMode.GetOrigin().X() * fScaleX, rMapMode.GetOrigin().Y() * fScaleY );
2384 0 : ImplScale( fScaleX, fScaleY );
2385 0 : }
2386 :
2387 :
2388 :
2389 0 : inline void PSWriter::ImplExecMode( sal_uLong nMode )
2390 : {
2391 0 : if ( nMode & PS_WRAP )
2392 : {
2393 0 : if ( mnCursorPos >= PS_LINESIZE )
2394 : {
2395 0 : mnCursorPos = 0;
2396 0 : mpPS->WriteUChar( 0xa );
2397 0 : return;
2398 : }
2399 : }
2400 0 : if ( nMode & PS_SPACE )
2401 : {
2402 0 : mpPS->WriteUChar( 32 );
2403 0 : mnCursorPos++;
2404 : }
2405 0 : if ( nMode & PS_RET )
2406 : {
2407 0 : mpPS->WriteUChar( 0xa );
2408 0 : mnCursorPos = 0;
2409 : }
2410 : }
2411 :
2412 :
2413 :
2414 0 : inline void PSWriter::ImplWriteLine( const char* pString, sal_uLong nMode )
2415 : {
2416 0 : sal_uLong i = 0;
2417 0 : while ( pString[ i ] )
2418 : {
2419 0 : mpPS->WriteUChar( pString[ i++ ] );
2420 : }
2421 0 : mnCursorPos += i;
2422 0 : ImplExecMode( nMode );
2423 0 : }
2424 :
2425 :
2426 :
2427 0 : void PSWriter::ImplWriteLineInfo( double fLWidth, double fMLimit,
2428 : SvtGraphicStroke::CapType eLCap,
2429 : SvtGraphicStroke::JoinType eJoin,
2430 : SvtGraphicStroke::DashArray& rLDash )
2431 : {
2432 0 : if ( fLineWidth != fLWidth )
2433 : {
2434 0 : fLineWidth = fLWidth;
2435 0 : ImplWriteDouble( fLineWidth );
2436 0 : ImplWriteLine( "lw", PS_SPACE );
2437 : }
2438 0 : if ( eLineCap != eLCap )
2439 : {
2440 0 : eLineCap = eLCap;
2441 0 : ImplWriteLong( (sal_Int32)eLineCap, PS_SPACE );
2442 0 : ImplWriteLine( "lc", PS_SPACE );
2443 : }
2444 0 : if ( eJoinType != eJoin )
2445 : {
2446 0 : eJoinType = eJoin;
2447 0 : ImplWriteLong( (sal_Int32)eJoinType, PS_SPACE );
2448 0 : ImplWriteLine( "lj", PS_SPACE );
2449 : }
2450 0 : if ( eJoinType == SvtGraphicStroke::joinMiter )
2451 : {
2452 0 : if ( fMiterLimit != fMLimit )
2453 : {
2454 0 : fMiterLimit = fMLimit;
2455 0 : ImplWriteDouble( fMiterLimit );
2456 0 : ImplWriteLine( "ml", PS_SPACE );
2457 : }
2458 : }
2459 0 : if ( aDashArray != rLDash )
2460 : {
2461 0 : aDashArray = rLDash;
2462 0 : sal_uInt32 j, i = aDashArray.size();
2463 0 : ImplWriteLine( "[", PS_SPACE );
2464 0 : for ( j = 0; j < i; j++ )
2465 0 : ImplWriteDouble( aDashArray[ j ] );
2466 0 : ImplWriteLine( "] 0 ld" );
2467 : }
2468 0 : }
2469 :
2470 :
2471 :
2472 0 : void PSWriter::ImplWriteLineInfo( const LineInfo& rLineInfo )
2473 : {
2474 0 : SvtGraphicStroke::DashArray l_aDashArray;
2475 0 : if ( rLineInfo.GetStyle() == LINE_DASH )
2476 0 : l_aDashArray.push_back( 2 );
2477 0 : const double fLWidth(( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5);
2478 0 : SvtGraphicStroke::JoinType aJoinType(SvtGraphicStroke::joinMiter);
2479 0 : SvtGraphicStroke::CapType aCapType(SvtGraphicStroke::capButt);
2480 :
2481 0 : switch(rLineInfo.GetLineJoin())
2482 : {
2483 : default: // B2DLineJoin::NONE, B2DLineJoin::Middle
2484 : // do NOT use SvtGraphicStroke::joinNone here
2485 : // since it will be written as numerical value directly
2486 : // and is NOT a valid EPS value
2487 0 : break;
2488 : case basegfx::B2DLineJoin::Miter:
2489 0 : aJoinType = SvtGraphicStroke::joinMiter;
2490 0 : break;
2491 : case basegfx::B2DLineJoin::Bevel:
2492 0 : aJoinType = SvtGraphicStroke::joinBevel;
2493 0 : break;
2494 : case basegfx::B2DLineJoin::Round:
2495 0 : aJoinType = SvtGraphicStroke::joinRound;
2496 0 : break;
2497 : }
2498 0 : switch(rLineInfo.GetLineCap())
2499 : {
2500 : default: /* com::sun::star::drawing::LineCap_BUTT */
2501 : {
2502 0 : aCapType = SvtGraphicStroke::capButt;
2503 0 : break;
2504 : }
2505 : case com::sun::star::drawing::LineCap_ROUND:
2506 : {
2507 0 : aCapType = SvtGraphicStroke::capRound;
2508 0 : break;
2509 : }
2510 : case com::sun::star::drawing::LineCap_SQUARE:
2511 : {
2512 0 : aCapType = SvtGraphicStroke::capSquare;
2513 0 : break;
2514 : }
2515 : }
2516 :
2517 0 : ImplWriteLineInfo( fLWidth, fMiterLimit, aCapType, aJoinType, l_aDashArray );
2518 0 : }
2519 :
2520 :
2521 :
2522 0 : void PSWriter::ImplWriteLong(sal_Int32 nNumber, sal_uLong nMode)
2523 : {
2524 0 : const OString aNumber(OString::number(nNumber));
2525 0 : mnCursorPos += aNumber.getLength();
2526 0 : mpPS->WriteCharPtr( aNumber.getStr() );
2527 0 : ImplExecMode(nMode);
2528 0 : }
2529 :
2530 :
2531 :
2532 0 : void PSWriter::ImplWriteDouble( double fNumber, sal_uLong nMode )
2533 : {
2534 0 : sal_Int32 nPTemp = (sal_Int32)fNumber;
2535 0 : sal_Int32 nATemp = labs( (sal_Int32)( ( fNumber - nPTemp ) * 100000 ) );
2536 :
2537 0 : if ( !nPTemp && nATemp && ( fNumber < 0.0 ) )
2538 0 : mpPS->WriteChar( '-' );
2539 :
2540 0 : const OString aNumber1(OString::number(nPTemp));
2541 0 : mpPS->WriteCharPtr( aNumber1.getStr() );
2542 0 : mnCursorPos += aNumber1.getLength();
2543 :
2544 0 : if ( nATemp )
2545 : {
2546 0 : int zCount = 0;
2547 0 : mpPS->WriteUChar( '.' );
2548 0 : mnCursorPos++;
2549 0 : const OString aNumber2(OString::number(nATemp));
2550 :
2551 0 : sal_Int16 n, nLen = aNumber2.getLength();
2552 0 : if ( nLen < 8 )
2553 : {
2554 0 : mnCursorPos += 6 - nLen;
2555 0 : for ( n = 0; n < ( 5 - nLen ); n++ )
2556 : {
2557 0 : mpPS->WriteUChar( '0' );
2558 : }
2559 : }
2560 0 : mnCursorPos += nLen;
2561 0 : for ( n = 0; n < nLen; n++ )
2562 : {
2563 0 : mpPS->WriteChar( aNumber2[n] );
2564 0 : zCount--;
2565 0 : if ( aNumber2[n] != '0' )
2566 0 : zCount = 0;
2567 : }
2568 0 : if ( zCount )
2569 0 : mpPS->SeekRel( zCount );
2570 : }
2571 0 : ImplExecMode( nMode );
2572 0 : }
2573 :
2574 :
2575 :
2576 : // writes the number to stream: nNumber / ( 10^nCount )
2577 :
2578 0 : void PSWriter::ImplWriteF( sal_Int32 nNumber, sal_uLong nCount, sal_uLong nMode )
2579 : {
2580 0 : if ( nNumber < 0 )
2581 : {
2582 0 : mpPS->WriteUChar( '-' );
2583 0 : nNumber = -nNumber;
2584 0 : mnCursorPos++;
2585 : }
2586 0 : const OString aScaleFactor(OString::number(nNumber));
2587 0 : sal_uLong nLen = aScaleFactor.getLength();
2588 0 : long nStSize = ( nCount + 1 ) - nLen;
2589 0 : if ( nStSize >= 1 )
2590 : {
2591 0 : mpPS->WriteUChar( '0' );
2592 0 : mnCursorPos++;
2593 : }
2594 0 : if ( nStSize >= 2 )
2595 : {
2596 0 : mpPS->WriteUChar( '.' );
2597 0 : for ( long i = 1; i < nStSize; i++ )
2598 : {
2599 0 : mpPS->WriteUChar( '0' );
2600 0 : mnCursorPos++;
2601 : }
2602 : }
2603 0 : mnCursorPos += nLen;
2604 0 : for( sal_uLong n = 0; n < nLen; n++ )
2605 : {
2606 0 : if ( n == nLen - nCount )
2607 : {
2608 0 : mpPS->WriteUChar( '.' );
2609 0 : mnCursorPos++;
2610 : }
2611 0 : mpPS->WriteChar( aScaleFactor[n] );
2612 : }
2613 0 : ImplExecMode( nMode );
2614 0 : }
2615 :
2616 :
2617 :
2618 0 : void PSWriter::ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode )
2619 : {
2620 0 : mpPS->WriteUChar( nNumb );
2621 0 : mnCursorPos++;
2622 0 : ImplExecMode( nMode );
2623 0 : }
2624 :
2625 :
2626 :
2627 0 : void PSWriter::ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode )
2628 : {
2629 0 : if ( ( nNumb >> 4 ) > 9 )
2630 0 : mpPS->WriteUChar( ( nNumb >> 4 ) + 'A' - 10 );
2631 : else
2632 0 : mpPS->WriteUChar( ( nNumb >> 4 ) + '0' );
2633 :
2634 0 : if ( ( nNumb & 0xf ) > 9 )
2635 0 : mpPS->WriteUChar( ( nNumb & 0xf ) + 'A' - 10 );
2636 : else
2637 0 : mpPS->WriteUChar( ( nNumb & 0xf ) + '0' );
2638 0 : mnCursorPos += 2;
2639 0 : ImplExecMode( nMode );
2640 0 : }
2641 :
2642 :
2643 :
2644 : // writes the sal_uInt8 nNumb as a Number from 0.000 up to 1.000
2645 :
2646 0 : void PSWriter::ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode )
2647 : {
2648 0 : ImplWriteF( 1000 * ( nNumb + 1 ) / 256 , 3, nMode );
2649 0 : }
2650 :
2651 :
2652 :
2653 :
2654 0 : inline void PSWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
2655 : {
2656 0 : dwShift |= ( nCode << ( nOffset - nCodeLen ) );
2657 0 : nOffset -= nCodeLen;
2658 0 : while ( nOffset < 24 )
2659 : {
2660 0 : ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2661 0 : dwShift <<= 8;
2662 0 : nOffset += 8;
2663 : }
2664 0 : if ( nCode == 257 && nOffset != 32 )
2665 0 : ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2666 0 : }
2667 :
2668 :
2669 :
2670 0 : void PSWriter::StartCompression()
2671 : {
2672 : sal_uInt16 i;
2673 0 : nDataSize = 8;
2674 :
2675 0 : nClearCode = 1 << nDataSize;
2676 0 : nEOICode = nClearCode + 1;
2677 0 : nTableSize = nEOICode + 1;
2678 0 : nCodeSize = nDataSize + 1;
2679 :
2680 0 : nOffset = 32; // number of free unused in dwShift
2681 0 : dwShift = 0;
2682 :
2683 0 : pTable = new PSLZWCTreeNode[ 4096 ];
2684 :
2685 0 : for ( i = 0; i < 4096; i++ )
2686 : {
2687 0 : pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL;
2688 0 : pTable[ i ].nValue = (sal_uInt8)( pTable[ i ].nCode = i );
2689 : }
2690 0 : pPrefix = NULL;
2691 0 : WriteBits( nClearCode, nCodeSize );
2692 0 : }
2693 :
2694 :
2695 :
2696 0 : void PSWriter::Compress( sal_uInt8 nCompThis )
2697 : {
2698 : PSLZWCTreeNode* p;
2699 : sal_uInt16 i;
2700 : sal_uInt8 nV;
2701 :
2702 0 : if( !pPrefix )
2703 : {
2704 0 : pPrefix = pTable + nCompThis;
2705 : }
2706 : else
2707 : {
2708 0 : nV = nCompThis;
2709 0 : for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother )
2710 : {
2711 0 : if ( p->nValue == nV )
2712 0 : break;
2713 : }
2714 :
2715 0 : if( p )
2716 0 : pPrefix = p;
2717 : else
2718 : {
2719 0 : WriteBits( pPrefix->nCode, nCodeSize );
2720 :
2721 0 : if ( nTableSize == 409 )
2722 : {
2723 0 : WriteBits( nClearCode, nCodeSize );
2724 :
2725 0 : for ( i = 0; i < nClearCode; i++ )
2726 0 : pTable[ i ].pFirstChild = NULL;
2727 :
2728 0 : nCodeSize = nDataSize + 1;
2729 0 : nTableSize = nEOICode + 1;
2730 : }
2731 : else
2732 : {
2733 0 : if( nTableSize == (sal_uInt16)( ( 1 << nCodeSize ) - 1 ) )
2734 0 : nCodeSize++;
2735 :
2736 0 : p = pTable + ( nTableSize++ );
2737 0 : p->pBrother = pPrefix->pFirstChild;
2738 0 : pPrefix->pFirstChild = p;
2739 0 : p->nValue = nV;
2740 0 : p->pFirstChild = NULL;
2741 : }
2742 :
2743 0 : pPrefix = pTable + nV;
2744 : }
2745 : }
2746 0 : }
2747 :
2748 :
2749 :
2750 0 : void PSWriter::EndCompression()
2751 : {
2752 0 : if( pPrefix )
2753 0 : WriteBits( pPrefix->nCode, nCodeSize );
2754 :
2755 0 : WriteBits( nEOICode, nCodeSize );
2756 0 : delete[] pTable;
2757 0 : }
2758 :
2759 :
2760 :
2761 0 : sal_uInt8* PSWriter::ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize )
2762 : {
2763 0 : while ( nComp-- >= nSize )
2764 : {
2765 : sal_uLong i;
2766 0 : for ( i = 0; i < nSize; i++ )
2767 : {
2768 0 : if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
2769 0 : break;
2770 : }
2771 0 : if ( i == nSize )
2772 0 : return pSource;
2773 0 : pSource++;
2774 : }
2775 0 : return NULL;
2776 : }
2777 :
2778 :
2779 :
2780 0 : bool PSWriter::ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize )
2781 : {
2782 0 : bool bRetValue = false;
2783 : sal_uLong nBytesRead;
2784 :
2785 0 : if ( nSize < 256 ) // we assume that the file is greater than 256 bytes
2786 0 : return false;
2787 :
2788 0 : if ( nSize < POSTSCRIPT_BOUNDINGSEARCH )
2789 0 : nBytesRead = nSize;
2790 : else
2791 0 : nBytesRead = POSTSCRIPT_BOUNDINGSEARCH;
2792 :
2793 0 : sal_uInt8* pDest = ImplSearchEntry( pSource, reinterpret_cast<sal_uInt8 const *>("%%BoundingBox:"), nBytesRead, 14 );
2794 0 : if ( pDest )
2795 : {
2796 0 : int nSecurityCount = 100; // only 100 bytes following the bounding box will be checked
2797 0 : nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
2798 0 : pDest += 14;
2799 0 : for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
2800 : {
2801 0 : int nDivision = 1;
2802 0 : bool bDivision = false;
2803 0 : bool bNegative = false;
2804 0 : bool bValid = true;
2805 :
2806 0 : while ( ( --nSecurityCount ) && ( ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) )
2807 0 : pDest++;
2808 0 : sal_uInt8 nByte = *pDest;
2809 0 : while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
2810 : {
2811 0 : switch ( nByte )
2812 : {
2813 : case '.' :
2814 0 : if ( bDivision )
2815 0 : bValid = false;
2816 : else
2817 0 : bDivision = true;
2818 0 : break;
2819 : case '-' :
2820 0 : bNegative = true;
2821 0 : break;
2822 : default :
2823 0 : if ( ( nByte < '0' ) || ( nByte > '9' ) )
2824 0 : nSecurityCount = 1; // error parsing the bounding box values
2825 0 : else if ( bValid )
2826 : {
2827 0 : if ( bDivision )
2828 0 : nDivision*=10;
2829 0 : nNumb[i] *= 10;
2830 0 : nNumb[i] += nByte - '0';
2831 : }
2832 0 : break;
2833 : }
2834 0 : nSecurityCount--;
2835 0 : nByte = *(++pDest);
2836 : }
2837 0 : if ( bNegative )
2838 0 : nNumb[i] = -nNumb[i];
2839 0 : if ( bDivision && ( nDivision != 1 ) )
2840 0 : nNumb[i] /= nDivision;
2841 : }
2842 0 : if ( nSecurityCount)
2843 0 : bRetValue = true;
2844 : }
2845 0 : return bRetValue;
2846 : }
2847 :
2848 : //================== GraphicExport - die exportierte Funktion ================
2849 :
2850 : // this needs to be kept in sync with
2851 : // ImpFilterLibCacheEntry::GetImportFunction() from
2852 : // vcl/source/filter/graphicfilter.cxx
2853 : #if defined(DISABLE_DYNLOADING)
2854 : #define GraphicExport epsGraphicExport
2855 : #endif
2856 :
2857 : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
2858 0 : GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem )
2859 : {
2860 0 : PSWriter aPSWriter;
2861 0 : return aPSWriter.WritePS( rGraphic, rStream, pFilterConfigItem );
2862 0 : }
2863 :
2864 :
2865 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|