LCOV - code coverage report
Current view: top level - vcl/generic/print - common_gfx.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 27 630 4.3 %
Date: 2014-11-03 Functions: 6 44 13.6 %
Legend: Lines: hit not hit

          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        1360 : GraphicsStatus::GraphicsStatus() :
      42             :         maEncoding(RTL_TEXTENCODING_DONTKNOW),
      43             :         mbArtItalic( false ),
      44             :         mbArtBold( false ),
      45             :         mnTextHeight( 0 ),
      46             :         mnTextWidth( 0 ),
      47        1360 :         mfLineWidth( -1 )
      48             : {
      49        1360 : }
      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         680 : PrinterGfx::Init (const JobData& rData)
      74             : {
      75         680 :     mpPageHeader    = NULL;
      76         680 :     mpPageBody      = NULL;
      77         680 :     mnDepth         = rData.m_nColorDepth;
      78         680 :     mnPSLevel       = rData.m_nPSLevel ? rData.m_nPSLevel : (rData.m_pParser ? rData.m_pParser->getLanguageLevel() : 2 );
      79         680 :     mbColor         = rData.m_nColorDevice ? ( rData.m_nColorDevice != -1 ) : ( rData.m_pParser ? rData.m_pParser->isColorDevice() : true );
      80         680 :     int nRes = rData.m_aContext.getRenderResolution();
      81         680 :     mnDpi           = nRes;
      82         680 :     mfScaleX        = (double)72.0 / (double)mnDpi;
      83         680 :     mfScaleY        = (double)72.0 / (double)mnDpi;
      84         680 :     const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( rData.m_aPrinterName ) );
      85         680 :     mbUploadPS42Fonts = rInfo.m_pParser && rInfo.m_pParser->isType42Capable();
      86             : 
      87         680 :     return true;
      88             : }
      89             : 
      90             : 
      91         680 : 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         680 :     , mrFontMgr(PrintFontManager::get())
     106             :     , mbCompressBmp(true)
     107             :     , maFillColor(0xff,0,0)
     108             :     , maTextColor(0,0,0)
     109        1360 :     , maLineColor(0, 0xff, 0)
     110             : {
     111         680 :     maVirtualStatus.mfLineWidth = 1.0;
     112         680 :     maVirtualStatus.mnTextHeight = 12;
     113         680 :     maVirtualStatus.mnTextWidth = 0;
     114             : 
     115         680 :     maGraphicsStack.push_back( GraphicsStatus() );
     116         680 : }
     117             : 
     118         677 : PrinterGfx::~PrinterGfx()
     119             : {
     120         677 : }
     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, STREAM_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 == false ) )
    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( ((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        1233 : }
    1234             : 
    1235             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10