Dear PoDoFo team,

PDF specification does not support changing the font's style. If the used font is not bold and/or italic then it can not be made such. When the PdfFontCache gets/creates a PdfFont object that object's bold and italic properties are set to the parameter values specified for the GetFont method. On the other hand, the PdfFontMetricsFreetype objects represent the actual font's bold and italic flags. This means that for a font which has only a regular face the PdfFont objects are, effectively, duplicated and look the exactly the same.

The solution is - just before calling PdfFontCache::CreateFontObject check if the font metrics and the font creation parameters are different. If they are, then restart the font search (call either GetFont or GetFontSubset) with the parameters from the font metrics. This allows to avoid the duplication of the font objects. Also the PdfFont::IsBold and PdfFont::IsItalic will show if the font face will look bold or italic in the actual PDF file.

The above also applies to the SymbolCharset flag.

The proposed changes to address the issue are in the attached patch file.

Regards Nikita Shlyapnikov.

Index: PdfFontCache.cpp
===================================================================
--- PdfFontCache.cpp    (revision 1818)
+++ PdfFontCache.cpp    (working copy)
@@ -270,6 +270,21 @@
 }
 #endif // _WIN32
 
+static bool AreActualFontParamsDifferrent( PdfFontMetricsFreetype* pMetrics, 
bool& use_bold, bool& use_italic, bool& use_symbols )
+{
+    bool is_bold = pMetrics->IsBold();
+    bool is_italic = pMetrics->IsItalic();
+    bool is_symbols = pMetrics->IsSymbol();
+    bool different = ( is_bold != use_bold || is_italic != use_italic || 
is_symbols != use_symbols );
+    if (different)
+    {
+        use_bold = is_bold;
+        use_italic = is_italic;
+        use_symbols = is_symbols;
+    }
+    return different;
+}
+
 PdfFontCache::PdfFontCache( PdfVecObjects* pParent )
     : m_pParent( pParent )
 {
@@ -385,8 +400,8 @@
 {
     PODOFO_ASSERT( pEncoding );
 
-    PdfFont*          pFont = NULL;
-    PdfFontMetrics*   pMetrics = NULL;
+    PdfFont*                  pFont = NULL;
+    PdfFontMetricsFreetype*   pMetrics = NULL;
     std::pair<TISortedFontList,TCISortedFontList> it;
 
     it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), 
@@ -451,8 +466,14 @@
             else
             {
                 pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, 
sPath.c_str(), bSymbolCharset, bSubsetting ? genSubsetBasename() : NULL );
-                pFont    = this->CreateFontObject( it.first, m_vecFonts, 
pMetrics, 
-                           bEmbedd, bBold, bItalic, pszFontName, pEncoding, 
bSubsetting );
+                if ( AreActualFontParamsDifferrent( pMetrics, bBold, bItalic, 
bSymbolCharset ) )
+                {
+                    pFont = this->GetFont( pszFontName, bBold, bItalic, 
bSymbolCharset, bEmbedd, eFontCreationFlags, pEncoding, pszFileName );
+                }
+                else
+                {
+                    pFont = this->CreateFontObject( it.first, m_vecFonts, 
pMetrics, bEmbedd, bBold, bItalic, pszFontName, pEncoding, bSubsetting );
+                }
             }
 
         }
@@ -548,8 +569,8 @@
 
 PdfFont* PdfFontCache::GetFont( FT_Face face, bool bSymbolCharset, bool 
bEmbedd, const PdfEncoding * const pEncoding )
 {
-    PdfFont*          pFont;
-    PdfFontMetrics*   pMetrics;
+    PdfFont*                  pFont;
+    PdfFontMetricsFreetype*   pMetrics;
     std::pair<TISortedFontList,TCISortedFontList> it;
 
     std::string sName = FT_Get_Postscript_Name( face );
@@ -568,7 +589,7 @@
     {
         pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, face, 
bSymbolCharset );
         pFont    = this->CreateFontObject( it.first, m_vecFonts, pMetrics, 
-                       bEmbedd, bBold, bItalic, sName.c_str(), pEncoding );
+                       bEmbedd, pMetrics->IsBold(), pMetrics->IsItalic(), 
sName.c_str(), pEncoding );
     }
     else
         pFont = (*it.first).m_pFont;
@@ -630,8 +651,8 @@
                       const PdfEncoding * const pEncoding,
                       const char* pszFileName )
 {
-    PdfFont*        pFont = 0;
-    PdfFontMetrics* pMetrics;
+    PdfFont*                pFont = 0;
+    PdfFontMetricsFreetype* pMetrics;
     std::pair<TISortedFontList,TCISortedFontList> it;
 
     // WARNING: The characters are completely ignored right now!
@@ -658,9 +679,19 @@
             sPath = pszFileName;
         }
         
+
+        bool bActualBold = bBold;
+        bool bActualItalic = bItalic;
+        bActuallySymbols = bSymbolCharset;
         pMetrics = PdfFontMetricsFreetype::CreateForSubsetting( &m_ftLibrary, 
sPath.c_str(), bSymbolCharset, genSubsetBasename() );
-        pFont = this->CreateFontObject( it.first, m_vecFontSubsets, pMetrics, 
-                                        true, bBold, bItalic, pszFontName, 
pEncoding, true );
+        if ( AreActualFontParamsDifferrent( pMetrics, bBold, bItalic, 
bSymbolCharset ) )
+        {
+            pFont = this->GetFontSubset( pszFontName, bBold, bItalic, 
bSymbolCharset, pEncoding, pszFileName );
+        }
+        else
+        {
+            pFont = this->CreateFontObject( it.first, m_vecFontSubsets, 
pMetrics, true, bBold, bItalic, pszFontName, pEncoding, true );
+        }
     }
     else
         pFont = (*it.first).m_pFont;
@@ -756,12 +787,12 @@
     if( !GetDataFromLPFONT( &logFont, &pBuffer, nLen ) )
         return NULL;
     
-    PdfFontMetrics* pMetrics;
-    PdfFont*        pFont = NULL;
+    PdfFontMetricsFreetype* pMetrics;
+    PdfFont*                pFont = NULL;
     try {
-         pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pBuffer, nLen, 
logFont.lfCharSet == SYMBOL_CHARSET, pSubsetting ? genSubsetBasename() : NULL );
+        pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pBuffer, nLen, 
logFont.lfCharSet == SYMBOL_CHARSET, pSubsetting ? genSubsetBasename() : NULL );
         pFont    = this->CreateFontObject( itSorted, vecContainer, pMetrics, 
-              bEmbedd, logFont.lfWeight >= FW_BOLD ? true : false, 
logFont.lfItalic ? true : false, logFont.lfFaceName, pEncoding, pSubsetting );
+              bEmbedd, pMetrics->IsBold(), pMetrics->IsItalic(), 
logFont.lfFaceName, pEncoding, pSubsetting );
     } catch( PdfError & error ) {
         podofo_free( pBuffer );
         throw error;
@@ -796,12 +827,24 @@
     if (!GetDataFromLPFONT(&logFont, &pBuffer, nLen))
         return NULL;
 
-    PdfFontMetrics* pMetrics;
-    PdfFont*        pFont = NULL;
+    PdfFontMetricsFreetype* pMetrics;
+    PdfFont*                pFont = NULL;
     try {
         pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pBuffer, nLen, 
logFont.lfCharSet == SYMBOL_CHARSET, pSubsetting ? genSubsetBasename() : NULL );
-        pFont    = this->CreateFontObject( itSorted, vecContainer, pMetrics, 
-              bEmbedd, logFont.lfWeight >= FW_BOLD ? true : false, 
logFont.lfItalic ? true : false, pmbFontName, pEncoding, pSubsetting );
+        bool bActualBold = ( logFont.lfWeight >= FW_BOLD );
+        bool bActualItalic = ( logFont.lfItalic != 0 );
+        bool bActuallySymbols = ( logFont.lfCharSet == SYMBOL_CHARSET );
+        if ( AreActualFontParamsDifferrent( pMetrics, bActualBold, 
bActualItalic, bActuallySymbols ) )
+        {
+            if ( pSubsetting )
+                pFont = this->GetFontSubset( pmbFontName, bActualBold, 
bActualItalic, bActuallySymbols, pEncoding );
+            else
+                pFont = this->GetFont( pmbFontName, bActualBold, 
bActualItalic, bActuallySymbols, bEmbedd, eFontCreationFlags_AutoSelectBase14, 
pEncoding );
+        }
+        else
+        {
+            pFont = this->CreateFontObject( itSorted, vecContainer, pMetrics, 
bEmbedd, bActualBold, bActualItalic, pmbFontName, pEncoding, pSubsetting );
+        }
         podofo_free( pmbFontName );
         pmbFontName = NULL;
     } catch( PdfError & error ) {
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to