include/vcl/embeddedfontshelper.hxx | 5 - include/xmloff/xmltoken.hxx | 1 vcl/Library_vcl.mk | 1 vcl/source/gdi/embeddedfontshelper.cxx | 63 ++++++++++++++++++-- vcl/source/gdi/pdfwriter_impl.cxx | 6 + xmloff/source/core/xmltoken.cxx | 1 xmloff/source/style/XMLFontStylesContext.cxx | 67 +++++++++++++++++++++- xmloff/source/style/XMLFontStylesContext_impl.hxx | 33 ++++++++++ 8 files changed, 165 insertions(+), 12 deletions(-)
New commits: commit 5ce50b8d171c9d86d2175dd35b1e7ef23255e895 Author: Brennan Vincent <brenn...@email.arizona.edu> Date: Sat Oct 5 16:50:24 2013 -0700 Respect svg:font-face-format element. Call libeot to parse font if value "embedded-opentype" is found. Change-Id: I03a072fd4db47d151a3934e959ad17c1e24fcf09 Reviewed-on: https://gerrit.libreoffice.org/6144 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/include/vcl/embeddedfontshelper.hxx b/include/vcl/embeddedfontshelper.hxx index 2250aa3..b02431e 100644 --- a/include/vcl/embeddedfontshelper.hxx +++ b/include/vcl/embeddedfontshelper.hxx @@ -44,10 +44,11 @@ public: @param fontName name of the font (e.g. 'Times New Roman') @param extra additional text to use for name (e.g. to distinguish regular from bold, italic,...), "?" for unique @param key key to xor the data with, from the start until the key's length (not repeated) + @param eot whether the data is compressed in Embedded OpenType format */ static bool addEmbeddedFont( com::sun::star::uno::Reference< com::sun::star::io::XInputStream > stream, const OUString& fontName, const char* extra, - std::vector< unsigned char > key = std::vector< unsigned char >()); + std::vector< unsigned char > key = std::vector< unsigned char >(), bool eot = false); /** Returns an URL for a file where to store contents of a given temporary font. @@ -75,7 +76,7 @@ public: @param size size of the font data @param rights type of operation to be allowed for the font */ - static bool sufficientFontRights( const void* data, long size, FontRights rights ); + static bool sufficientTTFRights( const void* data, long size, FontRights rights ); /** Removes all temporary fonts in the path used by fileUrlForTemporaryFont(). diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index 33f2bee..bb585c6 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -2482,6 +2482,7 @@ namespace xmloff { namespace token { XML_FONT_FACE, XML_FONT_FACE_SRC, XML_FONT_FACE_URI, + XML_FONT_FACE_FORMAT, XML_FONT_ADORNMENTS, XML_INCH, XML_SPACE_AFTER, diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index fd24589..38cf55a 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -58,6 +58,7 @@ $(eval $(call gb_Library_use_custom_headers,vcl,\ $(eval $(call gb_Library_use_externals,vcl,\ jpeg \ nss3 \ + libeot \ )) $(eval $(call gb_Library_use_libraries,vcl,\ diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx index 3460f78..c3101df 100644 --- a/vcl/source/gdi/embeddedfontshelper.cxx +++ b/vcl/source/gdi/embeddedfontshelper.cxx @@ -18,16 +18,29 @@ #include <vcl/svapp.hxx> #include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> #include <fontsubset.hxx> #include <outdev.h> #include <outfont.hxx> #include <salgdi.hxx> +#include <config_eot.h> + +#if ENABLE_EOT +extern "C" +{ +namespace libeot +{ +#include <libeot.h> +} // namespace libeot +} // extern "C" +#endif + using namespace com::sun::star; using namespace vcl; static void clearDir( const OUString& path ) - { +{ osl::Directory dir( path ); if( dir.reset() == osl::Directory::E_None ) { @@ -53,7 +66,7 @@ void EmbeddedFontsHelper::clearTemporaryFontFiles() } bool EmbeddedFontsHelper::addEmbeddedFont( uno::Reference< io::XInputStream > stream, const OUString& fontName, - const char* extra, std::vector< unsigned char > key ) + const char* extra, std::vector< unsigned char > key, bool eot ) { OUString fileUrl = EmbeddedFontsHelper::fileUrlForTemporaryFont( fontName, extra ); osl::File file( fileUrl ); @@ -78,7 +91,8 @@ bool EmbeddedFontsHelper::addEmbeddedFont( uno::Reference< io::XInputStream > st pos < read && keyPos < key.size(); ++pos ) buffer[ pos ] ^= key[ keyPos++ ]; - if( read > 0 ) + // if eot, don't write the file out yet, since we need to unpack it first. + if( !eot && read > 0 ) { sal_uInt64 writtenTotal = 0; while( writtenTotal < read ) @@ -92,13 +106,50 @@ bool EmbeddedFontsHelper::addEmbeddedFont( uno::Reference< io::XInputStream > st if( read <= 0 ) break; } + bool sufficientFontRights; +#if ENABLE_EOT + if( eot ) + { + unsigned uncompressedFontSize = 0; + unsigned char *nakedPointerToUncompressedFont = NULL; + libeot::EOTMetadata eotMetadata; + libeot::EOTError uncompressError = + libeot::eot2ttf_buffer( (const unsigned char *)&fontData[0], fontData.size(), &eotMetadata, &nakedPointerToUncompressedFont, &uncompressedFontSize ): + boost::shared_ptr<unsigned char> uncompressedFont( nakedPointerToUncompressedFont, libeot::freeEOTBuffer ); + if( uncompressError != libeot::EOT_SUCCESS ) + { + SAL_WARN( "vcl.fonts", "Failed to uncompress font" ); + osl::File::remove( fileUrl ); + return false; + } + sal_uInt64 writtenTotal = 0; + while( writtenTotal < uncompressedFontSize ) + { + sal_uInt64 written; + if( file.write( uncompressedFont.get() + writtenTotal, uncompressedFontSize - writtenTotal, written ) != osl::File::E_None ) + { + SAL_WARN( "vcl.fonts", "Error writing temporary font file" ); + osl::File::remove( fileUrl ); + return false; + } + writtenTotal += written; + } + sufficientFontRights = libeot::canLegallyEdit( eotMetadata ); + libeot::EOTfreeMetadata( &eotMetadata ); + } +#endif + if( file.close() != osl::File::E_None ) { SAL_WARN( "vcl.fonts", "Writing temporary font file failed" ); osl::File::remove( fileUrl ); return false; } - if( !sufficientFontRights( &fontData.front(), fontData.size(), EditingAllowed )) + if( !eot ) + { + sufficientFontRights = sufficientTTFRights( &fontData.front(), fontData.size(), EditingAllowed ); + } + if( sufficientFontRights ) { // It would be actually better to open the document in read-only mode in this case, // warn the user about this, and provide a button to drop the font(s) in order @@ -139,7 +190,7 @@ void EmbeddedFontsHelper::activateFont( const OUString& fontName, const OUString // to have a different meaning (guessing from code, IsSubsettable() might // possibly mean it's ttf, while IsEmbeddable() might mean it's type1). // So just try to open the data as ttf and see. -bool EmbeddedFontsHelper::sufficientFontRights( const void* data, long size, FontRights rights ) +bool EmbeddedFontsHelper::sufficientTTFRights( const void* data, long size, FontRights rights ) { TrueTypeFont* font; if( OpenTTFontBuffer( data, size, 0 /*TODO*/, &font ) == SF_OK ) @@ -225,7 +276,7 @@ OUString EmbeddedFontsHelper::fontFileUrl( const OUString& familyName, FontFamil long size; if( const void* data = graphics->GetEmbedFontData( selected, unicodes, widths, info, &size )) { - if( sufficientFontRights( data, size, rights )) + if( sufficientTTFRights( data, size, rights )) { osl::File file( url ); if( file.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ) == osl::File::E_None ) diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index f6e823a..b6001cb 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -85,6 +85,12 @@ #include "cmst.h" #endif +#include <config_eot.h> + +#if ENABLE_EOT +#include "libeot.h" +#endif + using namespace vcl; #if (OSL_DEBUG_LEVEL < 3) diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index 4051104..dedb2b4 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -2486,6 +2486,7 @@ namespace xmloff { namespace token { TOKEN( "font-face", XML_FONT_FACE ), TOKEN( "font-face-src", XML_FONT_FACE_SRC ), TOKEN( "font-face-uri", XML_FONT_FACE_URI ), + TOKEN( "font-face-format", XML_FONT_FACE_FORMAT ), TOKEN( "font-adornments", XML_FONT_ADORNMENTS ), TOKEN( "inch", XML_INCH ), TOKEN( "space-after", XML_SPACE_AFTER ), diff --git a/xmloff/source/style/XMLFontStylesContext.cxx b/xmloff/source/style/XMLFontStylesContext.cxx index 33f998a..29f4808 100644 --- a/xmloff/source/style/XMLFontStylesContext.cxx +++ b/xmloff/source/style/XMLFontStylesContext.cxx @@ -190,6 +190,26 @@ OUString XMLFontStyleContextFontFace::familyName() const return ret; } +TYPEINIT1( XMLFontStyleContextFontFaceFormat, SvXMLStyleContext ); + +XMLFontStyleContextFontFaceFormat::XMLFontStyleContextFontFaceFormat( SvXMLImport& rImport, + sal_uInt16 nPrfx, const OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > &xAttrList, + XMLFontStyleContextFontFaceUri& _uri ) + : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList) + , uri(_uri) +{ +} + +void XMLFontStyleContextFontFaceFormat::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, + const OUString& rValue ) +{ + if( nPrefixKey == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_STRING )) + uri.SetFormat(rValue); + else + SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); +} TYPEINIT1( XMLFontStyleContextFontFaceSrc, SvXMLImportContext ); @@ -224,16 +244,57 @@ XMLFontStyleContextFontFaceUri::XMLFontStyleContextFontFaceUri( SvXMLImport& rIm { } +SvXMLImportContext * XMLFontStyleContextFontFaceUri::CreateChildContext( + sal_uInt16 nPrefix, + const 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_FORMAT )) + return new XMLFontStyleContextFontFaceFormat( GetImport(), nPrefix, rLocalName, xAttrList, *this ); + return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList ); +} + void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, const OUString& rValue ) { if( nPrefixKey == XML_NAMESPACE_XLINK && IsXMLToken( rLocalName, XML_HREF )) - handleEmbeddedFont( rValue ); + linkPath = rValue; else SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); } -void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url ) +void XMLFontStyleContextFontFaceUri::SetFormat( const OUString& rFormat ) +{ + format = rFormat; +} +void XMLFontStyleContextFontFaceUri::EndElement() +{ + if( linkPath.getLength() == 0 ) + { + SAL_WARN( "xmloff", "svg:font-face-uri tag with no link; ignoring." ); + return; + } + bool eot; + // Assume by default that the font is not compressed. + if( format.getLength() == 0 + || format.equalsAscii( OPENTYPE_FORMAT ) + || format.equalsAscii( TRUETYPE_FORMAT )) + { + eot = false; + } + else if( format.equalsAscii( EOT_FORMAT )) + { + eot = true; + } + else + { + SAL_WARN( "xmloff", "Unknown format of embedded font; assuming TTF." ); + eot = false; + } + handleEmbeddedFont( linkPath, eot ); +} + +void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url, bool eot ) { if( GetImport().embeddedFontAlreadyProcessed( url )) { @@ -252,7 +313,7 @@ void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url ) uno::Reference< io::XInputStream > inputStream; inputStream.set( storage->openStreamElement( url.copy( url.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ ), UNO_QUERY_THROW ); - if( EmbeddedFontsHelper::addEmbeddedFont( inputStream, fontName, "?" )) + if( EmbeddedFontsHelper::addEmbeddedFont( inputStream, fontName, "?", std::vector< unsigned char >(), eot )) GetImport().NotifyEmbeddedFontRead(); inputStream->closeInput(); } diff --git a/xmloff/source/style/XMLFontStylesContext_impl.hxx b/xmloff/source/style/XMLFontStylesContext_impl.hxx index 81e1b7a..6ad621f 100644 --- a/xmloff/source/style/XMLFontStylesContext_impl.hxx +++ b/xmloff/source/style/XMLFontStylesContext_impl.hxx @@ -88,8 +88,16 @@ public: /// Handles <style:font-face-uri> class XMLFontStyleContextFontFaceUri : public SvXMLStyleContext { + // the CSS2 standard ( http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#referencing ) + // defines these format strings. + const char* OPENTYPE_FORMAT = "opentype"; + const char* TRUETYPE_FORMAT = "truetype"; + const char* EOT_FORMAT = "embedded-opentype"; + const XMLFontStyleContextFontFace& font; - void handleEmbeddedFont( const OUString& url ); + OUString format; + OUString linkPath; + void handleEmbeddedFont( const OUString& url, bool eot ); public: TYPEINFO(); @@ -102,6 +110,29 @@ public: virtual void SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, const OUString& rValue ); + void SetFormat( const OUString& rFormat ); + void EndElement(); + SvXMLImportContext * CreateChildContext( + sal_uInt16 nPrefix, + const OUString& rLocalName, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList ); +}; + +/// Handles <svg:font-face-format> +class XMLFontStyleContextFontFaceFormat : public SvXMLStyleContext +{ + XMLFontStyleContextFontFaceUri& uri; +public: + TYPEINFO(); + + XMLFontStyleContextFontFaceFormat( SvXMLImport& rImport, sal_uInt16 nPrfx, + const OUString& rLName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList > & xAttrList, + XMLFontStyleContextFontFaceUri& uri ); + + void SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, + const OUString& rValue ); }; #endif
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits