LCOV - code coverage report
Current view: top level - vcl/generic/print - text_gfx.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 46 328 14.0 %
Date: 2014-11-03 Functions: 10 21 47.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <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        4172 :         fontID  GetFont (int nIdx) const
      55        4172 :                     { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
      56        4172 :         bool    IsSymbolFont () const
      57        4172 :                     { return mbSymbol; }
      58             : 
      59             :         Font2 (const PrinterGfx &rGfx);
      60        4172 :         ~Font2 () {}
      61             : };
      62             : 
      63        4172 : Font2::Font2(const PrinterGfx &rGfx)
      64             : {
      65        4172 :     mpFont[0] = rGfx.GetFontID();
      66        4172 :     mpFont[1] = rGfx.getFallbackID();
      67             : 
      68        4172 :     PrintFontManager &rMgr = PrintFontManager::get();
      69        8344 :     mbSymbol = mpFont[0] != -1 &&
      70        8344 :                 rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL;
      71        4172 : }
      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        1092 : 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        1092 :     mnFontID                          = nFontID;
     117        1092 :     maVirtualStatus.maFont            = OString();
     118        1092 :     maVirtualStatus.maEncoding        = RTL_TEXTENCODING_DONTKNOW;
     119        1092 :     maVirtualStatus.mnTextHeight      = nHeight;
     120        1092 :     maVirtualStatus.mnTextWidth       = nWidth;
     121        1092 :     maVirtualStatus.mbArtItalic       = bArtItalic;
     122        1092 :     maVirtualStatus.mbArtBold         = bArtBold;
     123        1092 :     mnTextAngle                       = nAngle;
     124        1092 :     mbTextVertical                    = bVertical;
     125             : 
     126        1092 :     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 :     if (!nLen)
     307           0 :         return;
     308             : 
     309           0 :     fontID nRestoreFont = mnFontID;
     310             : 
     311             :     // setup font[substitutes] and map the string into the symbol area in case of
     312             :     // symbol font
     313           0 :     Font2 aFont(*this);
     314             :     sal_Unicode *pEffectiveStr;
     315           0 :     if ( aFont.IsSymbolFont() )
     316             :     {
     317           0 :         pEffectiveStr = (sal_Unicode*)alloca(nLen * sizeof(pStr[0]));
     318           0 :         for (int i = 0; i < nLen; i++)
     319           0 :             pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
     320             :     }
     321             :     else
     322             :     {
     323           0 :         pEffectiveStr = const_cast<sal_Unicode*>(pStr);
     324             :     }
     325             : 
     326           0 :     fontID    *pFontMap   = (fontID*)    alloca(nLen * sizeof(fontID));
     327           0 :     sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32));
     328             : 
     329           0 :     for( int n = 0; n < nLen; n++ )
     330             :     {
     331           0 :         CharacterMetric aBBox;
     332             :         // coverity[array_vs_singleton]
     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           0 :                     Point(nCurrentPointX + nDelta, nCurrentPointY),
     400             :                     pEffectiveStr + nFrom, nTo - nFrom,
     401           0 :                     pNewDeltaArray + nFrom );
     402             :         }
     403             :         else
     404             :         {
     405             :             drawText(
     406           0 :                     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             : }
     428             : 
     429           0 : bool PrinterGfx::drawVerticalizedText(
     430             :                                       const Point& rPoint,
     431             :                                       const sal_Unicode* pStr,
     432             :                                       sal_Int16 nLen,
     433             :                                       const sal_Int32* pDeltaArray
     434             :                                       )
     435             : {
     436           0 :     PrintFontManager &rMgr = PrintFontManager::get();
     437           0 :     PrintFontInfo aInfo;
     438           0 :     if (!rMgr.getFontInfo(mnFontID, aInfo))
     439           0 :         return false;
     440             : 
     441           0 :     sal_Int32* pDelta = (sal_Int32*)alloca( nLen * sizeof(sal_Int32) );
     442             : 
     443           0 :     int nTextScale   = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     444           0 :     int nNormalAngle = mnTextAngle;
     445           0 :     int nDeltaAngle, nLastPos = 0;
     446             : 
     447           0 :     double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
     448           0 :     double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
     449             : 
     450           0 :     bool* pGsubFlags = (bool*)alloca( nLen * sizeof(bool) );
     451           0 :     rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
     452             : 
     453           0 :     Point aPoint( rPoint );
     454           0 :     for( int i = 0; i < nLen; )
     455             :     {
     456           0 :         while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
     457           0 :             i++;
     458           0 :         if( i <= nLen && i > nLastPos )
     459             :         {
     460           0 :             for( int n = nLastPos; n < i; n++ )
     461           0 :                 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
     462             : 
     463             :             SetFont( mnFontID,
     464             :                      maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
     465             :                      nNormalAngle, mbTextVertical,
     466             :                      maVirtualStatus.mbArtItalic,
     467           0 :                      maVirtualStatus.mbArtBold );
     468           0 :             drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
     469             : 
     470           0 :             aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
     471           0 :             aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
     472             :         }
     473           0 :         if( i < nLen )
     474             :         {
     475           0 :             int nOldWidth   = maVirtualStatus.mnTextWidth;
     476           0 :             int nOldHeight  = maVirtualStatus.mnTextHeight;
     477             :             SetFont( mnFontID,
     478             :                      nTextScale,
     479             :                      maVirtualStatus.mnTextHeight,
     480             :                      nNormalAngle + nDeltaAngle,
     481             :                      mbTextVertical,
     482             :                      maVirtualStatus.mbArtItalic,
     483           0 :                      maVirtualStatus.mbArtBold );
     484             : 
     485           0 :             double nA = nTextScale * aInfo.m_nAscend / 1000.0;
     486           0 :             double nD = nTextScale * aInfo.m_nDescend / 1000.0;
     487           0 :             double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
     488           0 :             if( !pGsubFlags[i] )
     489           0 :                 nD *= fStretch;
     490             : 
     491           0 :             Point aPos( aPoint );
     492           0 :             switch( nDeltaAngle )
     493             :             {
     494             :                 case +900:
     495           0 :                     aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
     496           0 :                     aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
     497           0 :                     break;
     498             :                 case -900:
     499           0 :                     aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
     500           0 :                     aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
     501           0 :                     break;
     502             :             }
     503           0 :             drawText( aPos, pStr+i, 1, NULL );
     504           0 :             if( i < nLen-1 && pDeltaArray )
     505             :             {
     506           0 :                 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
     507           0 :                 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
     508             :             }
     509             : 
     510             :             // swap text width/height again
     511             :             SetFont( mnFontID,
     512             :                      nOldHeight,
     513             :                      nOldWidth,
     514             :                      nNormalAngle,
     515             :                      mbTextVertical,
     516             :                      maVirtualStatus.mbArtItalic,
     517           0 :                      maVirtualStatus.mbArtBold );
     518             :         }
     519           0 :         i++;
     520           0 :         nLastPos = i;
     521             :     }
     522           0 :     mnTextAngle = nNormalAngle;
     523           0 :     return true;
     524             : }
     525             : 
     526             : void
     527           0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
     528             :                            sal_Int16 nLen, const sal_Int32* pDeltaArray)
     529             : {
     530             :     // treat it like a builtin font in case a user has that font also in the
     531             :     // printer. This is not so unlikely as it may seem; no print embedding
     532             :     // licensed fonts are often used (or so they say) in companies:
     533             :     // they are installed on displays and printers, but get not embedded in
     534             :     // print files or documents because they are not licensed for use outside
     535             :     // the company.
     536           0 :     OString aMessage( "The font " );
     537           0 :     aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
     538           0 :             RTL_TEXTENCODING_ASCII_US );
     539           0 :     aMessage += " could not be downloaded\nbecause its license does not allow for that";
     540           0 :     PSComment( aMessage.getStr() );
     541             : 
     542             :     OString aFontName = OUStringToOString(
     543           0 :             mrFontMgr.getPSName(mnFontID),
     544           0 :             RTL_TEXTENCODING_ASCII_US);
     545           0 :     PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
     546             : 
     547           0 :     sal_Size  nSize    = 4 * nLen;
     548           0 :     unsigned char* pBuffer = (unsigned char*)alloca (nSize* sizeof(unsigned char));
     549             : 
     550           0 :     ConverterFactory &rCvt = GetConverterFactory ();
     551           0 :     nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
     552             : 
     553           0 :     PSMoveTo (rPoint);
     554           0 :     PSShowText (pBuffer, nLen, nSize, pDeltaArray);
     555           0 : }
     556             : 
     557             : void
     558           0 : PrinterGfx::drawText(
     559             :                      const Point& rPoint,
     560             :                      const sal_Unicode* pStr,
     561             :                      sal_Int16 nLen,
     562             :                      const sal_Int32* pDeltaArray
     563             :                      )
     564             : {
     565           0 :     if (!(nLen > 0))
     566           0 :         return;
     567             : 
     568           0 :     fonttype::type   eType          = mrFontMgr.getFontType (mnFontID);
     569             : 
     570           0 :     if (eType == fonttype::Type1)
     571           0 :         PSUploadPS1Font (mnFontID);
     572             : 
     573           0 :     if (   eType == fonttype::TrueType
     574           0 :         && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
     575             :     {
     576           0 :         LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
     577           0 :         return;
     578             :     }
     579             : 
     580           0 :     if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
     581             :     {
     582           0 :         GlyphSet aGSet( mnFontID, mbTextVertical );
     583           0 :         aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
     584           0 :         return;
     585             :     }
     586             : 
     587             :     // search for a glyph set matching the set font
     588           0 :     std::list< GlyphSet >::iterator aIter;
     589           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     590           0 :         if (   ((*aIter).GetFontID()  == mnFontID)
     591           0 :             && ((*aIter).IsVertical() == mbTextVertical))
     592             :         {
     593           0 :             (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     594           0 :             break;
     595             :         }
     596             : 
     597             :     // not found ? create a new one
     598           0 :     if (aIter == maPS3Font.end())
     599             :     {
     600           0 :         maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
     601           0 :         maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     602             :     }
     603             : }
     604             : 
     605             : int
     606        4172 : PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
     607             : {
     608        4172 :     b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
     609        4172 :     int w = b_vert ? p_bbox->height : p_bbox->width;
     610        4172 :     w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     611        4172 :     return w;
     612             : }
     613             : 
     614             : fontID
     615        4172 : PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
     616             : {
     617        4172 :     p_bbox->width  = -1;
     618        4172 :     p_bbox->height = -1;
     619             : 
     620        4172 :     for (fontID n = 0; n < Font2Size; n++)
     621             :     {
     622        4172 :         fontID n_font = rFont.GetFont(n);
     623        4172 :         if (n_font != -1)
     624        4172 :             mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
     625        4172 :         if (p_bbox->width >= 0 && p_bbox->height >= 0)
     626        4172 :             return n_font;
     627             :     }
     628           0 :     if (n_char != '?')
     629           0 :         return getCharMetric (rFont, '?', p_bbox);
     630             : 
     631           0 :     return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
     632             : }
     633             : 
     634             : sal_Int32
     635        4172 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
     636             : {
     637        4172 :     Font2 aFont(*this);
     638        4172 :     if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
     639             :     {
     640           0 :         nFrom += 0xF000;
     641           0 :         nTo   += 0xF000;
     642             :     }
     643             : 
     644        8344 :     for( int n = 0; n < (nTo - nFrom + 1); n++ )
     645             :     {
     646        4172 :         CharacterMetric aBBox;
     647             :         // coverity[array_vs_singleton]
     648        4172 :         getCharMetric (aFont, n + nFrom, &aBBox);
     649        4172 :         pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
     650             :     }
     651             : 
     652             :     // returned metrics have postscript precision
     653        4172 :     return 1000;
     654             : }
     655             : 
     656             : /*
     657             :  * spool the converted truetype fonts to the page header after the page body is
     658             :  * complete
     659             :  * for Type1 fonts spool additional reencoding vectors that are necessary to access the
     660             :  * whole font
     661             :  */
     662             : 
     663             : void
     664           0 : PrinterGfx::OnEndPage ()
     665             : {
     666           0 : }
     667             : 
     668             : void
     669           0 : PrinterGfx::OnEndJob ()
     670             : {
     671           0 :     maPS3Font.clear();
     672           0 :     maPS1Font.clear();
     673           0 : }
     674             : 
     675             : void
     676           0 : PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
     677             : {
     678             :     // write all type 1 fonts
     679           0 :     std::list< sal_Int32 >::iterator aFont;
     680             :     // already in the document header ?
     681           0 :     for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
     682             :     {
     683           0 :         const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
     684           0 :         OUString aUNCPath;
     685           0 :         osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
     686           0 :         osl::File aFontFile (aUNCPath);
     687             : 
     688             :         // provide the pfb or pfa font as a (pfa-)font resource
     689             :         OString aPostScriptName =
     690           0 :             OUStringToOString ( mrFontMgr.getPSName(*aFont),
     691           0 :                                      RTL_TEXTENCODING_ASCII_US );
     692             : 
     693           0 :         WritePS (pFile, "%%BeginResource: font ");
     694           0 :         WritePS (pFile, aPostScriptName.getStr());
     695           0 :         WritePS (pFile, "\n");
     696             : 
     697           0 :         osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
     698           0 :         if (nError == osl::File::E_None)
     699             :         {
     700           0 :             convertPfbToPfa (aFontFile, *pFile);
     701           0 :             aFontFile.close ();
     702             : 
     703           0 :             char lastchar = '\n';
     704             : 
     705           0 :             if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
     706             :             {
     707           0 :                 sal_uInt64 uBytes(1);
     708           0 :                 pFile->read((void *)(&lastchar), uBytes, uBytes);
     709             :             }
     710             : 
     711           0 :             if (lastchar != '\n')
     712           0 :                 WritePS (pFile, "\n");
     713             :         }
     714           0 :         WritePS (pFile, "%%EndResource\n");
     715           0 :         rSuppliedFonts.push_back( aPostScriptName );
     716           0 :     }
     717             : 
     718             :     // write glyphsets and reencodings
     719           0 :     std::list< GlyphSet >::iterator aIter;
     720           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     721             :     {
     722           0 :         if (aIter->GetFontType() == fonttype::TrueType)
     723             :         {
     724           0 :             aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts, rSuppliedFonts );
     725             :         }
     726             :         else
     727             :         {
     728           0 :             aIter->PSUploadEncoding (pFile, *this);
     729             :         }
     730             :     }
     731        1233 : }
     732             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10