diff options
Diffstat (limited to 'xmloff/source/style')
-rw-r--r-- | xmloff/source/style/XMLFontAutoStylePool.cxx | 80 |
1 files changed, 71 insertions, 9 deletions
diff --git a/xmloff/source/style/XMLFontAutoStylePool.cxx b/xmloff/source/style/XMLFontAutoStylePool.cxx index 1c13ea75cff4..1fb06598f841 100644 --- a/xmloff/source/style/XMLFontAutoStylePool.cxx +++ b/xmloff/source/style/XMLFontAutoStylePool.cxx @@ -34,6 +34,7 @@ #include <com/sun/star/ucb/SimpleFileAccess.hpp> #include <XMLBase64Export.hxx> +#include <comphelper/hash.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -367,7 +368,7 @@ void XMLFontAutoStylePool::exportXML() if (!fontFilesMap.count(sFileUrl)) { const OUString docUrl = bExportFlat ? - lcl_checkFontFile(sFileUrl) : embedFontFile(sFileUrl); + lcl_checkFontFile(sFileUrl) : embedFontFile(sFileUrl, pEntry->GetFamilyName()); if (!docUrl.isEmpty()) fontFilesMap[sFileUrl] = docUrl; else @@ -429,10 +430,72 @@ void XMLFontAutoStylePool::exportXML() } } -OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl ) +OUString getFreeFontName(uno::Reference<embed::XStorage> const & rxStorage, OUString const & rFamilyName) +{ + OUString sName; + int nIndex = 1; + do + { + sName = "Font_" + + rFamilyName.replaceAll(" ", "_") + "_" + + OUString::number(nIndex) + ".ttf"; + nIndex++; + } while (rxStorage->hasByName(sName)); + + return sName; +} + +OString convertToHashString(std::vector<unsigned char> const & rHash) +{ + std::stringstream aStringStream; + for (auto const & rByte : rHash) + { + aStringStream << std::setw(2) << std::setfill('0') << std::hex << int(rByte); + } + + return OString(aStringStream.str().c_str()); +} + +OString getFileHash(OUString const & rFileUrl) +{ + OString aHash; + osl::File aFile(rFileUrl); + if (aFile.open(osl_File_OpenFlag_Read) != osl::File::E_None) + return aHash; + + comphelper::Hash aHashEngine(comphelper::HashType::SHA512); + for (;;) + { + sal_Int8 aBuffer[4096]; + sal_uInt64 nReadSize; + sal_Bool bEof; + if (aFile.isEndOfFile(&bEof) != osl::File::E_None) + { + SAL_WARN("xmloff", "Error reading font file " << rFileUrl); + return aHash; + } + if (bEof) + break; + if (aFile.read(aBuffer, 4096, nReadSize) != osl::File::E_None) + { + SAL_WARN("xmloff", "Error reading font file " << rFileUrl); + return aHash; + } + if (nReadSize == 0) + break; + aHashEngine.update(reinterpret_cast<unsigned char*>(aBuffer), nReadSize); + } + return convertToHashString(aHashEngine.finalize()); +} + +OUString XMLFontAutoStylePool::embedFontFile(OUString const & fileUrl, OUString const & rFamilyName) { try { + OString sHashString = getFileHash(fileUrl); + if (m_aEmbeddedFontFiles.find(sHashString) != m_aEmbeddedFontFiles.end()) + return m_aEmbeddedFontFiles.at(sHashString); + osl::File file( fileUrl ); if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None ) return OUString(); @@ -443,12 +506,9 @@ OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl ) uno::Reference< embed::XStorage > storage; storage.set( GetExport().GetTargetStorage()->openStorageElement( "Fonts", ::embed::ElementModes::WRITE ), uno::UNO_QUERY_THROW ); - int index = 0; - OUString name; - do - { - name = "font" + OUString::number( ++index ) + ".ttf"; - } while( storage->hasByName( name ) ); + + OUString name = getFreeFontName(storage, rFamilyName); + uno::Reference< io::XOutputStream > outputStream; outputStream.set( storage->openStreamElement( name, ::embed::ElementModes::WRITE ), UNO_QUERY_THROW ); uno::Reference < beans::XPropertySet > propertySet( outputStream, uno::UNO_QUERY ); @@ -484,7 +544,9 @@ OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl ) if( transaction.is()) { transaction->commit(); - return "Fonts/" + name; + OUString sInternalName = "Fonts/" + name; + m_aEmbeddedFontFiles.emplace(sHashString, sInternalName); + return sInternalName; } } } catch( const Exception& e ) |