LCOV - code coverage report
Current view: top level - vcl/generic/print - glyphset.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 368 0.3 %
Date: 2015-06-13 12:38:46 Functions: 2 31 6.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "glyphset.hxx"
      21             : #include "psputil.hxx"
      22             : 
      23             : #include "sft.hxx"
      24             : 
      25             : #include "generic/printergfx.hxx"
      26             : #include "fontsubset.hxx"
      27             : #include "fontmanager.hxx"
      28             : 
      29             : #include <tools/gen.hxx>
      30             : 
      31             : #include "osl/thread.h"
      32             : 
      33             : #include "sal/alloca.h"
      34             : 
      35             : #include "rtl/ustring.hxx"
      36             : #include "rtl/strbuf.hxx"
      37             : 
      38             : #include <unotools/tempfile.hxx>
      39             : 
      40             : #include <set>
      41             : #include <map>
      42             : #include <algorithm>
      43             : 
      44             : using namespace vcl;
      45             : using namespace psp;
      46             : 
      47           0 : GlyphSet::GlyphSet (sal_Int32 nFontID, bool bVertical)
      48             :         : mnFontID (nFontID),
      49           0 :           mbVertical (bVertical)
      50             : {
      51           0 :     PrintFontManager &rMgr = PrintFontManager::get();
      52           0 :     meBaseType          = rMgr.getFontType (mnFontID);
      53           0 :     maBaseName          = OUStringToOString (rMgr.getPSName(mnFontID),
      54           0 :                                            RTL_TEXTENCODING_ASCII_US);
      55           0 :     mnBaseEncoding      = rMgr.getFontEncoding(mnFontID);
      56           0 :     mbUseFontEncoding   = rMgr.getUseOnlyFontEncoding(mnFontID);
      57           0 : }
      58             : 
      59           0 : GlyphSet::~GlyphSet ()
      60             : {
      61             :     /* FIXME delete the glyphlist ??? */
      62           0 : }
      63             : 
      64             : bool
      65           0 : GlyphSet::GetCharID (
      66             :                      sal_Unicode nChar,
      67             :                      unsigned char* nOutGlyphID,
      68             :                      sal_Int32* nOutGlyphSetID
      69             :                      )
      70             : {
      71           0 :     return    LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
      72           0 :            || AddCharID    (nChar, nOutGlyphID, nOutGlyphSetID);
      73             : }
      74             : 
      75             : bool
      76           0 : GlyphSet::GetGlyphID (
      77             :                       sal_GlyphId nGlyph,
      78             :                       sal_Unicode nUnicode,
      79             :                       unsigned char* nOutGlyphID,
      80             :                       sal_Int32* nOutGlyphSetID
      81             :                      )
      82             : {
      83           0 :     return    LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
      84           0 :            || AddGlyphID    (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
      85             : }
      86             : 
      87             : bool
      88           0 : GlyphSet::LookupCharID (
      89             :                         sal_Unicode nChar,
      90             :                         unsigned char* nOutGlyphID,
      91             :                         sal_Int32* nOutGlyphSetID
      92             :                         )
      93             : {
      94           0 :     char_list_t::iterator aGlyphSet;
      95             :     sal_Int32             nGlyphSetID;
      96             : 
      97             :     // loop through all the font subsets
      98           0 :     for (aGlyphSet  = maCharList.begin(), nGlyphSetID = 1;
      99           0 :          aGlyphSet != maCharList.end();
     100             :          ++aGlyphSet, nGlyphSetID++)
     101             :     {
     102             :         // check every subset if it contains the queried unicode char
     103           0 :         char_map_t::const_iterator aGlyph = (*aGlyphSet).find (nChar);
     104           0 :         if (aGlyph != (*aGlyphSet).end())
     105             :         {
     106             :             // success: found the unicode char, return the glyphid and the glyphsetid
     107           0 :             *nOutGlyphSetID = nGlyphSetID;
     108           0 :             *nOutGlyphID    = (*aGlyph).second;
     109           0 :             return true;
     110             :         }
     111             :     }
     112             : 
     113           0 :     *nOutGlyphSetID = -1;
     114           0 :     *nOutGlyphID    =  0;
     115           0 :     return false;
     116             : }
     117             : 
     118             : bool
     119           0 : GlyphSet::LookupGlyphID (
     120             :                         sal_GlyphId nGlyph,
     121             :                         unsigned char* nOutGlyphID,
     122             :                         sal_Int32* nOutGlyphSetID
     123             :                         )
     124             : {
     125           0 :     glyph_list_t::iterator aGlyphSet;
     126             :     sal_Int32             nGlyphSetID;
     127             : 
     128             :     // loop through all the font subsets
     129           0 :     for (aGlyphSet  = maGlyphList.begin(), nGlyphSetID = 1;
     130           0 :          aGlyphSet != maGlyphList.end();
     131             :          ++aGlyphSet, nGlyphSetID++)
     132             :     {
     133             :         // check every subset if it contains the queried unicode char
     134           0 :         glyph_map_t::const_iterator aGlyph = (*aGlyphSet).find (nGlyph);
     135           0 :         if (aGlyph != (*aGlyphSet).end())
     136             :         {
     137             :             // success: found the glyph id, return the mapped glyphid and the glyphsetid
     138           0 :             *nOutGlyphSetID = nGlyphSetID;
     139           0 :             *nOutGlyphID    = (*aGlyph).second;
     140           0 :             return true;
     141             :         }
     142             :     }
     143             : 
     144           0 :     *nOutGlyphSetID = -1;
     145           0 :     *nOutGlyphID    =  0;
     146           0 :     return false;
     147             : }
     148             : 
     149             : unsigned char
     150           0 : GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar)
     151             : {
     152             :     static rtl_UnicodeToTextConverter aConverter =
     153           0 :                 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252);
     154             :     static rtl_UnicodeToTextContext aContext =
     155           0 :              rtl_createUnicodeToTextContext( aConverter );
     156             : 
     157             :     sal_Char            nAnsiChar;
     158             :     sal_uInt32          nCvtInfo;
     159             :     sal_Size            nCvtChars;
     160             :        const sal_uInt32    nCvtFlags =  RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
     161           0 :                                    | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
     162             : 
     163             :     sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
     164             :                 &nUnicodeChar, 1, &nAnsiChar, 1,
     165           0 :                 nCvtFlags, &nCvtInfo, &nCvtChars );
     166             : 
     167           0 :     return nSize == 1 ? (unsigned char)nAnsiChar : (unsigned char)0;
     168             : }
     169             : 
     170             : unsigned char
     171           0 : GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar)
     172             : {
     173           0 :     if (0x0000 < nUnicodeChar && nUnicodeChar < 0x0100)
     174           0 :         return (unsigned char)nUnicodeChar;
     175           0 :     if (0xf000 < nUnicodeChar && nUnicodeChar < 0xf100)
     176           0 :         return (unsigned char)nUnicodeChar;
     177             : 
     178           0 :     return 0;
     179             : }
     180             : 
     181             : void
     182           0 : GlyphSet::AddNotdef (char_map_t &rCharMap)
     183             : {
     184           0 :     if (rCharMap.empty())
     185           0 :         rCharMap[0] = 0;
     186           0 : }
     187             : 
     188             : void
     189           0 : GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
     190             : {
     191           0 :     if (rGlyphMap.empty())
     192           0 :         rGlyphMap[0] = 0;
     193           0 : }
     194             : bool
     195           0 : GlyphSet::AddCharID (
     196             :                      sal_Unicode nChar,
     197             :                      unsigned char* nOutGlyphID,
     198             :                      sal_Int32* nOutGlyphSetID
     199             :                      )
     200             : {
     201             :     unsigned char nMappedChar;
     202             : 
     203             :     // XXX important: avoid to reencode type1 symbol fonts
     204           0 :     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
     205           0 :         nMappedChar = GetSymbolMapping (nChar);
     206             :     else
     207           0 :         nMappedChar = GetAnsiMapping (nChar);
     208             : 
     209             :     // create an empty glyphmap that is reserved for iso1252 encoded glyphs
     210             :     // (or -- unencoded -- symbol glyphs) and a second map that takes any other
     211           0 :     if (maCharList.empty())
     212             :     {
     213           0 :         char_map_t aMap, aMapp;
     214             : 
     215           0 :         maCharList.push_back (aMap);
     216           0 :         maCharList.push_back (aMapp);
     217             :     }
     218             :     // if the last map is full, create a new one
     219           0 :     if ((!nMappedChar) && (maCharList.back().size() == 255))
     220             :     {
     221           0 :         char_map_t aMap;
     222           0 :         maCharList.push_back (aMap);
     223             :     }
     224             : 
     225             :     // insert a new glyph in the font subset
     226           0 :     if (nMappedChar)
     227             :     {
     228             :         // always put iso1252 chars into the first map, map them on itself
     229           0 :         char_map_t& aGlyphSet = maCharList.front();
     230           0 :         AddNotdef (aGlyphSet);
     231             : 
     232           0 :         aGlyphSet [nChar] = nMappedChar;
     233           0 :         *nOutGlyphSetID   = 1;
     234           0 :         *nOutGlyphID      = nMappedChar;
     235             :     }
     236             :     else
     237             :     {
     238             :         // other chars are just appended to the list
     239           0 :         char_map_t& aGlyphSet = maCharList.back();
     240           0 :         AddNotdef (aGlyphSet);
     241             : 
     242           0 :         int nSize         = aGlyphSet.size();
     243             : 
     244           0 :         aGlyphSet [nChar] = nSize;
     245           0 :         *nOutGlyphSetID   = maCharList.size();
     246           0 :         *nOutGlyphID      = aGlyphSet [nChar];
     247             :     }
     248             : 
     249           0 :     return true;
     250             : }
     251             : 
     252             : bool
     253           0 : GlyphSet::AddGlyphID (
     254             :                      sal_GlyphId nGlyph,
     255             :                      sal_Unicode nUnicode,
     256             :                      unsigned char* nOutGlyphID,
     257             :                      sal_Int32* nOutGlyphSetID
     258             :                      )
     259             : {
     260           0 :     unsigned char nMappedChar = 0;
     261             : 
     262             :     // XXX important: avoid to reencode type1 symbol fonts
     263           0 :     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
     264           0 :         nMappedChar = GetSymbolMapping (nUnicode);
     265             : 
     266             :     // create an empty glyphmap that is reserved for unencoded symbol glyphs,
     267             :     // and a second map that takes any other
     268           0 :     if (maGlyphList.empty())
     269             :     {
     270           0 :         glyph_map_t aMap, aMapp;
     271             : 
     272           0 :         maGlyphList.push_back (aMap);
     273           0 :         maGlyphList.push_back (aMapp);
     274             :     }
     275             :     // if the last map is full, create a new one
     276           0 :     if ((!nMappedChar) && (maGlyphList.back().size() == 255))
     277             :     {
     278           0 :         glyph_map_t aMap;
     279           0 :         maGlyphList.push_back (aMap);
     280             :     }
     281             : 
     282             :     // insert a new glyph in the font subset
     283           0 :     if (nMappedChar)
     284             :     {
     285             :         // always put symbol glyphs into the first map, map them on itself
     286           0 :         glyph_map_t& aGlyphSet = maGlyphList.front();
     287           0 :         AddNotdef (aGlyphSet);
     288             : 
     289           0 :         aGlyphSet [nGlyph] = nMappedChar;
     290           0 :         *nOutGlyphSetID    = 1;
     291           0 :         *nOutGlyphID       = nMappedChar;
     292             :     }
     293             :     else
     294             :     {
     295             :         // other glyphs are just appended to the list
     296           0 :         glyph_map_t& aGlyphSet = maGlyphList.back();
     297           0 :         AddNotdef (aGlyphSet);
     298             : 
     299           0 :         int nSize         = aGlyphSet.size();
     300             : 
     301           0 :         aGlyphSet [nGlyph] = nSize;
     302           0 :         *nOutGlyphSetID   = maGlyphList.size();
     303           0 :         *nOutGlyphID      = aGlyphSet [nGlyph];
     304             :     }
     305             : 
     306           0 :     return true;
     307             : }
     308             : 
     309             : OString
     310           0 : GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID)
     311             : {
     312           0 :     if (meBaseType == fonttype::TrueType)
     313             :     {
     314           0 :         OStringBuffer aSetName( maBaseName.getLength() + 32 );
     315           0 :         aSetName.append( maBaseName );
     316           0 :         aSetName.append( "FID" );
     317           0 :         aSetName.append( mnFontID );
     318           0 :         aSetName.append( mbVertical ? "VCSet" : "HCSet" );
     319           0 :         aSetName.append( nGlyphSetID );
     320           0 :         return aSetName.makeStringAndClear();
     321             :     }
     322             :     else
     323             :     {
     324           0 :         return maBaseName;
     325             :     }
     326             : }
     327             : 
     328             : OString
     329           0 : GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
     330             : {
     331           0 :     if (meBaseType == fonttype::TrueType)
     332             :     {
     333           0 :         OStringBuffer aSetName( maBaseName.getLength() + 32 );
     334           0 :         aSetName.append( maBaseName );
     335           0 :         aSetName.append( "FID" );
     336           0 :         aSetName.append( mnFontID );
     337           0 :         aSetName.append( mbVertical ? "VGSet" : "HGSet" );
     338           0 :         aSetName.append( nGlyphSetID );
     339           0 :         return aSetName.makeStringAndClear();
     340             :     }
     341             :     else
     342             :     {
     343           0 :         return maBaseName;
     344             :     }
     345             : }
     346             : 
     347             : sal_Int32
     348           0 : GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
     349             : {
     350           0 :     if (meBaseType == fonttype::TrueType)
     351           0 :         return RTL_TEXTENCODING_DONTKNOW;
     352             :     else
     353             :     {
     354           0 :         if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
     355           0 :             return RTL_TEXTENCODING_SYMBOL;
     356             :         else
     357             :             return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
     358           0 :                                     : RTL_TEXTENCODING_USER_START + nGlyphSetID;
     359             :     }
     360             : }
     361             : 
     362             : OString
     363           0 : GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc, const OString &rFontName)
     364             : {
     365           0 :     if (   nEnc == RTL_TEXTENCODING_MS_1252
     366           0 :         || nEnc == RTL_TEXTENCODING_ISO_8859_1)
     367             :     {
     368           0 :         return OString("ISO1252Encoding");
     369             :     }
     370             :     else
     371           0 :     if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
     372             :     {
     373             :         return  rFontName
     374           0 :                 + OString("Enc")
     375           0 :                 + OString::number ((nEnc - RTL_TEXTENCODING_USER_START));
     376             :     }
     377             :     else
     378             :     {
     379           0 :         return OString();
     380             :     }
     381             : }
     382             : 
     383             : OString
     384           0 : GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
     385             : {
     386           0 :     return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
     387             : }
     388             : 
     389             : void
     390           0 : GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
     391             : {
     392             :     // only for ps fonts
     393           0 :     if (meBaseType != fonttype::Type1)
     394           0 :         return;
     395             : 
     396             :     sal_Char  pEncodingVector [256];
     397           0 :     sal_Int32 nSize = 0;
     398             : 
     399           0 :     nSize += psp::appendStr ("(", pEncodingVector + nSize);
     400             :     nSize += psp::appendStr (GetReencodedFontName(nGlyphSetID).getStr(),
     401           0 :                                   pEncodingVector + nSize);
     402           0 :     nSize += psp::appendStr (") cvn (", pEncodingVector + nSize);
     403             :     nSize += psp::appendStr (maBaseName.getStr(),
     404           0 :                                   pEncodingVector + nSize);
     405           0 :     nSize += psp::appendStr (") cvn ", pEncodingVector + nSize);
     406             :     nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
     407           0 :                                   pEncodingVector + nSize);
     408             :     nSize += psp::appendStr (" psp_definefont\n",
     409           0 :                                   pEncodingVector + nSize);
     410             : 
     411           0 :     psp::WritePS (pOutFile, pEncodingVector);
     412             : }
     413             : 
     414             : OString
     415           0 : GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
     416             : {
     417           0 :     if (   nEnc == RTL_TEXTENCODING_MS_1252
     418           0 :         || nEnc == RTL_TEXTENCODING_ISO_8859_1)
     419             :     {
     420             :         return rFontName
     421           0 :                + OString("-iso1252");
     422             :     }
     423             :     else
     424           0 :     if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
     425             :     {
     426             :         return rFontName
     427           0 :                + OString("-enc")
     428           0 :                + OString::number ((nEnc - RTL_TEXTENCODING_USER_START));
     429             :     }
     430             :     else
     431             :     {
     432           0 :         return OString();
     433             :     }
     434             : }
     435             : 
     436             : OString
     437           0 : GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
     438             : {
     439           0 :     return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
     440             : }
     441             : 
     442           0 : void GlyphSet::DrawGlyphs(
     443             :                           PrinterGfx& rGfx,
     444             :                           const Point& rPoint,
     445             :                           const sal_GlyphId* pGlyphIds,
     446             :                           const sal_Unicode* pUnicodes,
     447             :                           sal_Int16 nLen,
     448             :                           const sal_Int32* pDeltaArray,
     449             :                           const bool bUseGlyphs)
     450             : {
     451           0 :     unsigned char *pGlyphID    = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
     452           0 :     sal_Int32 *pGlyphSetID = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
     453           0 :     std::set< sal_Int32 > aGlyphSet;
     454             : 
     455             :     // convert unicode to font glyph id and font subset
     456           0 :     for (int nChar = 0; nChar < nLen; nChar++)
     457             :     {
     458           0 :         if (bUseGlyphs)
     459           0 :             GetGlyphID (pGlyphIds[nChar], pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
     460             :         else
     461           0 :             GetCharID (pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
     462           0 :         aGlyphSet.insert (pGlyphSetID[nChar]);
     463             :     }
     464             : 
     465             :     // loop over all glyph sets to detect substrings that can be xshown together
     466             :     // without changing the postscript font
     467           0 :     sal_Int32 *pDeltaSubset = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
     468           0 :     unsigned char *pGlyphSubset = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
     469             : 
     470           0 :     std::set< sal_Int32 >::iterator aSet;
     471           0 :     for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
     472             :     {
     473           0 :         Point     aPoint  = rPoint;
     474           0 :         sal_Int32 nOffset = 0;
     475           0 :         sal_Int32 nGlyphs = 0;
     476             :         sal_Int32 nChar;
     477             : 
     478             :         // get offset to first glyph
     479           0 :         for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
     480             :         {
     481           0 :             nOffset = pDeltaArray [nChar];
     482             :         }
     483             : 
     484             :         // loop over all chars to extract those that share the current glyph set
     485           0 :         for (nChar = 0; nChar < nLen; nChar++)
     486             :         {
     487           0 :             if (pGlyphSetID[nChar] == *aSet)
     488             :             {
     489           0 :                 pGlyphSubset [nGlyphs] = pGlyphID [nChar];
     490             :                 // the offset to the next glyph is determined by the glyph in
     491             :                 // front of the next glyph with the same glyphset id
     492             :                 // most often, this will be the current glyph
     493           0 :                 while ((nChar + 1) < nLen)
     494             :                 {
     495           0 :                     if (pGlyphSetID[nChar + 1] == *aSet)
     496           0 :                         break;
     497             :                     else
     498           0 :                         nChar += 1;
     499             :                 }
     500           0 :                 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
     501             : 
     502           0 :                 nGlyphs += 1;
     503             :             }
     504             :         }
     505             : 
     506             :         // show the text using the PrinterGfx text api
     507           0 :         aPoint.Move (nOffset, 0);
     508             : 
     509           0 :         OString aGlyphSetName;
     510           0 :         if (bUseGlyphs)
     511           0 :             aGlyphSetName = GetGlyphSetName(*aSet);
     512             :         else
     513           0 :             aGlyphSetName = GetCharSetName(*aSet);
     514             : 
     515           0 :         rGfx.PSSetFont  (aGlyphSetName, GetGlyphSetEncoding(*aSet));
     516           0 :         rGfx.PSMoveTo   (aPoint);
     517           0 :         rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
     518           0 :     }
     519           0 : }
     520             : 
     521             : void
     522           0 : GlyphSet::DrawText (PrinterGfx &rGfx, const Point& rPoint,
     523             :                     const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
     524             : {
     525             :     // dispatch to the impl method
     526           0 :     if (pDeltaArray == NULL)
     527           0 :         ImplDrawText (rGfx, rPoint, pStr, nLen);
     528             :     else
     529           0 :         ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
     530           0 : }
     531             : 
     532             : void
     533           0 : GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
     534             :                         const sal_Unicode* pStr, sal_Int16 nLen)
     535             : {
     536           0 :     rGfx.PSMoveTo (rPoint);
     537             : 
     538           0 :     if( mbUseFontEncoding )
     539             :     {
     540           0 :         OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
     541           0 :         OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
     542           0 :         rGfx.PSSetFont( aPSName, mnBaseEncoding );
     543           0 :         rGfx.PSShowText( reinterpret_cast<const unsigned char*>(aBytes.getStr()), nLen, aBytes.getLength() );
     544           0 :         return;
     545             :     }
     546             : 
     547             :     int nChar;
     548           0 :     unsigned char *pGlyphID    = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
     549           0 :     sal_Int32 *pGlyphSetID = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
     550             : 
     551             :     // convert unicode to glyph id and char set (font subset)
     552           0 :     for (nChar = 0; nChar < nLen; nChar++)
     553           0 :         GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
     554             : 
     555             :     // loop over the string to draw subsequent pieces of chars
     556             :     // with the same postscript font
     557           0 :     for (nChar = 0; nChar < nLen; /* atend */)
     558             :     {
     559           0 :         sal_Int32 nGlyphSetID = pGlyphSetID [nChar];
     560           0 :         sal_Int32 nGlyphs     = 1;
     561           0 :         for (int nNextChar = nChar + 1; nNextChar < nLen; nNextChar++)
     562             :         {
     563           0 :             if (pGlyphSetID[nNextChar] == nGlyphSetID)
     564           0 :                 nGlyphs++;
     565             :             else
     566           0 :                 break;
     567             :         }
     568             : 
     569             :         // show the text using the PrinterGfx text api
     570           0 :         OString aGlyphSetName(GetCharSetName(nGlyphSetID));
     571           0 :         rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(nGlyphSetID));
     572           0 :         rGfx.PSShowText (pGlyphID + nChar, nGlyphs, nGlyphs);
     573             : 
     574           0 :         nChar += nGlyphs;
     575           0 :     }
     576             : }
     577             : 
     578             : void
     579           0 : GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
     580             :                         const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
     581             : {
     582           0 :     if( mbUseFontEncoding )
     583             :     {
     584           0 :         OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
     585           0 :         OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
     586           0 :         rGfx.PSMoveTo( rPoint );
     587           0 :         rGfx.PSSetFont( aPSName, mnBaseEncoding );
     588           0 :         rGfx.PSShowText( reinterpret_cast<const unsigned char*>(aBytes.getStr()), nLen, aBytes.getLength(), pDeltaArray );
     589           0 :         return;
     590             :     }
     591             : 
     592           0 :     DrawGlyphs( rGfx, rPoint, NULL, pStr, nLen, pDeltaArray, false);
     593             : }
     594             : 
     595             : bool
     596           0 : GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
     597             : {
     598             :     // only for ps fonts
     599           0 :     if (meBaseType != fonttype::Type1)
     600           0 :         return false;
     601           0 :     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
     602           0 :         return false;
     603             : 
     604           0 :     PrintFontManager &rMgr = rGfx.GetFontMgr();
     605             : 
     606             :     // loop through all the font subsets
     607           0 :     sal_Int32               nGlyphSetID = 0;
     608           0 :     char_list_t::iterator   aGlyphSet;
     609           0 :     for (aGlyphSet = maCharList.begin(); aGlyphSet != maCharList.end(); ++aGlyphSet)
     610             :     {
     611           0 :         ++nGlyphSetID;
     612             : 
     613           0 :         if (nGlyphSetID == 1) // latin1 page uses global reencoding table
     614             :         {
     615           0 :             PSDefineReencodedFont (pOutFile, nGlyphSetID);
     616           0 :             continue;
     617             :         }
     618           0 :         if ((*aGlyphSet).empty()) // empty set, doesn't need reencoding
     619             :         {
     620           0 :             continue;
     621             :         }
     622             : 
     623             :         // create reencoding table
     624             : 
     625             :         sal_Char  pEncodingVector [256];
     626           0 :         sal_Int32 nSize = 0;
     627             : 
     628             :         nSize += psp::appendStr ("/",
     629           0 :                                  pEncodingVector + nSize);
     630             :         nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
     631           0 :                                  pEncodingVector + nSize);
     632             :         nSize += psp::appendStr (" [ ",
     633           0 :                                  pEncodingVector + nSize);
     634             : 
     635             :         // need a list of glyphs, sorted by glyphid
     636             :         typedef std::map< sal_uInt8, sal_Unicode > ps_mapping_t;
     637             :         typedef ps_mapping_t::value_type ps_value_t;
     638           0 :         ps_mapping_t aSortedGlyphSet;
     639             : 
     640           0 :         char_map_t::const_iterator aUnsortedGlyph;
     641           0 :         for (aUnsortedGlyph  = (*aGlyphSet).begin();
     642           0 :              aUnsortedGlyph != (*aGlyphSet).end();
     643             :              ++aUnsortedGlyph)
     644             :         {
     645           0 :             aSortedGlyphSet.insert(ps_value_t((*aUnsortedGlyph).second,
     646           0 :                                              (*aUnsortedGlyph).first));
     647             :         }
     648             : 
     649           0 :         ps_mapping_t::const_iterator aSortedGlyph;
     650             :         // loop through all the glyphs in the subset
     651           0 :         for (aSortedGlyph  = (aSortedGlyphSet).begin();
     652           0 :              aSortedGlyph != (aSortedGlyphSet).end();
     653             :              ++aSortedGlyph)
     654             :         {
     655             :             nSize += psp::appendStr ("/",
     656           0 :                                      pEncodingVector + nSize);
     657             : 
     658           0 :             std::list< OString > aName( rMgr.getAdobeNameFromUnicode((*aSortedGlyph).second) );
     659             : 
     660           0 :             if( aName.begin() != aName.end() )
     661           0 :                 nSize += psp::appendStr ( aName.front().getStr(), pEncodingVector + nSize);
     662             :             else
     663           0 :                 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
     664           0 :             nSize += psp::appendStr (" ",  pEncodingVector + nSize);
     665             :             // flush line
     666           0 :             if (nSize >= 70)
     667             :             {
     668           0 :                 psp::appendStr ("\n", pEncodingVector + nSize);
     669           0 :                 psp::WritePS (pOutFile, pEncodingVector);
     670           0 :                 nSize = 0;
     671             :             }
     672           0 :         }
     673             : 
     674           0 :         nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
     675           0 :         psp::WritePS (pOutFile, pEncodingVector);
     676             : 
     677           0 :         PSDefineReencodedFont (pOutFile, nGlyphSetID);
     678           0 :     }
     679             : 
     680           0 :     return true;
     681             : }
     682             : 
     683             : struct EncEntry
     684             : {
     685             :     unsigned char  aEnc;
     686             :     long       aGID;
     687             : 
     688           0 :     EncEntry() : aEnc( 0 ), aGID( 0 ) {}
     689             : 
     690           0 :     bool operator<( const EncEntry& rRight ) const
     691           0 :     { return aEnc < rRight.aEnc; }
     692             : };
     693             : 
     694           0 : static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile,
     695             :     const char* pGlyphSetName, int nGlyphCount,
     696             :     /*const*/ sal_uInt16* pRequestedGlyphs, /*const*/ unsigned char* pEncoding,
     697             :     bool bAllowType42, bool /*bAllowCID*/ )
     698             : {
     699             :     // match the font-subset to the printer capabilities
     700             :      // TODO: allow CFF for capable printers
     701           0 :     int nTargetMask = FontSubsetInfo::TYPE1_PFA | FontSubsetInfo::TYPE3_FONT;
     702           0 :     if( bAllowType42 )
     703           0 :         nTargetMask |= FontSubsetInfo::TYPE42_FONT;
     704             : 
     705           0 :     std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
     706           0 :     for( int i = 0; i < nGlyphCount; i++ )
     707             :     {
     708           0 :         aSorted[i].aEnc = pEncoding[i];
     709           0 :         aSorted[i].aGID = pRequestedGlyphs[i];
     710             :     }
     711             : 
     712           0 :     std::stable_sort( aSorted.begin(), aSorted.end() );
     713             : 
     714           0 :     std::vector< unsigned char > aEncoding( nGlyphCount );
     715           0 :     std::vector< sal_GlyphId > aRequestedGlyphs( nGlyphCount );
     716             : 
     717           0 :     for( int i = 0; i < nGlyphCount; i++ )
     718             :     {
     719           0 :         aEncoding[i]        = aSorted[i].aEnc;
     720           0 :         aRequestedGlyphs[i] = aSorted[i].aGID;
     721             :     }
     722             : 
     723           0 :     FontSubsetInfo aInfo;
     724           0 :     aInfo.LoadFont( pSrcFont );
     725             : 
     726             :     aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
     727           0 :         &aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL );
     728           0 : }
     729             : 
     730             : bool
     731           0 : GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
     732             : {
     733             :     // only for truetype fonts
     734           0 :     if (meBaseType != fonttype::TrueType)
     735           0 :         return false;
     736             : 
     737             : #if defined( UNX )
     738             :     TrueTypeFont *pTTFont;
     739           0 :     OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
     740           0 :     int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
     741           0 :     sal_Int32 nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace, &pTTFont);
     742           0 :     if (nSuccess != SF_OK)
     743           0 :         return false;
     744             : 
     745           0 :     utl::TempFile aTmpFile;
     746           0 :     aTmpFile.EnableKillingFile();
     747           0 :     FILE* pTmpFile = fopen(OUStringToOString(aTmpFile.GetFileName(), osl_getThreadTextEncoding()).getStr(), "w+b");
     748           0 :     if (pTmpFile == NULL)
     749           0 :         return false;
     750             : 
     751             :     // array of unicode source characters
     752             :     sal_Unicode pUChars[256];
     753             : 
     754             :     // encoding vector maps character encoding to the ordinal number
     755             :     // of the glyph in the output file
     756             :     unsigned char  pEncoding[256];
     757             :     sal_uInt16 pTTGlyphMapping[256];
     758           0 :     const bool bAllowCID = false; // TODO: nPSLanguageLevel>=3
     759             : 
     760             :     // loop through all the font subsets
     761             :     sal_Int32 nCharSetID;
     762           0 :     char_list_t::iterator aCharSet;
     763           0 :     for (aCharSet = maCharList.begin(), nCharSetID = 1;
     764           0 :          aCharSet != maCharList.end();
     765             :          ++aCharSet, nCharSetID++)
     766             :     {
     767           0 :         if ((*aCharSet).empty())
     768           0 :             continue;
     769             : 
     770             :         // loop through all the chars in the subset
     771           0 :         char_map_t::const_iterator aChar;
     772           0 :         sal_Int32 n = 0;
     773           0 :         for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); ++aChar)
     774             :         {
     775           0 :             pUChars [n]   = (*aChar).first;
     776           0 :             pEncoding [n] = (*aChar).second;
     777           0 :             n++;
     778             :         }
     779             :         // create a mapping from the unicode chars to the char encoding in
     780             :         // source TrueType font
     781           0 :         MapString (pTTFont, pUChars, (*aCharSet).size(), pTTGlyphMapping, mbVertical);
     782             : 
     783             :         // create the current subset
     784           0 :         OString aCharSetName = GetCharSetName(nCharSetID);
     785           0 :         fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aCharSetName.getStr() );
     786           0 :         CreatePSUploadableFont( pTTFont, pTmpFile, aCharSetName.getStr(), (*aCharSet).size(),
     787           0 :                                 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
     788           0 :         fprintf( pTmpFile, "%%%%EndResource\n" );
     789           0 :         rSuppliedFonts.push_back( aCharSetName );
     790           0 :     }
     791             : 
     792             :     // loop through all the font glyph subsets
     793             :     sal_Int32 nGlyphSetID;
     794           0 :     glyph_list_t::iterator aGlyphSet;
     795           0 :     for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
     796           0 :          aGlyphSet != maGlyphList.end();
     797             :          ++aGlyphSet, nGlyphSetID++)
     798             :     {
     799           0 :         if ((*aGlyphSet).empty())
     800           0 :             continue;
     801             : 
     802             :         // loop through all the glyphs in the subset
     803           0 :         glyph_map_t::const_iterator aGlyph;
     804           0 :         sal_Int32 n = 0;
     805           0 :         for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); ++aGlyph)
     806             :         {
     807           0 :             pTTGlyphMapping [n] = (*aGlyph).first;
     808           0 :             pEncoding       [n] = (*aGlyph).second;
     809           0 :             n++;
     810             :         }
     811             : 
     812             :         // create the current subset
     813           0 :         OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
     814           0 :         fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
     815           0 :         CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), (*aGlyphSet).size(),
     816           0 :                                 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
     817           0 :         fprintf( pTmpFile, "%%%%EndResource\n" );
     818           0 :         rSuppliedFonts.push_back( aGlyphSetName );
     819           0 :     }
     820             : 
     821             :     // copy the file into the page header
     822           0 :     rewind(pTmpFile);
     823           0 :     fflush(pTmpFile);
     824             : 
     825             :     unsigned char  pBuffer[0x2000];
     826             :     sal_uInt64 nIn;
     827             :     sal_uInt64 nOut;
     828           0 :     do
     829             :     {
     830           0 :         nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
     831           0 :         rOutFile.write (pBuffer, nIn, nOut);
     832             :     }
     833           0 :     while ((nIn == nOut) && !feof(pTmpFile));
     834             : 
     835             :     // cleanup
     836           0 :     CloseTTFont (pTTFont);
     837           0 :     fclose (pTmpFile);
     838             : 
     839           0 :     return true;
     840             : #else
     841             :     (void)rOutFile; (void)rGfx; (void)bAllowType42; (void)rSuppliedFonts;
     842             : #  warning FIXME: Missing OpenTTFontFile outside of Unix ...
     843             :     return false;
     844             : #endif
     845         801 : }
     846             : 
     847             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11