LCOV - code coverage report
Current view: top level - libreoffice/vcl/generic/print - text_gfx.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 336 0.0 %
Date: 2012-12-27 Functions: 0 21 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 <math.h>
      22             : 
      23             : #include "psputil.hxx"
      24             : #include "glyphset.hxx"
      25             : 
      26             : #include "generic/printergfx.hxx"
      27             : #include "vcl/fontmanager.hxx"
      28             : #include "vcl/helper.hxx"
      29             : 
      30             : #include "osl/thread.h"
      31             : 
      32             : #include "sal/alloca.h"
      33             : 
      34             : using namespace psp ;
      35             : 
      36             : namespace psp {
      37             : /*
      38             :  container for a font and its helper fonts:
      39             :  1st font is the font substitute e.g. helvetica substitutes arial on the printer
      40             :  2nd is the font itself
      41             :  3rd is a fallback font, usually a font with unicode glyph repertoir (e.g. andale)
      42             :  symbol fonts (adobe-fontspecific) may need special glyphmapping
      43             :  (symbol page vc. latin page)
      44             : */
      45             : class Font3
      46             : {
      47             :     private:
      48             : 
      49             :         #define Font3Size 3
      50             : 
      51             :         fontID  mpFont [Font3Size];
      52             :         bool    mbSymbol;
      53             : 
      54             :     public:
      55             : 
      56           0 :         fontID  GetFont (int nIdx) const
      57           0 :                     { return nIdx < Font3Size ? mpFont[nIdx] : -1 ; }
      58           0 :         bool    IsSymbolFont () const
      59           0 :                     { return mbSymbol; }
      60             : 
      61             :         Font3 (const PrinterGfx &rGfx);
      62           0 :         ~Font3 () {}
      63             : };
      64             : 
      65           0 : Font3::Font3(const PrinterGfx &rGfx)
      66             : {
      67           0 :     mpFont[0] = rGfx.getFontSubstitute();
      68           0 :     mpFont[1] = rGfx.GetFontID();
      69           0 :     mpFont[2] = rGfx.getFallbackID();
      70             :     // mpFont[2] = rGfx.GetFontID();
      71             : 
      72           0 :        PrintFontManager &rMgr = PrintFontManager::get();
      73           0 :     mbSymbol = mpFont[1] != -1 ?
      74           0 :                 rMgr.getFontEncoding(mpFont[1]) == RTL_TEXTENCODING_SYMBOL : false;
      75           0 : }
      76             : 
      77             : } // namespace psp
      78             : 
      79           0 : static int getVerticalDeltaAngle( sal_Unicode nChar )
      80             : {
      81           0 :     int nRotation = GetVerticalFlags(nChar);
      82           0 :     if (nRotation == GF_ROTR)
      83           0 :         return -900;
      84           0 :     if (nRotation == GF_ROTL)
      85           0 :         return 900;
      86           0 :     return 0;
      87             : }
      88             : 
      89             : void
      90           0 : PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID)
      91             : {
      92           0 :     std::list< sal_Int32 >::iterator aFont;
      93             :     // already in the document header ?
      94           0 :     for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont )
      95           0 :         if( nFontID == *aFont )
      96           0 :             return;
      97             : 
      98             :     // no occurrenc yet, mark for download
      99             :     // add the fontid to the list
     100           0 :     maPS1Font.push_back (nFontID);
     101             : }
     102             : 
     103             : /*
     104             :  * implement text handling printer routines,
     105             :  */
     106             : 
     107             : sal_uInt16
     108           0 : PrinterGfx::SetFont(
     109             :                     sal_Int32 nFontID,
     110             :                     sal_Int32 nHeight,
     111             :                     sal_Int32 nWidth,
     112             :                     sal_Int32 nAngle,
     113             :                     bool bVertical,
     114             :                     bool bArtItalic,
     115             :                     bool bArtBold
     116             :                     )
     117             : {
     118             :     // font and encoding will be set by drawText again immediately
     119             :     // before PSShowText
     120           0 :     mnFontID                          = nFontID;
     121           0 :     maVirtualStatus.maFont            = rtl::OString();
     122           0 :     maVirtualStatus.maEncoding        = RTL_TEXTENCODING_DONTKNOW;
     123           0 :     maVirtualStatus.mnTextHeight      = nHeight;
     124           0 :     maVirtualStatus.mnTextWidth       = nWidth;
     125           0 :     maVirtualStatus.mbArtItalic       = bArtItalic;
     126           0 :     maVirtualStatus.mbArtBold         = bArtBold;
     127           0 :     mnTextAngle                       = nAngle;
     128           0 :     mbTextVertical                    = bVertical;
     129             : 
     130           0 :     return 0;
     131             : }
     132             : 
     133           0 : void PrinterGfx::drawGlyphs(
     134             :                             const Point& rPoint,
     135             :                             sal_uInt32* pGlyphIds,
     136             :                             sal_Unicode* pUnicodes,
     137             :                             sal_Int16 nLen,
     138             :                             sal_Int32* pDeltaArray
     139             :                             )
     140             : {
     141             : 
     142             :     // draw the string
     143             :     // search for a glyph set matching the set font
     144           0 :     std::list< GlyphSet >::iterator aIter;
     145           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     146           0 :         if ( ((*aIter).GetFontID()  == mnFontID)
     147           0 :              && ((*aIter).IsVertical() == mbTextVertical))
     148             :         {
     149           0 :             (*aIter).DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
     150           0 :             break;
     151             :         }
     152             : 
     153             :     // not found ? create a new one
     154           0 :     if (aIter == maPS3Font.end())
     155             :     {
     156           0 :         maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
     157           0 :         maPS3Font.back().DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
     158             :     }
     159           0 : }
     160             : 
     161           0 : void PrinterGfx::DrawGlyphs(
     162             :                             const Point& rPoint,
     163             :                             sal_GlyphId* pGlyphIds,
     164             :                             sal_Unicode* pUnicodes,
     165             :                             sal_Int16 nLen,
     166             :                             sal_Int32* pDeltaArray
     167             :                             )
     168             : {
     169           0 :     if( nLen <= 0 )
     170             :         return;
     171             : 
     172           0 :     if ( !mrFontMgr.isFontDownloadingAllowed( mnFontID ) )
     173             :     {
     174           0 :         LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray);
     175             :         return;
     176             :     }
     177             : 
     178           0 :     if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType )
     179             :     {
     180           0 :         DrawText( rPoint, pUnicodes, nLen, pDeltaArray );
     181             :         return;
     182             :     }
     183             : 
     184             :     // move and rotate the user coordinate system
     185             :     // avoid the gsave/grestore for the simple cases since it allows
     186             :     // reuse of the current font if it hasn't changed
     187           0 :     sal_Int32 nCurrentTextAngle = mnTextAngle;
     188           0 :     Point aPoint( rPoint );
     189             : 
     190           0 :     if (nCurrentTextAngle != 0)
     191             :     {
     192           0 :         PSGSave ();
     193           0 :         PSTranslate (rPoint);
     194           0 :         PSRotate (nCurrentTextAngle);
     195           0 :         mnTextAngle = 0;
     196           0 :         aPoint = Point( 0, 0 );
     197             :     }
     198             : 
     199           0 :     if( mbTextVertical )
     200             :     {
     201             :         // vertical glyphs can have an additional rotation ... sigh.
     202             :         // so break up text in chunks of normal glyphs and print out
     203             :         // specially rotated glyphs extra
     204           0 :         sal_uInt32* pTempGlyphIds = (sal_uInt32*)alloca(sizeof(sal_Int32)*nLen);
     205           0 :         sal_Int32* pTempDelta = (sal_Int32*)alloca(sizeof(sal_Int32)*nLen);
     206           0 :         sal_Unicode* pTempUnicodes = (sal_Unicode*)alloca(sizeof(sal_Unicode)*nLen);
     207           0 :         sal_Int16 nTempLen = 0;
     208           0 :         sal_Int32 nTempFirstDelta = 0;
     209           0 :         Point aRotPoint;
     210           0 :         sal_Int32 nTextHeight = maVirtualStatus.mnTextHeight;
     211           0 :         sal_Int32 nTextWidth  = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     212           0 :         sal_Int32 nAscend = mrFontMgr.getFontAscend( mnFontID );
     213           0 :         sal_Int32 nDescend = mrFontMgr.getFontDescend( mnFontID );
     214             : 
     215           0 :         nDescend = nDescend * nTextHeight / 1000;
     216           0 :         nAscend = nAscend * nTextHeight / 1000;
     217             : 
     218           0 :         for( sal_Int16 i = 0; i < nLen; i++ )
     219             :         {
     220           0 :             const sal_GlyphId nRot = pGlyphIds[i] & GF_ROTMASK;
     221           0 :             if( nRot == GF_NONE )
     222             :             {
     223           0 :                 pTempUnicodes[nTempLen] = pUnicodes[i];
     224           0 :                 pTempGlyphIds[nTempLen] = pGlyphIds[i];
     225           0 :                 if( nTempLen > 0 )
     226           0 :                     pTempDelta[nTempLen-1]  = pDeltaArray[i-1]-nTempFirstDelta;
     227             :                 else
     228             :                 {
     229             :                     // the first element in pDeltaArray shows
     230             :                     // the offset of the second character
     231             :                     // so if the first glyph is normal
     232             :                     // then we do not need to move the delta indices
     233             :                     // else we have to move them down by one and
     234             :                     // recalculate aPoint and all deltas
     235           0 :                     if( i != 0 )
     236           0 :                         nTempFirstDelta = pDeltaArray[ i-1 ];
     237             :                 }
     238           0 :                 nTempLen++;
     239             :             }
     240             :             else
     241             :             {
     242           0 :                 sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0;
     243           0 :                 sal_Int32 nRotAngle = 0;
     244           0 :                 switch( nRot )
     245             :                 {
     246             :                     case GF_ROTR:
     247           0 :                         nRotAngle = 2700;
     248           0 :                         aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset );
     249           0 :                         break;
     250             :                     case GF_VERT:
     251           0 :                         nRotAngle = 1800;
     252           0 :                         aRotPoint = Point( -nOffset, (nAscend+nDescend) );
     253           0 :                         break;
     254             :                     case GF_ROTL:
     255           0 :                         nRotAngle = 900;
     256           0 :                         aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight );
     257           0 :                         break;
     258             :                 }
     259           0 :                 sal_GlyphId nRotGlyphId     = pGlyphIds[i];
     260           0 :                 sal_Unicode nRotUnicode     = pUnicodes[i];
     261           0 :                 sal_Int32 nRotDelta         = 0;
     262             : 
     263             :                 // transform matrix to new individual direction
     264           0 :                 PSGSave ();
     265           0 :                 GraphicsStatus aSaveStatus = maVirtualStatus;
     266           0 :                 if( nRot != 2 ) // switch font aspect
     267             :                 {
     268           0 :                     maVirtualStatus.mnTextWidth = nTextHeight;
     269           0 :                     maVirtualStatus.mnTextHeight = nTextWidth;
     270             :                 }
     271           0 :                 if( aPoint.X() || aPoint.Y() )
     272           0 :                     PSTranslate( aPoint );
     273           0 :                 PSRotate (nRotAngle);
     274             :                 // draw the rotated glyph
     275           0 :                 drawGlyphs( aRotPoint, &nRotGlyphId, &nRotUnicode, 1, &nRotDelta );
     276             : 
     277             :                 // restore previous state
     278           0 :                 maVirtualStatus = aSaveStatus;
     279           0 :                 PSGRestore();
     280             :             }
     281             :         }
     282             : 
     283           0 :         pGlyphIds = pTempGlyphIds;
     284           0 :         pUnicodes = pTempUnicodes;
     285           0 :         pDeltaArray = pTempDelta;
     286           0 :         nLen = nTempLen;
     287             : 
     288           0 :         aPoint.X() += nTempFirstDelta;
     289             :     }
     290             : 
     291           0 :     if( nLen > 0 )
     292           0 :         drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray );
     293             : 
     294             :     // restore the user coordinate system
     295           0 :     if (nCurrentTextAngle != 0)
     296             :     {
     297           0 :         PSGRestore ();
     298           0 :         mnTextAngle = nCurrentTextAngle;
     299             :     }
     300             : }
     301             : 
     302             : void
     303           0 : PrinterGfx::DrawText (
     304             :                       const Point& rPoint,
     305             :                       const sal_Unicode* pStr,
     306             :                       sal_Int16 nLen,
     307             :                       const sal_Int32* pDeltaArray
     308             :                       )
     309             : {
     310           0 :     fontID nRestoreFont = mnFontID;
     311             : 
     312             :     // setup font[substitutes] and map the string into the symbol area in case of
     313             :     // symbol font
     314           0 :     Font3 aFont(*this);
     315             :     sal_Unicode *pEffectiveStr;
     316           0 :     if ( aFont.IsSymbolFont() )
     317             :     {
     318           0 :         pEffectiveStr = (sal_Unicode*)alloca(nLen * sizeof(pStr[0]));
     319           0 :         for (int i = 0; i < nLen; i++)
     320           0 :             pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
     321             :     }
     322             :     else
     323             :     {
     324           0 :         pEffectiveStr = const_cast<sal_Unicode*>(pStr);
     325             :     }
     326             : 
     327           0 :     fontID    *pFontMap   = (fontID*)    alloca(nLen * sizeof(fontID));
     328           0 :     sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32));
     329             : 
     330           0 :     for( int n = 0; n < nLen; n++ )
     331             :     {
     332           0 :         CharacterMetric aBBox;
     333           0 :         pFontMap[n]   = getCharMetric (aFont, pEffectiveStr[n], &aBBox);
     334           0 :         pCharWidth[n] = getCharWidth  (mbTextVertical, pEffectiveStr[n], &aBBox);
     335             :     }
     336             : 
     337             :     // setup a new delta array, use virtual resolution of 1000
     338           0 :     sal_Int32* pNewDeltaArray = (sal_Int32*)alloca( sizeof( sal_Int32 )*nLen );
     339           0 :     if ( pDeltaArray != 0)
     340             :     {
     341           0 :         for (int i = 0; i < nLen - 1; i++)
     342           0 :             pNewDeltaArray[i] = 1000 * pDeltaArray[i];
     343           0 :         pNewDeltaArray[nLen - 1] = 0;
     344             :     }
     345             :     else
     346             :     {
     347           0 :         pNewDeltaArray[0] = pCharWidth[0];
     348           0 :         for (int i = 1; i < nLen; i++)
     349           0 :             pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i];
     350             :     }
     351             : 
     352             :     // move and rotate the user coordinate system
     353             :     // avoid the gsave/grestore for the simple cases since it allows
     354             :     // reuse of the current font if it hasn't changed
     355           0 :     sal_Int32 nCurrentTextAngle = mnTextAngle;
     356             :     sal_Int32 nCurrentPointX;
     357             :     sal_Int32 nCurrentPointY;
     358             : 
     359           0 :     if (nCurrentTextAngle != 0)
     360             :     {
     361           0 :         PSGSave ();
     362           0 :         PSTranslate (rPoint);
     363           0 :         PSRotate (nCurrentTextAngle);
     364           0 :         mnTextAngle = 0;
     365             : 
     366           0 :         nCurrentPointX = 0;
     367           0 :         nCurrentPointY = 0;
     368             :     }
     369             :     else
     370             :     {
     371           0 :         nCurrentPointX = rPoint.X();
     372           0 :         nCurrentPointY = rPoint.Y();
     373             :     }
     374             : 
     375             :     // draw the string
     376           0 :     sal_Int32 nDelta = 0;
     377           0 :     for (int nTo = 0; nTo < nLen; )
     378             :     {
     379           0 :         int    nFrom = nTo;
     380           0 :         fontID nFont = pFontMap[ nFrom ];
     381             : 
     382           0 :         while ((nTo < nLen) && (nFont == pFontMap[nTo]))
     383             :         {
     384           0 :             pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
     385           0 :             nTo++ ;
     386             :         }
     387             : 
     388             :         SetFont( nFont,
     389             :                  maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
     390             :                  mnTextAngle,
     391             :                  mbTextVertical,
     392             :                  maVirtualStatus.mbArtItalic,
     393             :                  maVirtualStatus.mbArtBold
     394           0 :                  );
     395             : 
     396           0 :         if (mbTextVertical)
     397             :         {
     398             :             drawVerticalizedText(
     399             :                     Point(nCurrentPointX + nDelta, nCurrentPointY),
     400             :                     pEffectiveStr + nFrom, nTo - nFrom,
     401           0 :                     pNewDeltaArray + nFrom );
     402             :         }
     403             :         else
     404             :         {
     405             :             drawText(
     406             :                     Point(nCurrentPointX + nDelta, nCurrentPointY),
     407             :                     pEffectiveStr + nFrom, nTo - nFrom,
     408           0 :                     pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom );
     409             :         }
     410           0 :         nDelta += pNewDeltaArray[ nTo - 1 ];
     411             :     }
     412             : 
     413             :     // restore the user coordinate system
     414           0 :     if (nCurrentTextAngle != 0)
     415             :     {
     416           0 :         PSGRestore ();
     417           0 :         mnTextAngle = nCurrentTextAngle;
     418             :     }
     419             : 
     420             :     // restore the original font settings
     421             :     SetFont( nRestoreFont,
     422             :              maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
     423             :              mnTextAngle, mbTextVertical,
     424             :              maVirtualStatus.mbArtItalic,
     425             :              maVirtualStatus.mbArtBold
     426           0 :              );
     427           0 : }
     428             : 
     429           0 : void PrinterGfx::drawVerticalizedText(
     430             :                                       const Point& rPoint,
     431             :                                       const sal_Unicode* pStr,
     432             :                                       sal_Int16 nLen,
     433             :                                       const sal_Int32* pDeltaArray
     434             :                                       )
     435             : {
     436           0 :     sal_Int32* pDelta = (sal_Int32*)alloca( nLen * sizeof(sal_Int32) );
     437             : 
     438           0 :     int nTextScale   = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     439           0 :     int nNormalAngle = mnTextAngle;
     440           0 :     int nDeltaAngle, nLastPos = 0;
     441             : 
     442           0 :     double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
     443           0 :     double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
     444             : 
     445           0 :     PrintFontManager &rMgr = PrintFontManager::get();
     446           0 :     PrintFontInfo aInfo;
     447           0 :     rMgr.getFontInfo( mnFontID, aInfo );
     448             : 
     449           0 :     bool* pGsubFlags = (bool*)alloca( nLen * sizeof(bool) );
     450           0 :     rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
     451             : 
     452           0 :     Point aPoint( rPoint );
     453           0 :     for( int i = 0; i < nLen; )
     454             :     {
     455           0 :         while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
     456           0 :             i++;
     457           0 :         if( i <= nLen && i > nLastPos )
     458             :         {
     459           0 :             for( int n = nLastPos; n < i; n++ )
     460           0 :                 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
     461             : 
     462             :             SetFont( mnFontID,
     463             :                      maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
     464             :                      nNormalAngle, mbTextVertical,
     465             :                      maVirtualStatus.mbArtItalic,
     466           0 :                      maVirtualStatus.mbArtBold );
     467           0 :             drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
     468             : 
     469           0 :             aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
     470           0 :             aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
     471             :         }
     472           0 :         if( i < nLen )
     473             :         {
     474           0 :             int nOldWidth   = maVirtualStatus.mnTextWidth;
     475           0 :             int nOldHeight  = maVirtualStatus.mnTextHeight;
     476             :             SetFont( mnFontID,
     477             :                      nTextScale,
     478             :                      maVirtualStatus.mnTextHeight,
     479             :                      nNormalAngle + nDeltaAngle,
     480             :                      mbTextVertical,
     481             :                      maVirtualStatus.mbArtItalic,
     482           0 :                      maVirtualStatus.mbArtBold );
     483             : 
     484           0 :             double nA = nTextScale * aInfo.m_nAscend / 1000.0;
     485           0 :             double nD = nTextScale * aInfo.m_nDescend / 1000.0;
     486           0 :             double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
     487           0 :             if( !pGsubFlags[i] )
     488           0 :                 nD *= fStretch;
     489             : 
     490           0 :             Point aPos( aPoint );
     491           0 :             switch( nDeltaAngle )
     492             :             {
     493             :                 case +900:
     494           0 :                     aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
     495           0 :                     aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
     496           0 :                     break;
     497             :                 case -900:
     498           0 :                     aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
     499           0 :                     aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
     500           0 :                     break;
     501             :             }
     502           0 :             drawText( aPos, pStr+i, 1, NULL );
     503           0 :             if( i < nLen-1 && pDeltaArray )
     504             :             {
     505           0 :                 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
     506           0 :                 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
     507             :             }
     508             : 
     509             :             // swap text width/height again
     510             :             SetFont( mnFontID,
     511             :                      nOldHeight,
     512             :                      nOldWidth,
     513             :                      nNormalAngle,
     514             :                      mbTextVertical,
     515             :                      maVirtualStatus.mbArtItalic,
     516           0 :                      maVirtualStatus.mbArtBold );
     517             :         }
     518           0 :         i++;
     519           0 :         nLastPos = i;
     520             :     }
     521           0 :     mnTextAngle = nNormalAngle;
     522           0 : }
     523             : 
     524             : void
     525           0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
     526             :                            sal_Int16 nLen, const sal_Int32* pDeltaArray)
     527             : {
     528             :     // treat it like a builtin font in case a user has that font also in the
     529             :     // printer. This is not so unlikely as it may seem; no print embedding
     530             :     // licensed fonts are often used (or so they say) in companies:
     531             :     // they are installed on displays and printers, but get not embedded in
     532             :     // they are installed on displays and printers, but get not embedded in
     533             :     // print files or documents because they are not licensed for use outside
     534             :     // the company.
     535           0 :     rtl::OString aMessage( "The font " );
     536           0 :     aMessage += rtl::OUStringToOString( mrFontMgr.getPSName(mnFontID),
     537           0 :             RTL_TEXTENCODING_ASCII_US );
     538           0 :     aMessage += " could not be downloaded\nbecause its license does not allow for that";
     539           0 :     PSComment( aMessage.getStr() );
     540             : 
     541             :     rtl::OString aFontName = rtl::OUStringToOString(
     542           0 :             mrFontMgr.getPSName(mnFontID),
     543           0 :             RTL_TEXTENCODING_ASCII_US);
     544           0 :     PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
     545             : 
     546           0 :     sal_Size  nSize    = 4 * nLen;
     547           0 :     sal_uChar* pBuffer = (sal_uChar*)alloca (nSize* sizeof(sal_uChar));
     548             : 
     549           0 :     ConverterFactory &rCvt = GetConverterFactory ();
     550           0 :     nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
     551             : 
     552           0 :     PSMoveTo (rPoint);
     553           0 :     PSShowText (pBuffer, nLen, nSize, pDeltaArray);
     554           0 : }
     555             : 
     556             : void
     557           0 : PrinterGfx::drawText(
     558             :                      const Point& rPoint,
     559             :                      const sal_Unicode* pStr,
     560             :                      sal_Int16 nLen,
     561             :                      const sal_Int32* pDeltaArray
     562             :                      )
     563             : {
     564           0 :     if (!(nLen > 0))
     565             :         return;
     566             : 
     567           0 :     fonttype::type   eType          = mrFontMgr.getFontType (mnFontID);
     568             : 
     569           0 :     if (eType == fonttype::Type1)
     570           0 :         PSUploadPS1Font (mnFontID);
     571             : 
     572           0 :     if (   eType == fonttype::TrueType
     573           0 :         && !mrFontMgr.isFontDownloadingAllowed(mnFontID))
     574             :     {
     575           0 :         LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
     576             :         return;
     577             :     }
     578             : 
     579           0 :     if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
     580             :     {
     581           0 :         GlyphSet aGSet( mnFontID, mbTextVertical );
     582           0 :         aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
     583           0 :         return;
     584             :     }
     585             : 
     586             :     // search for a glyph set matching the set font
     587           0 :     std::list< GlyphSet >::iterator aIter;
     588           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     589           0 :         if (   ((*aIter).GetFontID()  == mnFontID)
     590           0 :             && ((*aIter).IsVertical() == mbTextVertical))
     591             :         {
     592           0 :             (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     593           0 :             break;
     594             :         }
     595             : 
     596             :     // not found ? create a new one
     597           0 :     if (aIter == maPS3Font.end())
     598             :     {
     599           0 :         maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
     600           0 :         maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     601             :     }
     602             : }
     603             : 
     604             : int
     605           0 : PrinterGfx::getCharWidth (sal_Bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
     606             : {
     607           0 :     b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
     608           0 :     int w = b_vert ? p_bbox->height : p_bbox->width;
     609           0 :     w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     610           0 :     return w;
     611             : }
     612             : 
     613             : fontID
     614           0 : PrinterGfx::getCharMetric (const Font3 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
     615             : {
     616           0 :     p_bbox->width  = -1;
     617           0 :     p_bbox->height = -1;
     618             : 
     619           0 :     for (fontID n = 0; n < 3; n++)
     620             :     {
     621           0 :         fontID n_font = rFont.GetFont(n);
     622           0 :         if (n_font != -1)
     623           0 :             mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
     624           0 :         if (p_bbox->width >= 0 && p_bbox->height >= 0)
     625           0 :             return n_font;
     626             :     }
     627           0 :     if (n_char != '?')
     628           0 :         return getCharMetric (rFont, '?', p_bbox);
     629             : 
     630           0 :     return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
     631             : }
     632             : 
     633             : fontID
     634           0 : PrinterGfx::getFontSubstitute () const
     635             : {
     636           0 :     if( mpFontSubstitutes )
     637             :     {
     638             :         ::boost::unordered_map< fontID, fontID >::const_iterator it =
     639           0 :               mpFontSubstitutes->find( mnFontID );
     640           0 :         if( it != mpFontSubstitutes->end() )
     641           0 :             return it->second;
     642             :     }
     643             : 
     644           0 :     return -1;
     645             : }
     646             : 
     647             : sal_Int32
     648           0 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
     649             : {
     650           0 :     Font3 aFont(*this);
     651           0 :     if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
     652             :     {
     653           0 :         nFrom += 0xF000;
     654           0 :         nTo   += 0xF000;
     655             :     }
     656             : 
     657           0 :     for( int n = 0; n < (nTo - nFrom + 1); n++ )
     658             :     {
     659           0 :         CharacterMetric aBBox;
     660           0 :         getCharMetric (aFont, n + nFrom, &aBBox);
     661           0 :         pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
     662             :     }
     663             : 
     664             :     // returned metrics have postscript precision
     665           0 :     return 1000;
     666             : }
     667             : 
     668           0 : const ::std::list< KernPair >& PrinterGfx::getKernPairs( bool bVertical ) const
     669             : {
     670             :     /*
     671             :      *  Note: this is only a 80% solution: if a font is only
     672             :      *  partially substituted in a string due to missing glyphs
     673             :      *  the results may not be perfect; the more so the more the
     674             :      *  substitution differs from the original metricwise. But
     675             :      *  vcl only asks for KernPairs for each font once and NOT
     676             :      *  in a string context this is the best we can do.
     677             :      *  In future the kerning should be done on a per string basis.
     678             :      */
     679           0 :     fontID nFont = mnFontID;
     680           0 :     if( mpFontSubstitutes )
     681             :     {
     682             :         ::boost::unordered_map< fontID, fontID >::const_iterator it =
     683           0 :               mpFontSubstitutes->find( mnFontID );
     684           0 :         if( it != mpFontSubstitutes->end() )
     685           0 :             nFont = it->second;
     686             :     }
     687           0 :     return mrFontMgr.getKernPairs( nFont, bVertical );
     688             : }
     689             : 
     690             : /*
     691             :  * spool the converted truetype fonts to the page header after the page body is
     692             :  * complete
     693             :  * for Type1 fonts spool additional reencoding vectors that are necessary to access the
     694             :  * whole font
     695             :  */
     696             : 
     697             : void
     698           0 : PrinterGfx::OnEndPage ()
     699             : {
     700           0 : }
     701             : 
     702             : void
     703           0 : PrinterGfx::OnEndJob ()
     704             : {
     705           0 :     maPS3Font.clear();
     706           0 :     maPS1Font.clear();
     707           0 : }
     708             : 
     709             : void
     710           0 : PrinterGfx::writeResources( osl::File* pFile, std::list< rtl::OString >& rSuppliedFonts, std::list< rtl::OString >& rNeededFonts )
     711             : {
     712             :     // write all type 1 fonts
     713           0 :     std::list< sal_Int32 >::iterator aFont;
     714             :     // already in the document header ?
     715           0 :     for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
     716             :     {
     717           0 :         const rtl::OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
     718           0 :         rtl::OUString aUNCPath;
     719           0 :         osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
     720           0 :         osl::File aFontFile (aUNCPath);
     721             : 
     722             :         // provide the pfb or pfa font as a (pfa-)font resource
     723             :         rtl::OString aPostScriptName =
     724           0 :             rtl::OUStringToOString ( mrFontMgr.getPSName(*aFont),
     725           0 :                                      RTL_TEXTENCODING_ASCII_US );
     726             : 
     727           0 :         WritePS (pFile, "%%BeginResource: font ");
     728           0 :         WritePS (pFile, aPostScriptName.getStr());
     729           0 :         WritePS (pFile, "\n");
     730             : 
     731           0 :         osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
     732           0 :         if (nError == osl::File::E_None)
     733             :         {
     734           0 :             convertPfbToPfa (aFontFile, *pFile);
     735           0 :             aFontFile.close ();
     736             : 
     737           0 :             char lastchar = '\n';
     738             : 
     739           0 :             if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
     740             :             {
     741           0 :                 sal_uInt64 uBytes(1);
     742           0 :                 pFile->read((void *)(&lastchar), uBytes, uBytes);
     743             :             }
     744             : 
     745           0 :             if (lastchar != '\n')
     746           0 :                 WritePS (pFile, "\n");
     747             :         }
     748           0 :         WritePS (pFile, "%%EndResource\n");
     749           0 :         rSuppliedFonts.push_back( aPostScriptName );
     750           0 :     }
     751             : 
     752             :     // write glyphsets and reencodings
     753           0 :     std::list< GlyphSet >::iterator aIter;
     754           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     755             :     {
     756           0 :         if (aIter->GetFontType() == fonttype::TrueType)
     757             :         {
     758           0 :             aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts ? true : false, rSuppliedFonts );
     759             :         }
     760             :         else
     761             :         // (   aIter->GetFontType() == fonttype::Type1
     762             :         //  || aIter->GetFontType() == fonttype::Builtin )
     763             :         {
     764           0 :             aIter->PSUploadEncoding (pFile, *this);
     765           0 :             if( aIter->GetFontType() == fonttype::Builtin )
     766             :                 rNeededFonts.push_back(
     767             :                       rtl::OUStringToOString(
     768           0 :                            mrFontMgr.getPSName( aIter->GetFontID() ),
     769           0 :                            RTL_TEXTENCODING_ASCII_US ) );
     770             :         }
     771             :     }
     772           0 : }
     773             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10