LCOV - code coverage report
Current view: top level - vcl/generic/print - text_gfx.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 11 336 3.3 %
Date: 2012-08-25 Functions: 1 21 4.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 423 0.0 %

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

Generated by: LCOV version 1.10