Kaydet (Commit) 5ce50b8d authored tarafından Brennan Vincent's avatar Brennan Vincent Kaydeden (comit) Caolán McNamara

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/6144Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 4f1e4c05
......@@ -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().
......
......@@ -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,
......
......@@ -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,\
......
......@@ -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 )
......
......@@ -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)
......
......@@ -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 ),
......
......@@ -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();
}
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment