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 <sal/config.h>
21 :
22 : #include <cstdlib>
23 :
24 : #include "psputil.hxx"
25 : #include "glyphset.hxx"
26 :
27 : #include "generic/printergfx.hxx"
28 : #include "generic/printerjob.hxx"
29 : #include "fontmanager.hxx"
30 : #include "vcl/strhelper.hxx"
31 : #include "vcl/printerinfomanager.hxx"
32 :
33 : #include "tools/debug.hxx"
34 : #include "tools/color.hxx"
35 : #include "tools/poly.hxx"
36 :
37 : using namespace psp ;
38 :
39 : static const sal_Int32 nMaxTextColumn = 80;
40 :
41 0 : GraphicsStatus::GraphicsStatus() :
42 : mbArtItalic( false ),
43 : mbArtBold( false ),
44 : mnTextHeight( 0 ),
45 : mnTextWidth( 0 ),
46 0 : mfLineWidth( -1 )
47 : {
48 0 : }
49 :
50 : /*
51 : * non graphics graphics routines
52 : */
53 :
54 : bool
55 0 : PrinterGfx::Init (PrinterJob &rPrinterJob)
56 : {
57 0 : mpPageHeader = rPrinterJob.GetCurrentPageHeader ();
58 0 : mpPageBody = rPrinterJob.GetCurrentPageBody ();
59 0 : mnDepth = rPrinterJob.GetDepth ();
60 0 : mnPSLevel = rPrinterJob.GetPostscriptLevel ();
61 0 : mbColor = rPrinterJob.IsColorPrinter ();
62 :
63 0 : mnDpi = rPrinterJob.GetResolution();
64 0 : rPrinterJob.GetScale (mfScaleX, mfScaleY);
65 0 : const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( rPrinterJob.GetPrinterName() ) );
66 0 : mbUploadPS42Fonts = rInfo.m_pParser ? ( rInfo.m_pParser->isType42Capable() ? true : false ) : false;
67 :
68 0 : return true;
69 : }
70 :
71 : bool
72 0 : PrinterGfx::Init (const JobData& rData)
73 : {
74 0 : mpPageHeader = NULL;
75 0 : mpPageBody = NULL;
76 0 : mnDepth = rData.m_nColorDepth;
77 0 : mnPSLevel = rData.m_nPSLevel ? rData.m_nPSLevel : (rData.m_pParser ? rData.m_pParser->getLanguageLevel() : 2 );
78 0 : mbColor = rData.m_nColorDevice ? ( rData.m_nColorDevice == -1 ? false : true ) : (( rData.m_pParser ? (rData.m_pParser->isColorDevice() ? true : false ) : true ) );
79 0 : int nRes = rData.m_aContext.getRenderResolution();
80 0 : mnDpi = nRes;
81 0 : mfScaleX = (double)72.0 / (double)mnDpi;
82 0 : mfScaleY = (double)72.0 / (double)mnDpi;
83 0 : const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( rData.m_aPrinterName ) );
84 0 : mbUploadPS42Fonts = rInfo.m_pParser ? ( rInfo.m_pParser->isType42Capable() ? true : false ) : false;
85 :
86 0 : return true;
87 : }
88 :
89 : sal_uInt16
90 0 : PrinterGfx::GetBitCount ()
91 : {
92 0 : return mnDepth;
93 : }
94 :
95 0 : PrinterGfx::PrinterGfx() :
96 : mpPageHeader (NULL),
97 : mpPageBody (NULL),
98 : mnFontID (0),
99 : mnFallbackID (0),
100 : mnTextAngle (0),
101 : mbTextVertical (false),
102 0 : mrFontMgr (PrintFontManager::get()),
103 : mbCompressBmp (true),
104 : maFillColor (0xff,0,0),
105 : maTextColor (0,0,0),
106 0 : maLineColor (0, 0xff, 0)
107 : {
108 0 : maVirtualStatus.mfLineWidth = 1.0;
109 0 : maVirtualStatus.mnTextHeight = 12;
110 0 : maVirtualStatus.mnTextWidth = 0;
111 :
112 0 : maGraphicsStack.push_back( GraphicsStatus() );
113 0 : }
114 :
115 0 : PrinterGfx::~PrinterGfx()
116 : {
117 0 : }
118 :
119 : void
120 0 : PrinterGfx::Clear()
121 : {
122 0 : mpPageHeader = NULL;
123 0 : mpPageBody = NULL;
124 0 : mnFontID = 0;
125 0 : maVirtualStatus = GraphicsStatus();
126 0 : maVirtualStatus.mnTextHeight = 12;
127 0 : maVirtualStatus.mnTextWidth = 0;
128 0 : maVirtualStatus.mfLineWidth = 1.0;
129 0 : mbTextVertical = false;
130 0 : maLineColor = PrinterColor();
131 0 : maFillColor = PrinterColor();
132 0 : maTextColor = PrinterColor();
133 0 : mbCompressBmp = true;
134 0 : mnDpi = 300;
135 0 : mnDepth = 24;
136 0 : mnPSLevel = 2;
137 0 : mbColor = true;
138 0 : mnTextAngle = 0;
139 :
140 0 : maClipRegion.clear();
141 0 : maGraphicsStack.clear();
142 0 : maGraphicsStack.push_back( GraphicsStatus() );
143 0 : }
144 :
145 : /*
146 : * clip region handling
147 : */
148 :
149 : void
150 0 : PrinterGfx::ResetClipRegion()
151 : {
152 0 : maClipRegion.clear();
153 0 : PSGRestore ();
154 0 : PSGSave (); // get "clean" clippath
155 0 : }
156 :
157 : void
158 0 : PrinterGfx::BeginSetClipRegion( sal_uInt32 )
159 : {
160 0 : maClipRegion.clear();
161 0 : }
162 :
163 : bool
164 0 : PrinterGfx::UnionClipRegion (sal_Int32 nX,sal_Int32 nY,sal_Int32 nDX,sal_Int32 nDY)
165 : {
166 0 : if( nDX && nDY )
167 0 : maClipRegion.push_back (Rectangle(Point(nX,nY ), Size(nDX,nDY)));
168 0 : return true;
169 : }
170 :
171 : bool
172 0 : PrinterGfx::JoinVerticalClipRectangles( std::list< Rectangle >::iterator& it,
173 : Point& rOldPoint, sal_Int32& rColumn )
174 : {
175 0 : bool bSuccess = false;
176 :
177 0 : std::list< Rectangle >::iterator tempit, nextit;
178 0 : nextit = it;
179 0 : ++nextit;
180 0 : std::list< Point > leftside, rightside;
181 :
182 0 : Rectangle aLastRect( *it );
183 0 : leftside.push_back( Point( it->Left(), it->Top() ) );
184 0 : rightside.push_back( Point( it->Right()+1, it->Top() ) );
185 0 : while( nextit != maClipRegion.end() )
186 : {
187 0 : tempit = nextit;
188 0 : ++tempit;
189 0 : if( nextit->Top() == aLastRect.Bottom()+1 )
190 : {
191 0 : if(
192 0 : ( nextit->Left() >= aLastRect.Left() && nextit->Left() <= aLastRect.Right() ) // left endpoint touches last rectangle
193 0 : ||
194 0 : ( nextit->Right() >= aLastRect.Left() && nextit->Right() <= aLastRect.Right() ) // right endpoint touches last rectangle
195 0 : ||
196 0 : ( nextit->Left() <= aLastRect.Left() && nextit->Right() >= aLastRect.Right() ) // whole line touches last rectangle
197 : )
198 : {
199 0 : if( aLastRect.GetHeight() > 1 ||
200 0 : std::abs( aLastRect.Left() - nextit->Left() ) > 2 ||
201 0 : std::abs( aLastRect.Right() - nextit->Right() ) > 2
202 : )
203 : {
204 0 : leftside.push_back( Point( aLastRect.Left(), aLastRect.Bottom()+1 ) );
205 0 : rightside.push_back( Point( aLastRect.Right()+1, aLastRect.Bottom()+1 ) );
206 : }
207 0 : aLastRect = *nextit;
208 0 : leftside.push_back( aLastRect.TopLeft() );
209 0 : rightside.push_back( aLastRect.TopRight() );
210 0 : maClipRegion.erase( nextit );
211 : }
212 : }
213 0 : nextit = tempit;
214 : }
215 0 : if( leftside.size() > 1 )
216 : {
217 : // push the last coordinates
218 0 : leftside.push_back( Point( aLastRect.Left(), aLastRect.Bottom()+1 ) );
219 0 : rightside.push_back( Point( aLastRect.Right()+1, aLastRect.Bottom()+1 ) );
220 :
221 : // cool, we can concatenate rectangles
222 0 : const int nDX = -65536, nDY = 65536;
223 0 : int nNewDX = 0, nNewDY = 0;
224 :
225 0 : Point aLastPoint = leftside.front();
226 0 : PSBinMoveTo (aLastPoint, rOldPoint, rColumn);
227 0 : leftside.pop_front();
228 0 : while( leftside.begin() != leftside.end() )
229 : {
230 0 : Point aPoint (leftside.front());
231 0 : leftside.pop_front();
232 : // may have been the last one
233 0 : if( leftside.begin() != leftside.end() )
234 : {
235 0 : nNewDX = aPoint.X() - aLastPoint.X();
236 0 : nNewDY = aPoint.Y() - aLastPoint.Y();
237 0 : if( nNewDX != 0 &&
238 0 : (double)nNewDY/(double)nNewDX == (double)nDY/(double)nDX )
239 0 : continue;
240 : }
241 0 : PSBinLineTo (aPoint, rOldPoint, rColumn);
242 0 : aLastPoint = aPoint;
243 : }
244 :
245 0 : aLastPoint = rightside.back();
246 0 : PSBinLineTo (aLastPoint, rOldPoint, rColumn);
247 0 : rightside.pop_back();
248 0 : while( rightside.begin() != rightside.end() )
249 : {
250 0 : Point aPoint (rightside.back());
251 0 : rightside.pop_back();
252 0 : if( rightside.begin() != rightside.end() )
253 : {
254 0 : nNewDX = aPoint.X() - aLastPoint.X();
255 0 : nNewDY = aPoint.Y() - aLastPoint.Y();
256 0 : if( nNewDX != 0 &&
257 0 : (double)nNewDY/(double)nNewDX == (double)nDY/(double)nDX )
258 0 : continue;
259 : }
260 0 : PSBinLineTo (aPoint, rOldPoint, rColumn);
261 : }
262 :
263 0 : tempit = it;
264 0 : ++tempit;
265 0 : maClipRegion.erase( it );
266 0 : it = tempit;
267 0 : bSuccess = true;
268 : }
269 0 : return bSuccess;
270 : }
271 :
272 : void
273 0 : PrinterGfx::EndSetClipRegion()
274 : {
275 0 : PSGRestore ();
276 0 : PSGSave (); // get "clean" clippath
277 :
278 0 : PSBinStartPath ();
279 0 : Point aOldPoint (0, 0);
280 0 : sal_Int32 nColumn = 0;
281 :
282 0 : std::list< Rectangle >::iterator it = maClipRegion.begin();
283 0 : while( it != maClipRegion.end() )
284 : {
285 : // try to concatenate adjacent rectangles
286 : // first try in y direction, then in x direction
287 0 : if( ! JoinVerticalClipRectangles( it, aOldPoint, nColumn ) )
288 : {
289 : // failed, so it is a single rectangle
290 0 : PSBinMoveTo (it->TopLeft(), aOldPoint, nColumn );
291 0 : PSBinLineTo (Point( it->Left(), it->Bottom()+1 ), aOldPoint, nColumn );
292 0 : PSBinLineTo (Point( it->Right()+1, it->Bottom()+1 ), aOldPoint, nColumn );
293 0 : PSBinLineTo (Point( it->Right()+1, it->Top() ), aOldPoint, nColumn );
294 0 : ++it;
295 : }
296 : }
297 :
298 0 : PSBinEndPath ();
299 :
300 0 : WritePS (mpPageBody, "closepath clip newpath\n");
301 0 : maClipRegion.clear();
302 0 : }
303 :
304 : /*
305 : * draw graphic primitives
306 : */
307 :
308 : void
309 0 : PrinterGfx::DrawRect (const Rectangle& rRectangle )
310 : {
311 : char pRect [128];
312 0 : sal_Int32 nChar = 0;
313 :
314 0 : nChar = psp::getValueOf (rRectangle.TopLeft().X(), pRect);
315 0 : nChar += psp::appendStr (" ", pRect + nChar);
316 0 : nChar += psp::getValueOf (rRectangle.TopLeft().Y(), pRect + nChar);
317 0 : nChar += psp::appendStr (" ", pRect + nChar);
318 0 : nChar += psp::getValueOf (rRectangle.GetWidth(), pRect + nChar);
319 0 : nChar += psp::appendStr (" ", pRect + nChar);
320 0 : nChar += psp::getValueOf (rRectangle.GetHeight(), pRect + nChar);
321 0 : nChar += psp::appendStr (" ", pRect + nChar);
322 :
323 0 : if( maFillColor.Is() )
324 : {
325 0 : PSSetColor (maFillColor);
326 0 : PSSetColor ();
327 0 : WritePS (mpPageBody, pRect, nChar);
328 0 : WritePS (mpPageBody, "rectfill\n");
329 : }
330 0 : if( maLineColor.Is() )
331 : {
332 0 : PSSetColor (maLineColor);
333 0 : PSSetColor ();
334 0 : PSSetLineWidth ();
335 0 : WritePS (mpPageBody, pRect, nChar);
336 0 : WritePS (mpPageBody, "rectstroke\n");
337 : }
338 0 : }
339 :
340 : void
341 0 : PrinterGfx::DrawLine (const Point& rFrom, const Point& rTo)
342 : {
343 0 : if( maLineColor.Is() )
344 : {
345 0 : PSSetColor (maLineColor);
346 0 : PSSetColor ();
347 0 : PSSetLineWidth ();
348 :
349 0 : PSMoveTo (rFrom);
350 0 : PSLineTo (rTo);
351 0 : WritePS (mpPageBody, "stroke\n" );
352 : }
353 0 : }
354 :
355 : void
356 0 : PrinterGfx::DrawPixel (const Point& rPoint, const PrinterColor& rPixelColor)
357 : {
358 0 : if( rPixelColor.Is() )
359 : {
360 0 : PSSetColor (rPixelColor);
361 0 : PSSetColor ();
362 :
363 0 : PSMoveTo (rPoint);
364 0 : PSLineTo (Point (rPoint.X ()+1, rPoint.Y ()));
365 0 : PSLineTo (Point (rPoint.X ()+1, rPoint.Y ()+1));
366 0 : PSLineTo (Point (rPoint.X (), rPoint.Y ()+1));
367 0 : WritePS (mpPageBody, "fill\n" );
368 : }
369 0 : }
370 :
371 : void
372 0 : PrinterGfx::DrawPolyLine (sal_uInt32 nPoints, const Point* pPath)
373 : {
374 0 : if( maLineColor.Is() && nPoints && pPath )
375 : {
376 0 : PSSetColor (maLineColor);
377 0 : PSSetColor ();
378 0 : PSSetLineWidth ();
379 :
380 0 : PSBinCurrentPath (nPoints, pPath);
381 :
382 0 : WritePS (mpPageBody, "stroke\n" );
383 : }
384 0 : }
385 :
386 : void
387 0 : PrinterGfx::DrawPolygon (sal_uInt32 nPoints, const Point* pPath)
388 : {
389 : // premature end of operation
390 0 : if (!(nPoints > 1) || (pPath == NULL) || !(maFillColor.Is() || maLineColor.Is()))
391 0 : return;
392 :
393 : // setup closed path
394 0 : Point aPoint( 0, 0 );
395 0 : sal_Int32 nColumn( 0 );
396 :
397 0 : PSBinStartPath();
398 0 : PSBinMoveTo( pPath[0], aPoint, nColumn );
399 0 : for( unsigned int n = 1; n < nPoints; n++ )
400 0 : PSBinLineTo( pPath[n], aPoint, nColumn );
401 0 : if( pPath[0] != pPath[nPoints-1] )
402 0 : PSBinLineTo( pPath[0], aPoint, nColumn );
403 0 : PSBinEndPath();
404 :
405 : // fill the polygon first, then draw the border, note that fill and
406 : // stroke reset the currentpath
407 :
408 : // if fill and stroke, save the current path
409 0 : if( maFillColor.Is() && maLineColor.Is())
410 0 : PSGSave();
411 :
412 0 : if (maFillColor.Is ())
413 : {
414 0 : PSSetColor (maFillColor);
415 0 : PSSetColor ();
416 0 : WritePS (mpPageBody, "eofill\n");
417 : }
418 :
419 : // restore the current path
420 0 : if( maFillColor.Is() && maLineColor.Is())
421 0 : PSGRestore();
422 :
423 0 : if (maLineColor.Is ())
424 : {
425 0 : PSSetColor (maLineColor);
426 0 : PSSetColor ();
427 0 : PSSetLineWidth ();
428 0 : WritePS (mpPageBody, "stroke\n");
429 : }
430 : }
431 :
432 : void
433 0 : PrinterGfx::DrawPolyPolygon (sal_uInt32 nPoly, const sal_uInt32* pSizes, const Point** pPaths )
434 : {
435 : // sanity check
436 0 : if ( !nPoly || !pPaths || !(maFillColor.Is() || maLineColor.Is()))
437 0 : return;
438 :
439 : // setup closed path
440 0 : for( unsigned int i = 0; i < nPoly; i++ )
441 : {
442 0 : Point aPoint( 0, 0 );
443 0 : sal_Int32 nColumn( 0 );
444 :
445 0 : PSBinStartPath();
446 0 : PSBinMoveTo( pPaths[i][0], aPoint, nColumn );
447 0 : for( unsigned int n = 1; n < pSizes[i]; n++ )
448 0 : PSBinLineTo( pPaths[i][n], aPoint, nColumn );
449 0 : if( pPaths[i][0] != pPaths[i][pSizes[i]-1] )
450 0 : PSBinLineTo( pPaths[i][0], aPoint, nColumn );
451 0 : PSBinEndPath();
452 : }
453 :
454 : // if eofill and stroke, save the current path
455 0 : if( maFillColor.Is() && maLineColor.Is())
456 0 : PSGSave();
457 :
458 : // first draw area
459 0 : if( maFillColor.Is() )
460 : {
461 0 : PSSetColor (maFillColor);
462 0 : PSSetColor ();
463 0 : WritePS (mpPageBody, "eofill\n");
464 : }
465 :
466 : // restore the current path
467 0 : if( maFillColor.Is() && maLineColor.Is())
468 0 : PSGRestore();
469 :
470 : // now draw outlines
471 0 : if( maLineColor.Is() )
472 : {
473 0 : PSSetColor (maLineColor);
474 0 : PSSetColor ();
475 0 : PSSetLineWidth ();
476 0 : WritePS (mpPageBody, "stroke\n");
477 : }
478 : }
479 :
480 : /*
481 : * Bezier Polygon Drawing methods.
482 : */
483 :
484 : void
485 0 : PrinterGfx::DrawPolyLineBezier (sal_uInt32 nPoints, const Point* pPath, const sal_uInt8* pFlgAry)
486 : {
487 0 : const sal_uInt32 nBezString= 1024;
488 : sal_Char pString[nBezString];
489 :
490 0 : if ( nPoints > 1 && maLineColor.Is() && pPath )
491 : {
492 0 : PSSetColor (maLineColor);
493 0 : PSSetColor ();
494 0 : PSSetLineWidth ();
495 :
496 0 : snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y());
497 0 : WritePS(mpPageBody, pString);
498 :
499 : // Handle the drawing of mixed lines mixed with curves
500 : // - a normal point followed by a normal point is a line
501 : // - a normal point followed by 2 control points and a normal point is a curve
502 0 : for (unsigned int i=1; i<nPoints;)
503 : {
504 0 : if (pFlgAry[i] != POLY_CONTROL) //If the next point is a POLY_NORMAL, we're drawing a line
505 : {
506 0 : snprintf(pString, nBezString, "%li %li lineto\n", pPath[i].X(), pPath[i].Y());
507 0 : i++;
508 : }
509 : else //Otherwise we're drawing a spline
510 : {
511 0 : if (i+2 >= nPoints)
512 0 : return; //Error: wrong sequence of contol/normal points somehow
513 0 : if ((pFlgAry[i] == POLY_CONTROL) && (pFlgAry[i+1] == POLY_CONTROL) &&
514 0 : (pFlgAry[i+2] != POLY_CONTROL))
515 : {
516 : snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n",
517 : pPath[i].X(), pPath[i].Y(),
518 : pPath[i+1].X(), pPath[i+1].Y(),
519 0 : pPath[i+2].X(), pPath[i+2].Y());
520 : }
521 : else
522 : {
523 : OSL_FAIL( "PrinterGfx::DrawPolyLineBezier: Strange output" );
524 : }
525 0 : i+=3;
526 : }
527 0 : WritePS(mpPageBody, pString);
528 : }
529 :
530 : // now draw outlines
531 0 : WritePS (mpPageBody, "stroke\n");
532 : }
533 : }
534 :
535 : void
536 0 : PrinterGfx::DrawPolygonBezier (sal_uInt32 nPoints, const Point* pPath, const sal_uInt8* pFlgAry)
537 : {
538 0 : const sal_uInt32 nBezString = 1024;
539 : sal_Char pString[nBezString];
540 : // premature end of operation
541 0 : if (!(nPoints > 1) || (pPath == NULL) || !(maFillColor.Is() || maLineColor.Is()))
542 0 : return;
543 :
544 0 : snprintf(pString, nBezString, "%li %li moveto\n", pPath[0].X(), pPath[0].Y());
545 0 : WritePS(mpPageBody, pString); //Move to the starting point for the PolyPoygon
546 0 : for (unsigned int i=1; i < nPoints;)
547 : {
548 0 : if (pFlgAry[i] != POLY_CONTROL)
549 : {
550 0 : snprintf(pString, nBezString, "%li %li lineto\n", pPath[i].X(), pPath[i].Y());
551 0 : WritePS(mpPageBody, pString);
552 0 : i++;
553 : }
554 : else
555 : {
556 0 : if (i+2 >= nPoints)
557 0 : return; //Error: wrong sequence of contol/normal points somehow
558 0 : if ((pFlgAry[i] == POLY_CONTROL) && (pFlgAry[i+1] == POLY_CONTROL) &&
559 0 : (pFlgAry[i+2] != POLY_CONTROL))
560 : {
561 : snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n",
562 : pPath[i].X(), pPath[i].Y(),
563 : pPath[i+1].X(), pPath[i+1].Y(),
564 0 : pPath[i+2].X(), pPath[i+2].Y());
565 0 : WritePS(mpPageBody, pString);
566 : }
567 : else
568 : {
569 : OSL_FAIL( "PrinterGfx::DrawPolygonBezier: Strange output" );
570 : }
571 0 : i+=3;
572 : }
573 : }
574 :
575 : // if fill and stroke, save the current path
576 0 : if( maFillColor.Is() && maLineColor.Is())
577 0 : PSGSave();
578 :
579 0 : if (maFillColor.Is ())
580 : {
581 0 : PSSetColor (maFillColor);
582 0 : PSSetColor ();
583 0 : WritePS (mpPageBody, "eofill\n");
584 : }
585 :
586 : // restore the current path
587 0 : if( maFillColor.Is() && maLineColor.Is())
588 0 : PSGRestore();
589 : }
590 :
591 : void
592 0 : PrinterGfx::DrawPolyPolygonBezier (sal_uInt32 nPoly, const sal_uInt32 * pPoints, const Point* const * pPtAry, const sal_uInt8* const* pFlgAry)
593 : {
594 0 : const sal_uInt32 nBezString = 1024;
595 : sal_Char pString[nBezString];
596 0 : if ( !nPoly || !pPtAry || !pPoints || !(maFillColor.Is() || maLineColor.Is()))
597 0 : return;
598 :
599 0 : for (unsigned int i=0; i<nPoly;i++)
600 : {
601 0 : sal_uInt32 nPoints = pPoints[i];
602 : // sanity check
603 0 : if( nPoints == 0 || pPtAry[i] == NULL )
604 0 : continue;
605 :
606 0 : snprintf(pString, nBezString, "%li %li moveto\n", pPtAry[i][0].X(), pPtAry[i][0].Y()); //Move to the starting point
607 0 : WritePS(mpPageBody, pString);
608 0 : for (unsigned int j=1; j < nPoints;)
609 : {
610 : // if no flag array exists for this polygon, then it must be a regular
611 : // polygon without beziers
612 0 : if ( ! pFlgAry[i] || pFlgAry[i][j] != POLY_CONTROL)
613 : {
614 0 : snprintf(pString, nBezString, "%li %li lineto\n", pPtAry[i][j].X(), pPtAry[i][j].Y());
615 0 : WritePS(mpPageBody, pString);
616 0 : j++;
617 : }
618 : else
619 : {
620 0 : if (j+2 >= nPoints)
621 0 : break; //Error: wrong sequence of contol/normal points somehow
622 0 : if ((pFlgAry[i][j] == POLY_CONTROL) && (pFlgAry[i][j+1] == POLY_CONTROL) && (pFlgAry[i][j+2] != POLY_CONTROL))
623 : {
624 : snprintf(pString, nBezString, "%li %li %li %li %li %li curveto\n",
625 0 : pPtAry[i][j].X(), pPtAry[i][j].Y(),
626 0 : pPtAry[i][j+1].X(), pPtAry[i][j+1].Y(),
627 0 : pPtAry[i][j+2].X(), pPtAry[i][j+2].Y());
628 0 : WritePS(mpPageBody, pString);
629 : }
630 : else
631 : {
632 : OSL_FAIL( "PrinterGfx::DrawPolyPolygonBezier: Strange output" );
633 : }
634 0 : j+=3;
635 : }
636 : }
637 : }
638 :
639 : // if fill and stroke, save the current path
640 0 : if( maFillColor.Is() && maLineColor.Is())
641 0 : PSGSave();
642 :
643 0 : if (maFillColor.Is ())
644 : {
645 0 : PSSetColor (maFillColor);
646 0 : PSSetColor ();
647 0 : WritePS (mpPageBody, "eofill\n");
648 : }
649 :
650 : // restore the current path
651 0 : if( maFillColor.Is() && maLineColor.Is())
652 0 : PSGRestore();
653 : }
654 :
655 : /*
656 : * postscript generating routines
657 : */
658 : void
659 0 : PrinterGfx::PSGSave ()
660 : {
661 0 : WritePS (mpPageBody, "gsave\n" );
662 0 : GraphicsStatus aNewState;
663 0 : if( maGraphicsStack.begin() != maGraphicsStack.end() )
664 0 : aNewState = maGraphicsStack.front();
665 0 : maGraphicsStack.push_front( aNewState );
666 0 : }
667 :
668 : void
669 0 : PrinterGfx::PSGRestore ()
670 : {
671 0 : WritePS (mpPageBody, "grestore\n" );
672 0 : if( maGraphicsStack.begin() == maGraphicsStack.end() )
673 0 : WritePS (mpPageBody, "Error: too many grestores\n" );
674 : else
675 0 : maGraphicsStack.pop_front();
676 0 : }
677 :
678 : void
679 0 : PrinterGfx::PSSetLineWidth ()
680 : {
681 0 : if( currentState().mfLineWidth != maVirtualStatus.mfLineWidth )
682 : {
683 : char pBuffer[128];
684 0 : sal_Int32 nChar = 0;
685 :
686 0 : currentState().mfLineWidth = maVirtualStatus.mfLineWidth;
687 0 : nChar = psp::getValueOfDouble (pBuffer, maVirtualStatus.mfLineWidth, 5);
688 0 : nChar += psp::appendStr (" setlinewidth\n", pBuffer + nChar);
689 0 : WritePS (mpPageBody, pBuffer, nChar);
690 : }
691 0 : }
692 :
693 : void
694 0 : PrinterGfx::PSSetColor ()
695 : {
696 0 : PrinterColor& rColor( maVirtualStatus.maColor );
697 :
698 0 : if( currentState().maColor != rColor )
699 : {
700 0 : currentState().maColor = rColor;
701 :
702 : char pBuffer[128];
703 0 : sal_Int32 nChar = 0;
704 :
705 0 : if( mbColor )
706 : {
707 : nChar = psp::getValueOfDouble (pBuffer,
708 0 : (double)rColor.GetRed() / 255.0, 5);
709 0 : nChar += psp::appendStr (" ", pBuffer + nChar);
710 : nChar += psp::getValueOfDouble (pBuffer + nChar,
711 0 : (double)rColor.GetGreen() / 255.0, 5);
712 0 : nChar += psp::appendStr (" ", pBuffer + nChar);
713 : nChar += psp::getValueOfDouble (pBuffer + nChar,
714 0 : (double)rColor.GetBlue() / 255.0, 5);
715 0 : nChar += psp::appendStr (" setrgbcolor\n", pBuffer + nChar );
716 : }
717 : else
718 : {
719 0 : Color aColor( rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue() );
720 0 : sal_uInt8 nCol = aColor.GetLuminance();
721 0 : nChar = psp::getValueOfDouble( pBuffer, (double)nCol / 255.0, 5 );
722 0 : nChar += psp::appendStr( " setgray\n", pBuffer + nChar );
723 : }
724 :
725 0 : WritePS (mpPageBody, pBuffer, nChar);
726 : }
727 0 : }
728 :
729 : void
730 0 : PrinterGfx::PSSetFont ()
731 : {
732 0 : GraphicsStatus& rCurrent( currentState() );
733 0 : if( maVirtualStatus.maFont != rCurrent.maFont ||
734 0 : maVirtualStatus.mnTextHeight != rCurrent.mnTextHeight ||
735 0 : maVirtualStatus.maEncoding != rCurrent.maEncoding ||
736 0 : maVirtualStatus.mnTextWidth != rCurrent.mnTextWidth ||
737 0 : maVirtualStatus.mbArtBold != rCurrent.mbArtBold ||
738 0 : maVirtualStatus.mbArtItalic != rCurrent.mbArtItalic
739 : )
740 : {
741 0 : rCurrent.maFont = maVirtualStatus.maFont;
742 0 : rCurrent.maEncoding = maVirtualStatus.maEncoding;
743 0 : rCurrent.mnTextWidth = maVirtualStatus.mnTextWidth;
744 0 : rCurrent.mnTextHeight = maVirtualStatus.mnTextHeight;
745 0 : rCurrent.mbArtItalic = maVirtualStatus.mbArtItalic;
746 0 : rCurrent.mbArtBold = maVirtualStatus.mbArtBold;
747 :
748 0 : sal_Int32 nTextHeight = rCurrent.mnTextHeight;
749 : sal_Int32 nTextWidth = rCurrent.mnTextWidth ? rCurrent.mnTextWidth
750 0 : : rCurrent.mnTextHeight;
751 :
752 : sal_Char pSetFont [256];
753 0 : sal_Int32 nChar = 0;
754 :
755 : // postscript based fonts need reencoding
756 0 : if ( ( rCurrent.maEncoding == RTL_TEXTENCODING_MS_1252)
757 0 : || ( rCurrent.maEncoding == RTL_TEXTENCODING_ISO_8859_1)
758 0 : || ( rCurrent.maEncoding >= RTL_TEXTENCODING_USER_START
759 0 : && rCurrent.maEncoding <= RTL_TEXTENCODING_USER_END)
760 : )
761 : {
762 : OString aReencodedFont =
763 : psp::GlyphSet::GetReencodedFontName (rCurrent.maEncoding,
764 0 : rCurrent.maFont);
765 :
766 0 : nChar += psp::appendStr ("(", pSetFont + nChar);
767 : nChar += psp::appendStr (aReencodedFont.getStr(),
768 0 : pSetFont + nChar);
769 : nChar += psp::appendStr (") cvn findfont ",
770 0 : pSetFont + nChar);
771 : }
772 : else
773 : // tt based fonts mustn't reencode, the encoding is implied by the fontname
774 : // same for symbol type1 fonts, dont try to touch them
775 : {
776 0 : nChar += psp::appendStr ("(", pSetFont + nChar);
777 : nChar += psp::appendStr (rCurrent.maFont.getStr(),
778 0 : pSetFont + nChar);
779 : nChar += psp::appendStr (") cvn findfont ",
780 0 : pSetFont + nChar);
781 : }
782 :
783 0 : if( ! rCurrent.mbArtItalic )
784 : {
785 0 : nChar += psp::getValueOf (nTextWidth, pSetFont + nChar);
786 0 : nChar += psp::appendStr (" ", pSetFont + nChar);
787 0 : nChar += psp::getValueOf (-nTextHeight, pSetFont + nChar);
788 0 : nChar += psp::appendStr (" matrix scale makefont setfont\n", pSetFont + nChar);
789 : }
790 : else // skew 15 degrees to right
791 : {
792 0 : nChar += psp::appendStr ( " [", pSetFont + nChar);
793 0 : nChar += psp::getValueOf (nTextWidth, pSetFont + nChar);
794 0 : nChar += psp::appendStr (" 0 ", pSetFont + nChar);
795 0 : nChar += psp::getValueOfDouble (pSetFont + nChar, 0.27*(double)nTextWidth, 3 );
796 0 : nChar += psp::appendStr ( " ", pSetFont + nChar);
797 0 : nChar += psp::getValueOf (-nTextHeight, pSetFont + nChar);
798 :
799 0 : nChar += psp::appendStr (" 0 0] makefont setfont\n", pSetFont + nChar);
800 : }
801 :
802 0 : WritePS (mpPageBody, pSetFont);
803 : }
804 0 : }
805 :
806 : void
807 0 : PrinterGfx::PSRotate (sal_Int32 nAngle)
808 : {
809 0 : sal_Int32 nPostScriptAngle = -nAngle;
810 0 : while( nPostScriptAngle < 0 )
811 0 : nPostScriptAngle += 3600;
812 :
813 0 : if (nPostScriptAngle == 0)
814 0 : return;
815 :
816 0 : sal_Int32 nFullAngle = nPostScriptAngle / 10;
817 0 : sal_Int32 nTenthAngle = nPostScriptAngle % 10;
818 :
819 : sal_Char pRotate [48];
820 0 : sal_Int32 nChar = 0;
821 :
822 0 : nChar = psp::getValueOf (nFullAngle, pRotate);
823 0 : nChar += psp::appendStr (".", pRotate + nChar);
824 0 : nChar += psp::getValueOf (nTenthAngle, pRotate + nChar);
825 0 : nChar += psp::appendStr (" rotate\n", pRotate + nChar);
826 :
827 0 : WritePS (mpPageBody, pRotate);
828 : }
829 :
830 : void
831 0 : PrinterGfx::PSPointOp (const Point& rPoint, const sal_Char* pOperator)
832 : {
833 : sal_Char pPSCommand [48];
834 0 : sal_Int32 nChar = 0;
835 :
836 0 : nChar = psp::getValueOf (rPoint.X(), pPSCommand);
837 0 : nChar += psp::appendStr (" ", pPSCommand + nChar);
838 0 : nChar += psp::getValueOf (rPoint.Y(), pPSCommand + nChar);
839 0 : nChar += psp::appendStr (" ", pPSCommand + nChar);
840 0 : nChar += psp::appendStr (pOperator, pPSCommand + nChar);
841 0 : nChar += psp::appendStr ("\n", pPSCommand + nChar);
842 :
843 : DBG_ASSERT (nChar < 48, "Buffer overflow in PSPointOp");
844 :
845 0 : WritePS (mpPageBody, pPSCommand);
846 0 : }
847 :
848 : void
849 0 : PrinterGfx::PSTranslate (const Point& rPoint)
850 : {
851 0 : PSPointOp (rPoint, "translate");
852 0 : }
853 :
854 : void
855 0 : PrinterGfx::PSMoveTo (const Point& rPoint)
856 : {
857 0 : PSPointOp (rPoint, "moveto");
858 0 : }
859 :
860 : void
861 0 : PrinterGfx::PSLineTo (const Point& rPoint)
862 : {
863 0 : PSPointOp (rPoint, "lineto");
864 0 : }
865 :
866 : /* get a compressed representation of the path information */
867 :
868 : #define DEBUG_BINPATH 0
869 :
870 : void
871 0 : PrinterGfx::PSBinLineTo (const Point& rCurrent, Point& rOld, sal_Int32& nColumn)
872 : {
873 : #if (DEBUG_BINPATH == 1)
874 : PSLineTo (rCurrent);
875 : #else
876 0 : PSBinPath (rCurrent, rOld, lineto, nColumn);
877 : #endif
878 0 : }
879 :
880 : void
881 0 : PrinterGfx::PSBinMoveTo (const Point& rCurrent, Point& rOld, sal_Int32& nColumn)
882 : {
883 : #if (DEBUG_BINPATH == 1)
884 : PSMoveTo (rCurrent);
885 : #else
886 0 : PSBinPath (rCurrent, rOld, moveto, nColumn);
887 : #endif
888 0 : }
889 :
890 : void
891 0 : PrinterGfx::PSBinStartPath ()
892 : {
893 : #if (DEBUG_BINPATH == 1)
894 : WritePS (mpPageBody, "% PSBinStartPath\n");
895 : #else
896 0 : WritePS (mpPageBody, "readpath\n" );
897 : #endif
898 0 : }
899 :
900 : void
901 0 : PrinterGfx::PSBinEndPath ()
902 : {
903 : #if (DEBUG_BINPATH == 1)
904 : WritePS (mpPageBody, "% PSBinEndPath\n");
905 : #else
906 0 : WritePS (mpPageBody, "~\n");
907 : #endif
908 0 : }
909 :
910 : void
911 0 : PrinterGfx::PSBinCurrentPath (sal_uInt32 nPoints, const Point* pPath)
912 : {
913 : // create the path
914 0 : Point aPoint (0, 0);
915 0 : sal_Int32 nColumn = 0;
916 :
917 0 : PSBinStartPath ();
918 0 : PSBinMoveTo (*pPath, aPoint, nColumn);
919 0 : for (unsigned int i = 1; i < nPoints; i++)
920 0 : PSBinLineTo (pPath[i], aPoint, nColumn);
921 0 : PSBinEndPath ();
922 0 : }
923 :
924 : void
925 0 : PrinterGfx::PSBinPath (const Point& rCurrent, Point& rOld,
926 : pspath_t eType, sal_Int32& nColumn)
927 : {
928 0 : sal_Char pPath[48] = {0};
929 : sal_Int32 nChar;
930 :
931 : // create the hex representation of the dx and dy path shift, store the field
932 : // width as it is needed for the building the command
933 0 : sal_Int32 nXPrec = getAlignedHexValueOf (rCurrent.X() - rOld.X(), pPath + 1);
934 0 : sal_Int32 nYPrec = getAlignedHexValueOf (rCurrent.Y() - rOld.Y(), pPath + 1 + nXPrec);
935 0 : pPath [ 1 + nXPrec + nYPrec ] = 0;
936 :
937 : // build the command, it is a char with bit represention 000cxxyy
938 : // c represents the char, xx and yy repr. the field width of the dx and dy shift,
939 : // dx and dy represent the number of bytes to read after the opcode
940 0 : sal_Char cCmd = (eType == lineto ? (sal_Char)0x00 : (sal_Char)0x10);
941 0 : switch (nYPrec)
942 : {
943 0 : case 2: break;
944 0 : case 4: cCmd |= 0x01; break;
945 0 : case 6: cCmd |= 0x02; break;
946 0 : case 8: cCmd |= 0x03; break;
947 : default: OSL_FAIL("invalid x precision in binary path");
948 : }
949 0 : switch (nXPrec)
950 : {
951 0 : case 2: break;
952 0 : case 4: cCmd |= 0x04; break;
953 0 : case 6: cCmd |= 0x08; break;
954 0 : case 8: cCmd |= 0x0c; break;
955 : default: OSL_FAIL("invalid y precision in binary path");
956 : }
957 0 : cCmd += 'A';
958 0 : pPath[0] = cCmd;
959 :
960 : // write the command to file,
961 : // line breaking at column nMaxTextColumn (80)
962 0 : nChar = 1 + nXPrec + nYPrec;
963 0 : if ((nColumn + nChar) > nMaxTextColumn)
964 : {
965 0 : sal_Int32 nSegment = nMaxTextColumn - nColumn;
966 :
967 0 : WritePS (mpPageBody, pPath, nSegment);
968 0 : WritePS (mpPageBody, "\n", 1);
969 0 : WritePS (mpPageBody, pPath + nSegment, nChar - nSegment);
970 :
971 0 : nColumn = nChar - nSegment;
972 : }
973 : else
974 : {
975 0 : WritePS (mpPageBody, pPath, nChar);
976 :
977 0 : nColumn += nChar;
978 : }
979 :
980 0 : rOld = rCurrent;
981 0 : }
982 :
983 : void
984 0 : PrinterGfx::PSScale (double fScaleX, double fScaleY)
985 : {
986 : sal_Char pScale [48];
987 0 : sal_Int32 nChar = 0;
988 :
989 0 : nChar = psp::getValueOfDouble (pScale, fScaleX, 5);
990 0 : nChar += psp::appendStr (" ", pScale + nChar);
991 0 : nChar += psp::getValueOfDouble (pScale + nChar, fScaleY, 5);
992 0 : nChar += psp::appendStr (" scale\n", pScale + nChar);
993 :
994 0 : WritePS (mpPageBody, pScale);
995 0 : }
996 :
997 : /* psshowtext helper routines: draw an hex string for show/xshow */
998 : void
999 0 : PrinterGfx::PSHexString (const unsigned char* pString, sal_Int16 nLen)
1000 : {
1001 : sal_Char pHexString [128];
1002 0 : sal_Int32 nChar = 0;
1003 :
1004 0 : nChar = psp::appendStr ("<", pHexString);
1005 0 : for (int i = 0; i < nLen; i++)
1006 : {
1007 0 : if (nChar >= (nMaxTextColumn - 1))
1008 : {
1009 0 : nChar += psp::appendStr ("\n", pHexString + nChar);
1010 0 : WritePS (mpPageBody, pHexString, nChar);
1011 0 : nChar = 0;
1012 : }
1013 0 : nChar += psp::getHexValueOf ((sal_Int32)pString[i], pHexString + nChar);
1014 : }
1015 :
1016 0 : nChar += psp::appendStr (">\n", pHexString + nChar);
1017 0 : WritePS (mpPageBody, pHexString, nChar);
1018 0 : }
1019 :
1020 : /* psshowtext helper routines: draw an array for xshow ps operator */
1021 : void
1022 0 : PrinterGfx::PSDeltaArray (const sal_Int32 *pArray, sal_Int16 nEntries)
1023 : {
1024 : sal_Char pPSArray [128];
1025 0 : sal_Int32 nChar = 0;
1026 :
1027 0 : nChar = psp::appendStr ("[", pPSArray + nChar);
1028 0 : nChar += psp::getValueOf (pArray[0], pPSArray + nChar);
1029 :
1030 0 : for (int i = 1; i < nEntries; i++)
1031 : {
1032 0 : if (nChar >= (nMaxTextColumn - 1))
1033 : {
1034 0 : nChar += psp::appendStr ("\n", pPSArray + nChar);
1035 0 : WritePS (mpPageBody, pPSArray, nChar);
1036 0 : nChar = 0;
1037 : }
1038 :
1039 0 : nChar += psp::appendStr (" ", pPSArray + nChar);
1040 0 : nChar += psp::getValueOf (pArray[i] - pArray[i-1], pPSArray + nChar);
1041 : }
1042 :
1043 0 : nChar += psp::appendStr (" 0]\n", pPSArray + nChar);
1044 0 : WritePS (mpPageBody, pPSArray);
1045 0 : }
1046 :
1047 : /* the DrawText equivalent, pDeltaArray may be NULL. For Type1 fonts or single byte
1048 : * fonts in general nBytes and nGlyphs is the same. For printer resident Composite
1049 : * fonts it may be different (these fonts may be SJIS encoded for example) */
1050 : void
1051 0 : PrinterGfx::PSShowText (const unsigned char* pStr, sal_Int16 nGlyphs, sal_Int16 nBytes,
1052 : const sal_Int32* pDeltaArray)
1053 : {
1054 0 : PSSetColor (maTextColor);
1055 0 : PSSetColor ();
1056 0 : PSSetFont ();
1057 : // rotate the user coordinate system
1058 0 : if (mnTextAngle != 0)
1059 : {
1060 0 : PSGSave ();
1061 0 : PSRotate (mnTextAngle);
1062 : }
1063 :
1064 : sal_Char pBuffer[256];
1065 0 : if( maVirtualStatus.mbArtBold )
1066 : {
1067 0 : sal_Int32 nLW = maVirtualStatus.mnTextWidth;
1068 0 : if( nLW == 0 )
1069 0 : nLW = maVirtualStatus.mnTextHeight;
1070 : else
1071 0 : nLW = nLW < maVirtualStatus.mnTextHeight ? nLW : maVirtualStatus.mnTextHeight;
1072 0 : psp::getValueOfDouble( pBuffer, (double)nLW / 30.0 );
1073 : }
1074 : // dispatch to the drawing method
1075 0 : if (pDeltaArray == NULL)
1076 : {
1077 0 : PSHexString (pStr, nBytes);
1078 :
1079 0 : if( maVirtualStatus.mbArtBold )
1080 : {
1081 0 : WritePS( mpPageBody, pBuffer );
1082 0 : WritePS( mpPageBody, " bshow\n" );
1083 : }
1084 : else
1085 0 : WritePS (mpPageBody, "show\n");
1086 : }
1087 : else
1088 : {
1089 0 : PSHexString (pStr, nBytes);
1090 0 : PSDeltaArray (pDeltaArray, nGlyphs - 1);
1091 0 : if( maVirtualStatus.mbArtBold )
1092 : {
1093 0 : WritePS( mpPageBody, pBuffer );
1094 0 : WritePS( mpPageBody, " bxshow\n" );
1095 : }
1096 : else
1097 0 : WritePS (mpPageBody, "xshow\n");
1098 : }
1099 :
1100 : // restore the user coordinate system
1101 0 : if (mnTextAngle != 0)
1102 0 : PSGRestore ();
1103 0 : }
1104 :
1105 : void
1106 0 : PrinterGfx::PSComment( const sal_Char* pComment )
1107 : {
1108 0 : const sal_Char* pLast = pComment;
1109 0 : while( pComment && *pComment )
1110 : {
1111 0 : while( *pComment && *pComment != '\n' && *pComment != '\r' )
1112 0 : pComment++;
1113 0 : if( pComment - pLast > 1 )
1114 : {
1115 0 : WritePS( mpPageBody, "% ", 2 );
1116 0 : WritePS( mpPageBody, pLast, pComment - pLast );
1117 0 : WritePS( mpPageBody, "\n", 1 );
1118 : }
1119 0 : if( *pComment )
1120 0 : pLast = ++pComment;
1121 : }
1122 0 : }
1123 :
1124 : bool
1125 0 : PrinterGfx::DrawEPS( const Rectangle& rBoundingBox, void* pPtr, sal_uInt32 nSize )
1126 : {
1127 0 : if( nSize == 0 )
1128 0 : return true;
1129 0 : if( ! mpPageBody )
1130 0 : return false;
1131 :
1132 0 : bool bSuccess = false;
1133 :
1134 : // first search the BoundingBox of the EPS data
1135 0 : SvMemoryStream aStream( pPtr, nSize, STREAM_READ );
1136 0 : aStream.Seek( STREAM_SEEK_TO_BEGIN );
1137 0 : OString aLine;
1138 :
1139 0 : OString aDocTitle;
1140 0 : double fLeft = 0, fRight = 0, fTop = 0, fBottom = 0;
1141 0 : bool bEndComments = false;
1142 0 : while( ! aStream.IsEof()
1143 0 : && ( ( fLeft == 0 && fRight == 0 && fTop == 0 && fBottom == 0 ) ||
1144 0 : ( aDocTitle.isEmpty() && bEndComments == false ) )
1145 : )
1146 : {
1147 0 : aStream.ReadLine( aLine );
1148 0 : if( aLine.getLength() > 1 && aLine[0] == '%' )
1149 : {
1150 0 : char cChar = aLine[1];
1151 0 : if( cChar == '%' )
1152 : {
1153 0 : if( aLine.matchIgnoreAsciiCase( OString( "%%BoundingBox:") ) )
1154 : {
1155 0 : aLine = WhitespaceToSpace( aLine.getToken(1, ':') );
1156 0 : if( !aLine.isEmpty() && aLine.indexOf( "atend" ) == -1 )
1157 : {
1158 0 : fLeft = StringToDouble( GetCommandLineToken( 0, aLine ) );
1159 0 : fBottom = StringToDouble( GetCommandLineToken( 1, aLine ) );
1160 0 : fRight = StringToDouble( GetCommandLineToken( 2, aLine ) );
1161 0 : fTop = StringToDouble( GetCommandLineToken( 3, aLine ) );
1162 : }
1163 : }
1164 0 : else if( aLine.matchIgnoreAsciiCase( "%%Title:" ) )
1165 0 : aDocTitle = WhitespaceToSpace( aLine.copy( 8 ) );
1166 0 : else if( aLine.matchIgnoreAsciiCase( "%%EndComments" ) )
1167 0 : bEndComments = true;
1168 : }
1169 0 : else if( cChar == ' ' || cChar == '\t' || cChar == '\r' || cChar == '\n' )
1170 0 : bEndComments = true;
1171 : }
1172 : else
1173 0 : bEndComments = true;
1174 : }
1175 :
1176 : static sal_uInt16 nEps = 0;
1177 0 : if( aDocTitle.isEmpty() )
1178 0 : aDocTitle = OString::number(nEps++);
1179 :
1180 0 : if( fLeft != fRight && fTop != fBottom )
1181 : {
1182 0 : double fScaleX = (double)rBoundingBox.GetWidth()/(fRight-fLeft);
1183 0 : double fScaleY = -(double)rBoundingBox.GetHeight()/(fTop-fBottom);
1184 0 : Point aTranslatePoint( (int)(rBoundingBox.Left()-fLeft*fScaleX),
1185 0 : (int)(rBoundingBox.Bottom()+1-fBottom*fScaleY) );
1186 : // prepare EPS
1187 : WritePS( mpPageBody,
1188 : "/b4_Inc_state save def\n"
1189 : "/dict_count countdictstack def\n"
1190 : "/op_count count 1 sub def\n"
1191 : "userdict begin\n"
1192 : "/showpage {} def\n"
1193 : "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin\n"
1194 : "10 setmiterlimit [] 0 setdash newpath\n"
1195 : "/languagelevel where\n"
1196 : "{pop languagelevel\n"
1197 : "1 ne\n"
1198 : " {false setstrokeadjust false setoverprint\n"
1199 : " } if\n"
1200 0 : "}if\n" );
1201 : // set up clip path and scale
1202 0 : BeginSetClipRegion( 1 );
1203 0 : UnionClipRegion( rBoundingBox.Left(), rBoundingBox.Top(), rBoundingBox.GetWidth(), rBoundingBox.GetHeight() );
1204 0 : EndSetClipRegion();
1205 0 : PSTranslate( aTranslatePoint );
1206 0 : PSScale( fScaleX, fScaleY );
1207 :
1208 : // DSC requires BeginDocument
1209 0 : WritePS( mpPageBody, "%%BeginDocument: " );
1210 0 : WritePS( mpPageBody, aDocTitle );
1211 0 : WritePS( mpPageBody, "\n" );
1212 :
1213 : // write the EPS data
1214 : sal_uInt64 nOutLength;
1215 0 : mpPageBody->write( pPtr, nSize, nOutLength );
1216 0 : bSuccess = nOutLength == nSize;
1217 :
1218 : // corresponding EndDocument
1219 0 : if( ((char*)pPtr)[ nSize-1 ] != '\n' )
1220 0 : WritePS( mpPageBody, "\n" );
1221 0 : WritePS( mpPageBody, "%%EndDocument\n" );
1222 :
1223 : // clean up EPS
1224 : WritePS( mpPageBody,
1225 : "count op_count sub {pop} repeat\n"
1226 : "countdictstack dict_count sub {end} repeat\n"
1227 0 : "b4_Inc_state restore\n" );
1228 : }
1229 0 : return bSuccess;
1230 3 : }
1231 :
1232 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|