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

Generated by: LCOV version 1.10