From 6441cd60c3c903727487e0e10955bd51486e47d9 Mon Sep 17 00:00:00 2001
From: Michael Stahl <mstahl@redhat.com>
Date: Tue, 27 Jan 2015 14:11:09 +0000
Subject: [PATCH] rhbz#1177022: vcl: fix PDF embedding of Type 1 fonts
Change-Id: I03056c9e1cfb87f2f0e339db701954c150c8ea3c
---
include/vcl/fontmanager.hxx | 7 ++++++-
vcl/generic/fontmanager/fontmanager.cxx | 25 +++++++++++++++++++++-
vcl/generic/print/genpspgraphics.cxx | 8 +++----
vcl/headless/svptext.cxx | 4 ++--
vcl/inc/generic/genpspgraphics.h | 4 ++--
vcl/inc/headless/svpgdi.hxx | 2 +-
vcl/inc/salgdi.hxx | 8 +++++--
vcl/inc/unx/salgdi.h | 2 +-
vcl/inc/win/salgdi.h | 2 +-
vcl/source/gdi/pdfwriter_impl.cxx | 37 +++++++++++++++++++++++++++++++--
vcl/unx/generic/gdi/salgdi3.cxx | 4 ++--
vcl/win/source/gdi/salgdi3.cxx | 2 +-
12 files changed, 85 insertions(+), 20 deletions(-)
diff --git a/include/vcl/fontmanager.hxx b/include/vcl/fontmanager.hxx
index 7f8511d..675287e 100644
--- a/include/vcl/fontmanager.hxx
+++ b/include/vcl/fontmanager.hxx
@@ -202,7 +202,12 @@ class VCL_PLUGIN_PUBLIC PrintFontManager
bool m_bHaveVerticalSubstitutedGlyphs;
bool m_bUserOverride;
+ /// mapping from unicode (well, UCS-2) to font code
std::map< sal_Unicode, sal_Int32 > m_aEncodingVector;
+ /// HACK for Type 1 fonts: if multiple UCS-2 codes map to the same
+ /// font code, this set contains the preferred one, i.e., the one that
+ /// is specified explicitly via "C" or "CH" in the AFM file
+ std::set<sal_Unicode> m_aEncodingVectorPriority;
std::map< sal_Unicode, OString > m_aNonEncoded;
explicit PrintFont( fonttype::type eType );
@@ -458,7 +463,7 @@ public:
// builtin; if ppNonEncoded is set and non encoded type1 glyphs exist
// then *ppNonEncoded is set to the mapping for nonencoded glyphs.
// the encoding vector contains -1 for non encoded glyphs
- const std::map< sal_Unicode, sal_Int32 >* getEncodingMap( fontID nFontID, const std::map< sal_Unicode, OString >** ppNonEncoded ) const;
+ const std::map< sal_Unicode, sal_Int32 >* getEncodingMap( fontID nFontID, const std::map< sal_Unicode, OString >** ppNonEncoded, std::set<sal_Unicode> const** ppPriority ) const;
// evaluates copyright flags for TrueType fonts for printing/viewing
// type1 fonts do not have such a feature, so return for them is true
diff --git a/vcl/generic/fontmanager/fontmanager.cxx b/vcl/generic/fontmanager/fontmanager.cxx
index 9f545cc..dd490d0 100644
--- a/vcl/generic/fontmanager/fontmanager.cxx
+++ b/vcl/generic/fontmanager/fontmanager.cxx
@@ -332,6 +332,7 @@ bool PrintFontManager::PrintFont::readAfmMetrics( MultiAtomProvider* pProvider,
}
m_aEncodingVector.clear();
+ m_aEncodingVectorPriority.clear();
// fill in global info
// PSName
@@ -561,7 +562,10 @@ bool PrintFontManager::PrintFont::readAfmMetrics( MultiAtomProvider* pProvider,
{
pUnicodes[i] = pChar->code + 0xf000;
if( bFillEncodingvector )
+ {
m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
+ m_aEncodingVectorPriority.insert(pUnicodes[i]);
+ }
continue;
}
@@ -622,7 +626,10 @@ bool PrintFontManager::PrintFont::readAfmMetrics( MultiAtomProvider* pProvider,
{
m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric;
if( bFillEncodingvector )
+ {
m_aEncodingVector[ pUnicodes[i] ] = pChar->code;
+ m_aEncodingVectorPriority.insert(pUnicodes[i]);
+ }
}
else if( pChar->name )
{
@@ -650,13 +657,21 @@ bool PrintFontManager::PrintFont::readAfmMetrics( MultiAtomProvider* pProvider,
::std::pair< ::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator,
::boost::unordered_multimap< sal_uInt8, sal_Unicode >::const_iterator >
aCodes = rManager.getUnicodeFromAdobeCode( pChar->code );
+ bool bFirst = true;
while( aCodes.first != aCodes.second )
{
if( (*aCodes.first).second != 0 )
{
m_pMetrics->m_aMetrics[ (*aCodes.first).second ] = aMetric;
if( bFillEncodingvector )
+ {
m_aEncodingVector[ (*aCodes.first).second ] = pChar->code;
+ if (bFirst) // arbitrarily prefer the first one
+ {
+ m_aEncodingVectorPriority.insert((*aCodes.first).second);
+ bFirst = false;
+ }
+ }
}
++aCodes.first;
}
@@ -670,7 +685,10 @@ bool PrintFontManager::PrintFont::readAfmMetrics( MultiAtomProvider* pProvider,
m_pMetrics->m_aMetrics[ code ] = aMetric;
// maybe should try to find the name in the convtabs ?
if( bFillEncodingvector )
+ {
m_aEncodingVector[ code ] = pChar->code;
+ m_aEncodingVectorPriority.insert(code);
+ }
}
}
}
@@ -2474,7 +2492,7 @@ void PrintFontManager::getGlyphWidths( fontID nFont,
// -------------------------------------------------------------------------
-const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, OString >** pNonEncoded ) const
+const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( fontID nFont, const std::map< sal_Unicode, OString >** pNonEncoded, std::set<sal_Unicode> const** ppPriority ) const
{
PrintFont* pFont = getFont( nFont );
if( !pFont ||
@@ -2488,6 +2506,11 @@ const std::map< sal_Unicode, sal_Int32 >* PrintFontManager::getEncodingMap( font
if( pNonEncoded )
*pNonEncoded = pFont->m_aNonEncoded.size() ? &pFont->m_aNonEncoded : NULL;
+ if (ppPriority)
+ {
+ *ppPriority = &pFont->m_aEncodingVectorPriority;
+ }
+
return pFont->m_aEncodingVector.size() ? &pFont->m_aEncodingVector : NULL;
}
diff --git a/vcl/generic/print/genpspgraphics.cxx b/vcl/generic/print/genpspgraphics.cxx
index 542986a..0c9d073 100644
--- a/vcl/generic/print/genpspgraphics.cxx
+++ b/vcl/generic/print/genpspgraphics.cxx
@@ -1046,7 +1046,7 @@ sal_Bool GenPspGraphics::CreateFontSubset(
//--------------------------------------------------------------------------
-const Ucs2SIntMap* GenPspGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
+const Ucs2SIntMap* GenPspGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority)
{
// in this context the pFont->GetFontId() is a valid PSP
// font since they are the only ones left after the PDF
@@ -1054,7 +1054,7 @@ const Ucs2SIntMap* GenPspGraphics::GetFontEncodingVector( const PhysicalFontFace
// which this method was created). The correct way would
// be to have the GlyphCache search for the PhysicalFontFace pFont
psp::fontID aFont = pFont->GetFontId();
- return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
+ return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded, ppPriority );
}
//--------------------------------------------------------------------------
@@ -1073,7 +1073,7 @@ void GenPspGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
}
-const Ucs2SIntMap* GenPspGraphics::DoGetFontEncodingVector( fontID aFont, const Ucs2OStrMap** pNonEncoded )
+const Ucs2SIntMap* GenPspGraphics::DoGetFontEncodingVector( fontID aFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority)
{
psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
@@ -1085,7 +1085,7 @@ const Ucs2SIntMap* GenPspGraphics::DoGetFontEncodingVector( fontID aFont, const
return NULL;
}
- return rMgr.getEncodingMap( aFont, pNonEncoded );
+ return rMgr.getEncodingMap( aFont, pNonEncoded, ppPriority );
}
void GenPspGraphics::DoGetGlyphWidths( psp::fontID aFont,
diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx
index 0a4bbd1..9c99101 100644
--- a/vcl/headless/svptext.cxx
+++ b/vcl/headless/svptext.cxx
@@ -340,7 +340,7 @@ sal_Bool SvpSalGraphics::CreateFontSubset(
}
-const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
+const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority)
{
// in this context the pFont->GetFontId() is a valid PSP
// font since they are the only ones left after the PDF
@@ -348,7 +348,7 @@ const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace
// which this method was created). The correct way would
// be to have the GlyphCache search for the PhysicalFontFace pFont
psp::fontID aFont = pFont->GetFontId();
- return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
+ return GenPspGraphics::DoGetFontEncodingVector(aFont, pNonEncoded, ppPriority);
}
diff --git a/vcl/inc/generic/genpspgraphics.h b/vcl/inc/generic/genpspgraphics.h
index 74ccf65..bb45c75 100644
--- a/vcl/inc/generic/genpspgraphics.h
+++ b/vcl/inc/generic/genpspgraphics.h
@@ -62,7 +62,7 @@ public:
static void DoFreeEmbedFontData( const void* pData, long nLen );
// helper methods for sharing with X11SalGraphics
- static const Ucs2SIntMap* DoGetFontEncodingVector( psp::fontID aFont, const Ucs2OStrMap** pNonEncoded );
+ static const Ucs2SIntMap* DoGetFontEncodingVector( psp::fontID aFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority );
static void DoGetGlyphWidths( psp::fontID aFont,
bool bVertical,
Int32Vector& rWidths,
@@ -106,7 +106,7 @@ public:
int nGlyphs,
FontSubsetInfo& rInfo
);
- virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** ppPriority );
virtual const void* GetEmbedFontData( const PhysicalFontFace*,
const sal_Ucs* pUnicodes,
sal_Int32* pWidths,
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index c36cfd3..b45a562 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -146,7 +146,7 @@ public:
int nGlyphs,
FontSubsetInfo& rInfo
);
- virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** ppPriority );
virtual const void* GetEmbedFontData( const PhysicalFontFace*,
const sal_Ucs* pUnicodes,
sal_Int32* pWidths,
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index 323c66a..4b8effa 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -29,6 +29,7 @@
#include "sallayout.hxx"
#include <map>
+#include <set>
class ImplDevFontList;
@@ -278,8 +279,11 @@ public:
// glyphs with only a name) exist it is set to the corresponding
// map for non encoded glyphs; the encoding vector contains -1
// as encoding for these cases
- virtual const Ucs2SIntMap*
- GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ) = 0;
+ virtual const Ucs2SIntMap* GetFontEncodingVector(
+ const PhysicalFontFace*,
+ const Ucs2OStrMap** ppNonEncoded,
+ std::set<sal_Unicode> const** ppPriority) = 0;
+
// GetEmbedFontData: gets the font data for a font marked
// embeddable by GetDevFontList or NULL in case of error
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 9e3e9a5..3476149 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -242,7 +242,7 @@ public:
int nGlyphs,
FontSubsetInfo& rInfo
);
- virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** ppPriority );
virtual const void* GetEmbedFontData( const PhysicalFontFace*,
const sal_Ucs* pUnicodes,
sal_Int32* pWidths,
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index b54c876..bf33acb 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -346,7 +346,7 @@ public:
// glyphs with only a name) exist it is set to the corresponding
// map for non encoded glyphs; the encoding vector contains -1
// as encoding for these cases
- virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded );
+ virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** );
// GetEmbedFontData: gets the font data for a font marked
// embeddable by GetDevFontList or NULL in case of error
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 89355ad..c09b81b 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -3071,7 +3071,9 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const Physical
sal_Int32 nFontDescriptor = 0;
// prepare font encoding
- const Ucs2SIntMap* pEncoding = m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pFont, NULL );
+ std::set<sal_Unicode> const * pPriority(0);
+ const Ucs2SIntMap *const pEncoding =
+ m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pFont, NULL, &pPriority );
sal_Int32 nToUnicodeStream = 0;
sal_uInt8 nEncoding[256];
sal_Ucs nEncodedCodes[256];
@@ -3090,6 +3092,37 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const Physical
if( it->second != -1 )
{
sal_Int32 nCode = (sal_Int32)(it->second & 0x000000ff);
+ SAL_WARN_IF(nCode != it->second, "vcl.gdi", "emitEmbeddedFont: FIXME: cannot handle Type 1 font with code points > 256");
+ if (nEncoding[nCode] != 0)
+ {
+ // should not have 2 identical mappings
+ assert(nEncodedCodes[nCode] != it->first);
+ if (pPriority)
+ {
+ bool bExist = pPriority->find(nEncodedCodes[nCode]) != pPriority->end();
+ bool bIter = pPriority->find(it->first) != pPriority->end();
+ SAL_WARN_IF(bExist && bIter, "vcl.gdi", "both are preferred? odd...");
+ if (bExist)
+ {
+ continue;
+ }
+ // note: aUnicodes will contain the old one but that
+ // does not matter because there's nothing iterating it
+ }
+ else
+ {
+ // is this fallback important? let's prefer lower one
+ if (nEncodedCodes[nCode] < it->first)
+ {
+ SAL_WARN("vcl.gdi", "emitEmbeddedFont: ignoring code " << nCode << " mapping to " << it->first << " in favor of " << nEncodedCodes[nCode]);
+ continue;
+ }
+ else
+ {
+ SAL_WARN("vcl.gdi", "emitEmbeddedFont: ignoring code " << nCode << " mapping to " << nEncodedCodes[nCode] << " in favor of " << it->first);
+ }
+ }
+ }
nEncoding[ nCode ] = static_cast<sal_uInt8>( nCode );
nEncodedCodes[ nCode ] = it->first;
pEncToUnicodeIndex[ nCode ] = static_cast<sal_Int32>(aUnicodes.size());
@@ -7067,7 +7100,7 @@ void PDFWriterImpl::registerGlyphs( int nGlyphs,
const Ucs2SIntMap* pEncoding = NULL;
const Ucs2OStrMap* pNonEncoded = NULL;
getReferenceDevice()->ImplGetGraphics();
- pEncoding = m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pCurrentFont, &pNonEncoded );
+ pEncoding = m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pCurrentFont, &pNonEncoded, 0 );
Ucs2SIntMap::const_iterator enc_it;
Ucs2OStrMap::const_iterator nonenc_it;
diff --git a/vcl/unx/generic/gdi/salgdi3.cxx b/vcl/unx/generic/gdi/salgdi3.cxx
index d6a506971..c28c53d 100644
--- a/vcl/unx/generic/gdi/salgdi3.cxx
+++ b/vcl/unx/generic/gdi/salgdi3.cxx
@@ -778,7 +778,7 @@ void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen )
//--------------------------------------------------------------------------
-const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
+const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority)
{
// in this context the pFont->GetFontId() is a valid PSP
// font since they are the only ones left after the PDF
@@ -786,7 +786,7 @@ const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const PhysicalFontFace
// which this method was created). The correct way would
// be to have the GlyphCache search for the PhysicalFontFace pFont
psp::fontID aFont = pFont->GetFontId();
- return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
+ return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded, ppPriority );
}
//--------------------------------------------------------------------------
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index 59f8f4e..7a465c4 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -2755,7 +2755,7 @@ void WinSalGraphics::FreeEmbedFontData( const void* pData, long /*nLen*/ )
}
-const Ucs2SIntMap* WinSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
+const Ucs2SIntMap* WinSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const**)
{
// TODO: even for builtin fonts we get here... why?
if( !pFont->IsEmbeddable() )
--
1.9.3