LCOV - code coverage report
Current view: top level - vcl/generic/fontmanager - fontsubst.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 69 78 88.5 %
Date: 2015-06-13 12:38:46 Functions: 13 15 86.7 %
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 "outdev.h"
      31             : #include "PhysicalFontCollection.hxx"
      32             : #include "fontsubset.hxx"
      33             : #include "salprn.hxx"
      34             : 
      35             : #include <unotools/fontdefs.hxx>
      36             : #include <list>
      37             : 
      38             : // platform specific font substitution hooks
      39             : 
      40         410 : class FcPreMatchSubstititution
      41             : :   public ImplPreMatchFontSubstitution
      42             : {
      43             : public:
      44             :     bool FindFontSubstitute( FontSelectPattern& ) const SAL_OVERRIDE;
      45             :     typedef ::std::pair<FontSelectPatternAttributes, FontSelectPatternAttributes> value_type;
      46             : private:
      47             :     typedef ::std::list<value_type> CachedFontMapType;
      48             :     mutable CachedFontMapType maCachedFontMap;
      49             : };
      50             : 
      51         205 : class FcGlyphFallbackSubstititution
      52             : :    public ImplGlyphFallbackFontSubstitution
      53             : {
      54             :     // TODO: add a cache
      55             : public:
      56             :     bool FindFontSubstitute( FontSelectPattern&, OUString& rMissingCodes ) const SAL_OVERRIDE;
      57             : };
      58             : 
      59         205 : int SalGenericInstance::FetchFontSubstitutionFlags()
      60             : {
      61             :     // init font substitution defaults
      62         205 :     int nDisableBits = 0;
      63             : #ifdef SOLARIS
      64             :     nDisableBits = 1; // disable "font fallback" here on default
      65             : #endif
      66             :     // apply the environment variable if any
      67         205 :     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
      68         205 :     if( pEnvStr )
      69             :     {
      70           0 :         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
      71           0 :             nDisableBits = (*pEnvStr - '0');
      72             :         else
      73           0 :             nDisableBits = ~0U; // no specific bits set: disable all
      74             :     }
      75         205 :     return nDisableBits;
      76             : }
      77             : 
      78         859 : void SalGenericInstance::RegisterFontSubstitutors( PhysicalFontCollection* pFontCollection )
      79             : {
      80             :     // init font substitution defaults
      81         859 :     int nDisableBits = 0;
      82             : #ifdef SOLARIS
      83             :     nDisableBits = 1; // disable "font fallback" here on default
      84             : #endif
      85             :     // apply the environment variable if any
      86         859 :     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
      87         859 :     if( pEnvStr )
      88             :     {
      89           0 :         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
      90           0 :             nDisableBits = (*pEnvStr - '0');
      91             :         else
      92           0 :             nDisableBits = ~0U; // no specific bits set: disable all
      93             :     }
      94             : 
      95             :     // register font fallback substitutions (unless disabled by bit0)
      96         859 :     if( (nDisableBits & 1) == 0 )
      97             :     {
      98         859 :         static FcPreMatchSubstititution aSubstPreMatch;
      99         859 :         pFontCollection->SetPreMatchHook( &aSubstPreMatch );
     100             :     }
     101             : 
     102             :     // register glyph fallback substitutions (unless disabled by bit1)
     103         859 :     if( (nDisableBits & 2) == 0 )
     104             :     {
     105         859 :         static FcGlyphFallbackSubstititution aSubstFallback;
     106         859 :         pFontCollection->SetFallbackHook( &aSubstFallback );
     107             :     }
     108         859 : }
     109             : 
     110       11319 : static FontSelectPattern GetFcSubstitute(const FontSelectPattern &rFontSelData, OUString& rMissingCodes )
     111             : {
     112       11319 :     FontSelectPattern aSubstituted(rFontSelData);
     113       11319 :     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
     114       11319 :     rMgr.Substitute(aSubstituted, rMissingCodes);
     115       11319 :     return aSubstituted;
     116             : }
     117             : 
     118             : namespace
     119             : {
     120       11319 :     bool uselessmatch(const FontSelectPattern &rOrig, const FontSelectPattern &rNew)
     121             :     {
     122             :         return
     123             :           (
     124       11357 :             rOrig.maTargetName == rNew.maSearchName &&
     125          67 :             rOrig.GetWeight() == rNew.GetWeight() &&
     126          58 :             rOrig.GetSlant() == rNew.GetSlant() &&
     127       11377 :             rOrig.GetPitch() == rNew.GetPitch() &&
     128          29 :             rOrig.GetWidthType() == rNew.GetWidthType()
     129       11319 :           );
     130             :     }
     131             : 
     132             :     class equal
     133             :     {
     134             :     private:
     135             :         const FontSelectPatternAttributes& mrAttributes;
     136             :     public:
     137        8511 :         explicit equal(const FontSelectPatternAttributes& rAttributes)
     138        8511 :             : mrAttributes(rAttributes)
     139             :         {
     140        8511 :         }
     141       50679 :         bool operator()(const FcPreMatchSubstititution::value_type& rOther) const
     142       50679 :             { return rOther.first == mrAttributes; }
     143             :     };
     144             : }
     145             : 
     146        9525 : bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelData ) const
     147             : {
     148             :     // We don't actually want to talk to Fontconfig at all for symbol fonts
     149        9525 :     if( rFontSelData.IsSymbolFont() )
     150         124 :         return false;
     151             :     // StarSymbol is a unicode font, but it still deserves the symbol flag
     152        9401 :     if ( IsStarSymbol(rFontSelData.maSearchName) )
     153         890 :         return false;
     154             : 
     155             :     //see fdo#41556 and fdo#47636
     156             :     //fontconfig can return e.g. an italic font for a non-italic input and/or
     157             :     //different fonts depending on fontsize, bold, etc settings so don't cache
     158             :     //just on the name, cache map all the input and all the output not just map
     159             :     //from original selection to output fontname
     160        8511 :     FontSelectPatternAttributes& rPatternAttributes = rFontSelData;
     161        8511 :     CachedFontMapType &rCachedFontMap = const_cast<CachedFontMapType &>(maCachedFontMap);
     162        8511 :     CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes));
     163        8511 :     if (itr != rCachedFontMap.end())
     164             :     {
     165             :         // Cached substitution
     166        2609 :         rFontSelData.copyAttributes(itr->second);
     167        2609 :         if (itr != rCachedFontMap.begin())
     168             :         {
     169             :             // MRU, move it to the front
     170        1967 :             rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr);
     171             :         }
     172        2609 :         return true;
     173             :     }
     174             : 
     175        5902 :     OUString aDummy;
     176       11804 :     const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy );
     177             : 
     178        5902 :     if( aOut.maSearchName.isEmpty() )
     179           0 :         return false;
     180             : 
     181        5902 :     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
     182             : 
     183             : #ifdef DEBUG
     184             :     const OString aOrigName(OUStringToOString(rFontSelData.maTargetName,
     185             :         RTL_TEXTENCODING_UTF8));
     186             :     const OString aSubstName(OUStringToOString(aOut.maSearchName,
     187             :         RTL_TEXTENCODING_UTF8));
     188             :     printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
     189             :         aOrigName.getStr(), rFontSelData.GetWeight(), rFontSelData.GetSlant(),
     190             :         rFontSelData.GetPitch(), rFontSelData.GetWidthType() );
     191             :     if( !bHaveSubstitute )
     192             :         printf( "no substitute available\n" );
     193             :     else
     194             :         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
     195             :         aOut.GetWeight(), aOut.GetSlant(), aOut.GetPitch(), aOut.GetWidthType() );
     196             : #endif
     197             : 
     198        5902 :     if( bHaveSubstitute )
     199             :     {
     200        5902 :         rCachedFontMap.push_front(value_type(rFontSelData, aOut));
     201             :         //fairly arbitrary limit in this case, but I recall measuring max 8
     202             :         //fonts as the typical max amount of fonts in medium sized documents
     203        5902 :         if (rCachedFontMap.size() > 8)
     204        4957 :             rCachedFontMap.pop_back();
     205        5902 :         rFontSelData = aOut;
     206             :     }
     207             : 
     208       11804 :     return bHaveSubstitute;
     209             : }
     210             : 
     211        5455 : bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFontSelData,
     212             :     OUString& rMissingCodes ) const
     213             : {
     214             :     // We don't actually want to talk to Fontconfig at all for symbol fonts
     215        5455 :     if( rFontSelData.IsSymbolFont() )
     216           0 :         return false;
     217             :     // StarSymbol is a unicode font, but it still deserves the symbol flag
     218        5455 :     if ( IsStarSymbol(rFontSelData.maSearchName) )
     219          38 :         return false;
     220             : 
     221        5417 :     const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
     222             :     // TODO: cache the unicode + srcfont specific result
     223             :     // FC doing it would be preferable because it knows the invariables
     224             :     // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
     225             :     // whereas we would have to check for every size or attribute
     226        5417 :     if( aOut.maSearchName.isEmpty() )
     227           0 :         return false;
     228             : 
     229        5417 :     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
     230             : 
     231             : #ifdef DEBUG
     232             :     const OString aOrigName(OUStringToOString(rFontSelData.maTargetName,
     233             :         RTL_TEXTENCODING_UTF8));
     234             :     const OString aSubstName(OUStringToOString(aOut.maSearchName,
     235             :         RTL_TEXTENCODING_UTF8));
     236             :     printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
     237             :         aOrigName.getStr(), rFontSelData.GetWeight(), rFontSelData.GetSlant(),
     238             :         rFontSelData.GetPitch(), rFontSelData.GetWidthType() );
     239             :     if( !bHaveSubstitute )
     240             :         printf( "no substitute available\n" );
     241             :     else
     242             :         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
     243             :         aOut.GetWeight(), aOut.GetSlant(), aOut.GetPitch(), aOut.GetWidthType() );
     244             : #endif
     245             : 
     246        5417 :     if( bHaveSubstitute )
     247        5395 :         rFontSelData = aOut;
     248             : 
     249        5417 :     return bHaveSubstitute;
     250         801 : }
     251             : 
     252             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11