LCOV - code coverage report
Current view: top level - vcl/generic/print - text_gfx.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 46 326 14.1 %
Date: 2015-06-13 12:38:46 Functions: 10 20 50.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             : #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        2086 :         fontID  GetFont (int nIdx) const
      55        2086 :                     { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
      56        2086 :         bool    IsSymbolFont () const
      57        2086 :                     { return mbSymbol; }
      58             : 
      59             :         explicit Font2 (const PrinterGfx &rGfx);
      60        2086 :         ~Font2 () {}
      61             : };
      62             : 
      63        2086 : Font2::Font2(const PrinterGfx &rGfx)
      64             : {
      65        2086 :     mpFont[0] = rGfx.GetFontID();
      66        2086 :     mpFont[1] = rGfx.getFallbackID();
      67             : 
      68        2086 :     PrintFontManager &rMgr = PrintFontManager::get();
      69        4172 :     mbSymbol = mpFont[0] != -1 &&
      70        4172 :                 rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL;
      71        2086 : }
      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         753 : 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         753 :     mnFontID                          = nFontID;
     117         753 :     maVirtualStatus.maFont.clear();
     118         753 :     maVirtualStatus.maEncoding        = RTL_TEXTENCODING_DONTKNOW;
     119         753 :     maVirtualStatus.mnTextHeight      = nHeight;
     120         753 :     maVirtualStatus.mnTextWidth       = nWidth;
     121         753 :     maVirtualStatus.mbArtItalic       = bArtItalic;
     122         753 :     maVirtualStatus.mbArtBold         = bArtBold;
     123         753 :     mnTextAngle                       = nAngle;
     124         753 :     mbTextVertical                    = bVertical;
     125             : 
     126         753 :     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 = static_cast<sal_GlyphId*>(alloca(sizeof(sal_Int32)*nLen));
     201           0 :         sal_Int32* pTempDelta = static_cast<sal_Int32*>(alloca(sizeof(sal_Int32)*nLen));
     202           0 :         sal_Unicode* pTempUnicodes = static_cast<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 = static_cast<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   = static_cast<fontID*>(alloca(nLen * sizeof(fontID)));
     327           0 :     sal_Int32 *pCharWidth = static_cast<sal_Int32*>(alloca(nLen * sizeof(sal_Int32)));
     328             : 
     329           0 :     for( int n = 0; n < nLen; n++ )
     330             :     {
     331           0 :         CharacterMetric aBBox;
     332             :         // coverity[callee_ptr_arith]
     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 = static_cast<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 = static_cast<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 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 = static_cast<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             :         int nDeltaAngle;
     457           0 :         while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
     458           0 :             i++;
     459           0 :         if( i <= nLen && i > nLastPos )
     460             :         {
     461           0 :             for( int n = nLastPos; n < i; n++ )
     462           0 :                 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
     463             : 
     464             :             SetFont( mnFontID,
     465             :                      maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
     466             :                      nNormalAngle, mbTextVertical,
     467             :                      maVirtualStatus.mbArtItalic,
     468           0 :                      maVirtualStatus.mbArtBold );
     469           0 :             drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
     470             : 
     471           0 :             aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
     472           0 :             aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
     473             :         }
     474           0 :         if( i < nLen )
     475             :         {
     476           0 :             int nOldWidth   = maVirtualStatus.mnTextWidth;
     477           0 :             int nOldHeight  = maVirtualStatus.mnTextHeight;
     478             :             SetFont( mnFontID,
     479             :                      nTextScale,
     480             :                      maVirtualStatus.mnTextHeight,
     481             :                      nNormalAngle + nDeltaAngle,
     482             :                      mbTextVertical,
     483             :                      maVirtualStatus.mbArtItalic,
     484           0 :                      maVirtualStatus.mbArtBold );
     485             : 
     486           0 :             double nA = nTextScale * aInfo.m_nAscend / 1000.0;
     487           0 :             double nD = nTextScale * aInfo.m_nDescend / 1000.0;
     488           0 :             double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
     489           0 :             if( !pGsubFlags[i] )
     490           0 :                 nD *= fStretch;
     491             : 
     492           0 :             Point aPos( aPoint );
     493           0 :             switch( nDeltaAngle )
     494             :             {
     495             :                 case +900:
     496           0 :                     aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
     497           0 :                     aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
     498           0 :                     break;
     499             :                 case -900:
     500           0 :                     aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
     501           0 :                     aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
     502           0 :                     break;
     503             :             }
     504           0 :             drawText( aPos, pStr+i, 1, NULL );
     505           0 :             if( i < nLen-1 && pDeltaArray )
     506             :             {
     507           0 :                 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
     508           0 :                 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
     509             :             }
     510             : 
     511             :             // swap text width/height again
     512             :             SetFont( mnFontID,
     513             :                      nOldHeight,
     514             :                      nOldWidth,
     515             :                      nNormalAngle,
     516             :                      mbTextVertical,
     517             :                      maVirtualStatus.mbArtItalic,
     518           0 :                      maVirtualStatus.mbArtBold );
     519             :         }
     520           0 :         i++;
     521           0 :         nLastPos = i;
     522             :     }
     523           0 :     mnTextAngle = nNormalAngle;
     524           0 :     return true;
     525             : }
     526             : 
     527             : void
     528           0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
     529             :                            sal_Int16 nLen, const sal_Int32* pDeltaArray)
     530             : {
     531             :     // treat it like a builtin font in case a user has that font also in the
     532             :     // printer. This is not so unlikely as it may seem; no print embedding
     533             :     // licensed fonts are often used (or so they say) in companies:
     534             :     // they are installed on displays and printers, but get not embedded in
     535             :     // print files or documents because they are not licensed for use outside
     536             :     // the company.
     537           0 :     OString aMessage( "The font " );
     538           0 :     aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
     539           0 :             RTL_TEXTENCODING_ASCII_US );
     540           0 :     aMessage += " could not be downloaded\nbecause its license does not allow for that";
     541           0 :     PSComment( aMessage.getStr() );
     542             : 
     543             :     OString aFontName = OUStringToOString(
     544           0 :             mrFontMgr.getPSName(mnFontID),
     545           0 :             RTL_TEXTENCODING_ASCII_US);
     546           0 :     PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
     547             : 
     548           0 :     sal_Size  nSize    = 4 * nLen;
     549           0 :     unsigned char* pBuffer = static_cast<unsigned char*>(alloca (nSize* sizeof(unsigned char)));
     550             : 
     551           0 :     ConverterFactory &rCvt = GetConverterFactory ();
     552           0 :     nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
     553             : 
     554           0 :     PSMoveTo (rPoint);
     555           0 :     PSShowText (pBuffer, nLen, nSize, pDeltaArray);
     556           0 : }
     557             : 
     558             : void
     559           0 : PrinterGfx::drawText(
     560             :                      const Point& rPoint,
     561             :                      const sal_Unicode* pStr,
     562             :                      sal_Int16 nLen,
     563             :                      const sal_Int32* pDeltaArray
     564             :                      )
     565             : {
     566           0 :     if (!(nLen > 0))
     567           0 :         return;
     568             : 
     569           0 :     fonttype::type   eType          = mrFontMgr.getFontType (mnFontID);
     570             : 
     571           0 :     if (eType == fonttype::Type1)
     572           0 :         PSUploadPS1Font (mnFontID);
     573             : 
     574           0 :     if (   eType == fonttype::TrueType
     575           0 :         && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
     576             :     {
     577           0 :         LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
     578           0 :         return;
     579             :     }
     580             : 
     581           0 :     if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
     582             :     {
     583           0 :         GlyphSet aGSet( mnFontID, mbTextVertical );
     584           0 :         aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
     585           0 :         return;
     586             :     }
     587             : 
     588             :     // search for a glyph set matching the set font
     589           0 :     std::list< GlyphSet >::iterator aIter;
     590           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     591           0 :         if (   ((*aIter).GetFontID()  == mnFontID)
     592           0 :             && ((*aIter).IsVertical() == mbTextVertical))
     593             :         {
     594           0 :             (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     595           0 :             break;
     596             :         }
     597             : 
     598             :     // not found ? create a new one
     599           0 :     if (aIter == maPS3Font.end())
     600             :     {
     601           0 :         maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
     602           0 :         maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
     603             :     }
     604             : }
     605             : 
     606             : int
     607        2086 : PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
     608             : {
     609        2086 :     b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
     610        2086 :     int w = b_vert ? p_bbox->height : p_bbox->width;
     611        2086 :     w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
     612        2086 :     return w;
     613             : }
     614             : 
     615             : fontID
     616        2086 : PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
     617             : {
     618        2086 :     p_bbox->width  = -1;
     619        2086 :     p_bbox->height = -1;
     620             : 
     621        2086 :     for (fontID n = 0; n < Font2Size; n++)
     622             :     {
     623        2086 :         fontID n_font = rFont.GetFont(n);
     624        2086 :         if (n_font != -1)
     625        2086 :             mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
     626        2086 :         if (p_bbox->width >= 0 && p_bbox->height >= 0)
     627        2086 :             return n_font;
     628             :     }
     629           0 :     if (n_char != '?')
     630           0 :         return getCharMetric (rFont, '?', p_bbox);
     631             : 
     632           0 :     return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
     633             : }
     634             : 
     635             : sal_Int32
     636        2086 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
     637             : {
     638        2086 :     Font2 aFont(*this);
     639        2086 :     if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
     640             :     {
     641           0 :         nFrom += 0xF000;
     642           0 :         nTo   += 0xF000;
     643             :     }
     644             : 
     645        4172 :     for( int n = 0; n < (nTo - nFrom + 1); n++ )
     646             :     {
     647        2086 :         CharacterMetric aBBox;
     648             :         // coverity[callee_ptr_arith]
     649        2086 :         getCharMetric(aFont, n + nFrom, &aBBox);
     650        2086 :         pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
     651             :     }
     652             : 
     653             :     // returned metrics have postscript precision
     654        2086 :     return 1000;
     655             : }
     656             : 
     657             : /*
     658             :  * spool the converted truetype fonts to the page header after the page body is
     659             :  * complete
     660             :  * for Type1 fonts spool additional reencoding vectors that are necessary to access the
     661             :  * whole font
     662             :  */
     663             : 
     664             : void
     665           0 : PrinterGfx::OnEndJob ()
     666             : {
     667           0 :     maPS3Font.clear();
     668           0 :     maPS1Font.clear();
     669           0 : }
     670             : 
     671             : void
     672           0 : PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
     673             : {
     674             :     // write all type 1 fonts
     675           0 :     std::list< sal_Int32 >::iterator aFont;
     676             :     // already in the document header ?
     677           0 :     for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
     678             :     {
     679           0 :         const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
     680           0 :         OUString aUNCPath;
     681           0 :         osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
     682           0 :         osl::File aFontFile (aUNCPath);
     683             : 
     684             :         // provide the pfb or pfa font as a (pfa-)font resource
     685             :         OString aPostScriptName =
     686           0 :             OUStringToOString ( mrFontMgr.getPSName(*aFont),
     687           0 :                                      RTL_TEXTENCODING_ASCII_US );
     688             : 
     689           0 :         WritePS (pFile, "%%BeginResource: font ");
     690           0 :         WritePS (pFile, aPostScriptName.getStr());
     691           0 :         WritePS (pFile, "\n");
     692             : 
     693           0 :         osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
     694           0 :         if (nError == osl::File::E_None)
     695             :         {
     696           0 :             convertPfbToPfa (aFontFile, *pFile);
     697           0 :             aFontFile.close ();
     698             : 
     699           0 :             char lastchar = '\n';
     700             : 
     701           0 :             if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
     702             :             {
     703           0 :                 sal_uInt64 uBytes(1);
     704           0 :                 pFile->read(static_cast<void *>(&lastchar), uBytes, uBytes);
     705             :             }
     706             : 
     707           0 :             if (lastchar != '\n')
     708           0 :                 WritePS (pFile, "\n");
     709             :         }
     710           0 :         WritePS (pFile, "%%EndResource\n");
     711           0 :         rSuppliedFonts.push_back( aPostScriptName );
     712           0 :     }
     713             : 
     714             :     // write glyphsets and reencodings
     715           0 :     std::list< GlyphSet >::iterator aIter;
     716           0 :     for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
     717             :     {
     718           0 :         if (aIter->GetFontType() == fonttype::TrueType)
     719             :         {
     720           0 :             aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts, rSuppliedFonts );
     721             :         }
     722             :         else
     723             :         {
     724           0 :             aIter->PSUploadEncoding (pFile, *this);
     725             :         }
     726             :     }
     727         801 : }
     728             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11