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/XMLFontStylesContext.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/XMLFontStylesContext.cxx')
-rw-r--r-- | xmloff/source/style/XMLFontStylesContext.cxx | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/xmloff/source/style/XMLFontStylesContext.cxx b/xmloff/source/style/XMLFontStylesContext.cxx index 6a6e290f53d8..8cdb5ed012a3 100644 --- a/xmloff/source/style/XMLFontStylesContext.cxx +++ b/xmloff/source/style/XMLFontStylesContext.cxx @@ -21,8 +21,11 @@ #include <com/sun/star/awt/FontFamily.hpp> #include <com/sun/star/awt/FontPitch.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <osl/file.hxx> #include <rtl/logfile.hxx> +#include <vcl/temporaryfonts.hxx> #include <xmloff/nmspmap.hxx> #include "xmloff/xmlnmspe.hxx" @@ -172,6 +175,127 @@ void XMLFontStyleContext_Impl::FillProperties( } } +SvXMLImportContext * XMLFontStyleContext_Impl::CreateChildContext( + sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) +{ + if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_SRC )) + return new XMLFontStyleContextFontFaceSrc( GetImport(), nPrefix, rLocalName, *this ); + return SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName, xAttrList ); +} + +OUString XMLFontStyleContext_Impl::familyName() const +{ + OUString ret; + aFamilyName >>= ret; + return ret; +} + + +TYPEINIT1( XMLFontStyleContextFontFaceSrc, SvXMLImportContext ); + +XMLFontStyleContextFontFaceSrc::XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const XMLFontStyleContext_Impl& _font ) + : SvXMLImportContext( rImport, nPrfx, rLName ) + , font( _font ) +{ +} + +SvXMLImportContext * XMLFontStyleContextFontFaceSrc::CreateChildContext( + sal_uInt16 nPrefix, + const ::rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) +{ + if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_URI )) + return new XMLFontStyleContextFontFaceUri( GetImport(), nPrefix, rLocalName, xAttrList, font ); + return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList ); +} + + +TYPEINIT1( XMLFontStyleContextFontFaceUri, SvXMLImportContext ); + +XMLFontStyleContextFontFaceUri::XMLFontStyleContextFontFaceUri( SvXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + const XMLFontStyleContext_Impl& _font ) + : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList ) + , font( _font ) +{ +} + +void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, + const OUString& rValue ) +{ + if( nPrefixKey == XML_NAMESPACE_XLINK && IsXMLToken( rLocalName, XML_HREF )) + handleEmbeddedFont( rValue ); + else + SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); +} + +void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url ) +{ + OUString fontName = font.familyName(); + const char* style = ""; + // OOXML needs to know what kind of style the font is (regular, italic, bold, bold-italic), + // and the TemporaryFonts class is modelled after it. But ODF doesn't (need to) include + // this information, so try to guess from the name (LO encodes the style), otherwise + // go with regular and hope it works. + if( url.endsWithIgnoreAsciiCase( "bi.ttf" )) + style = "bi"; + else if( url.endsWithIgnoreAsciiCase( "b.ttf" )) + style = "b"; + else if( url.endsWithIgnoreAsciiCase( "i.ttf" )) + style = "i"; + // If there's any giveMeStreamForThisURL(), then it's well-hidden for me to find it. + if( GetImport().IsPackageURL( url )) + { + uno::Reference< embed::XStorage > storage; + storage.set( GetImport().GetSourceStorage(), UNO_QUERY_THROW ); + if( url.indexOf( '/' ) > -1 ) // TODO what if more levels? + storage.set( storage->openStorageElement( url.copy( 0, url.indexOf( '/' )), + ::embed::ElementModes::READ ), uno::UNO_QUERY_THROW ); + OUString fileUrl = TemporaryFonts::fileUrlForFont( fontName, style ); + osl::File file( fileUrl ); + switch( file.open( osl_File_OpenFlag_Create | osl_File_OpenFlag_Write )) + { + case osl::File::E_None: + break; // ok + case osl::File::E_EXIST: + return; // Assume it's already been added correctly. + default: + SAL_WARN( "xmloff", "Cannot open file for temporary font" ); + return; + } + uno::Reference< io::XInputStream > inputStream; + inputStream.set( storage->openStreamElement( url.copy( url.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ ), + UNO_QUERY_THROW ); + for(;;) + { + uno::Sequence< sal_Int8 > buffer; + int read = inputStream->readBytes( buffer, 1024 ); + sal_uInt64 dummy; + if( read > 0 ) + file.write( buffer.getConstArray(), read, dummy ); + if( read < 1024 ) + break; + } + inputStream->closeInput(); + if( file.close() != osl::File::E_None ) + { + SAL_WARN( "xmloff", "Writing temporary font file failed" ); + osl::File::remove( fileUrl ); + return; + } + TemporaryFonts::activateFont( fontName, fileUrl ); + GetImport().NotifyEmbeddedFontRead(); + } + else + SAL_WARN( "xmloff", "External URL for font file not handled." ); +} + SvXMLStyleContext *XMLFontStylesContext::CreateStyleChildContext( sal_uInt16 nPrefix, const ::rtl::OUString& rLocalName, |