sw/source/filter/ww8/docxattributeoutput.cxx | 109 ++++++++++++++------------- sw/source/filter/ww8/docxattributeoutput.hxx | 6 + vcl/inc/sft.hxx | 2 vcl/inc/vcl/embeddedfontshelper.hxx | 4 vcl/source/fontsubset/sft.cxx | 2 vcl/source/gdi/embeddedfontshelper.cxx | 82 ++++++++++++++------ xmloff/inc/xmloff/XMLFontAutoStylePool.hxx | 2 xmloff/inc/xmloff/xmlimp.hxx | 7 + xmloff/source/core/xmlimp.cxx | 8 + xmloff/source/style/XMLFontAutoStylePool.cxx | 12 +- xmloff/source/style/XMLFontStylesContext.cxx | 21 +---- 11 files changed, 153 insertions(+), 102 deletions(-)
New commits: commit 3fbc15ce456d0112700e1832e860e06f01eb5c03 Author: LuboÅ¡ LuÅák <l.lu...@suse.cz> Date: Tue Mar 5 19:35:42 2013 +0100 remove the need to explicitly specify font style for font embedding The information can be read from the font data itself now, so this is a bit pointless. It wasn't entirely reliable anyway, as it is also necessary to ensure two font different font files don't overwrite each other. Change-Id: Ie17ab8118e1c08228beb7c749c5c8d6cf3426362 diff --git a/vcl/inc/vcl/embeddedfontshelper.hxx b/vcl/inc/vcl/embeddedfontshelper.hxx index 96e8226..ac47786 100644 --- a/vcl/inc/vcl/embeddedfontshelper.hxx +++ b/vcl/inc/vcl/embeddedfontshelper.hxx @@ -33,9 +33,9 @@ public: Use activateTemporaryFont() to actually enable usage of the font. @param fontName name of the font (e.g. 'Times New Roman') - @param fontStyle font style, "" for regular, "bi" for bold italic, etc. + @param extra additional text to use for name (e.g. to distinguish regular from bold, italic,...), "?" for unique */ - static OUString fileUrlForTemporaryFont( const OUString& fontName, const char* fontStyle ); + static OUString fileUrlForTemporaryFont( const OUString& fontName, const char* extra ); /** Adds the given font to the list of known fonts. The font is used only until application diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx index ac18655..e53ed18 100644 --- a/vcl/source/gdi/embeddedfontshelper.cxx +++ b/vcl/source/gdi/embeddedfontshelper.cxx @@ -49,14 +49,18 @@ void EmbeddedFontsHelper::clearTemporaryFontFiles() clearDir( path + "fromsystem/" ); } -OUString EmbeddedFontsHelper::fileUrlForTemporaryFont( const OUString& fontName, const char* fontStyle ) +OUString EmbeddedFontsHelper::fileUrlForTemporaryFont( const OUString& fontName, const char* extra ) { OUString path = "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}"; rtl::Bootstrap::expandMacros( path ); path += "/user/temp/embeddedfonts/fromdocs/"; osl::Directory::createPath( path ); OUString filename = fontName; - filename += OStringToOUString( fontStyle, RTL_TEXTENCODING_ASCII_US ); + static int uniqueCounter = 0; + if( strcmp( extra, "?" ) == 0 ) + filename += OUString::number( uniqueCounter++ ); + else + filename += OStringToOUString( extra, RTL_TEXTENCODING_ASCII_US ); filename += ".ttf"; // TODO is it always ttf? return path + filename; } diff --git a/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx b/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx index 1b16725..ad6a46d 100644 --- a/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx +++ b/xmloff/inc/xmloff/XMLFontAutoStylePool.hxx @@ -39,7 +39,7 @@ class XMLOFF_DLLPUBLIC XMLFontAutoStylePool : public UniRefBase XMLFontAutoStylePoolNames_Impl m_aNames; bool tryToEmbedFonts; - OUString embedFontFile( const OUString& fontUrl, const char* style ); + OUString embedFontFile( const OUString& fontUrl ); protected: diff --git a/xmloff/inc/xmloff/xmlimp.hxx b/xmloff/inc/xmloff/xmlimp.hxx index 24f1f97..750f567 100644 --- a/xmloff/inc/xmloff/xmlimp.hxx +++ b/xmloff/inc/xmloff/xmlimp.hxx @@ -138,6 +138,7 @@ class XMLOFF_DLLPUBLIC SvXMLImport : public ::cppu::WeakImplHelper6< sal_uInt16 mnImportFlags; sal_uInt16 mnErrorFlags; + std::set< OUString > embeddedFontUrlsKnown; protected: @@ -449,6 +450,12 @@ public: */ bool isGraphicLoadOnDemandSupported() const; + /** + Returns true if the embedded font document URL has already been processed. + Otherwise returns false and consequent calls with the same URL will return true. + */ + bool embeddedFontAlreadyProcessed( const OUString& url ); + virtual void NotifyEmbeddedFontRead() {}; }; diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 9962db5..2edbac4 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -1902,4 +1902,12 @@ SvXMLImport::AddRDFa(uno::Reference<rdf::XMetadatable> i_xObject, i_rAbout, i_rProperty, i_rContent, i_rDatatype); } +bool SvXMLImport::embeddedFontAlreadyProcessed( const OUString& url ) +{ + if( embeddedFontUrlsKnown.count( url ) != 0 ) + return true; + embeddedFontUrlsKnown.insert( url ); + return false; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/style/XMLFontAutoStylePool.cxx b/xmloff/source/style/XMLFontAutoStylePool.cxx index e8c33aa..561814d 100644 --- a/xmloff/source/style/XMLFontAutoStylePool.cxx +++ b/xmloff/source/style/XMLFontAutoStylePool.cxx @@ -275,13 +275,11 @@ void XMLFontAutoStylePool::exportXML() if( tryToEmbedFonts ) { std::vector< OUString > fileUrls; - static const char* const styles[] = { "", "b", "i", "bi" }; static const FontWeight weight[] = { WEIGHT_NORMAL, WEIGHT_BOLD, WEIGHT_NORMAL, WEIGHT_BOLD }; static const FontItalic italic[] = { ITALIC_NONE, ITALIC_NONE, ITALIC_NORMAL, ITALIC_NORMAL }; - assert( SAL_N_ELEMENTS( styles ) == SAL_N_ELEMENTS( italic )); - assert( SAL_N_ELEMENTS( styles ) == SAL_N_ELEMENTS( weight )); + assert( SAL_N_ELEMENTS( weight ) == SAL_N_ELEMENTS( italic )); for( unsigned int j = 0; - j < SAL_N_ELEMENTS( styles ); + j < SAL_N_ELEMENTS( weight ); ++j ) { OUString fileUrl = EmbeddedFontsHelper::fontFileUrl( pEntry->GetFamilyName(), pEntry->GetFamily(), @@ -290,7 +288,7 @@ void XMLFontAutoStylePool::exportXML() continue; if( !fontFilesMap.count( fileUrl )) { - OUString docUrl = embedFontFile( fileUrl, styles[ j ] ); + OUString docUrl = embedFontFile( fileUrl ); if( !docUrl.isEmpty()) fontFilesMap[ fileUrl ] = docUrl; else @@ -319,7 +317,7 @@ void XMLFontAutoStylePool::exportXML() } } -OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl, const char* style ) +OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl ) { try { @@ -333,7 +331,7 @@ OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl, const cha OUString name; do { - name = "font" + OUString::number( ++index ) + OUString::createFromAscii( style ) + ".ttf"; + name = "font" + OUString::number( ++index ) + ".ttf"; } while( storage->hasByName( name ) ); uno::Reference< io::XOutputStream > outputStream; outputStream.set( storage->openStreamElement( name, ::embed::ElementModes::WRITE ), UNO_QUERY_THROW ); diff --git a/xmloff/source/style/XMLFontStylesContext.cxx b/xmloff/source/style/XMLFontStylesContext.cxx index f269284..21b9cdb 100644 --- a/xmloff/source/style/XMLFontStylesContext.cxx +++ b/xmloff/source/style/XMLFontStylesContext.cxx @@ -238,18 +238,12 @@ void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey, const void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url ) { + if( GetImport().embeddedFontAlreadyProcessed( url )) + { + GetImport().NotifyEmbeddedFontRead(); + return; + } 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 EmbeddedFontsHelper 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 )) { @@ -258,15 +252,12 @@ void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url ) 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 = EmbeddedFontsHelper::fileUrlForTemporaryFont( fontName, style ); + OUString fileUrl = EmbeddedFontsHelper::fileUrlForTemporaryFont( fontName, "?" ); 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: - GetImport().NotifyEmbeddedFontRead(); - return; // Assume it's already been added correctly. default: SAL_WARN( "xmloff", "Cannot open file for temporary font" ); return; commit 595f954424a5b99f0a9d396b77d2d5b89b5ae664 Author: LuboÅ¡ LuÅák <l.lu...@suse.cz> Date: Tue Mar 5 18:37:14 2013 +0100 check whether font files allow being embedded in documents Change-Id: I95842a35a7c795cb0a3c1957f4062a373a9c4797 diff --git a/vcl/inc/sft.hxx b/vcl/inc/sft.hxx index f7cf58c..3cef61b 100644 --- a/vcl/inc/sft.hxx +++ b/vcl/inc/sft.hxx @@ -280,7 +280,7 @@ namespace vcl * @return value of SFErrCodes enum * @ingroup sft */ - int VCL_DLLPUBLIC OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf); /*FOLD01*/ + int VCL_DLLPUBLIC OpenTTFontBuffer(const void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf); /*FOLD01*/ #if !defined(WIN32) /** * TrueTypeFont constructor. diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx index e110c12..558c648 100644 --- a/vcl/source/fontsubset/sft.cxx +++ b/vcl/source/fontsubset/sft.cxx @@ -1566,7 +1566,7 @@ cleanup: } #endif -int OpenTTFontBuffer(void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) +int OpenTTFontBuffer(const void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, TrueTypeFont** ttf) { allocTrueTypeFont( ttf ); if( *ttf == NULL ) diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx index dfde14a..ac18655 100644 --- a/vcl/source/gdi/embeddedfontshelper.cxx +++ b/vcl/source/gdi/embeddedfontshelper.cxx @@ -11,6 +11,7 @@ #include <osl/file.hxx> #include <rtl/bootstrap.hxx> +#include <sft.hxx> #include <vcl/outdev.hxx> #include <vcl/svapp.hxx> @@ -20,6 +21,8 @@ #include <outfont.hxx> #include <salgdi.hxx> +using namespace vcl; + static void clearDir( const OUString& path ) { osl::Directory dir( path ); @@ -65,6 +68,30 @@ void EmbeddedFontsHelper::activateFont( const OUString& fontName, const OUString pDevice->ImplUpdateAllFontData( true ); } +// Check if it's (legally) allowed to embed the font file into a document +// (ttf has a flag allowing this). PhysicalFontFace::IsEmbeddable() appears +// 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. +static bool isEmbeddingAllowed( const void* data, long size ) +{ + TrueTypeFont* font; + if( OpenTTFontBuffer( data, size, 0 /*TODO*/, &font ) == SF_OK ) + { + TTGlobalFontInfo info; + GetTTGlobalFontInfo( font, &info ); + CloseTTFont( font ); + // http://www.microsoft.com/typography/tt/ttf_spec/ttch02.doc + // font embedding is allowed if either + // no restriction at all (bit 1 clear) + // editting allowed (bit 1 set, bit 3 set) + // (preview&print is considered insufficent, as it would force the document to be read-only) + int copyright = info.typeFlags & TYPEFLAG_COPYRIGHT_MASK; + return ( copyright & 0x02 ) == 0 || ( copyright & 0x08 ); + } + return true; // no known restriction +} + OUString EmbeddedFontsHelper::fontFileUrl( const OUString& familyName, FontFamily family, FontItalic italic, FontWeight weight, FontPitch pitch, rtl_TextEncoding ) { @@ -128,33 +155,36 @@ OUString EmbeddedFontsHelper::fontFileUrl( const OUString& familyName, FontFamil long size; if( const void* data = graphics->GetEmbedFontData( selected, unicodes, widths, info, &size )) { - osl::File file( url ); - if( file.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ) == osl::File::E_None ) + if( isEmbeddingAllowed( data, size )) { - sal_uInt64 written = 0; - sal_uInt64 totalSize = size; - bool error = false; - while( written < totalSize && !error) + osl::File file( url ); + if( file.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ) == osl::File::E_None ) { - sal_uInt64 nowWritten; - switch( file.write( static_cast< const char* >( data ) + written, size - written, nowWritten )) + sal_uInt64 written = 0; + sal_uInt64 totalSize = size; + bool error = false; + while( written < totalSize && !error) { - case osl::File::E_None: - written += nowWritten; - break; - case osl::File::E_AGAIN: - case osl::File::E_INTR: - break; - default: - error = true; - break; + sal_uInt64 nowWritten; + switch( file.write( static_cast< const char* >( data ) + written, size - written, nowWritten )) + { + case osl::File::E_None: + written += nowWritten; + break; + case osl::File::E_AGAIN: + case osl::File::E_INTR: + break; + default: + error = true; + break; + } } + file.close(); + if( error ) + osl::File::remove( url ); + else + ok = true; } - file.close(); - if( error ) - osl::File::remove( url ); - else - ok = true; } graphics->FreeEmbedFontData( data, size ); } commit 25a5ee2aebebe9e175ad3b1c770bba9826fe4d48 Author: LuboÅ¡ LuÅák <l.lu...@suse.cz> Date: Tue Mar 5 17:04:31 2013 +0100 do not embed the same font file twice into one .docx Change-Id: I6d38e83a7fa609d53f2f687ccfe289440d23e960 diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index b40b70d..e5366ee 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3077,67 +3077,74 @@ void DocxAttributeOutput::EmbedFontStyle( const OUString& name, int tag, FontFam if( fontUrl.isEmpty()) return; // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS - osl::File file( fontUrl ); - if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None ) - return; - uno::Reference< com::sun::star::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream( - OUString( "word/fonts/font" ) + OUString::number(m_nextFontId) + ".odttf", - "application/vnd.openxmlformats-officedocument.obfuscatedFont" ); - // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway, - // so just alter the first and last part of the key. - char fontKeyStr[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}"; - sal_uInt8 fontKey[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E, - 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 }; - fontKey[ 0 ] = fontKey[ 15 ] = m_nextFontId % 256; - fontKeyStr[ 1 ] = fontKeyStr[ 35 ] = toHexChar(( m_nextFontId % 256 ) / 16 ); - fontKeyStr[ 2 ] = fontKeyStr[ 36 ] = toHexChar(( m_nextFontId % 256 ) % 16 ); - char buffer[ 4096 ]; - sal_uInt64 readSize; - file.read( buffer, 32, readSize ); - if( readSize < 32 ) - { - SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" ); - xOutStream->closeOutput(); - return; - } - for( int i = 0; - i < 16; - ++i ) + if( !fontFilesMap.count( fontUrl )) { - buffer[ i ] ^= fontKey[ i ]; - buffer[ i + 16 ] ^= fontKey[ i ]; - } - xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), 32 )); - for(;;) - { - sal_Bool eof; - if( file.isEndOfFile( &eof ) != osl::File::E_None ) + osl::File file( fontUrl ); + if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None ) + return; + uno::Reference< com::sun::star::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream( + OUString( "word/fonts/font" ) + OUString::number(m_nextFontId) + ".odttf", + "application/vnd.openxmlformats-officedocument.obfuscatedFont" ); + // Not much point in trying hard with the obfuscation key, whoever reads the spec can read the font anyway, + // so just alter the first and last part of the key. + char fontKeyStr[] = "{00014A78-CABC-4EF0-12AC-5CD89AEFDE00}"; + sal_uInt8 fontKey[ 16 ] = { 0, 0xDE, 0xEF, 0x9A, 0xD8, 0x5C, 0xAC, 0x12, 0xF0, 0x4E, + 0xBC, 0xCA, 0x78, 0x4A, 0x01, 0 }; + fontKey[ 0 ] = fontKey[ 15 ] = m_nextFontId % 256; + fontKeyStr[ 1 ] = fontKeyStr[ 35 ] = toHexChar(( m_nextFontId % 256 ) / 16 ); + fontKeyStr[ 2 ] = fontKeyStr[ 36 ] = toHexChar(( m_nextFontId % 256 ) % 16 ); + char buffer[ 4096 ]; + sal_uInt64 readSize; + file.read( buffer, 32, readSize ); + if( readSize < 32 ) { - SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl ); + SAL_WARN( "sw.ww8", "Font file size too small (" << fontUrl << ")" ); xOutStream->closeOutput(); return; } - if( eof ) - break; - if( file.read( buffer, 4096, readSize ) != osl::File::E_None ) + for( int i = 0; + i < 16; + ++i ) { - SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl ); - xOutStream->closeOutput(); - return; + buffer[ i ] ^= fontKey[ i ]; + buffer[ i + 16 ] ^= fontKey[ i ]; } - if( readSize == 0 ) - break; - xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize )); + xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), 32 )); + for(;;) + { + sal_Bool eof; + if( file.isEndOfFile( &eof ) != osl::File::E_None ) + { + SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl ); + xOutStream->closeOutput(); + return; + } + if( eof ) + break; + if( file.read( buffer, 4096, readSize ) != osl::File::E_None ) + { + SAL_WARN( "sw.ww8", "Error reading font file " << fontUrl ); + xOutStream->closeOutput(); + return; + } + if( readSize == 0 ) + break; + xOutStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize )); + } + xOutStream->closeOutput(); + OString relId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", + OUString( "fonts/font" ) + OUString::number( m_nextFontId ) + ".odttf" ), RTL_TEXTENCODING_UTF8 ); + EmbeddedFontRef ref; + ref.relId = relId; + ref.fontKey = fontKeyStr; + fontFilesMap[ fontUrl ] = ref; + ++m_nextFontId; } - xOutStream->closeOutput(); - OString relId = OUStringToOString( GetExport().GetFilter().addRelation( m_pSerializer->getOutputStream(), - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font", - OUString( "fonts/font" ) + OUString::number(m_nextFontId) + ".odttf" ), RTL_TEXTENCODING_UTF8 ); m_pSerializer->singleElementNS( XML_w, tag, - FSNS( XML_r, XML_id ), relId.getStr(), - FSNS( XML_w, XML_fontKey ), fontKeyStr, + FSNS( XML_r, XML_id ), fontFilesMap[ fontUrl ].relId, + FSNS( XML_w, XML_fontKey ), fontFilesMap[ fontUrl ].fontKey, FSEND ); - ++m_nextFontId; } void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule ) diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 37a6d4e..eb12e56 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -630,6 +630,12 @@ private: unsigned int m_postitFieldsMaxId; int m_anchorId; int m_nextFontId; + struct EmbeddedFontRef + { + OString relId; + OString fontKey; + }; + std::map< OUString, EmbeddedFontRef > fontFilesMap; // font file url to data // Remember first cell (used for for default borders/margins) of each table std::vector<ww8::WW8TableNodeInfoInner::Pointer_t> tableFirstCells;
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits