summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/source/filter/xml/xmlfonte.cxx23
-rw-r--r--sw/source/filter/xml/xmlimp.hxx2
-rw-r--r--xmloff/Library_xo.mk1
-rw-r--r--xmloff/inc/xmloff/XMLFontAutoStylePool.hxx5
-rw-r--r--xmloff/inc/xmloff/XMLFontStylesContext.hxx39
-rw-r--r--xmloff/inc/xmloff/xmlimp.hxx2
-rw-r--r--xmloff/inc/xmloff/xmltoken.hxx2
-rw-r--r--xmloff/source/core/xmltoken.cxx2
-rw-r--r--xmloff/source/style/XMLFontAutoStylePool.cxx111
-rw-r--r--xmloff/source/style/XMLFontStylesContext.cxx124
10 files changed, 304 insertions, 7 deletions
diff --git a/sw/source/filter/xml/xmlfonte.cxx b/sw/source/filter/xml/xmlfonte.cxx
index 4b4e48cd33c7..60e9dca5137a 100644
--- a/sw/source/filter/xml/xmlfonte.cxx
+++ b/sw/source/filter/xml/xmlfonte.cxx
@@ -25,6 +25,7 @@
#include <unotext.hxx>
#include <doc.hxx>
#include <xmlexp.hxx>
+#include <xmlimp.hxx>
using namespace ::com::sun::star::uno;
@@ -35,13 +36,13 @@ class SwXMLFontAutoStylePool_Impl: public XMLFontAutoStylePool
{
public:
- SwXMLFontAutoStylePool_Impl( SwXMLExport& rExport );
+ SwXMLFontAutoStylePool_Impl( SwXMLExport& rExport, bool blockFontEmbedding );
};
SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl(
- SwXMLExport& _rExport ) :
- XMLFontAutoStylePool( _rExport )
+ SwXMLExport& _rExport, bool blockFontEmbedding ) :
+ XMLFontAutoStylePool( _rExport, blockFontEmbedding )
{
sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
RES_CHRATR_CTL_FONT };
@@ -75,7 +76,21 @@ SwXMLFontAutoStylePool_Impl::SwXMLFontAutoStylePool_Impl(
XMLFontAutoStylePool* SwXMLExport::CreateFontAutoStylePool()
{
- return new SwXMLFontAutoStylePool_Impl( *this );
+ bool blockFontEmbedding = false;
+ // We write font info to both content.xml and styles.xml, but they are both
+ // written by different SwXMLExport instance, and would therefore write each
+ // font file twice without complicated checking for duplicates, so handle
+ // the embedding only in one of them.
+ if(( getExportFlags() & EXPORT_CONTENT ) == 0 )
+ blockFontEmbedding = true;
+ if( !getDoc()->get( IDocumentSettingAccess::EMBED_FONTS ))
+ blockFontEmbedding = true;
+ return new SwXMLFontAutoStylePool_Impl( *this, !blockFontEmbedding );
+}
+
+void SwXMLImport::NotifyEmbeddedFontRead()
+{
+ getDoc()->set( IDocumentSettingAccess::EMBED_FONTS, true );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/xml/xmlimp.hxx b/sw/source/filter/xml/xmlimp.hxx
index 093aea3bd394..992236015971 100644
--- a/sw/source/filter/xml/xmlimp.hxx
+++ b/sw/source/filter/xml/xmlimp.hxx
@@ -197,6 +197,8 @@ public:
::com::sun::star::document::XDocumentProperties>
GetDocumentProperties() const;
+ virtual void NotifyEmbeddedFontRead() SAL_OVERRIDE;
+
const SwDoc* getDoc() const;
SwDoc* getDoc();
};
diff --git a/xmloff/Library_xo.mk b/xmloff/Library_xo.mk
index a24b6fd27812..7ffa8ba4c459 100644
--- a/xmloff/Library_xo.mk
+++ b/xmloff/Library_xo.mk
@@ -50,6 +50,7 @@ $(eval $(call gb_Library_use_libraries,xo,\
svl \
tl \
utl \
+ vcl \
$(gb_UWINAPI) \
))
diff --git a/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx b/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx
index 4fd666b50efc..8ed243daa321 100644
--- a/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx
+++ b/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx
@@ -37,6 +37,9 @@ class XMLOFF_DLLPUBLIC XMLFontAutoStylePool : public UniRefBase
XMLFontAutoStylePool_Impl *pPool;
XMLFontAutoStylePoolNames_Impl m_aNames;
sal_uInt32 nName;
+ bool tryToEmbedFonts;
+
+ OUString embedFontFile( const OUString& fontUrl, const char* style );
protected:
@@ -44,7 +47,7 @@ protected:
public:
- XMLFontAutoStylePool( SvXMLExport& rExport );
+ XMLFontAutoStylePool( SvXMLExport& rExport, bool tryToEmbedFonts = false );
~XMLFontAutoStylePool();
::rtl::OUString Add(
diff --git a/xmloff/inc/xmloff/XMLFontStylesContext.hxx b/xmloff/inc/xmloff/XMLFontStylesContext.hxx
index e48ae0a60c48..7a50fc76ee2f 100644
--- a/xmloff/inc/xmloff/XMLFontStylesContext.hxx
+++ b/xmloff/inc/xmloff/XMLFontStylesContext.hxx
@@ -121,12 +121,51 @@ public:
sal_Int32 nPitchIdx,
sal_Int32 nCharsetIdx ) const;
+ OUString familyName() const;
+
SvXMLImportContext * CreateChildContext(
sal_uInt16 nPrefix,
const ::rtl::OUString& rLocalName,
const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
};
+/// Handles <style:font-face-src>
+class XMLFontStyleContextFontFaceSrc : public SvXMLImportContext
+{
+ const XMLFontStyleContext_Impl& font;
+public:
+
+ TYPEINFO();
+
+ XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport, sal_uInt16 nPrfx,
+ const ::rtl::OUString& rLName,
+ const XMLFontStyleContext_Impl& font );
+
+ virtual SvXMLImportContext * CreateChildContext(
+ sal_uInt16 nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+};
+
+/// Handles <style:font-face-uri>
+class XMLFontStyleContextFontFaceUri : public SvXMLStyleContext
+{
+ const XMLFontStyleContext_Impl& font;
+ void handleEmbeddedFont( const OUString& url );
+public:
+
+ TYPEINFO();
+
+ XMLFontStyleContextFontFaceUri( SvXMLImport& rImport, sal_uInt16 nPrfx,
+ const ::rtl::OUString& rLName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
+ const XMLFontStyleContext_Impl& font );
+
+ virtual void SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName,
+ const OUString& rValue );
+};
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/inc/xmloff/xmlimp.hxx b/xmloff/inc/xmloff/xmlimp.hxx
index d97fe847ceda..7e6381a867ad 100644
--- a/xmloff/inc/xmloff/xmlimp.hxx
+++ b/xmloff/inc/xmloff/xmlimp.hxx
@@ -453,6 +453,8 @@ public:
@see <member>mbIsGraphicLoadOnDemandSupported</member>
*/
bool isGraphicLoadOnDemandSupported() const;
+
+ virtual void NotifyEmbeddedFontRead() {};
};
inline UniReference< XMLTextImportHelper > SvXMLImport::GetTextImport()
diff --git a/xmloff/inc/xmloff/xmltoken.hxx b/xmloff/inc/xmloff/xmltoken.hxx
index c4dff1c69ae8..13b59fe083fb 100644
--- a/xmloff/inc/xmloff/xmltoken.hxx
+++ b/xmloff/inc/xmloff/xmltoken.hxx
@@ -2457,6 +2457,8 @@ namespace xmloff { namespace token {
XML_SCRIPTS,
XML_FONT_FACE_DECLS,
XML_FONT_FACE,
+ XML_FONT_FACE_SRC,
+ XML_FONT_FACE_URI,
XML_FONT_ADORNMENTS,
XML_INCH,
XML_SPACE_AFTER,
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 4011f4963c2e..03180526de8f 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -2459,6 +2459,8 @@ namespace xmloff { namespace token {
TOKEN( "scripts", XML_SCRIPTS ),
TOKEN( "font-face-decls", XML_FONT_FACE_DECLS ),
TOKEN( "font-face", XML_FONT_FACE ),
+ TOKEN( "font-face-src", XML_FONT_FACE_SRC ),
+ TOKEN( "font-face-uri", XML_FONT_FACE_URI ),
TOKEN( "font-adornments", XML_FONT_ADORNMENTS ),
TOKEN( "inch", XML_INCH ),
TOKEN( "space-after", XML_SPACE_AFTER ),
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();
}
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,