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 : bool bLineCol;
75 : Color aLineCol;
76 : bool bFillCol;
77 : Color aFillCol;
78 : Color aTextCol;
79 : bool bTextFillCol;
80 : Color aTextFillCol;
81 : Color aBackgroundCol;
82 : vcl::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 : 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 : bool mbGrayScale;
111 : 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 : bool bLineColor;
129 : Color aLineColor; // current GDIMetafile color settings
130 : bool bFillColor;
131 : Color aFillColor;
132 : Color aTextColor;
133 : bool bTextFillColor;
134 : Color aTextFillColor;
135 : Color aBackgroundColor;
136 : 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 : vcl::Font maFont;
146 : vcl::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_uInt32 nOffset;
159 : sal_uInt32 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 ImplAddPath( const Polygon & rPolygon );
200 : void ImplWriteLineInfo( double fLineWidth, double fMiterLimit, SvtGraphicStroke::CapType eLineCap,
201 : SvtGraphicStroke::JoinType eJoinType, SvtGraphicStroke::DashArray& rDashArray );
202 : void ImplWriteLineInfo( const LineInfo& rLineInfo );
203 : void ImplRect( const Rectangle & rRectangle );
204 : void ImplRectFill ( const Rectangle & rRectangle );
205 : void ImplWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev );
206 : void ImplIntersect( const tools::PolyPolygon& rPolyPoly );
207 : void ImplPolyPoly( const tools::PolyPolygon & rPolyPolygon, bool bTextOutline = false );
208 : void ImplPolyLine( const Polygon & rPolygon );
209 :
210 : void ImplSetClipRegion( vcl::Region& rRegion );
211 : void ImplBmp( Bitmap*, Bitmap*, const Point &, double nWidth, double nHeight );
212 : void ImplText( const OUString& rUniString, const Point& rPos, const long* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev );
213 : void ImplSetAttrForText( const Point & rPoint );
214 : void ImplWriteCharacter( sal_Char );
215 : void ImplWriteString( const OString&, VirtualDevice& rVDev, const long* pDXArry = NULL, bool bStretch = false );
216 : void ImplDefineFont( const char*, const char* );
217 :
218 : void ImplClosePathDraw( sal_uLong nMode = PS_RET );
219 : void ImplPathDraw();
220 :
221 : inline void ImplWriteLineColor( sal_uLong nMode = PS_RET );
222 : inline void ImplWriteFillColor( sal_uLong nMode = PS_RET );
223 : inline void ImplWriteTextColor( sal_uLong nMode = PS_RET );
224 : void ImplWriteColor( sal_uLong nMode );
225 :
226 : double ImplGetScaling( const MapMode& );
227 : void ImplGetMapMode( const MapMode& );
228 : bool ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize );
229 : sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize );
230 : // LZW methods
231 : void StartCompression();
232 : void Compress( sal_uInt8 nSrc );
233 : void EndCompression();
234 : inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
235 :
236 : public:
237 : bool WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* );
238 : PSWriter();
239 : ~PSWriter();
240 : };
241 :
242 : //========================== Methoden von PSWriter ==========================
243 :
244 :
245 :
246 0 : PSWriter::PSWriter()
247 : : mbStatus(false)
248 : , mnLevelWarning(0)
249 : , mnLastPercent(0)
250 : , mnLatestPush(0)
251 : , mnLevel(0)
252 : , mbGrayScale(false)
253 : , mbCompression(false)
254 : , mnPreview(0)
255 : , mnTextMode(0)
256 : , mpPS(NULL)
257 : , pMTF(NULL)
258 : , pAMTF(NULL)
259 : , aVDev()
260 : , nBoundingX1(0)
261 : , nBoundingY1(0)
262 : , nBoundingX2(0)
263 : , nBoundingY2(0)
264 : , pGDIStack(NULL)
265 : , mnCursorPos(0)
266 : , aColor()
267 : , bLineColor(false)
268 : , aLineColor()
269 : , bFillColor(false)
270 : , aFillColor()
271 : , aTextColor()
272 : , bTextFillColor(false)
273 : , aTextFillColor()
274 : , aBackgroundColor()
275 : , bRegionChanged(false)
276 : , eTextAlign()
277 : , fLineWidth(0)
278 : , fMiterLimit(0)
279 : , eLineCap()
280 : , eJoinType()
281 : , aDashArray()
282 : , maFont()
283 : , maLastFont()
284 : , nChrSet(0)
285 : , pChrSetList(NULL)
286 : , nNextChrSetId(0)
287 : , pTable(NULL)
288 : , pPrefix(NULL)
289 : , nDataSize(0)
290 : , nClearCode(0)
291 : , nEOICode(0)
292 : , nTableSize(0)
293 : , nCodeSize(0)
294 : , nOffset(0)
295 : , dwShift(0)
296 0 : , xStatusIndicator()
297 : {
298 0 : pAMTF = NULL;
299 0 : }
300 :
301 :
302 0 : PSWriter::~PSWriter()
303 : {
304 0 : delete pAMTF;
305 0 : }
306 :
307 :
308 :
309 0 : bool PSWriter::WritePS( const Graphic& rGraphic, SvStream& rTargetStream, FilterConfigItem* pFilterConfigItem )
310 : {
311 0 : sal_uInt32 nStreamPosition = 0, nPSPosition = 0; // -Wall warning, unset, check
312 :
313 0 : mbStatus = true;
314 0 : mnPreview = 0;
315 0 : mnLevelWarning = 0;
316 0 : mnLastPercent = 0;
317 0 : mnLatestPush = 0xEFFFFFFE;
318 :
319 0 : if ( pFilterConfigItem )
320 : {
321 0 : xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
322 0 : if ( xStatusIndicator.is() )
323 : {
324 0 : OUString aMsg;
325 0 : xStatusIndicator->start( aMsg, 100 );
326 : }
327 : }
328 :
329 0 : mpPS = &rTargetStream;
330 0 : mpPS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
331 :
332 : // default values for the dialog options
333 0 : mnLevel = 2;
334 0 : mbGrayScale = false;
335 : #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
336 0 : mbCompression = false;
337 : #else
338 : mbCompression = sal_True;
339 : #endif
340 0 : mnTextMode = 0; // default0 : export glyph outlines
341 :
342 : // try to get the dialog selection
343 0 : if ( pFilterConfigItem )
344 : {
345 0 : boost::scoped_ptr<ResMgr> pResMgr(ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() ));
346 :
347 0 : if( pResMgr )
348 : {
349 : #ifdef UNX // don't put binary tiff preview ahead of postscript code by default on unix as ghostscript is unable to read it
350 0 : mnPreview = pFilterConfigItem->ReadInt32( "Preview", 0 );
351 : #else
352 : mnPreview = pFilterConfigItem->ReadInt32( "Preview", 1 );
353 : #endif
354 0 : mnLevel = pFilterConfigItem->ReadInt32( "Version", 2 );
355 0 : if ( mnLevel != 1 )
356 0 : mnLevel = 2;
357 0 : mbGrayScale = pFilterConfigItem->ReadInt32( "ColorFormat", 1 ) == 2;
358 : #ifdef UNX // don't compress by default on unix as ghostscript is unable to read LZW compressed eps
359 0 : mbCompression = pFilterConfigItem->ReadInt32( "CompressionMode", 0 ) != 0;
360 : #else
361 : mbCompression = pFilterConfigItem->ReadInt32( "CompressionMode", 1 ) == 1;
362 : #endif
363 0 : mnTextMode = pFilterConfigItem->ReadInt32( "TextMode", 0 );
364 0 : if ( mnTextMode > 2 )
365 0 : mnTextMode = 0;
366 0 : }
367 : }
368 :
369 : // compression is not available for Level 1
370 0 : if ( mnLevel == 1 )
371 : {
372 0 : mbGrayScale = true;
373 0 : mbCompression = false;
374 : }
375 :
376 0 : if ( mnPreview & EPS_PREVIEW_TIFF )
377 : {
378 0 : rTargetStream.WriteUInt32( 0xC6D3D0C5 );
379 0 : nStreamPosition = rTargetStream.Tell();
380 0 : rTargetStream.WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 )
381 0 : .WriteUInt32( nStreamPosition + 26 ).WriteUInt32( 0 ).WriteUInt16( 0xffff );
382 :
383 : sal_uInt32 nErrCode;
384 0 : if ( mbGrayScale )
385 : {
386 0 : BitmapEx aTempBitmapEx( rGraphic.GetBitmapEx() );
387 0 : aTempBitmapEx.Convert( BMP_CONVERSION_8BIT_GREYS );
388 0 : nErrCode = GraphicConverter::Export( rTargetStream, aTempBitmapEx, CVT_TIF ) ;
389 : }
390 : else
391 0 : nErrCode = GraphicConverter::Export( rTargetStream, rGraphic, CVT_TIF ) ;
392 :
393 0 : if ( nErrCode == ERRCODE_NONE )
394 : {
395 0 : rTargetStream.Seek( STREAM_SEEK_TO_END );
396 0 : nPSPosition = rTargetStream.Tell();
397 0 : rTargetStream.Seek( nStreamPosition + 20 );
398 0 : rTargetStream.WriteUInt32( nPSPosition - 30 ); // size of tiff gfx
399 0 : rTargetStream.Seek( nPSPosition );
400 : }
401 : else
402 : {
403 0 : mnPreview &=~ EPS_PREVIEW_TIFF;
404 0 : rTargetStream.Seek( nStreamPosition - 4 );
405 : }
406 : }
407 :
408 : // global default value setting
409 : ChrSet* pCS;
410 : StackMember* pGS;
411 :
412 0 : if (rGraphic.GetType() == GRAPHIC_GDIMETAFILE)
413 0 : pMTF = &rGraphic.GetGDIMetaFile();
414 0 : else if (rGraphic.GetGDIMetaFile().GetActionSize())
415 0 : pMTF = pAMTF = new GDIMetaFile( rGraphic.GetGDIMetaFile() );
416 : else
417 : {
418 0 : Bitmap aBmp( rGraphic.GetBitmap() );
419 0 : pAMTF = new GDIMetaFile();
420 0 : VirtualDevice aTmpVDev;
421 0 : pAMTF->Record( &aTmpVDev );
422 0 : aTmpVDev.DrawBitmap( Point(), aBmp );
423 0 : pAMTF->Stop();
424 0 : pAMTF->SetPrefSize( aBmp.GetSizePixel() );
425 0 : pMTF = pAMTF;
426 : }
427 0 : aVDev.SetMapMode( pMTF->GetPrefMapMode() );
428 0 : nBoundingX1 = nBoundingY1 = 0;
429 0 : nBoundingX2 = pMTF->GetPrefSize().Width();
430 0 : nBoundingY2 = pMTF->GetPrefSize().Height();
431 :
432 0 : pGDIStack = NULL;
433 0 : aColor = Color( COL_TRANSPARENT );
434 0 : bLineColor = true;
435 0 : aLineColor = Color( COL_BLACK );
436 0 : bFillColor = true;
437 0 : aFillColor = Color( COL_WHITE );
438 0 : bTextFillColor = true;
439 0 : aTextFillColor = Color( COL_BLACK );
440 0 : fLineWidth = 1;
441 0 : fMiterLimit = 15; // use same limit as most graphic systems and basegfx
442 0 : eLineCap = SvtGraphicStroke::capButt;
443 0 : eJoinType = SvtGraphicStroke::joinMiter;
444 0 : aBackgroundColor = Color( COL_WHITE );
445 0 : eTextAlign = ALIGN_BASELINE;
446 0 : bRegionChanged = false;
447 :
448 0 : nChrSet = 0x00;
449 0 : pChrSetList = NULL;
450 0 : nNextChrSetId = 1;
451 :
452 0 : if( pMTF->GetActionSize() )
453 : {
454 0 : ImplWriteProlog( ( mnPreview & EPS_PREVIEW_EPSI ) ? &rGraphic : NULL );
455 0 : mnCursorPos = 0;
456 0 : ImplWriteActions( *pMTF, aVDev );
457 0 : ImplWriteEpilog();
458 0 : if ( mnPreview & EPS_PREVIEW_TIFF )
459 : {
460 0 : sal_uInt32 nPosition = rTargetStream.Tell();
461 0 : rTargetStream.Seek( nStreamPosition );
462 0 : rTargetStream.WriteUInt32( nPSPosition );
463 0 : rTargetStream.WriteUInt32( nPosition - nPSPosition );
464 0 : rTargetStream.Seek( nPosition );
465 : }
466 0 : while( pChrSetList )
467 : {
468 0 : pCS=pChrSetList;
469 0 : pChrSetList=pCS->pSucc;
470 0 : delete pCS;
471 : }
472 0 : while( pGDIStack )
473 : {
474 0 : pGS=pGDIStack;
475 0 : pGDIStack=pGS->pSucc;
476 0 : delete pGS;
477 : }
478 : }
479 : else
480 0 : mbStatus = false;
481 :
482 0 : if ( mbStatus && mnLevelWarning && pFilterConfigItem )
483 : {
484 : ResMgr* pResMgr;
485 0 : pResMgr = ResMgr::CreateResMgr( "eps", Application::GetSettings().GetUILanguageTag() );
486 0 : if( pResMgr )
487 : {
488 0 : InfoBox aInfoBox( NULL, ResId(KEY_VERSION_CHECK, *pResMgr).toString() );
489 0 : aInfoBox.Execute();
490 0 : delete pResMgr;
491 : }
492 : }
493 :
494 0 : if ( xStatusIndicator.is() )
495 0 : xStatusIndicator->end();
496 :
497 0 : return mbStatus;
498 : }
499 :
500 :
501 :
502 0 : void PSWriter::ImplWriteProlog( const Graphic* pPreview )
503 : {
504 0 : ImplWriteLine( "%!PS-Adobe-3.0 EPSF-3.0 " );
505 0 : mpPS->WriteCharPtr( "%%BoundingBox: " ); // BoundingBox
506 0 : ImplWriteLong( 0 );
507 0 : ImplWriteLong( 0 );
508 0 : Size aSizePoint = OutputDevice::LogicToLogic( pMTF->GetPrefSize(),
509 0 : pMTF->GetPrefMapMode(), MAP_POINT );
510 0 : ImplWriteLong( aSizePoint.Width() );
511 0 : ImplWriteLong( aSizePoint.Height() ,PS_RET );
512 0 : ImplWriteLine( "%%Pages: 0" );
513 0 : OUString aCreator( "%%Creator: " + utl::ConfigManager::getProductName() + " " +
514 0 : utl::ConfigManager::getProductVersion() );
515 0 : ImplWriteLine( OUStringToOString( aCreator, RTL_TEXTENCODING_UTF8 ).getStr() );
516 0 : ImplWriteLine( "%%Title: none" );
517 0 : ImplWriteLine( "%%CreationDate: none" );
518 :
519 : // defaults
520 :
521 0 : mpPS->WriteCharPtr( "%%LanguageLevel: " ); // Language level
522 0 : ImplWriteLong( mnLevel, PS_RET );
523 0 : if ( !mbGrayScale && mnLevel == 1 )
524 0 : ImplWriteLine( "%%Extensions: CMYK" ); // CMYK extension is to set in color mode in level 1
525 0 : ImplWriteLine( "%%EndComments" );
526 0 : if ( pPreview && aSizePoint.Width() && aSizePoint.Height() )
527 : {
528 0 : Size aSizeBitmap( ( aSizePoint.Width() + 7 ) & ~7, aSizePoint.Height() );
529 0 : Bitmap aTmpBitmap( pPreview->GetBitmap() );
530 0 : aTmpBitmap.Scale( aSizeBitmap, BMP_SCALE_BESTQUALITY );
531 0 : aTmpBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
532 0 : BitmapReadAccess* pAcc = aTmpBitmap.AcquireReadAccess();
533 0 : if ( pAcc )
534 : {
535 0 : mpPS->WriteCharPtr( "%%BeginPreview: " ); // BoundingBox
536 0 : ImplWriteLong( aSizeBitmap.Width() );
537 0 : ImplWriteLong( aSizeBitmap.Height() );
538 0 : mpPS->WriteCharPtr( "1 " );
539 0 : sal_Int32 nLines = aSizeBitmap.Width() / 312;
540 0 : if ( ( nLines * 312 ) != aSizeBitmap.Width() )
541 0 : nLines++;
542 0 : nLines *= aSizeBitmap.Height();
543 0 : ImplWriteLong( nLines );
544 : char nVal;
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 : 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 : aTmpBitmap.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 META_NULL_ACTION :
666 0 : break;
667 :
668 : case META_PIXEL_ACTION :
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 META_POINT_ACTION :
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 META_LINE_ACTION :
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 META_RECT_ACTION :
704 : {
705 0 : ImplRect( static_cast<const MetaRectAction*>(pMA)->GetRect() );
706 : }
707 0 : break;
708 :
709 : case META_ROUNDRECT_ACTION :
710 0 : ImplRect( static_cast<const MetaRoundRectAction*>(pMA)->GetRect() );
711 0 : break;
712 :
713 : case META_ELLIPSE_ACTION :
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 META_ARC_ACTION :
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 META_PIE_ACTION :
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 META_CHORD_ACTION :
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 META_POLYLINE_ACTION :
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 META_POLYGON_ACTION :
793 : {
794 0 : tools::PolyPolygon aPolyPoly( static_cast<const MetaPolygonAction*>(pMA)->GetPolygon() );
795 0 : ImplPolyPoly( aPolyPoly );
796 : }
797 0 : break;
798 :
799 : case META_POLYPOLYGON_ACTION :
800 : {
801 0 : ImplPolyPoly( static_cast<const MetaPolyPolygonAction*>(pMA)->GetPolyPolygon() );
802 : }
803 0 : break;
804 :
805 : case META_TEXT_ACTION:
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 META_TEXTRECT_ACTION:
817 : {
818 : OSL_FAIL( "Unsupported action: TextRect...Action!" );
819 : }
820 0 : break;
821 :
822 : case META_STRETCHTEXT_ACTION :
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 META_TEXTARRAY_ACTION:
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 META_BMP_ACTION :
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 META_BMPSCALE_ACTION :
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 META_BMPSCALEPART_ACTION :
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 META_BMPEX_ACTION :
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 META_BMPEXSCALE_ACTION :
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 META_BMPEXSCALEPART_ACTION :
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 META_MASK_ACTION:
920 : case META_MASKSCALE_ACTION:
921 : case META_MASKSCALEPART_ACTION:
922 : {
923 : OSL_FAIL( "Unsupported action: MetaMask...Action!" );
924 : }
925 0 : break;
926 :
927 : case META_GRADIENT_ACTION :
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 META_GRADIENTEX_ACTION :
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 META_HATCH_ACTION :
942 : {
943 0 : VirtualDevice l_aVDev;
944 0 : GDIMetaFile aTmpMtf;
945 :
946 0 : l_aVDev.SetMapMode( rVDev.GetMapMode() );
947 0 : l_aVDev.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 META_WALLPAPER_ACTION :
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 META_ISECTRECTCLIPREGION_ACTION:
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 META_CLIPREGION_ACTION:
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 META_ISECTREGIONCLIPREGION_ACTION:
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 META_MOVECLIPREGION_ACTION:
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 META_LINECOLOR_ACTION :
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 META_FILLCOLOR_ACTION :
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 META_TEXTCOLOR_ACTION :
1056 : {
1057 0 : aTextColor = static_cast<const MetaTextColorAction*>(pMA)->GetColor();
1058 : }
1059 0 : break;
1060 :
1061 : case META_TEXTFILLCOLOR_ACTION :
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 META_TEXTALIGN_ACTION :
1074 : {
1075 0 : eTextAlign = static_cast<const MetaTextAlignAction*>(pMA)->GetTextAlign();
1076 : }
1077 0 : break;
1078 :
1079 : case META_MAPMODE_ACTION :
1080 : {
1081 0 : pMA->Execute( &rVDev );
1082 0 : ImplGetMapMode( rVDev.GetMapMode() );
1083 : }
1084 0 : break;
1085 :
1086 : case META_FONT_ACTION :
1087 : {
1088 0 : maFont = static_cast<const MetaFontAction*>(pMA)->GetFont();
1089 0 : rVDev.SetFont( maFont );
1090 : }
1091 0 : break;
1092 :
1093 : case META_PUSH_ACTION :
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 META_POP_ACTION :
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 META_EPS_ACTION :
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 = (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, (sal_uInt8*)"%%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 META_TRANSPARENT_ACTION:
1222 : {
1223 : // ImplLine( ( (const MetaTransparentAction*) pMA )->GetPolyPolygon() );
1224 : }
1225 0 : break;
1226 :
1227 : case META_RASTEROP_ACTION:
1228 : {
1229 0 : pMA->Execute( &rVDev );
1230 : }
1231 0 : break;
1232 :
1233 : case META_FLOATTRANSPARENT_ACTION:
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 META_COMMENT_ACTION:
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() == META_GRADIENTEX_ACTION )
1271 0 : pGradAction = static_cast<const MetaGradientExAction*>(pAction);
1272 0 : else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
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( (void*)pData, pA->GetDataSize(), STREAM_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 META_BMPSCALE_ACTION :
1395 : case META_BMPSCALEPART_ACTION :
1396 : case META_BMPEXSCALE_ACTION :
1397 : case META_BMPEXSCALEPART_ACTION :
1398 : {
1399 0 : nBitmapCount++;
1400 0 : nBitmapAction = nCurAction;
1401 : }
1402 0 : break;
1403 : case META_COMMENT_ACTION :
1404 : {
1405 0 : if (static_cast<const MetaCommentAction*>(pAction)->GetComment().equals("XPATHFILL_SEQ_END"))
1406 0 : bOk = false;
1407 : }
1408 0 : break;
1409 : }
1410 : }
1411 0 : if( nBitmapCount == 2 )
1412 : {
1413 0 : ImplWriteLine( "gs" );
1414 0 : ImplIntersect( aFillPath );
1415 0 : GDIMetaFile aTempMtf;
1416 0 : aTempMtf.AddAction( rMtf.GetAction( nBitmapAction )->Clone() );
1417 0 : ImplWriteActions( aTempMtf, rVDev );
1418 0 : ImplWriteLine( "gr" );
1419 0 : aFillPath = tools::PolyPolygon();
1420 : }
1421 : else
1422 0 : nCurAction = nCommentStartAction + 1;
1423 : }
1424 0 : break;
1425 :
1426 : case SvtGraphicFill::fillGradient :
1427 0 : aFill.getPath( aFillPath );
1428 0 : break;
1429 :
1430 : case SvtGraphicFill::fillHatch :
1431 0 : break;
1432 : }
1433 0 : if ( aFillPath.Count() )
1434 : {
1435 0 : ImplWriteLine( "gs" );
1436 0 : ImplIntersect( aFillPath );
1437 0 : }
1438 : }
1439 0 : if ( bSkipSequence )
1440 : {
1441 0 : while( ++nCurAction < nCount )
1442 : {
1443 0 : pMA = rMtf.GetAction( nCurAction );
1444 0 : if ( pMA->GetType() == META_COMMENT_ACTION )
1445 : {
1446 0 : OString sComment( static_cast<MetaCommentAction*>(pMA)->GetComment() );
1447 0 : if ( sComment.equals( sSeqEnd ) )
1448 0 : break;
1449 : }
1450 : }
1451 0 : }
1452 : }
1453 : }
1454 : }
1455 0 : break;
1456 : }
1457 0 : }
1458 0 : }
1459 :
1460 :
1461 :
1462 :
1463 :
1464 0 : inline void PSWriter::ImplWritePoint( const Point& rPoint, sal_uInt32 nMode )
1465 : {
1466 0 : ImplWriteDouble( rPoint.X() );
1467 0 : ImplWriteDouble( rPoint.Y(), nMode );
1468 0 : }
1469 :
1470 :
1471 :
1472 0 : void PSWriter::ImplMoveTo( const Point& rPoint, sal_uInt32 nMode )
1473 : {
1474 0 : ImplWritePoint( rPoint );
1475 0 : ImplWriteByte( 'm' );
1476 0 : ImplExecMode( nMode );
1477 0 : }
1478 :
1479 :
1480 :
1481 0 : void PSWriter::ImplLineTo( const Point& rPoint, sal_uInt32 nMode )
1482 : {
1483 0 : ImplWritePoint( rPoint );
1484 0 : ImplWriteByte( 'l' );
1485 0 : ImplExecMode( nMode );
1486 0 : }
1487 :
1488 :
1489 :
1490 0 : void PSWriter::ImplCurveTo( const Point& rP1, const Point& rP2, const Point& rP3, sal_uInt32 nMode )
1491 : {
1492 0 : ImplWritePoint( rP1 );
1493 0 : ImplWritePoint( rP2 );
1494 0 : ImplWritePoint( rP3 );
1495 0 : mpPS->WriteCharPtr( "ct " );
1496 0 : ImplExecMode( nMode );
1497 0 : }
1498 :
1499 :
1500 :
1501 0 : void PSWriter::ImplTranslate( const double& fX, const double& fY, sal_uInt32 nMode )
1502 : {
1503 0 : ImplWriteDouble( fX );
1504 0 : ImplWriteDouble( fY );
1505 0 : ImplWriteByte( 't' );
1506 0 : ImplExecMode( nMode );
1507 0 : }
1508 :
1509 :
1510 :
1511 0 : void PSWriter::ImplScale( const double& fX, const double& fY, sal_uInt32 nMode )
1512 : {
1513 0 : ImplWriteDouble( fX );
1514 0 : ImplWriteDouble( fY );
1515 0 : ImplWriteByte( 's' );
1516 0 : ImplExecMode( nMode );
1517 0 : }
1518 :
1519 :
1520 :
1521 0 : void PSWriter::ImplRect( const Rectangle & rRect )
1522 : {
1523 0 : if ( bFillColor )
1524 0 : ImplRectFill( rRect );
1525 0 : if ( bLineColor )
1526 : {
1527 0 : double nWidth = rRect.GetWidth();
1528 0 : double nHeight = rRect.GetHeight();
1529 :
1530 0 : ImplWriteLineColor( PS_SPACE );
1531 0 : ImplMoveTo( rRect.TopLeft() );
1532 0 : ImplWriteDouble( nWidth );
1533 0 : mpPS->WriteCharPtr( "0 rl 0 " );
1534 0 : ImplWriteDouble( nHeight );
1535 0 : mpPS->WriteCharPtr( "rl " );
1536 0 : ImplWriteDouble( nWidth );
1537 0 : mpPS->WriteCharPtr( "neg 0 rl " );
1538 0 : ImplClosePathDraw();
1539 : }
1540 0 : mpPS->WriteUChar( 10 );
1541 0 : mnCursorPos = 0;
1542 0 : }
1543 :
1544 :
1545 :
1546 0 : void PSWriter::ImplRectFill( const Rectangle & rRect )
1547 : {
1548 0 : double nWidth = rRect.GetWidth();
1549 0 : double nHeight = rRect.GetHeight();
1550 :
1551 0 : ImplWriteFillColor( PS_SPACE );
1552 0 : ImplMoveTo( rRect.TopLeft() );
1553 0 : ImplWriteDouble( nWidth );
1554 0 : mpPS->WriteCharPtr( "0 rl 0 " );
1555 0 : ImplWriteDouble( nHeight );
1556 0 : mpPS->WriteCharPtr( "rl " );
1557 0 : ImplWriteDouble( nWidth );
1558 0 : mpPS->WriteCharPtr( "neg 0 rl ef " );
1559 0 : mpPS->WriteCharPtr( "p ef" );
1560 0 : mnCursorPos += 2;
1561 0 : ImplExecMode( PS_RET );
1562 0 : }
1563 :
1564 :
1565 :
1566 0 : void PSWriter::ImplAddPath( const Polygon & rPolygon )
1567 : {
1568 0 : sal_uInt16 nPointCount = rPolygon.GetSize();
1569 0 : if ( nPointCount > 1 )
1570 : {
1571 0 : sal_uInt16 i = 1;
1572 0 : ImplMoveTo( rPolygon.GetPoint( 0 ) );
1573 0 : while ( i < nPointCount )
1574 : {
1575 0 : if ( ( rPolygon.GetFlags( i ) == POLY_CONTROL )
1576 0 : && ( ( i + 2 ) < nPointCount )
1577 0 : && ( rPolygon.GetFlags( i + 1 ) == POLY_CONTROL )
1578 0 : && ( rPolygon.GetFlags( i + 2 ) != POLY_CONTROL ) )
1579 : {
1580 0 : ImplCurveTo( rPolygon[ i ], rPolygon[ i + 1 ], rPolygon[ i + 2 ], PS_WRAP );
1581 0 : i += 3;
1582 : }
1583 : else
1584 0 : ImplLineTo( rPolygon.GetPoint( i++ ), PS_SPACE | PS_WRAP );
1585 : }
1586 : }
1587 0 : }
1588 :
1589 :
1590 :
1591 0 : void PSWriter::ImplIntersect( const tools::PolyPolygon& rPolyPoly )
1592 : {
1593 0 : sal_uInt16 i, nPolyCount = rPolyPoly.Count();
1594 0 : for ( i = 0; i < nPolyCount; )
1595 : {
1596 0 : ImplAddPath( rPolyPoly.GetObject( i ) );
1597 0 : if ( ++i < nPolyCount )
1598 : {
1599 0 : mpPS->WriteCharPtr( "p" );
1600 0 : mnCursorPos += 2;
1601 0 : ImplExecMode( PS_RET );
1602 : }
1603 : }
1604 0 : ImplWriteLine( "eoclip newpath" );
1605 0 : }
1606 :
1607 :
1608 :
1609 0 : void PSWriter::ImplWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, VirtualDevice& rVDev )
1610 : {
1611 0 : VirtualDevice l_aVDev;
1612 0 : GDIMetaFile aTmpMtf;
1613 0 : l_aVDev.SetMapMode( rVDev.GetMapMode() );
1614 0 : l_aVDev.AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
1615 0 : ImplWriteActions( aTmpMtf, rVDev );
1616 0 : }
1617 :
1618 :
1619 :
1620 0 : void PSWriter::ImplPolyPoly( const tools::PolyPolygon & rPolyPoly, bool bTextOutline )
1621 : {
1622 0 : sal_uInt16 i, nPolyCount = rPolyPoly.Count();
1623 0 : if ( nPolyCount )
1624 : {
1625 0 : if ( bFillColor || bTextOutline )
1626 : {
1627 0 : if ( bTextOutline )
1628 0 : ImplWriteTextColor( PS_SPACE );
1629 : else
1630 0 : ImplWriteFillColor( PS_SPACE );
1631 0 : for ( i = 0; i < nPolyCount; )
1632 : {
1633 0 : ImplAddPath( rPolyPoly.GetObject( i ) );
1634 0 : if ( ++i < nPolyCount )
1635 : {
1636 0 : mpPS->WriteCharPtr( "p" );
1637 0 : mnCursorPos += 2;
1638 0 : ImplExecMode( PS_RET );
1639 : }
1640 : }
1641 0 : mpPS->WriteCharPtr( "p ef" );
1642 0 : mnCursorPos += 4;
1643 0 : ImplExecMode( PS_RET );
1644 : }
1645 0 : if ( bLineColor )
1646 : {
1647 0 : ImplWriteLineColor( PS_SPACE );
1648 0 : for ( i = 0; i < nPolyCount; i++ )
1649 0 : ImplAddPath( rPolyPoly.GetObject( i ) );
1650 0 : ImplClosePathDraw( PS_RET );
1651 : }
1652 : }
1653 0 : }
1654 :
1655 :
1656 :
1657 0 : void PSWriter::ImplPolyLine( const Polygon & rPoly )
1658 : {
1659 0 : if ( bLineColor )
1660 : {
1661 0 : ImplWriteLineColor( PS_SPACE );
1662 0 : sal_uInt16 i, nPointCount = rPoly.GetSize();
1663 0 : if ( nPointCount )
1664 : {
1665 0 : if ( nPointCount > 1 )
1666 : {
1667 0 : ImplMoveTo( rPoly.GetPoint( 0 ) );
1668 0 : i = 1;
1669 0 : while ( i < nPointCount )
1670 : {
1671 0 : if ( ( rPoly.GetFlags( i ) == POLY_CONTROL )
1672 0 : && ( ( i + 2 ) < nPointCount )
1673 0 : && ( rPoly.GetFlags( i + 1 ) == POLY_CONTROL )
1674 0 : && ( rPoly.GetFlags( i + 2 ) != POLY_CONTROL ) )
1675 : {
1676 0 : ImplCurveTo( rPoly[ i ], rPoly[ i + 1 ], rPoly[ i + 2 ], PS_WRAP );
1677 0 : i += 3;
1678 : }
1679 : else
1680 0 : ImplLineTo( rPoly.GetPoint( i++ ), PS_SPACE | PS_WRAP );
1681 : }
1682 : }
1683 :
1684 : // #104645# explicitly close path if polygon is closed
1685 0 : if( rPoly[ 0 ] == rPoly[ nPointCount-1 ] )
1686 0 : ImplClosePathDraw( PS_RET );
1687 : else
1688 0 : ImplPathDraw();
1689 : }
1690 : }
1691 0 : }
1692 :
1693 :
1694 :
1695 0 : void PSWriter::ImplSetClipRegion( vcl::Region& rClipRegion )
1696 : {
1697 0 : if ( !rClipRegion.IsEmpty() )
1698 : {
1699 0 : RectangleVector aRectangles;
1700 0 : rClipRegion.GetRegionRectangles(aRectangles);
1701 :
1702 0 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
1703 : {
1704 0 : double nX1(aRectIter->Left());
1705 0 : double nY1(aRectIter->Top());
1706 0 : double nX2(aRectIter->Right());
1707 0 : double nY2(aRectIter->Bottom());
1708 :
1709 0 : ImplWriteDouble( nX1 );
1710 0 : ImplWriteDouble( nY1 );
1711 0 : ImplWriteByte( 'm' );
1712 0 : ImplWriteDouble( nX2 );
1713 0 : ImplWriteDouble( nY1 );
1714 0 : ImplWriteByte( 'l' );
1715 0 : ImplWriteDouble( nX2 );
1716 0 : ImplWriteDouble( nY2 );
1717 0 : ImplWriteByte( 'l' );
1718 0 : ImplWriteDouble( nX1 );
1719 0 : ImplWriteDouble( nY2 );
1720 0 : ImplWriteByte( 'l' );
1721 0 : ImplWriteDouble( nX1 );
1722 0 : ImplWriteDouble( nY1 );
1723 0 : ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
1724 : }
1725 :
1726 : //Rectangle aRect;
1727 : //RegionHandle hRegionHandle = rClipRegion.BeginEnumRects();
1728 : //
1729 : //while ( rClipRegion.GetEnumRects( hRegionHandle, aRect ) )
1730 : //{
1731 : // double nX1 = aRect.Left();
1732 : // double nY1 = aRect.Top();
1733 : // double nX2 = aRect.Right();
1734 : // double nY2 = aRect.Bottom();
1735 : // ImplWriteDouble( nX1 );
1736 : // ImplWriteDouble( nY1 );
1737 : // ImplWriteByte( 'm' );
1738 : // ImplWriteDouble( nX2 );
1739 : // ImplWriteDouble( nY1 );
1740 : // ImplWriteByte( 'l' );
1741 : // ImplWriteDouble( nX2 );
1742 : // ImplWriteDouble( nY2 );
1743 : // ImplWriteByte( 'l' );
1744 : // ImplWriteDouble( nX1 );
1745 : // ImplWriteDouble( nY2 );
1746 : // ImplWriteByte( 'l' );
1747 : // ImplWriteDouble( nX1 );
1748 : // ImplWriteDouble( nY1 );
1749 : // ImplWriteByte( 'l', PS_SPACE | PS_WRAP );
1750 : //};
1751 : //rClipRegion.EndEnumRects( hRegionHandle );
1752 0 : ImplWriteLine( "eoclip newpath" );
1753 : }
1754 0 : }
1755 :
1756 :
1757 : // possible gfx formats:
1758 : //
1759 : // level 1: grayscale 8 bit
1760 : // color 24 bit
1761 : //
1762 : // level 2: grayscale 8 bit
1763 : // color 1(pal), 4(pal), 8(pal), 24 Bit
1764 : //
1765 :
1766 0 : void PSWriter::ImplBmp( Bitmap* pBitmap, Bitmap* pMaskBitmap, const Point & rPoint, double nXWidth, double nYHeightOrg )
1767 : {
1768 0 : if ( !pBitmap )
1769 0 : return;
1770 :
1771 0 : sal_Int32 nHeightOrg = pBitmap->GetSizePixel().Height();
1772 0 : sal_Int32 nHeightLeft = nHeightOrg;
1773 0 : long nWidth = pBitmap->GetSizePixel().Width();
1774 0 : Point aSourcePos( rPoint );
1775 :
1776 0 : while ( nHeightLeft )
1777 : {
1778 0 : Bitmap aTileBitmap( *pBitmap );
1779 0 : long nHeight = nHeightLeft;
1780 0 : double nYHeight = nYHeightOrg;
1781 :
1782 0 : bool bDoTrans = false;
1783 :
1784 0 : Rectangle aRect;
1785 0 : vcl::Region aRegion;
1786 :
1787 0 : if ( pMaskBitmap )
1788 : {
1789 0 : bDoTrans = true;
1790 : while (true)
1791 : {
1792 0 : if ( mnLevel == 1 )
1793 : {
1794 0 : if ( nHeight > 10 )
1795 0 : nHeight = 8;
1796 : }
1797 0 : aRect = Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( (long)nWidth, (long)nHeight ) );
1798 0 : aRegion = vcl::Region( pMaskBitmap->CreateRegion( COL_BLACK, aRect ) );
1799 :
1800 0 : if( mnLevel == 1 )
1801 : {
1802 0 : RectangleVector aRectangleVector;
1803 0 : aRegion.GetRegionRectangles(aRectangleVector);
1804 :
1805 0 : if ( aRectangleVector.size() * 5 > 1000 )
1806 : {
1807 0 : nHeight >>= 1;
1808 0 : if ( nHeight < 2 )
1809 0 : return;
1810 0 : continue;
1811 0 : }
1812 : }
1813 0 : break;
1814 0 : }
1815 : }
1816 0 : if ( nHeight != nHeightOrg )
1817 : {
1818 0 : nYHeight = nYHeightOrg * nHeight / nHeightOrg;
1819 0 : aTileBitmap.Crop( Rectangle( Point( 0, nHeightOrg - nHeightLeft ), Size( nWidth, nHeight ) ) );
1820 : }
1821 0 : if ( bDoTrans )
1822 : {
1823 0 : ImplWriteLine( "gs\npum" );
1824 0 : ImplTranslate( aSourcePos.X(), aSourcePos.Y() );
1825 0 : ImplScale( nXWidth / nWidth, nYHeight / nHeight );
1826 :
1827 0 : RectangleVector aRectangles;
1828 0 : aRegion.GetRegionRectangles(aRectangles);
1829 0 : const long nMoveVertical(nHeightLeft - nHeightOrg);
1830 :
1831 0 : for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
1832 : {
1833 0 : aRectIter->Move(0, nMoveVertical);
1834 :
1835 0 : ImplWriteLong( aRectIter->Left() );
1836 0 : ImplWriteLong( aRectIter->Top() );
1837 0 : ImplWriteByte( 'm' );
1838 0 : ImplWriteLong( aRectIter->Right() + 1 );
1839 0 : ImplWriteLong( aRectIter->Top() );
1840 0 : ImplWriteByte( 'l' );
1841 0 : ImplWriteLong( aRectIter->Right() + 1 );
1842 0 : ImplWriteLong( aRectIter->Bottom() + 1 );
1843 0 : ImplWriteByte( 'l' );
1844 0 : ImplWriteLong( aRectIter->Left() );
1845 0 : ImplWriteLong( aRectIter->Bottom() + 1 );
1846 0 : ImplWriteByte( 'l' );
1847 0 : ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
1848 : }
1849 :
1850 : //RegionHandle hRegionHandle = aRegion.BeginEnumRects();
1851 : //
1852 : //while ( aRegion.GetEnumRects( hRegionHandle, aRect ) )
1853 : //{
1854 : // aRect.Move( 0, - ( nHeightOrg - nHeightLeft ) );
1855 : // ImplWriteLong( aRect.Left() );
1856 : // ImplWriteLong( aRect.Top() );
1857 : // ImplWriteByte( 'm' );
1858 : // ImplWriteLong( aRect.Right() + 1 );
1859 : // ImplWriteLong( aRect.Top() );
1860 : // ImplWriteByte( 'l' );
1861 : // ImplWriteLong( aRect.Right() + 1 );
1862 : // ImplWriteLong( aRect.Bottom() + 1 );
1863 : // ImplWriteByte( 'l' );
1864 : // ImplWriteLong( aRect.Left() );
1865 : // ImplWriteLong( aRect.Bottom() + 1 );
1866 : // ImplWriteByte( 'l' );
1867 : // ImplWriteByte( 'p', PS_SPACE | PS_WRAP );
1868 : //};
1869 : //aRegion.EndEnumRects( hRegionHandle );
1870 0 : ImplWriteLine( "eoclip newpath" );
1871 0 : ImplWriteLine( "pom" );
1872 : }
1873 0 : BitmapReadAccess* pAcc = aTileBitmap.AcquireReadAccess();
1874 :
1875 0 : if (!bDoTrans )
1876 0 : ImplWriteLine( "pum" );
1877 :
1878 0 : ImplTranslate( aSourcePos.X(), aSourcePos.Y() + nYHeight );
1879 0 : ImplScale( nXWidth, nYHeight );
1880 0 : if ( mnLevel == 1 ) // level 1 is always grayscale !!!
1881 : {
1882 0 : ImplWriteLong( nWidth );
1883 0 : ImplWriteLong( nHeight );
1884 0 : mpPS->WriteCharPtr( "8 [" );
1885 0 : ImplWriteLong( nWidth );
1886 0 : mpPS->WriteCharPtr( "0 0 " );
1887 0 : ImplWriteLong( -nHeight );
1888 0 : ImplWriteLong( 0 );
1889 0 : ImplWriteLong( nHeight );
1890 0 : ImplWriteLine( "]" );
1891 0 : mpPS->WriteCharPtr( "{currentfile " );
1892 0 : ImplWriteLong( nWidth );
1893 0 : ImplWriteLine( "string readhexstring pop}" );
1894 0 : ImplWriteLine( "image" );
1895 0 : for ( long y = 0; y < nHeight; y++ )
1896 : {
1897 0 : for ( long x = 0; x < nWidth; x++ )
1898 : {
1899 0 : ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
1900 : }
1901 : }
1902 0 : mpPS->WriteUChar( 10 );
1903 : }
1904 : else // Level 2
1905 : {
1906 0 : if ( mbGrayScale )
1907 : {
1908 0 : ImplWriteLine( "/DeviceGray setcolorspace" );
1909 0 : ImplWriteLine( "<<" );
1910 0 : ImplWriteLine( "/ImageType 1" );
1911 0 : mpPS->WriteCharPtr( "/Width " );
1912 0 : ImplWriteLong( nWidth, PS_RET );
1913 0 : mpPS->WriteCharPtr( "/Height " );
1914 0 : ImplWriteLong( nHeight, PS_RET );
1915 0 : ImplWriteLine( "/BitsPerComponent 8" );
1916 0 : ImplWriteLine( "/Decode[0 1]" );
1917 0 : mpPS->WriteCharPtr( "/ImageMatrix[" );
1918 0 : ImplWriteLong( nWidth );
1919 0 : mpPS->WriteCharPtr( "0 0 " );
1920 0 : ImplWriteLong( -nHeight );
1921 0 : ImplWriteLong( 0 );
1922 0 : ImplWriteLong( nHeight, PS_NONE );
1923 0 : ImplWriteByte( ']', PS_RET );
1924 0 : ImplWriteLine( "/DataSource currentfile" );
1925 0 : ImplWriteLine( "/ASCIIHexDecode filter" );
1926 0 : if ( mbCompression )
1927 0 : ImplWriteLine( "/LZWDecode filter" );
1928 0 : ImplWriteLine( ">>" );
1929 0 : ImplWriteLine( "image" );
1930 0 : if ( mbCompression )
1931 : {
1932 0 : StartCompression();
1933 0 : for ( long y = 0; y < nHeight; y++ )
1934 : {
1935 0 : for ( long x = 0; x < nWidth; x++ )
1936 : {
1937 0 : Compress( pAcc->GetPixelIndex( y, x ) );
1938 : }
1939 : }
1940 0 : EndCompression();
1941 : }
1942 : else
1943 : {
1944 0 : for ( long y = 0; y < nHeight; y++ )
1945 : {
1946 0 : for ( long x = 0; x < nWidth; x++ )
1947 : {
1948 0 : ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
1949 : }
1950 : }
1951 : }
1952 : }
1953 : else
1954 : {
1955 : // have we to write a palette ?
1956 :
1957 0 : if ( pAcc->HasPalette() )
1958 : {
1959 0 : ImplWriteLine( "[/Indexed /DeviceRGB " );
1960 0 : ImplWriteLong( pAcc->GetPaletteEntryCount() - 1, PS_RET );
1961 0 : ImplWriteByte( '<', PS_NONE );
1962 0 : for ( sal_uInt16 i = 0; i < pAcc->GetPaletteEntryCount(); i++ )
1963 : {
1964 0 : BitmapColor aBitmapColor = pAcc->GetPaletteColor( i );
1965 0 : ImplWriteHexByte( aBitmapColor.GetRed(), PS_NONE );
1966 0 : ImplWriteHexByte( aBitmapColor.GetGreen(), PS_NONE );
1967 0 : ImplWriteHexByte( aBitmapColor.GetBlue(), PS_SPACE | PS_WRAP );
1968 0 : }
1969 0 : ImplWriteByte( '>', PS_RET );
1970 :
1971 0 : ImplWriteLine( "] setcolorspace" );
1972 0 : ImplWriteLine( "<<" );
1973 0 : ImplWriteLine( "/ImageType 1" );
1974 0 : mpPS->WriteCharPtr( "/Width " );
1975 0 : ImplWriteLong( nWidth, PS_RET );
1976 0 : mpPS->WriteCharPtr( "/Height " );
1977 0 : ImplWriteLong( nHeight, PS_RET );
1978 0 : ImplWriteLine( "/BitsPerComponent 8" );
1979 0 : ImplWriteLine( "/Decode[0 255]" );
1980 0 : mpPS->WriteCharPtr( "/ImageMatrix[" );
1981 0 : ImplWriteLong( nWidth );
1982 0 : mpPS->WriteCharPtr( "0 0 " );
1983 0 : ImplWriteLong( -nHeight );
1984 0 : ImplWriteLong( 0);
1985 0 : ImplWriteLong( nHeight, PS_NONE );
1986 0 : ImplWriteByte( ']', PS_RET );
1987 0 : ImplWriteLine( "/DataSource currentfile" );
1988 0 : ImplWriteLine( "/ASCIIHexDecode filter" );
1989 0 : if ( mbCompression )
1990 0 : ImplWriteLine( "/LZWDecode filter" );
1991 0 : ImplWriteLine( ">>" );
1992 0 : ImplWriteLine( "image" );
1993 0 : if ( mbCompression )
1994 : {
1995 0 : StartCompression();
1996 0 : for ( long y = 0; y < nHeight; y++ )
1997 : {
1998 0 : for ( long x = 0; x < nWidth; x++ )
1999 : {
2000 0 : Compress( pAcc->GetPixelIndex( y, x ) );
2001 : }
2002 : }
2003 0 : EndCompression();
2004 : }
2005 : else
2006 : {
2007 0 : for ( long y = 0; y < nHeight; y++ )
2008 : {
2009 0 : for ( long x = 0; x < nWidth; x++ )
2010 : {
2011 0 : ImplWriteHexByte( pAcc->GetPixelIndex( y, x ) );
2012 : }
2013 : }
2014 : }
2015 : }
2016 : else // 24 bit color
2017 : {
2018 0 : ImplWriteLine( "/DeviceRGB setcolorspace" );
2019 0 : ImplWriteLine( "<<" );
2020 0 : ImplWriteLine( "/ImageType 1" );
2021 0 : mpPS->WriteCharPtr( "/Width " );
2022 0 : ImplWriteLong( nWidth, PS_RET );
2023 0 : mpPS->WriteCharPtr( "/Height " );
2024 0 : ImplWriteLong( nHeight, PS_RET );
2025 0 : ImplWriteLine( "/BitsPerComponent 8" );
2026 0 : ImplWriteLine( "/Decode[0 1 0 1 0 1]" );
2027 0 : mpPS->WriteCharPtr( "/ImageMatrix[" );
2028 0 : ImplWriteLong( nWidth );
2029 0 : mpPS->WriteCharPtr( "0 0 " );
2030 0 : ImplWriteLong( -nHeight );
2031 0 : ImplWriteLong( 0 );
2032 0 : ImplWriteLong( nHeight, PS_NONE );
2033 0 : ImplWriteByte( ']', PS_RET );
2034 0 : ImplWriteLine( "/DataSource currentfile" );
2035 0 : ImplWriteLine( "/ASCIIHexDecode filter" );
2036 0 : if ( mbCompression )
2037 0 : ImplWriteLine( "/LZWDecode filter" );
2038 0 : ImplWriteLine( ">>" );
2039 0 : ImplWriteLine( "image" );
2040 0 : if ( mbCompression )
2041 : {
2042 0 : StartCompression();
2043 0 : for ( long y = 0; y < nHeight; y++ )
2044 : {
2045 0 : for ( long x = 0; x < nWidth; x++ )
2046 : {
2047 0 : const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) );
2048 0 : Compress( aBitmapColor.GetRed() );
2049 0 : Compress( aBitmapColor.GetGreen() );
2050 0 : Compress( aBitmapColor.GetBlue() );
2051 0 : }
2052 : }
2053 0 : EndCompression();
2054 : }
2055 : else
2056 : {
2057 0 : for ( long y = 0; y < nHeight; y++ )
2058 : {
2059 0 : for ( long x = 0; x < nWidth; x++ )
2060 : {
2061 0 : const BitmapColor aBitmapColor( pAcc->GetPixel( y, x ) );
2062 0 : ImplWriteHexByte( aBitmapColor.GetRed() );
2063 0 : ImplWriteHexByte( aBitmapColor.GetGreen() );
2064 0 : ImplWriteHexByte( aBitmapColor.GetBlue() );
2065 0 : }
2066 : }
2067 : }
2068 : }
2069 : }
2070 0 : ImplWriteLine( ">" ); // in Level 2 the dictionary needs to be closed (eod)
2071 : }
2072 0 : if ( bDoTrans )
2073 0 : ImplWriteLine( "gr" );
2074 : else
2075 0 : ImplWriteLine( "pom" );
2076 :
2077 0 : aTileBitmap.ReleaseAccess( pAcc );
2078 0 : nHeightLeft -= nHeight;
2079 0 : if ( nHeightLeft )
2080 : {
2081 0 : nHeightLeft++;
2082 0 : aSourcePos.Y() = (long) ( rPoint.Y() + ( nYHeightOrg * ( nHeightOrg - nHeightLeft ) ) / nHeightOrg );
2083 : }
2084 0 : }
2085 : }
2086 :
2087 :
2088 :
2089 0 : void PSWriter::ImplWriteCharacter( sal_Char nChar )
2090 : {
2091 0 : switch( nChar )
2092 : {
2093 : case '(' :
2094 : case ')' :
2095 : case '\\' :
2096 0 : ImplWriteByte( (sal_uInt8)'\\', PS_NONE );
2097 : }
2098 0 : ImplWriteByte( (sal_uInt8)nChar, PS_NONE );
2099 0 : }
2100 :
2101 :
2102 :
2103 0 : void PSWriter::ImplWriteString( const OString& rString, VirtualDevice& rVDev, const long* pDXArry, bool bStretch )
2104 : {
2105 0 : sal_Int32 nLen = rString.getLength();
2106 0 : if ( nLen )
2107 : {
2108 0 : if ( pDXArry )
2109 : {
2110 0 : double nx = 0;
2111 :
2112 0 : for (sal_Int32 i = 0; i < nLen; ++i)
2113 : {
2114 0 : if ( i > 0 )
2115 0 : nx = pDXArry[ i - 1 ];
2116 0 : ImplWriteDouble( ( bStretch ) ? nx : rVDev.GetTextWidth( OUString(rString[i]) ) );
2117 0 : ImplWriteDouble( nx );
2118 0 : ImplWriteLine( "(", PS_NONE );
2119 0 : ImplWriteCharacter( rString[i] );
2120 0 : ImplWriteLine( ") bs" );
2121 : }
2122 : }
2123 : else
2124 : {
2125 0 : ImplWriteByte( '(', PS_NONE );
2126 0 : for (sal_Int32 i = 0; i < nLen; ++i)
2127 0 : ImplWriteCharacter( rString[i] );
2128 0 : ImplWriteLine( ") sw" );
2129 : }
2130 : }
2131 0 : }
2132 :
2133 :
2134 :
2135 0 : void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, const long* pDXArry, sal_Int32 nWidth, VirtualDevice& rVDev )
2136 : {
2137 0 : if ( rUniString.isEmpty() )
2138 0 : return;
2139 0 : if ( mnTextMode == 0 ) // using glpyh outlines
2140 : {
2141 0 : vcl::Font aNotRotatedFont( maFont );
2142 0 : aNotRotatedFont.SetOrientation( 0 );
2143 :
2144 0 : VirtualDevice aVirDev( 1 );
2145 0 : aVirDev.SetMapMode( rVDev.GetMapMode() );
2146 0 : aVirDev.SetFont( aNotRotatedFont );
2147 0 : aVirDev.SetTextAlign( eTextAlign );
2148 :
2149 0 : sal_Int16 nRotation = maFont.GetOrientation();
2150 0 : Polygon aPolyDummy( 1 );
2151 :
2152 0 : Point aPos( rPos );
2153 0 : if ( nRotation )
2154 : {
2155 0 : aPolyDummy.SetPoint( aPos, 0 );
2156 0 : aPolyDummy.Rotate( rPos, nRotation );
2157 0 : aPos = aPolyDummy.GetPoint( 0 );
2158 : }
2159 0 : bool bOldLineColor = bLineColor;
2160 0 : bLineColor = false;
2161 0 : std::vector<tools::PolyPolygon> aPolyPolyVec;
2162 0 : if ( aVirDev.GetTextOutlines( aPolyPolyVec, rUniString, 0, 0, -1, true, nWidth, pDXArry ) )
2163 : {
2164 : // always adjust text position to match baseline alignment
2165 0 : ImplWriteLine( "pum" );
2166 0 : ImplWriteDouble( aPos.X() );
2167 0 : ImplWriteDouble( aPos.Y() );
2168 0 : ImplWriteLine( "t" );
2169 0 : if ( nRotation )
2170 : {
2171 0 : ImplWriteF( nRotation, 1 );
2172 0 : mpPS->WriteCharPtr( "r " );
2173 : }
2174 0 : std::vector<tools::PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
2175 0 : while ( aIter != aPolyPolyVec.end() )
2176 0 : ImplPolyPoly( *aIter++, true );
2177 0 : ImplWriteLine( "pom" );
2178 : }
2179 0 : bLineColor = bOldLineColor;
2180 : }
2181 0 : else if ( ( mnTextMode == 1 ) || ( mnTextMode == 2 ) ) // normal text output
2182 : {
2183 0 : if ( mnTextMode == 2 ) // forcing output one complete text packet, by
2184 0 : pDXArry = NULL; // ignoring the kerning array
2185 0 : ImplSetAttrForText( rPos );
2186 : OString aStr(OUStringToOString(rUniString,
2187 0 : maFont.GetCharSet()));
2188 0 : ImplWriteString( aStr, rVDev, pDXArry, nWidth != 0 );
2189 0 : if ( maFont.GetOrientation() )
2190 0 : ImplWriteLine( "gr" );
2191 : }
2192 : }
2193 :
2194 :
2195 :
2196 0 : void PSWriter::ImplSetAttrForText( const Point& rPoint )
2197 : {
2198 0 : Point aPoint( rPoint );
2199 :
2200 0 : long nRotation = maFont.GetOrientation();
2201 0 : ImplWriteTextColor();
2202 :
2203 0 : Size aSize = maFont.GetSize();
2204 :
2205 0 : if ( maLastFont != maFont )
2206 : {
2207 0 : if ( maFont.GetPitch() == PITCH_FIXED ) // a little bit font selection
2208 0 : ImplDefineFont( "Courier", "Oblique" );
2209 0 : else if ( maFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
2210 0 : ImplWriteLine( "/Symbol findfont" );
2211 0 : else if ( maFont.GetFamily() == FAMILY_SWISS )
2212 0 : ImplDefineFont( "Helvetica", "Oblique" );
2213 : else
2214 0 : ImplDefineFont( "Times", "Italic" );
2215 :
2216 0 : maLastFont = maFont;
2217 0 : aSize = maFont.GetSize();
2218 0 : ImplWriteDouble( aSize.Height() );
2219 0 : mpPS->WriteCharPtr( "sf " );
2220 : }
2221 0 : if ( eTextAlign != ALIGN_BASELINE )
2222 : { // PostScript kennt kein FontAlignment
2223 0 : if ( eTextAlign == ALIGN_TOP ) // -> so I assume that
2224 0 : aPoint.Y() += ( aSize.Height() * 4 / 5 ); // the area under the baseline
2225 0 : else if ( eTextAlign == ALIGN_BOTTOM ) // is about 20% of the font size
2226 0 : aPoint.Y() -= ( aSize.Height() / 5 );
2227 : }
2228 0 : ImplMoveTo( aPoint );
2229 0 : if ( nRotation )
2230 : {
2231 0 : mpPS->WriteCharPtr( "gs " );
2232 0 : ImplWriteF( nRotation, 1 );
2233 0 : mpPS->WriteCharPtr( "r " );
2234 : }
2235 0 : }
2236 :
2237 :
2238 :
2239 0 : void PSWriter::ImplDefineFont( const char* pOriginalName, const char* pItalic )
2240 : {
2241 0 : mpPS->WriteUChar( '/' ); //convert the font pOriginalName using ISOLatin1Encoding
2242 0 : mpPS->WriteCharPtr( pOriginalName );
2243 0 : switch ( maFont.GetWeight() )
2244 : {
2245 : case WEIGHT_SEMIBOLD :
2246 : case WEIGHT_BOLD :
2247 : case WEIGHT_ULTRABOLD :
2248 : case WEIGHT_BLACK :
2249 0 : mpPS->WriteCharPtr( "-Bold" );
2250 0 : if ( maFont.GetItalic() != ITALIC_NONE )
2251 0 : mpPS->WriteCharPtr( pItalic );
2252 0 : break;
2253 : default:
2254 0 : if ( maFont.GetItalic() != ITALIC_NONE )
2255 0 : mpPS->WriteCharPtr( pItalic );
2256 0 : break;
2257 : }
2258 0 : ImplWriteLine( " f" );
2259 0 : }
2260 :
2261 :
2262 :
2263 :
2264 :
2265 0 : void PSWriter::ImplClosePathDraw( sal_uLong nMode )
2266 : {
2267 0 : mpPS->WriteCharPtr( "pc" );
2268 0 : mnCursorPos += 2;
2269 0 : ImplExecMode( nMode );
2270 0 : }
2271 :
2272 0 : void PSWriter::ImplPathDraw()
2273 : {
2274 0 : mpPS->WriteCharPtr( "ps" );
2275 0 : mnCursorPos += 2;
2276 0 : ImplExecMode( PS_RET );
2277 0 : }
2278 :
2279 :
2280 :
2281 0 : inline void PSWriter::ImplWriteLineColor( sal_uLong nMode )
2282 : {
2283 0 : if ( aColor != aLineColor )
2284 : {
2285 0 : aColor = aLineColor;
2286 0 : ImplWriteColor( nMode );
2287 : }
2288 0 : }
2289 0 : inline void PSWriter::ImplWriteFillColor( sal_uLong nMode )
2290 : {
2291 0 : if ( aColor != aFillColor )
2292 : {
2293 0 : aColor = aFillColor;
2294 0 : ImplWriteColor( nMode );
2295 : }
2296 0 : }
2297 0 : inline void PSWriter::ImplWriteTextColor( sal_uLong nMode )
2298 : {
2299 0 : if ( aColor != aTextColor )
2300 : {
2301 0 : aColor = aTextColor;
2302 0 : ImplWriteColor( nMode );
2303 : }
2304 0 : }
2305 :
2306 0 : void PSWriter::ImplWriteColor( sal_uLong nMode )
2307 : {
2308 0 : if ( mbGrayScale )
2309 : {
2310 : // writes the Color (grayscale) as a Number from 0.000 up to 1.000
2311 :
2312 0 : ImplWriteF( 1000 * ( (sal_uInt8)aColor.GetRed() * 77 + (sal_uInt8)aColor.GetGreen() * 151 +
2313 0 : (sal_uInt8)aColor.GetBlue() * 28 + 1 ) / 65536, 3, nMode );
2314 : }
2315 : else
2316 : {
2317 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetRed() );
2318 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetGreen() );
2319 0 : ImplWriteB1 ( (sal_uInt8)aColor.GetBlue() );
2320 : }
2321 0 : mpPS->WriteCharPtr( "c" ); // ( c is defined as setrgbcolor or setgray )
2322 0 : ImplExecMode( nMode );
2323 0 : }
2324 :
2325 :
2326 :
2327 0 : double PSWriter::ImplGetScaling( const MapMode& rMapMode )
2328 : {
2329 : double nMul;
2330 0 : switch ( rMapMode.GetMapUnit() )
2331 : {
2332 : case MAP_PIXEL :
2333 : case MAP_SYSFONT :
2334 : case MAP_APPFONT :
2335 :
2336 : case MAP_100TH_MM :
2337 0 : nMul = 1;
2338 0 : break;
2339 : case MAP_10TH_MM :
2340 0 : nMul = 10;
2341 0 : break;
2342 : case MAP_MM :
2343 0 : nMul = 100;
2344 0 : break;
2345 : case MAP_CM :
2346 0 : nMul = 1000;
2347 0 : break;
2348 : case MAP_1000TH_INCH :
2349 0 : nMul = 2.54;
2350 0 : break;
2351 : case MAP_100TH_INCH :
2352 0 : nMul = 25.4;
2353 0 : break;
2354 : case MAP_10TH_INCH :
2355 0 : nMul = 254;
2356 0 : break;
2357 : case MAP_INCH :
2358 0 : nMul = 2540;
2359 0 : break;
2360 : case MAP_TWIP :
2361 0 : nMul = 1.76388889;
2362 0 : break;
2363 : case MAP_POINT :
2364 0 : nMul = 35.27777778;
2365 0 : break;
2366 : default:
2367 0 : nMul = 1.0;
2368 0 : break;
2369 : }
2370 0 : return nMul;
2371 : }
2372 :
2373 :
2374 :
2375 0 : void PSWriter::ImplGetMapMode( const MapMode& rMapMode )
2376 : {
2377 0 : ImplWriteLine( "tm setmatrix" );
2378 0 : double fMul = ImplGetScaling( rMapMode );
2379 0 : double fScaleX = (double)rMapMode.GetScaleX() * fMul;
2380 0 : double fScaleY = (double)rMapMode.GetScaleY() * fMul;
2381 0 : ImplTranslate( rMapMode.GetOrigin().X() * fScaleX, rMapMode.GetOrigin().Y() * fScaleY );
2382 0 : ImplScale( fScaleX, fScaleY );
2383 0 : }
2384 :
2385 :
2386 :
2387 0 : inline void PSWriter::ImplExecMode( sal_uLong nMode )
2388 : {
2389 0 : if ( nMode & PS_WRAP )
2390 : {
2391 0 : if ( mnCursorPos >= PS_LINESIZE )
2392 : {
2393 0 : mnCursorPos = 0;
2394 0 : mpPS->WriteUChar( 0xa );
2395 0 : return;
2396 : }
2397 : }
2398 0 : if ( nMode & PS_SPACE )
2399 : {
2400 0 : mpPS->WriteUChar( 32 );
2401 0 : mnCursorPos++;
2402 : }
2403 0 : if ( nMode & PS_RET )
2404 : {
2405 0 : mpPS->WriteUChar( 0xa );
2406 0 : mnCursorPos = 0;
2407 : }
2408 : }
2409 :
2410 :
2411 :
2412 0 : inline void PSWriter::ImplWriteLine( const char* pString, sal_uLong nMode )
2413 : {
2414 0 : sal_uLong i = 0;
2415 0 : while ( pString[ i ] )
2416 : {
2417 0 : mpPS->WriteUChar( pString[ i++ ] );
2418 : }
2419 0 : mnCursorPos += i;
2420 0 : ImplExecMode( nMode );
2421 0 : }
2422 :
2423 :
2424 :
2425 0 : void PSWriter::ImplWriteLineInfo( double fLWidth, double fMLimit,
2426 : SvtGraphicStroke::CapType eLCap,
2427 : SvtGraphicStroke::JoinType eJoin,
2428 : SvtGraphicStroke::DashArray& rLDash )
2429 : {
2430 0 : if ( fLineWidth != fLWidth )
2431 : {
2432 0 : fLineWidth = fLWidth;
2433 0 : ImplWriteDouble( fLineWidth );
2434 0 : ImplWriteLine( "lw", PS_SPACE );
2435 : }
2436 0 : if ( eLineCap != eLCap )
2437 : {
2438 0 : eLineCap = eLCap;
2439 0 : ImplWriteLong( (sal_Int32)eLineCap, PS_SPACE );
2440 0 : ImplWriteLine( "lc", PS_SPACE );
2441 : }
2442 0 : if ( eJoinType != eJoin )
2443 : {
2444 0 : eJoinType = eJoin;
2445 0 : ImplWriteLong( (sal_Int32)eJoinType, PS_SPACE );
2446 0 : ImplWriteLine( "lj", PS_SPACE );
2447 : }
2448 0 : if ( eJoinType == SvtGraphicStroke::joinMiter )
2449 : {
2450 0 : if ( fMiterLimit != fMLimit )
2451 : {
2452 0 : fMiterLimit = fMLimit;
2453 0 : ImplWriteDouble( fMiterLimit );
2454 0 : ImplWriteLine( "ml", PS_SPACE );
2455 : }
2456 : }
2457 0 : if ( aDashArray != rLDash )
2458 : {
2459 0 : aDashArray = rLDash;
2460 0 : sal_uInt32 j, i = aDashArray.size();
2461 0 : ImplWriteLine( "[", PS_SPACE );
2462 0 : for ( j = 0; j < i; j++ )
2463 0 : ImplWriteDouble( aDashArray[ j ] );
2464 0 : ImplWriteLine( "] 0 ld" );
2465 : }
2466 0 : }
2467 :
2468 :
2469 :
2470 0 : void PSWriter::ImplWriteLineInfo( const LineInfo& rLineInfo )
2471 : {
2472 0 : SvtGraphicStroke::DashArray l_aDashArray;
2473 0 : if ( rLineInfo.GetStyle() == LINE_DASH )
2474 0 : l_aDashArray.push_back( 2 );
2475 0 : const double fLWidth(( ( rLineInfo.GetWidth() + 1 ) + ( rLineInfo.GetWidth() + 1 ) ) * 0.5);
2476 0 : SvtGraphicStroke::JoinType aJoinType(SvtGraphicStroke::joinMiter);
2477 0 : SvtGraphicStroke::CapType aCapType(SvtGraphicStroke::capButt);
2478 :
2479 0 : switch(rLineInfo.GetLineJoin())
2480 : {
2481 : default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
2482 : // do NOT use SvtGraphicStroke::joinNone here
2483 : // since it will be written as numerical value directly
2484 : // and is NOT a valid EPS value
2485 0 : break;
2486 : case basegfx::B2DLINEJOIN_MITER:
2487 0 : aJoinType = SvtGraphicStroke::joinMiter;
2488 0 : break;
2489 : case basegfx::B2DLINEJOIN_BEVEL:
2490 0 : aJoinType = SvtGraphicStroke::joinBevel;
2491 0 : break;
2492 : case basegfx::B2DLINEJOIN_ROUND:
2493 0 : aJoinType = SvtGraphicStroke::joinRound;
2494 0 : break;
2495 : }
2496 0 : switch(rLineInfo.GetLineCap())
2497 : {
2498 : default: /* com::sun::star::drawing::LineCap_BUTT */
2499 : {
2500 0 : aCapType = SvtGraphicStroke::capButt;
2501 0 : break;
2502 : }
2503 : case com::sun::star::drawing::LineCap_ROUND:
2504 : {
2505 0 : aCapType = SvtGraphicStroke::capRound;
2506 0 : break;
2507 : }
2508 : case com::sun::star::drawing::LineCap_SQUARE:
2509 : {
2510 0 : aCapType = SvtGraphicStroke::capSquare;
2511 0 : break;
2512 : }
2513 : }
2514 :
2515 0 : ImplWriteLineInfo( fLWidth, fMiterLimit, aCapType, aJoinType, l_aDashArray );
2516 0 : }
2517 :
2518 :
2519 :
2520 0 : void PSWriter::ImplWriteLong(sal_Int32 nNumber, sal_uLong nMode)
2521 : {
2522 0 : const OString aNumber(OString::number(nNumber));
2523 0 : mnCursorPos += aNumber.getLength();
2524 0 : mpPS->WriteCharPtr( aNumber.getStr() );
2525 0 : ImplExecMode(nMode);
2526 0 : }
2527 :
2528 :
2529 :
2530 0 : void PSWriter::ImplWriteDouble( double fNumber, sal_uLong nMode )
2531 : {
2532 0 : sal_Int32 nPTemp = (sal_Int32)fNumber;
2533 0 : sal_Int32 nATemp = labs( (sal_Int32)( ( fNumber - nPTemp ) * 100000 ) );
2534 :
2535 0 : if ( !nPTemp && nATemp && ( fNumber < 0.0 ) )
2536 0 : mpPS->WriteChar( '-' );
2537 :
2538 0 : const OString aNumber1(OString::number(nPTemp));
2539 0 : mpPS->WriteCharPtr( aNumber1.getStr() );
2540 0 : mnCursorPos += aNumber1.getLength();
2541 :
2542 0 : if ( nATemp )
2543 : {
2544 0 : int zCount = 0;
2545 0 : mpPS->WriteUChar( '.' );
2546 0 : mnCursorPos++;
2547 0 : const OString aNumber2(OString::number(nATemp));
2548 :
2549 0 : sal_Int16 n, nLen = aNumber2.getLength();
2550 0 : if ( nLen < 8 )
2551 : {
2552 0 : mnCursorPos += 6 - nLen;
2553 0 : for ( n = 0; n < ( 5 - nLen ); n++ )
2554 : {
2555 0 : mpPS->WriteUChar( '0' );
2556 : }
2557 : }
2558 0 : mnCursorPos += nLen;
2559 0 : for ( n = 0; n < nLen; n++ )
2560 : {
2561 0 : mpPS->WriteChar( aNumber2[n] );
2562 0 : zCount--;
2563 0 : if ( aNumber2[n] != '0' )
2564 0 : zCount = 0;
2565 : }
2566 0 : if ( zCount )
2567 0 : mpPS->SeekRel( zCount );
2568 : }
2569 0 : ImplExecMode( nMode );
2570 0 : }
2571 :
2572 :
2573 :
2574 : // writes the number to stream: nNumber / ( 10^nCount )
2575 :
2576 0 : void PSWriter::ImplWriteF( sal_Int32 nNumber, sal_uLong nCount, sal_uLong nMode )
2577 : {
2578 0 : if ( nNumber < 0 )
2579 : {
2580 0 : mpPS->WriteUChar( '-' );
2581 0 : nNumber = -nNumber;
2582 0 : mnCursorPos++;
2583 : }
2584 0 : const OString aScaleFactor(OString::number(nNumber));
2585 0 : sal_uLong nLen = aScaleFactor.getLength();
2586 0 : long nStSize = ( nCount + 1 ) - nLen;
2587 0 : if ( nStSize >= 1 )
2588 : {
2589 0 : mpPS->WriteUChar( '0' );
2590 0 : mnCursorPos++;
2591 : }
2592 0 : if ( nStSize >= 2 )
2593 : {
2594 0 : mpPS->WriteUChar( '.' );
2595 0 : for ( long i = 1; i < nStSize; i++ )
2596 : {
2597 0 : mpPS->WriteUChar( '0' );
2598 0 : mnCursorPos++;
2599 : }
2600 : }
2601 0 : mnCursorPos += nLen;
2602 0 : for( sal_uInt16 n = 0UL; n < nLen; n++ )
2603 : {
2604 0 : if ( n == nLen - nCount )
2605 : {
2606 0 : mpPS->WriteUChar( '.' );
2607 0 : mnCursorPos++;
2608 : }
2609 0 : mpPS->WriteChar( aScaleFactor[n] );
2610 : }
2611 0 : ImplExecMode( nMode );
2612 0 : }
2613 :
2614 :
2615 :
2616 0 : void PSWriter::ImplWriteByte( sal_uInt8 nNumb, sal_uLong nMode )
2617 : {
2618 0 : mpPS->WriteUChar( ( nNumb ) );
2619 0 : mnCursorPos++;
2620 0 : ImplExecMode( nMode );
2621 0 : }
2622 :
2623 :
2624 :
2625 0 : void PSWriter::ImplWriteHexByte( sal_uInt8 nNumb, sal_uLong nMode )
2626 : {
2627 0 : if ( ( nNumb >> 4 ) > 9 )
2628 0 : mpPS->WriteUChar( ( ( nNumb >> 4 ) + 'A' - 10 ) );
2629 : else
2630 0 : mpPS->WriteUChar( ( ( nNumb >> 4 ) + '0' ) );
2631 :
2632 0 : if ( ( nNumb & 0xf ) > 9 )
2633 0 : mpPS->WriteUChar( ( ( nNumb & 0xf ) + 'A' - 10 ) );
2634 : else
2635 0 : mpPS->WriteUChar( ( ( nNumb & 0xf ) + '0' ) );
2636 0 : mnCursorPos += 2;
2637 0 : ImplExecMode( nMode );
2638 0 : }
2639 :
2640 :
2641 :
2642 : // writes the sal_uInt8 nNumb as a Number from 0.000 up to 1.000
2643 :
2644 0 : void PSWriter::ImplWriteB1( sal_uInt8 nNumb, sal_uLong nMode )
2645 : {
2646 0 : ImplWriteF( 1000 * ( nNumb + 1 ) / 256 , 3, nMode );
2647 0 : }
2648 :
2649 :
2650 :
2651 :
2652 0 : inline void PSWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
2653 : {
2654 0 : dwShift |= ( nCode << ( nOffset - nCodeLen ) );
2655 0 : nOffset -= nCodeLen;
2656 0 : while ( nOffset < 24 )
2657 : {
2658 0 : ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2659 0 : dwShift <<= 8;
2660 0 : nOffset += 8;
2661 : }
2662 0 : if ( nCode == 257 && nOffset != 32 )
2663 0 : ImplWriteHexByte( (sal_uInt8)( dwShift >> 24 ) );
2664 0 : }
2665 :
2666 :
2667 :
2668 0 : void PSWriter::StartCompression()
2669 : {
2670 : sal_uInt16 i;
2671 0 : nDataSize = 8;
2672 :
2673 0 : nClearCode = 1 << nDataSize;
2674 0 : nEOICode = nClearCode + 1;
2675 0 : nTableSize = nEOICode + 1;
2676 0 : nCodeSize = nDataSize + 1;
2677 :
2678 0 : nOffset = 32; // number of free unused in dwShift
2679 0 : dwShift = 0;
2680 :
2681 0 : pTable = new PSLZWCTreeNode[ 4096 ];
2682 :
2683 0 : for ( i = 0; i < 4096; i++ )
2684 : {
2685 0 : pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL;
2686 0 : pTable[ i ].nValue = (sal_uInt8)( pTable[ i ].nCode = i );
2687 : }
2688 0 : pPrefix = NULL;
2689 0 : WriteBits( nClearCode, nCodeSize );
2690 0 : }
2691 :
2692 :
2693 :
2694 0 : void PSWriter::Compress( sal_uInt8 nCompThis )
2695 : {
2696 : PSLZWCTreeNode* p;
2697 : sal_uInt16 i;
2698 : sal_uInt8 nV;
2699 :
2700 0 : if( !pPrefix )
2701 : {
2702 0 : pPrefix = pTable + nCompThis;
2703 : }
2704 : else
2705 : {
2706 0 : nV = nCompThis;
2707 0 : for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother )
2708 : {
2709 0 : if ( p->nValue == nV )
2710 0 : break;
2711 : }
2712 :
2713 0 : if( p )
2714 0 : pPrefix = p;
2715 : else
2716 : {
2717 0 : WriteBits( pPrefix->nCode, nCodeSize );
2718 :
2719 0 : if ( nTableSize == 409 )
2720 : {
2721 0 : WriteBits( nClearCode, nCodeSize );
2722 :
2723 0 : for ( i = 0; i < nClearCode; i++ )
2724 0 : pTable[ i ].pFirstChild = NULL;
2725 :
2726 0 : nCodeSize = nDataSize + 1;
2727 0 : nTableSize = nEOICode + 1;
2728 : }
2729 : else
2730 : {
2731 0 : if( nTableSize == (sal_uInt16)( ( 1 << nCodeSize ) - 1 ) )
2732 0 : nCodeSize++;
2733 :
2734 0 : p = pTable + ( nTableSize++ );
2735 0 : p->pBrother = pPrefix->pFirstChild;
2736 0 : pPrefix->pFirstChild = p;
2737 0 : p->nValue = nV;
2738 0 : p->pFirstChild = NULL;
2739 : }
2740 :
2741 0 : pPrefix = pTable + nV;
2742 : }
2743 : }
2744 0 : }
2745 :
2746 :
2747 :
2748 0 : void PSWriter::EndCompression()
2749 : {
2750 0 : if( pPrefix )
2751 0 : WriteBits( pPrefix->nCode, nCodeSize );
2752 :
2753 0 : WriteBits( nEOICode, nCodeSize );
2754 0 : delete[] pTable;
2755 0 : }
2756 :
2757 :
2758 :
2759 0 : sal_uInt8* PSWriter::ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize )
2760 : {
2761 0 : while ( nComp-- >= nSize )
2762 : {
2763 : sal_uLong i;
2764 0 : for ( i = 0; i < nSize; i++ )
2765 : {
2766 0 : if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
2767 0 : break;
2768 : }
2769 0 : if ( i == nSize )
2770 0 : return pSource;
2771 0 : pSource++;
2772 : }
2773 0 : return NULL;
2774 : }
2775 :
2776 :
2777 :
2778 0 : bool PSWriter::ImplGetBoundingBox( double* nNumb, sal_uInt8* pSource, sal_uLong nSize )
2779 : {
2780 0 : bool bRetValue = false;
2781 : sal_uLong nBytesRead;
2782 :
2783 0 : if ( nSize < 256 ) // we assume that the file is greater than 256 bytes
2784 0 : return false;
2785 :
2786 0 : if ( nSize < POSTSCRIPT_BOUNDINGSEARCH )
2787 0 : nBytesRead = nSize;
2788 : else
2789 0 : nBytesRead = POSTSCRIPT_BOUNDINGSEARCH;
2790 :
2791 0 : sal_uInt8* pDest = ImplSearchEntry( pSource, (sal_uInt8*)"%%BoundingBox:", nBytesRead, 14 );
2792 0 : if ( pDest )
2793 : {
2794 0 : int nSecurityCount = 100; // only 100 bytes following the bounding box will be checked
2795 0 : nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
2796 0 : pDest += 14;
2797 0 : for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
2798 : {
2799 0 : int nDivision = 1;
2800 0 : bool bDivision = false;
2801 0 : bool bNegative = false;
2802 0 : bool bValid = true;
2803 :
2804 0 : while ( ( --nSecurityCount ) && ( ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) )
2805 0 : pDest++;
2806 0 : sal_uInt8 nByte = *pDest;
2807 0 : while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
2808 : {
2809 0 : switch ( nByte )
2810 : {
2811 : case '.' :
2812 0 : if ( bDivision )
2813 0 : bValid = false;
2814 : else
2815 0 : bDivision = true;
2816 0 : break;
2817 : case '-' :
2818 0 : bNegative = true;
2819 0 : break;
2820 : default :
2821 0 : if ( ( nByte < '0' ) || ( nByte > '9' ) )
2822 0 : nSecurityCount = 1; // error parsing the bounding box values
2823 0 : else if ( bValid )
2824 : {
2825 0 : if ( bDivision )
2826 0 : nDivision*=10;
2827 0 : nNumb[i] *= 10;
2828 0 : nNumb[i] += nByte - '0';
2829 : }
2830 0 : break;
2831 : }
2832 0 : nSecurityCount--;
2833 0 : nByte = *(++pDest);
2834 : }
2835 0 : if ( bNegative )
2836 0 : nNumb[i] = -nNumb[i];
2837 0 : if ( bDivision && ( nDivision != 1 ) )
2838 0 : nNumb[i] /= nDivision;
2839 : }
2840 0 : if ( nSecurityCount)
2841 0 : bRetValue = true;
2842 : }
2843 0 : return bRetValue;
2844 : }
2845 :
2846 : //================== GraphicExport - die exportierte Funktion ================
2847 :
2848 : // this needs to be kept in sync with
2849 : // ImpFilterLibCacheEntry::GetImportFunction() from
2850 : // vcl/source/filter/graphicfilter.cxx
2851 : #if defined(DISABLE_DYNLOADING)
2852 : #define GraphicExport epsGraphicExport
2853 : #endif
2854 :
2855 : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
2856 0 : GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem )
2857 : {
2858 0 : PSWriter aPSWriter;
2859 0 : return aPSWriter.WritePS( rGraphic, rStream, pFilterConfigItem );
2860 0 : }
2861 :
2862 :
2863 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|