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