std::string PdfVecObjects::GetNextSubsetPrefix() { if ( m_sSubsetPrefix == "" ) { m_sSubsetPrefix = "AAAAAA+"; } else { PODOFO_ASSERT( m_sSubsetPrefix.length() == 7 ); PODOFO_ASSERT( m_sSubsetPrefix[6] == '+' ); for ( int i = 5; i >= 0; i-- ) { if ( m_sSubsetPrefix[i] < 'Z' ) { m_sSubsetPrefix[i]++; break; } m_sSubsetPrefix[i] = 'A'; } } return m_sSubsetPrefix; }
PdfFont* PdfFontCache::GetDuplicateFontType1( PdfFont * pFont, const char* pszSuffix ) { TCISortedFontList it = m_vecFonts.begin(); std::string id = pFont->GetIdentifier().GetName(); id += pszSuffix; // Search if the object is a cached normal font while( it != m_vecFonts.end() ) { if( (*it).m_pFont->GetIdentifier() == id ) return (*it).m_pFont; ++it; } // Search if the object is a cached font subset it = m_vecFontSubsets.begin(); while( it != m_vecFontSubsets.end() ) { if( (*it).m_pFont->GetIdentifier() == id ) return (*it).m_pFont; ++it; } // Create a copy of the font PODOFO_ASSERT( pFont->GetFontMetrics()->GetFontType() == ePdfFontType_Type1Pfb ); PdfFontMetrics *pMetrics = new PdfFontMetrics( &m_ftLibrary, pFont->GetFontMetrics()->GetFilename() ); PdfFont* newFont = new PdfFontType1( static_cast<PdfFontType1 *>(pFont), pMetrics, pszSuffix, m_pParent ); if( newFont ) { std::string name = newFont->GetFontMetrics()->GetFontname(); name += pszSuffix; TFontCacheElement element; element.m_pFont = newFont; element.m_bBold = newFont->IsBold(); element.m_bItalic = newFont->IsItalic(); element.m_sFontName = name; element.m_pEncoding = newFont->GetEncoding(); m_vecFonts .push_back( element ); // Now sort the font list std::sort( m_vecFonts.begin(), m_vecFonts.end() ); } return newFont; }
PdfFont* PdfFontCache::GetFont( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bEmbedd, const PdfEncoding * const pEncoding ) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont; std::pair<TISortedFontList,TCISortedFontList> it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( pszFontName, bBold, bItalic, pEncoding ) ); if( it.first == it.second ) return GetWin32Font( it.first, m_vecFonts, pszFontName, bBold, bItalic, bEmbedd, pEncoding ); else pFont = (*it.first).m_pFont; return pFont; }
PdfFont* PdfFontCache::GetFont( const char* pszFontName, bool bBold, bool bItalic, bool bEmbedd, const PdfEncoding * const pEncoding, const char* pszFileName ) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont; PdfFontMetrics* pMetrics; std::pair<TISortedFontList,TCISortedFontList> it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( pszFontName, bBold, bItalic, pEncoding ) ); if( it.first == it.second ) { std::string sPath; if ( pszFileName == NULL ) sPath = this->GetFontPath( pszFontName, bBold, bItalic ); else sPath = pszFileName; if( sPath.empty() ) { #ifdef _WIN32 return GetWin32Font( it.first, m_vecFonts, pszFontName, bBold, bItalic, bEmbedd, pEncoding ); #else PdfError::LogMessage( eLogSeverity_Critical, "No path was found for the specified fontname: %s\n", pszFontName ); return NULL; #endif // _WIN32 } pMetrics = new PdfFontMetrics( &m_ftLibrary, sPath.c_str() ); pFont = this->CreateFontObject( it.first, m_vecFonts, pMetrics, bEmbedd, bBold, bItalic, pszFontName, pEncoding ); } else pFont = (*it.first).m_pFont; return pFont; }
PdfFontMetricsObject::PdfFontMetricsObject( PdfObject* pFont, PdfObject* pDescriptor, const PdfEncoding* const pEncoding ) : PdfFontMetrics( ePdfFontType_Unknown, "", NULL ), m_pEncoding( pEncoding ), m_dDefWidth(0.0) { if( !pDescriptor ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } const PdfName & rSubType = pFont->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); // OC 15.08.2010 BugFix: /FirstChar /LastChar /Widths are in the Font dictionary and not in the FontDescriptor if ( rSubType == PdfName("Type1") || rSubType == PdfName("TrueType") ) { m_sName = pDescriptor->GetIndirectKey( "FontName" )->GetName(); m_bbox = pDescriptor->GetIndirectKey( "FontBBox" )->GetArray(); m_nFirst = static_cast<int>(pFont->GetDictionary().GetKeyAsLong( "FirstChar", 0L )); m_nLast = static_cast<int>(pFont->GetDictionary().GetKeyAsLong( "LastChar", 0L )); // OC 15.08.2010 BugFix: GetIndirectKey() instead of GetDictionary().GetKey() and "Widths" instead of "Width" PdfObject* widths = pFont->GetIndirectKey( "Widths" ); if( widths != NULL ) { m_width = widths->GetArray(); m_missingWidth = NULL; } else { widths = pDescriptor->GetDictionary().GetKey( "MissingWidth" ); if( widths == NULL ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, "Font object defines neither Widths, nor MissingWidth values!" ); m_missingWidth = widths; } } } else if ( rSubType == PdfName("CIDFontType0") || rSubType == PdfName("CIDFontType2") ) { PdfObject *pObj = pDescriptor->GetIndirectKey( "FontName" ); if (pObj) { m_sName = pObj->GetName(); } pObj = pDescriptor->GetIndirectKey( "FontBBox" ); if (pObj) { m_bbox = pObj->GetArray(); } m_nFirst = 0; m_nLast = 0; m_dDefWidth = static_cast<double>(pFont->GetDictionary().GetKeyAsLong( "DW", 1000L )); PdfVariant default_width(m_dDefWidth); PdfObject * pw = pFont->GetIndirectKey( "W" ); for (int i = m_nFirst; i <= m_nLast; ++i) { m_width.push_back(default_width); } if (pw) { PdfArray w = pw->GetArray(); int pos = 0; while (pos < static_cast<int>(w.GetSize())) { int start = static_cast<int>(w[pos++].GetNumber()); PODOFO_ASSERT (start >= 0); if (w[pos].IsArray()) { PdfArray widths = w[pos++].GetArray(); int length = start + static_cast<int>(widths.GetSize()); PODOFO_ASSERT (length >= start); if (length > static_cast<int>(m_width.GetSize())) { m_width.resize(length, default_width); } for (int i = 0; i < static_cast<int>(widths.GetSize()); ++i) { m_width[start + i] = widths[i]; } } else { int end = static_cast<int>(w[pos++].GetNumber()); int length = start + end; PODOFO_ASSERT (length >= start); if (length > static_cast<int>(m_width.GetSize())) { m_width.resize(length, default_width); } pdf_int64 width = w[pos++].GetNumber(); for (int i = start; i <= end; ++i) m_width[i] = PdfVariant(width); } } } m_nLast = m_width.GetSize() - 1; } else { PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFontFormat, rSubType.GetEscapedName().c_str() ); } m_nWeight = static_cast<unsigned int>(pDescriptor->GetDictionary().GetKeyAsLong( "FontWeight", 400L )); m_nItalicAngle = static_cast<int>(pDescriptor->GetDictionary().GetKeyAsLong( "ItalicAngle", 0L )); m_dPdfAscent = pDescriptor->GetDictionary().GetKeyAsReal( "Ascent", 0.0 ); m_dAscent = m_dPdfAscent / 1000.0; m_dPdfDescent = pDescriptor->GetDictionary().GetKeyAsReal( "Descent", 0.0 ); m_dDescent = m_dPdfDescent / 1000.0; m_dLineSpacing = m_dAscent + m_dDescent; // Try to fine some sensible values m_dUnderlineThickness = 1.0; m_dUnderlinePosition = 0.0; m_dStrikeOutThickness = m_dUnderlinePosition; m_dStrikeOutPosition = m_dAscent / 2.0; m_bSymbol = false; // TODO }
PdfFont* PdfFontCache::GetFontSubset( const char* pszFontName, bool bBold, bool bItalic, const PdfEncoding * const pEncoding, const char* pszFileName ) { PdfFont* pFont; PdfFontMetrics* pMetrics; std::pair<TISortedFontList,TCISortedFontList> it; // WARNING: The characters are completely ignored right now! it = std::equal_range( m_vecFontSubsets.begin(), m_vecFontSubsets.end(), TFontCacheElement( pszFontName, bBold, bItalic, pEncoding ) ); if( it.first == it.second ) { std::string sPath; if( pszFileName == NULL ) { sPath = this->GetFontPath( pszFontName, bBold, bItalic ); if( sPath.empty() ) { #ifdef _WIN32 // TODO: GetWin32Font PODOFO_ASSERT( 0 ); #else PdfError::LogMessage( eLogSeverity_Critical, "No path was found for the specified fontname: %s\n", pszFontName ); return NULL; #endif // _WIN32 } } else sPath = pszFileName; pMetrics = new PdfFontMetrics( &m_ftLibrary, sPath.c_str() ); if( !(pMetrics && pMetrics->GetFontType() == ePdfFontType_TrueType ) ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Subsetting is only supported for TrueType fonts." ); } PdfInputDevice input( sPath.c_str() ); PdfRefCountedBuffer buffer; PdfOutputDevice output( &buffer ); PdfFontTTFSubset subset( &input, pMetrics, PdfFontTTFSubset::eFontFileType_TTF ); PdfEncoding::const_iterator itChar = pEncoding->begin(); while( itChar != pEncoding->end() ) { subset.AddCharacter( *itChar ); ++itChar; } subset.BuildFont( &output ); // Delete metrics object, as it was only used so that PdfFontTTFSubset could // match unicode character points to glyph indeces delete pMetrics; // TODO: Do not hardcode unique basenames... pMetrics = new PdfFontMetrics( &m_ftLibrary, buffer, "ABCDEF+" ); pFont = this->CreateFontObject( it.first, m_vecFontSubsets, pMetrics, true, bBold, bItalic, pszFontName, pEncoding ); } else pFont = (*it.first).m_pFont; return pFont; }