LCOV - code coverage report
Current view: top level - libreoffice/vcl/generic/fontmanager - fontsubst.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 65 75 86.7 %
Date: 2012-12-27 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "generic/geninst.h"
      21             : #include "generic/genpspgraphics.h"
      22             : #include "generic/glyphcache.hxx"
      23             : 
      24             : #include "vcl/sysdata.hxx"
      25             : #include "outfont.hxx"
      26             : 
      27             : #include "generic/printergfx.hxx"
      28             : #include "salbmp.hxx"
      29             : #include "impfont.hxx"
      30             : #include "outfont.hxx"
      31             : #include "outdev.h"
      32             : #include "fontsubset.hxx"
      33             : #include "salprn.hxx"
      34             : #include "region.h"
      35             : 
      36             : #include <list>
      37             : 
      38             : // ===========================================================================
      39             : // platform specific font substitution hooks
      40             : // ===========================================================================
      41             : 
      42             : struct FontSelectPatternAttributesHash
      43             : {
      44             :     size_t operator()(const FontSelectPatternAttributes& rAttributes) const
      45             :         { return rAttributes.hashCode(); }
      46             : };
      47             : 
      48          40 : class FcPreMatchSubstititution
      49             : :   public ImplPreMatchFontSubstitution
      50             : {
      51             : public:
      52             :     bool FindFontSubstitute( FontSelectPattern& ) const;
      53             :     typedef ::std::pair<FontSelectPatternAttributes, FontSelectPatternAttributes> value_type;
      54             : private:
      55             :     typedef ::std::list<value_type> CachedFontMapType;
      56             :     mutable CachedFontMapType maCachedFontMap;
      57             : };
      58             : 
      59          20 : class FcGlyphFallbackSubstititution
      60             : :    public ImplGlyphFallbackFontSubstitution
      61             : {
      62             :     // TODO: add a cache
      63             : public:
      64             :     bool FindFontSubstitute( FontSelectPattern&, rtl::OUString& rMissingCodes ) const;
      65             : };
      66             : 
      67          20 : int SalGenericInstance::FetchFontSubstitutionFlags()
      68             : {
      69             :     // init font substitution defaults
      70          20 :     int nDisableBits = 0;
      71             : #ifdef SOLARIS
      72             :     nDisableBits = 1; // disable "font fallback" here on default
      73             : #endif
      74             :     // apply the environment variable if any
      75          20 :     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
      76          20 :     if( pEnvStr )
      77             :     {
      78           0 :         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
      79           0 :             nDisableBits = (*pEnvStr - '0');
      80             :         else
      81           0 :             nDisableBits = ~0U; // no specific bits set: disable all
      82             :     }
      83          20 :     return nDisableBits;
      84             : }
      85             : 
      86          23 : void SalGenericInstance::RegisterFontSubstitutors( ImplDevFontList* pList )
      87             : {
      88             :     // init font substitution defaults
      89          23 :     int nDisableBits = 0;
      90             : #ifdef SOLARIS
      91             :     nDisableBits = 1; // disable "font fallback" here on default
      92             : #endif
      93             :     // apply the environment variable if any
      94          23 :     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
      95          23 :     if( pEnvStr )
      96             :     {
      97           0 :         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
      98           0 :             nDisableBits = (*pEnvStr - '0');
      99             :         else
     100           0 :             nDisableBits = ~0U; // no specific bits set: disable all
     101             :     }
     102             : 
     103             :     // register font fallback substitutions (unless disabled by bit0)
     104          23 :     if( (nDisableBits & 1) == 0 )
     105             :     {
     106          23 :         static FcPreMatchSubstititution aSubstPreMatch;
     107          23 :         pList->SetPreMatchHook( &aSubstPreMatch );
     108             :     }
     109             : 
     110             :     // register glyph fallback substitutions (unless disabled by bit1)
     111          23 :     if( (nDisableBits & 2) == 0 )
     112             :     {
     113          23 :         static FcGlyphFallbackSubstititution aSubstFallback;
     114          23 :         pList->SetFallbackHook( &aSubstFallback );
     115             :     }
     116          23 : }
     117             : 
     118             : // -----------------------------------------------------------------------
     119             : 
     120        3852 : static FontSelectPattern GetFcSubstitute(const FontSelectPattern &rFontSelData, rtl::OUString& rMissingCodes )
     121             : {
     122        3852 :     FontSelectPattern aSubstituted(rFontSelData);
     123        3852 :     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
     124        3852 :     rMgr.Substitute(aSubstituted, rMissingCodes);
     125        3852 :     return aSubstituted;
     126             : }
     127             : 
     128             : namespace
     129             : {
     130        3852 :     bool uselessmatch(const FontSelectPattern &rOrig, const FontSelectPattern &rNew)
     131             :     {
     132             :         return
     133             :           (
     134        3852 :             rOrig.maTargetName == rNew.maSearchName &&
     135             :             rOrig.meWeight == rNew.meWeight &&
     136             :             rOrig.meItalic == rNew.meItalic &&
     137             :             rOrig.mePitch == rNew.mePitch &&
     138             :             rOrig.meWidthType == rNew.meWidthType
     139        3852 :           );
     140             :     }
     141             : 
     142             :     class equal
     143             :     {
     144             :     private:
     145             :         const FontSelectPatternAttributes& mrAttributes;
     146             :     public:
     147       33841 :         equal(const FontSelectPatternAttributes& rAttributes)
     148       33841 :             : mrAttributes(rAttributes)
     149             :         {
     150       33841 :         }
     151       91037 :         bool operator()(const FcPreMatchSubstititution::value_type& rOther) const
     152       91037 :             { return rOther.first == mrAttributes; }
     153             :     };
     154             : }
     155             : 
     156             : //--------------------------------------------------------------------------
     157             : 
     158       45709 : bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelData ) const
     159             : {
     160             :     // We dont' actually want to talk to Fontconfig at all for symbol fonts
     161       45709 :     if( rFontSelData.IsSymbolFont() )
     162         380 :         return false;
     163             :     // StarSymbol is a unicode font, but it still deserves the symbol flag
     164       89946 :     if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
     165       44617 :     ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
     166       11488 :         return false;
     167             : 
     168             :     //see fdo#41556 and fdo#47636
     169             :     //fontconfig can return e.g. an italic font for a non-italic input and/or
     170             :     //different fonts depending on fontsize, bold, etc settings so don't cache
     171             :     //just on the name, cache map all the input and all the output not just map
     172             :     //from original selection to output fontname
     173       33841 :     FontSelectPatternAttributes& rPatternAttributes = rFontSelData;
     174       33841 :     CachedFontMapType &rCachedFontMap = const_cast<CachedFontMapType &>(maCachedFontMap);
     175       33841 :     CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes));
     176       33841 :     if (itr != rCachedFontMap.end())
     177             :     {
     178             :         // Cached substitution
     179       31264 :         rFontSelData.copyAttributes(itr->second);
     180       31264 :         if (itr != rCachedFontMap.begin())
     181             :         {
     182             :             // MRU, move it to the front
     183       17099 :             rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr);
     184             :         }
     185       31264 :         return true;
     186             :     }
     187             : 
     188        2577 :     rtl::OUString aDummy;
     189        2577 :     const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy );
     190             : 
     191        2577 :     if( !aOut.maSearchName.Len() )
     192           0 :         return false;
     193             : 
     194        2577 :     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
     195             : 
     196             : #ifdef DEBUG
     197             :     const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
     198             :         RTL_TEXTENCODING_UTF8));
     199             :     const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
     200             :         RTL_TEXTENCODING_UTF8));
     201             :     printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
     202             :         aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
     203             :         rFontSelData.mePitch, rFontSelData.meWidthType );
     204             :     if( !bHaveSubstitute )
     205             :         printf( "no substitute available\n" );
     206             :     else
     207             :         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
     208             :         aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
     209             : #endif
     210             : 
     211        2577 :     if( bHaveSubstitute )
     212             :     {
     213        2577 :         rCachedFontMap.push_front(value_type(rFontSelData, aOut));
     214             :         //fairly arbitrary limit in this case, but I recall measuring max 8
     215             :         //fonts as the typical max amount of fonts in medium sized documents
     216        2577 :         if (rCachedFontMap.size() > 8)
     217        2433 :             rCachedFontMap.pop_back();
     218        2577 :         rFontSelData = aOut;
     219             :     }
     220             : 
     221        2577 :     return bHaveSubstitute;
     222             : }
     223             : 
     224             : // -----------------------------------------------------------------------
     225             : 
     226        1275 : bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFontSelData,
     227             :     rtl::OUString& rMissingCodes ) const
     228             : {
     229             :     // We dont' actually want to talk to Fontconfig at all for symbol fonts
     230        1275 :     if( rFontSelData.IsSymbolFont() )
     231           0 :         return false;
     232             :     // StarSymbol is a unicode font, but it still deserves the symbol flag
     233        2550 :     if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
     234        1275 :     ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
     235           0 :         return false;
     236             : 
     237        1275 :     const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
     238             :     // TODO: cache the unicode + srcfont specific result
     239             :     // FC doing it would be preferable because it knows the invariables
     240             :     // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
     241             :     // whereas we would have to check for every size or attribute
     242        1275 :     if( !aOut.maSearchName.Len() )
     243           0 :         return false;
     244             : 
     245        1275 :     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
     246             : 
     247             : #ifdef DEBUG
     248             :     const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
     249             :         RTL_TEXTENCODING_UTF8));
     250             :     const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
     251             :         RTL_TEXTENCODING_UTF8));
     252             :     printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
     253             :         aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
     254             :         rFontSelData.mePitch, rFontSelData.meWidthType );
     255             :     if( !bHaveSubstitute )
     256             :         printf( "no substitute available\n" );
     257             :     else
     258             :         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
     259             :         aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
     260             : #endif
     261             : 
     262        1275 :     if( bHaveSubstitute )
     263        1275 :         rFontSelData = aOut;
     264             : 
     265        1275 :     return bHaveSubstitute;
     266             : }
     267             : 
     268             : // ===========================================================================
     269             : 
     270             : 
     271             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10