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