summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2012-09-05 15:02:17 +0200
committerLuboš Luňák <l.lunak@suse.cz>2012-09-06 17:35:52 +0200
commit11f7d6aca36b25fb0b225cd0c641cd4f09338672 (patch)
tree1dbb17129d093920fd058ebd60ed53110db1fe9a /sw
parentcf6d2e2f8319fb4a2b15b9a805699312fe7305f9 (diff)
basic .docx write support for embedded fonts
Docx embedded fonts now should be usable for practical use, although there is still a number of small todos: - fonts are embedded when saving only if the document had embedded fonts when it was opened (this means the document needed to be saved in MSO first with the option enabled), there's no UI to enable it and it's a question if it makes sense on Linux - w:embedSystemFonts is similarly questionable, given that the spec is very vague on what system fonts are supposed to be - font subsetting is ignored, when reading a document, the font is simply used and it is hoped it will work (that should mean the document should not be modified, otherwise glyphs may be missing for the new text), write has no support for subsetting; also, since fonts are global for LO, opening several documents with the same but differently subset font probably will not work Change-Id: I470a9f2857738a10e82546223412bd9320841e65
Diffstat (limited to 'sw')
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx90
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx7
-rw-r--r--sw/source/filter/ww8/docxexport.cxx6
-rw-r--r--sw/source/filter/ww8/wrtw8sty.cxx3
-rw-r--r--sw/source/filter/ww8/wrtww8.hxx2
5 files changed, 104 insertions, 4 deletions
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 652a7cc6e3be..6590b8a26be6 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -118,9 +118,11 @@
#include <txtinet.hxx>
#include <numrule.hxx>
+#include <osl/file.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
+#include <vcl/fontmanager.hxx>
#include <tools/color.hxx>
@@ -130,6 +132,7 @@
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
#include <IMark.hxx>
#if OSL_DEBUG_LEVEL > 1
@@ -2809,6 +2812,90 @@ void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
FSEND );
}
+void DocxAttributeOutput::EmbedFont( const OUString& name )
+{
+ if( !m_rExport.pDoc->get( IDocumentSettingAccess::EMBED_FONTS ))
+ return; // no font embedding with this document
+ EmbedFontStyle( name, XML_embedRegular, "" );
+ EmbedFontStyle( name, XML_embedBold, "b" );
+ EmbedFontStyle( name, XML_embedItalic, "i" );
+ EmbedFontStyle( name, XML_embedBoldItalic, "bi" );
+}
+
+static inline char toHexChar( int value )
+{
+ return value >= 10 ? value + 'A' - 10 : value + '0';
+}
+
+void DocxAttributeOutput::EmbedFontStyle( const OUString& name, int tag, const char* style )
+{
+ OUString fontUrl = psp::PrintFontManager::get().fileUrlForTemporaryFont( name, style );
+ // If a temporary font file exists for this font, assume it was embedded
+ // and embed it again.
+ // TODO IDocumentSettingAccess::EMBED_SYSTEM_FONTS
+ osl::File file( fontUrl );
+ if( file.open( osl_File_OpenFlag_Write ) != osl::File::E_None )
+ return;
+ uno::Reference< com::sun::star::io::XOutputStream > xOutStream = m_rExport.GetFilter().openFragmentStream(
+ OUString( "word/fonts/font" ) + OUString::valueOf( m_nextFontId ) + ".ttf",
+ "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 )
+ {
+ 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 )
+ {
+ 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::valueOf( m_nextFontId ) + ".ttf" ), RTL_TEXTENCODING_UTF8 );
+ m_pSerializer->singleElementNS( XML_w, tag,
+ FSNS( XML_r, XML_id ), relId.getStr(),
+ FSNS( XML_w, XML_fontKey ), fontKeyStr,
+ FSEND );
+ ++m_nextFontId;
+}
+
void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
{
// nId is the same both for abstract numbering definition as well as the
@@ -4415,7 +4502,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
m_postponedGraphic( NULL ),
m_postponedMath( NULL ),
m_postitFieldsMaxId( 0 ),
- m_anchorId( 0 )
+ m_anchorId( 0 ),
+ m_nextFontId( 1 )
{
}
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 3a9c7cb6026a..8ab41d4692bd 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -240,6 +240,9 @@ public:
/// Font pitch.
void FontPitchType( FontPitch ePitch ) const;
+ /// Write out the font into the document, if it's an embedded font.
+ void EmbedFont( const OUString& name );
+
/// Definition of a numbering instance.
virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule );
@@ -314,6 +317,9 @@ private:
void FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph = false );
void WriteFFData( const FieldInfos& rInfos );
+
+ void EmbedFontStyle( const OUString& name, int tag, const char* style );
+
protected:
/// Output frames - the implementation.
@@ -605,6 +611,7 @@ private:
std::vector< const SwPostItField* > m_postitFields;
unsigned int m_postitFieldsMaxId;
int m_anchorId;
+ int m_nextFontId;
public:
DocxAttributeOutput( DocxExport &rExport, ::sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML );
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index b19b47b7aef3..59e9bd1f2f59 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -624,6 +624,7 @@ void DocxExport::WriteFonts()
pFS->startElementNS( XML_w, XML_fonts,
FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
FSEND );
// switch the serializer to redirect the output to word/styles.xml
@@ -675,7 +676,10 @@ void DocxExport::WriteSettings()
// Zoom
rtl::OString aZoom(rtl::OString::valueOf(sal_Int32(pViewShell->GetViewOptions()->GetZoom())));
pFS->singleElementNS(XML_w, XML_zoom, FSNS(XML_w, XML_percent), aZoom.getStr(), FSEND);
-
+ if( pDoc->get( IDocumentSettingAccess::EMBED_FONTS ))
+ pFS->singleElementNS( XML_w, XML_embedTrueTypeFonts, FSEND );
+ if( pDoc->get( IDocumentSettingAccess::EMBED_SYSTEM_FONTS ))
+ pFS->singleElementNS( XML_w, XML_embedSystemFonts, FSEND );
if( settings.defaultTabStop != 0 )
pFS->singleElementNS( XML_w, XML_defaultTabStop, FSNS( XML_w, XML_val ),
rtl::OString::valueOf( sal_Int32( settings.defaultTabStop )).getStr(), FSEND );
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
index 54cc347dd9da..00a0817a9c36 100644
--- a/sw/source/filter/ww8/wrtw8sty.cxx
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -714,7 +714,7 @@ bool wwFont::Write(SvStream *pTableStrm) const
return true;
}
-void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const
+void wwFont::WriteDocx( DocxAttributeOutput* rAttrOutput ) const
{
// no font embedding, panose id, subsetting, ... implemented
@@ -725,6 +725,7 @@ void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const
rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ), meChrSet );
rAttrOutput->FontFamilyType( meFamily );
rAttrOutput->FontPitchType( mePitch );
+ rAttrOutput->EmbedFont( msFamilyNm );
rAttrOutput->EndFont();
}
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 28cda40ba639..a601b38d6aeb 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -294,7 +294,7 @@ public:
wwFont( const String &rFamilyName, FontPitch ePitch, FontFamily eFamily,
rtl_TextEncoding eChrSet, bool bWrtWW8 );
bool Write( SvStream *pTableStram ) const;
- void WriteDocx( const DocxAttributeOutput* rAttrOutput ) const;
+ void WriteDocx( DocxAttributeOutput* rAttrOutput ) const;
void WriteRtf( const RtfAttributeOutput* rAttrOutput ) const;
rtl::OUString GetFamilyName() const { return rtl::OUString( msFamilyNm ); }
friend bool operator < (const wwFont &r1, const wwFont &r2);