diff --git a/vcl/inc/fontsubset.hxx b/vcl/inc/fontsubset.hxx index 830bad314e29..a20106b7762f 100644 --- a/vcl/inc/fontsubset.hxx +++ b/vcl/inc/fontsubset.hxx @@ -25,6 +25,8 @@ #include +#include + // Translate units from TT to PS (standard 1/1000) inline int XUnits(int nUPEM, int n) { return (n * 1000) / nUPEM; } @@ -50,6 +52,7 @@ public: // TODO: make subsetter results private and provide accessor methods ins int m_nCapHeight = 0; tools::Rectangle m_aFontBBox; FontType m_nFontType = FontType::NO_FONT; ///< font-type of subset result + std::vector m_aGlyphNames; ///< glyph names for CFF encoding }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx index 0ca3e3da9a4a..5db092f300d0 100644 --- a/vcl/source/font/PhysicalFontFace.cxx +++ b/vcl/source/font/PhysicalFontFace.cxx @@ -548,13 +548,28 @@ bool PhysicalFontFace::CreateFontSubset(std::vector& rOutBuffer, hb_blob_t* pCFFBlob = hb_face_reference_table(pSubsetFace, HB_TAG('C', 'F', 'F', ' ')); comphelper::ScopeGuard aCFFBlobGuard([&]() { hb_blob_destroy(pCFFBlob); }); if (pCFFBlob == hb_blob_get_empty()) - { - // This is not a font with CFF table, so we will create a TTF font subset. rInfo.m_nFontType = FontType::SFNT_TTF; + else + { + rInfo.m_nFontType = FontType::SFNT_CFF; - // HarfBuzz creates a Unicode cmap, but we need a fake cmap based on pEncoding, - // so we use face builder construct a new face based in the subset table, - // and create a new cmap table and add it to the new face. + // Get glyph names from the subset CFF charset, needed for building + // the PDF Encoding dictionary that maps character codes to glyph names. + rInfo.m_aGlyphNames.resize(nGlyphCount); + for (int i = 0; i < nGlyphCount; ++i) + { + char aName[64]; + if (hb_font_get_glyph_name(pSubsetFont, pEncoding[i], aName, sizeof(aName))) + rInfo.m_aGlyphNames[i] = OString(aName); + else + rInfo.m_aGlyphNames[i] = ".notdef"_ostr; + } + } + + // HarfBuzz creates a Unicode cmap, but we need a fake cmap based on pEncoding, + // so we use face builder to construct a new face based on the subset tables, + // and create a new cmap table and add it to the new face. + { hb_face_t* pBuilderFace = hb_face_builder_create(); comphelper::ScopeGuard aBuilderFaceGuard([&]() { hb_face_destroy(pBuilderFace); }); unsigned int nSubsetTableCount = hb_face_get_table_tags(pSubsetFace, 0, nullptr, nullptr); @@ -611,26 +626,6 @@ bool PhysicalFontFace::CreateFontSubset(std::vector& rOutBuffer, rOutBuffer.assign(reinterpret_cast(pSubsetData), reinterpret_cast(pSubsetData) + nSubsetLength); } - else - { - // Ideally we should be outputting a CFF (Type1C) font here, but I couldn’t get it to work. - // So we oconvert it to Type1 font instead. - // TODO: simplify CreateCFFfontSubset() to only do the conversion, since we already - // have the subsetted font. - rInfo.m_nFontType = FontType::TYPE1_PFB; - - unsigned int nCffLen; - const char* pCffData = hb_blob_get_data(pCFFBlob, &nCffLen); - if (!pCffData || !nCffLen) - return false; - - if (!ConvertCFFfontToType1(reinterpret_cast(pCffData), nCffLen, - rOutBuffer, rInfo)) - { - SAL_WARN("vcl.fonts.cff", "Failed to convert CFF data to Type 1 font"); - return false; - } - } return true; } diff --git a/vcl/source/pdf/pdfwriter_impl.cxx b/vcl/source/pdf/pdfwriter_impl.cxx index fa010d9dae23..407206f38f7d 100644 --- a/vcl/source/pdf/pdfwriter_impl.cxx +++ b/vcl/source/pdf/pdfwriter_impl.cxx @@ -2040,6 +2040,7 @@ sal_Int32 PDFWriterImpl::emitFontDescriptor( const vcl::font::PhysicalFontFace* aLine.append( '2' ); break; case FontType::CFF_FONT: + case FontType::SFNT_CFF: aLine.append( "3" ); break; case FontType::TYPE1_PFB: @@ -2131,9 +2132,23 @@ bool PDFWriterImpl::emitFonts() if (!writeBufferBytes(aBuffer.data(), aBuffer.size())) return false; } + else if( aSubsetInfo.m_nFontType == FontType::SFNT_CFF ) + { + aLine.append("/Length1 " + + OString::number(aBuffer.size()) + + "/Subtype/OpenType>>\n" + "stream\n" ); + if ( !writeBuffer( aLine ) ) return false; + if ( osl::File::E_None != m_aFile.getPos(nStartPos) ) return false; + + // copy font file + beginCompression(); + checkAndEnableStreamEncryption( nFontStream ); + if (!writeBufferBytes(aBuffer.data(), aBuffer.size())) + return false; + } else if( aSubsetInfo.m_nFontType & FontType::CFF_FONT) { - // CFF subset is embedded as an SFNT font (same as TrueType) aLine.append("/Subtype/Type1C>>\nstream\n"); if ( !writeBuffer( aLine ) ) return false; if ( osl::File::E_None != m_aFile.getPos(nStartPos) ) return false; @@ -2204,7 +2219,7 @@ bool PDFWriterImpl::emitFonts() if ( !updateObject( nFontObject ) ) return false; aLine.setLength( 0 ); aLine.append( OString::number(nFontObject) + " 0 obj\n" ); - aLine.append( (aSubsetInfo.m_nFontType & (FontType::TYPE1_PFB | FontType::CFF_FONT)) ? + aLine.append( (aSubsetInfo.m_nFontType & (FontType::SFNT_CFF | FontType::TYPE1_PFB | FontType::CFF_FONT)) ? "<>\n" ); + } aLine.append( ">>\n" "endobj\n\n" ); if ( !writeBuffer( aLine ) ) return false;