LCOV - code coverage report
Current view: top level - vcl/generic/print - text_gfx.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 1 325 0.3 %
Date: 2014-04-14 Functions: 2 21 9.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10