[Libreoffice-commits] core.git: include/vcl include/xmloff vcl/Library_vcl.mk vcl/source xmloff/source

Brennan Vincent brennanv at email.arizona.edu
Wed Nov 13 06:38:16 PST 2013


 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 <brennanv at 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 <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at 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


More information about the Libreoffice-commits mailing list