diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2013-02-01 14:26:36 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2013-02-01 14:26:36 +0100 |
commit | 989d0953a4d69bef3c8aba8e9dc7758194adcdc4 (patch) | |
tree | 678cdb4ca547e9b37248f1b3d5b54ea4e17286d5 /xmloff/source/style/XMLFontAutoStylePool.cxx | |
parent | 5ceaa68ca51c4d182210a28a64d574de6170b9ca (diff) |
basic support for embedded fonts in odt (fdo#42195)
There are still places that should be improved a bit, but this works.
Change-Id: Ieb7947a294ec95b6fd8cec2e8c4bc731e2594c42
Diffstat (limited to 'xmloff/source/style/XMLFontAutoStylePool.cxx')
-rw-r--r-- | xmloff/source/style/XMLFontAutoStylePool.cxx | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/xmloff/source/style/XMLFontAutoStylePool.cxx b/xmloff/source/style/XMLFontAutoStylePool.cxx index a496e79cbac9..0f92d66c41e9 100644 --- a/xmloff/source/style/XMLFontAutoStylePool.cxx +++ b/xmloff/source/style/XMLFontAutoStylePool.cxx @@ -25,11 +25,17 @@ #include "fonthdl.hxx" #include <xmloff/xmlexp.hxx> #include <xmloff/XMLFontAutoStylePool.hxx> +#include <vcl/temporaryfonts.hxx> +#include <osl/file.hxx> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> using ::rtl::OUString; using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::xmloff::token; @@ -128,9 +134,10 @@ public: ~XMLFontAutoStylePool_Impl() { DeleteAndDestroyAll(); } }; -XMLFontAutoStylePool::XMLFontAutoStylePool( SvXMLExport& rExp ) : +XMLFontAutoStylePool::XMLFontAutoStylePool( SvXMLExport& rExp, bool _tryToEmbedFonts ) : rExport( rExp ), - pPool( new XMLFontAutoStylePool_Impl ) + pPool( new XMLFontAutoStylePool_Impl ), + tryToEmbedFonts( _tryToEmbedFonts ) { } @@ -226,6 +233,7 @@ void XMLFontAutoStylePool::exportXML() XMLFontEncodingPropHdl aEncHdl; const SvXMLUnitConverter& rUnitConv = GetExport().GetMM100UnitConverter(); + std::map< OUString, OUString > fontFilesMap; // our url to document url sal_uInt32 nCount = pPool->size(); for( sal_uInt32 i=0; i<nCount; i++ ) { @@ -263,7 +271,106 @@ void XMLFontAutoStylePool::exportXML() SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE, XML_FONT_FACE, sal_True, sal_True ); + + if( tryToEmbedFonts ) + { + std::vector< OUString > fileUrls; + static const char* const styles[] = { "", "b", "i", "bi" }; + for( unsigned int j = 0; + j < SAL_N_ELEMENTS( styles ); + ++j ) + { + OUString fileUrl = TemporaryFonts::fileUrlForFont( pEntry->GetFamilyName(), styles[ j ] ); + if( !fontFilesMap.count( fileUrl )) + { + OUString docUrl = embedFontFile( fileUrl, styles[ j ] ); + if( !docUrl.isEmpty()) + fontFilesMap[ fileUrl ] = docUrl; + else + continue; // --> failed (most probably this font is not embedded) + } + fileUrls.push_back( fileUrl ); + } + if( !fileUrls.empty()) + { + SvXMLElementExport fontFaceSrc( GetExport(), XML_NAMESPACE_SVG, + XML_FONT_FACE_SRC, true, true ); + for( std::vector< OUString >::const_iterator it = fileUrls.begin(); + it != fileUrls.end(); + ++it ) + { + if( fontFilesMap.count( *it )) + { + GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, fontFilesMap[ *it ] ); + GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, "simple" ); + SvXMLElementExport fontFaceUri( GetExport(), XML_NAMESPACE_SVG, + XML_FONT_FACE_URI, true, true ); + } + } + } + } + } +} + +OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl, const char* style ) +{ + try + { + osl::File file( fileUrl ); + if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None ) + return OUString(); + uno::Reference< embed::XStorage > storage; + storage.set( GetExport().GetTargetStorage()->openStorageElement( OUString( "Fonts" ), + ::embed::ElementModes::WRITE ), uno::UNO_QUERY_THROW ); + int index = 0; + OUString name; + do + { + name = "font" + OUString::number( ++index ) + OUString::createFromAscii( style ) + ".ttf"; + } while( storage->hasByName( name ) ); + 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 ); + assert( propertySet.is()); + propertySet->setPropertyValue( "MediaType", uno::makeAny( OUString( "application/x-font-ttf" ))); // TODO + for(;;) + { + char buffer[ 4096 ]; + sal_uInt64 readSize; + sal_Bool eof; + if( file.isEndOfFile( &eof ) != osl::File::E_None ) + { + SAL_WARN( "xmloff", "Error reading font file " << fileUrl ); + outputStream->closeOutput(); + return OUString(); + } + if( eof ) + break; + if( file.read( buffer, 4096, readSize ) != osl::File::E_None ) + { + SAL_WARN( "xmloff", "Error reading font file " << fileUrl ); + outputStream->closeOutput(); + return OUString(); + } + if( readSize == 0 ) + break; + outputStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize )); + } + outputStream->closeOutput(); + if( storage.is() ) + { + Reference< embed::XTransactedObject > transaction( storage, UNO_QUERY ); + if( transaction.is()) + { + transaction->commit(); + return "Fonts/" + name; + } + } + } catch( const Exception& e ) + { + SAL_WARN( "xmloff", "Exception when embedding a font file:" << e.Message ); } + return OUString(); } |