summaryrefslogtreecommitdiff
path: root/oox/source/export/drawingml.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/export/drawingml.cxx')
-rw-r--r--oox/source/export/drawingml.cxx1567
1 files changed, 1567 insertions, 0 deletions
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
new file mode 100644
index 000000000000..48f4eb453ee0
--- /dev/null
+++ b/oox/source/export/drawingml.cxx
@@ -0,0 +1,1567 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/core/xmlfilterbase.hxx"
+#include "oox/export/drawingml.hxx"
+#include "oox/export/utils.hxx"
+#include <oox/token/tokens.hxx>
+
+#include <cstdio>
+#include <com/sun/star/awt/CharSet.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/style/LineSpacing.hpp>
+#include <com/sun/star/style/LineSpacingMode.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <tools/stream.hxx>
+#include <tools/string.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <unotools/fontcvt.hxx>
+#include <unotools/fontdefs.hxx>
+#include <vcl/graph.hxx>
+#include <svtools/grfmgr.hxx>
+#include <rtl/strbuf.hxx>
+#include <sfx2/app.hxx>
+#include <svl/languageoptions.hxx>
+#include <filter/msfilter/escherex.hxx>
+#include <editeng/svxenum.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using ::com::sun::star::beans::PropertyState;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XPropertyState;
+using ::com::sun::star::container::XEnumeration;
+using ::com::sun::star::container::XEnumerationAccess;
+using ::com::sun::star::container::XIndexAccess;
+using ::com::sun::star::io::XOutputStream;
+using ::com::sun::star::style::LineSpacing;
+using ::com::sun::star::text::XText;
+using ::com::sun::star::text::XTextContent;
+using ::com::sun::star::text::XTextField;
+using ::com::sun::star::text::XTextRange;
+using ::rtl::OString;
+using ::rtl::OStringBuffer;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::sax_fastparser::FSHelperPtr;
+
+DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet));
+
+namespace oox {
+namespace drawingml {
+
+#define GETA(propName) \
+ GetProperty( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ) )
+
+#define GETAD(propName) \
+ ( GetPropertyAndState( rXPropSet, rXPropState, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
+
+#define GET(variable, propName) \
+ if ( GETA(propName) ) \
+ mAny >>= variable;
+DBG(
+void lcl_dump_pset(Reference< XPropertySet > rXPropSet)
+{
+ Reference< XPropertySetInfo > info = rXPropSet->getPropertySetInfo ();
+ Sequence< beans::Property > props = info->getProperties ();
+
+ for (int i=0; i < props.getLength (); i++) {
+ OString name = OUStringToOString( props [i].Name, RTL_TEXTENCODING_UTF8);
+ fprintf (stderr,"%30s = ", name.getStr() );
+
+ try {
+ Any value = rXPropSet->getPropertyValue( props [i].Name );
+
+ OUString strValue;
+ sal_Int32 intValue;
+ bool boolValue;
+ LineSpacing spacing;
+
+ if( value >>= strValue )
+ fprintf (stderr,"\"%s\"\n", USS( strValue ) );
+ else if( value >>= intValue )
+ fprintf (stderr,"%" SAL_PRIdINT32 " (hex: %" SAL_PRIxUINT32 ")\n", intValue, intValue);
+ else if( value >>= boolValue )
+ fprintf (stderr,"%d (bool)\n", boolValue);
+ else if( value >>= spacing ) {
+ fprintf (stderr, "mode: %d value: %d\n", spacing.Mode, spacing.Height);
+ }
+ else
+ fprintf (stderr,"??? <unhandled type>\n");
+ } catch(const Exception &) {
+ fprintf (stderr,"unable to get '%s' value\n", USS(props [i].Name));
+ }
+ }
+}
+);
+
+// not thread safe
+int DrawingML::mnImageCounter = 1;
+
+void DrawingML::ResetCounters()
+{
+ mnImageCounter = 1;
+}
+
+bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, String aName )
+{
+ bool bRetValue = false;
+
+ try {
+ mAny = rXPropSet->getPropertyValue( aName );
+ if ( mAny.hasValue() )
+ bRetValue = true;
+ } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", ST(aName)); */ }
+
+ return bRetValue;
+}
+
+bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, String aName, PropertyState& eState )
+{
+ bool bRetValue = false;
+
+ try {
+ mAny = rXPropSet->getPropertyValue( aName );
+ if ( mAny.hasValue() ) {
+ bRetValue = true;
+ eState = rXPropState->getPropertyState( aName );
+ }
+ } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", ST(aName)); */ }
+
+ return bRetValue;
+}
+
+void DrawingML::WriteColor( sal_uInt32 nColor )
+{
+ OString sColor = OString::valueOf( ( sal_Int64 ) nColor, 16 );
+ if( sColor.getLength() < 6 ) {
+ OStringBuffer sBuf( "0" );
+ int remains = 5 - sColor.getLength();
+
+ while( remains > 0 ) {
+ sBuf.append( "0" );
+ remains--;
+ }
+
+ sBuf.append( sColor );
+
+ sColor = sBuf.getStr();
+ }
+ mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
+}
+
+void DrawingML::WriteSolidFill( sal_uInt32 nColor )
+{
+ mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
+ WriteColor( nColor );
+ mpFS->endElementNS( XML_a, XML_solidFill );
+}
+
+void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
+{
+ if ( GetProperty( rXPropSet, S( "FillColor" ) ) )
+ WriteSolidFill( *((sal_uInt32*) mAny.getValue()) & 0xffffff );
+}
+
+void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
+{
+ mpFS->startElementNS( XML_a, XML_gs,
+ XML_pos, I32S( nStop * 1000 ),
+ FSEND );
+ WriteColor( nColor );
+ mpFS->endElementNS( XML_a, XML_gs );
+}
+
+sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
+{
+ return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
+ | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
+ | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
+}
+
+void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
+{
+ awt::Gradient aGradient;
+ if( GETA( FillGradient ) ) {
+ aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
+
+ mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
+
+ switch( aGradient.Style ) {
+ default:
+ case GradientStyle_LINEAR:
+ mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
+ WriteGradientStop( 0, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
+ WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
+ mpFS->endElementNS( XML_a, XML_gsLst );
+ mpFS->singleElementNS( XML_a, XML_lin,
+ XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
+ FSEND );
+ break;
+
+ case GradientStyle_AXIAL:
+ mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
+ WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
+ WriteGradientStop( 50, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
+ WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
+ mpFS->endElementNS( XML_a, XML_gsLst );
+ mpFS->singleElementNS( XML_a, XML_lin,
+ XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
+ FSEND );
+ break;
+
+ /* I don't see how to apply transformation to gradients, so
+ * elliptical will end as radial and square as
+ * rectangular. also position offsets are not applied */
+ case GradientStyle_RADIAL:
+ case GradientStyle_ELLIPTICAL:
+ case GradientStyle_RECT:
+ case GradientStyle_SQUARE:
+ mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
+ WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
+ WriteGradientStop( 100, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
+ mpFS->endElementNS( XML_a, XML_gsLst );
+ mpFS->singleElementNS( XML_a, XML_path,
+ XML_path, ( aGradient.Style == awt::GradientStyle_RADIAL || aGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
+ FSEND );
+ break;
+ }
+
+ mpFS->endElementNS( XML_a, XML_gradFill );
+ }
+
+}
+
+void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, sal_Bool bLineStart )
+{
+ ESCHER_LineEnd eLineEnd;
+ sal_Int32 nArrowLength;
+ sal_Int32 nArrowWidth;
+
+ if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
+ const char* len;
+ const char* type;
+ const char* width;
+
+ switch( nArrowLength ) {
+ case ESCHER_LineShortArrow:
+ len = "sm";
+ break;
+ default:
+ case ESCHER_LineMediumLenArrow:
+ len = "med";
+ break;
+ case ESCHER_LineLongArrow:
+ len = "lg";
+ break;
+ }
+
+ switch( eLineEnd ) {
+ default:
+ case ESCHER_LineNoEnd:
+ type = "none";
+ break;
+ case ESCHER_LineArrowEnd:
+ type = "triangle";
+ break;
+ case ESCHER_LineArrowStealthEnd:
+ type = "stealth";
+ break;
+ case ESCHER_LineArrowDiamondEnd:
+ type = "diamond";
+ break;
+ case ESCHER_LineArrowOvalEnd:
+ type = "oval";
+ break;
+ case ESCHER_LineArrowOpenEnd:
+ type = "arrow";
+ break;
+ }
+
+ switch( nArrowWidth ) {
+ case ESCHER_LineNarrowArrow:
+ width = "sm";
+ break;
+ default:
+ case ESCHER_LineMediumWidthArrow:
+ width = "med";
+ break;
+ case ESCHER_LineWideArrow:
+ width = "lg";
+ break;
+ }
+
+ mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
+ XML_len, len,
+ XML_type, type,
+ XML_w, width,
+ FSEND );
+ }
+}
+
+void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
+{
+ drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
+
+ GET( aLineStyle, LineStyle );
+
+ if( aLineStyle == drawing::LineStyle_NONE )
+ return;
+
+ sal_uInt32 nLineWidth = 0;
+ sal_uInt32 nColor = 0;
+ sal_Bool bColorSet = sal_False;
+ const char* cap = NULL;
+ drawing::LineDash aLineDash;
+ sal_Bool bDashSet = sal_False;
+
+ GET( nLineWidth, LineWidth );
+
+ switch( aLineStyle ) {
+ case drawing::LineStyle_DASH:
+ if( GETA( LineDash ) ) {
+ aLineDash = *(drawing::LineDash*) mAny.getValue();
+ bDashSet = sal_True;
+ if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
+ cap = "rnd";
+
+ DBG(printf("dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
+ int( aLineDash.Dots ), int( aLineDash.Dashes ), int( aLineDash.DotLen ), int( aLineDash.DashLen ), int( aLineDash.Distance )));
+ }
+ /* fallthru intended */
+ case drawing::LineStyle_SOLID:
+ default:
+ if ( GETA( LineColor ) ) {
+ nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
+ bColorSet = sal_True;
+ }
+ break;
+ }
+
+ mpFS->startElementNS( XML_a, XML_ln,
+ XML_cap, cap,
+ XML_w, nLineWidth > 1 ? I64S( MM100toEMU( nLineWidth ) ) : NULL,
+ FSEND );
+ if( bColorSet )
+ WriteSolidFill( nColor );
+
+ if( bDashSet ) {
+ mpFS->startElementNS( XML_a, XML_custDash, FSEND );
+ int i;
+ for( i = 0; i < aLineDash.Dots; i ++ )
+ mpFS->singleElementNS( XML_a, XML_ds,
+ XML_d, aLineDash.DotLen ? I64S( aLineDash.DotLen*1000 ) : "100000",
+ XML_sp, I64S( aLineDash.Distance*1000 ),
+ FSEND );
+ for( i = 0; i < aLineDash.Dashes; i ++ )
+ mpFS->singleElementNS( XML_a, XML_ds,
+ XML_d, aLineDash.DashLen ? I64S( aLineDash.DashLen*1000 ) : "100000",
+ XML_sp, I64S( aLineDash.Distance*1000 ),
+ FSEND );
+ mpFS->endElementNS( XML_a, XML_custDash );
+ }
+
+ if( nLineWidth > 1 && GETA( LineJoint ) ) {
+ LineJoint eLineJoint;
+
+ mAny >>= eLineJoint;
+ switch( eLineJoint ) {
+ case LineJoint_NONE:
+ case LineJoint_MIDDLE:
+ case LineJoint_BEVEL:
+ mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
+ break;
+ default:
+ case LineJoint_MITER:
+ mpFS->singleElementNS( XML_a, XML_miter, FSEND );
+ break;
+ case LineJoint_ROUND:
+ mpFS->singleElementNS( XML_a, XML_round, FSEND );
+ break;
+ }
+ }
+
+ WriteLineArrow( rXPropSet, sal_True );
+ WriteLineArrow( rXPropSet, sal_False );
+
+ mpFS->endElementNS( XML_a, XML_ln );
+}
+
+OUString DrawingML::WriteImage( const OUString& rURL )
+{
+ ByteString aURLBS( UniString( rURL ), RTL_TEXTENCODING_UTF8 );
+
+ const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
+ int index = aURLBS.Search( aURLBegin );
+
+ if ( index != STRING_NOTFOUND ) {
+ DBG(printf ("begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + sizeof( aURLBegin ) - 1 ));
+ aURLBS.Erase( 0, sizeof( aURLBegin ) - 1 );
+ Graphic aGraphic = GraphicObject( aURLBS ).GetTransformedGraphic ();
+
+ return WriteImage( aGraphic );
+ } else {
+ // add link to relations
+ }
+
+ return OUString();
+}
+
+OUString DrawingML::WriteImage( const Graphic& rGraphic )
+{
+ GfxLink aLink = rGraphic.GetLink ();
+ OUString sMediaType;
+ const char* sExtension = NULL;
+ OUString sRelId;
+
+ SvMemoryStream aStream;
+ const void* aData = aLink.GetData();
+ sal_Size nDataSize = aLink.GetDataSize();
+
+ switch ( aLink.GetType() ) {
+ case GFX_LINK_TYPE_NATIVE_GIF:
+ sMediaType = US( "image/gif" );
+ sExtension = ".gif";
+ break;
+ case GFX_LINK_TYPE_NATIVE_JPG:
+ sMediaType = US( "image/jpeg" );
+ sExtension = ".jpeg";
+ break;
+ case GFX_LINK_TYPE_NATIVE_PNG:
+ sMediaType = US( "image/png" );
+ sExtension = ".png";
+ break;
+ case GFX_LINK_TYPE_NATIVE_TIF:
+ sMediaType = US( "image/tiff" );
+ sExtension = ".tiff";
+ break;
+ case GFX_LINK_TYPE_NATIVE_WMF:
+ sMediaType = US( "image/x-wmf" );
+ sExtension = ".wmf";
+ break;
+ case GFX_LINK_TYPE_NATIVE_MET:
+ sMediaType = US( "image/x-met" );
+ sExtension = ".met";
+ break;
+ case GFX_LINK_TYPE_NATIVE_PCT:
+ sMediaType = US( "image/x-pict" );
+ sExtension = ".pct";
+ break;
+ default: {
+ GraphicType aType = rGraphic.GetType();
+ if ( aType == GRAPHIC_BITMAP ) {
+ GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
+ sMediaType = US( "image/png" );
+ sExtension = ".png";
+ } else if ( aType == GRAPHIC_GDIMETAFILE ) {
+ GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
+ sMediaType = US( "image/x-emf" );
+ sExtension = ".emf";
+ } else {
+ OSL_TRACE( "unhandled graphic type" );
+ break;
+ }
+
+ aData = aStream.GetData();
+ nDataSize = aStream.GetEndOfData();
+ break;
+ }
+ }
+
+ const char *pComponent = NULL;
+ switch ( meDocumentType )
+ {
+ case DOCUMENT_DOCX: pComponent = "word"; break;
+ case DOCUMENT_PPTX: pComponent = "ppt"; break;
+ case DOCUMENT_XLSX: pComponent = "xl"; break;
+ }
+
+ Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
+ .appendAscii( pComponent )
+ .appendAscii( "/media/image" )
+ .append( (sal_Int32) mnImageCounter )
+ .appendAscii( sExtension )
+ .makeStringAndClear(),
+ sMediaType );
+ xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
+ xOutStream->closeOutput();
+
+ const char *pImagePrefix = NULL;
+ switch ( meDocumentType )
+ {
+ case DOCUMENT_DOCX:
+ pImagePrefix = "media/image";
+ break;
+ case DOCUMENT_PPTX:
+ case DOCUMENT_XLSX:
+ pImagePrefix = "../media/image";
+ break;
+ }
+
+ sRelId = mpFB->addRelation( mpFS->getOutputStream(),
+ US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
+ OUStringBuffer()
+ .appendAscii( pImagePrefix )
+ .append( (sal_Int32) mnImageCounter ++ )
+ .appendAscii( sExtension )
+ .makeStringAndClear() );
+
+ return sRelId;
+}
+
+OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, OUString& rURL )
+{
+ OUString sRelId = WriteImage( rURL );
+ sal_Int16 nBright = 0;
+ sal_Int32 nContrast = 0;
+
+ GET( nBright, AdjustLuminance );
+ GET( nContrast, AdjustContrast );
+
+ mpFS->startElementNS( XML_a, XML_blip,
+ FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+ if( nBright || nContrast )
+ mpFS->singleElementNS( XML_a, XML_lum,
+ XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
+ XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
+ FSEND );
+
+ mpFS->endElementNS( XML_a, XML_blip );
+
+ return sRelId;
+}
+
+void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet )
+{
+ BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
+ if (GetProperty( rXPropSet, S( "FillBitmapMode" ) ) )
+ mAny >>= eBitmapMode;
+
+ DBG(printf("fill bitmap mode: %d\n", eBitmapMode));
+
+ switch (eBitmapMode) {
+ case BitmapMode_REPEAT:
+ mpFS->singleElementNS( XML_a, XML_tile, FSEND );
+ break;
+ default:
+ ;
+ }
+}
+
+void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName )
+{
+ WriteBlipFill( rXPropSet, sURLPropName, XML_a );
+}
+
+void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName, sal_Int32 nXmlNamespace )
+{
+ if ( GetProperty( rXPropSet, sURLPropName ) ) {
+ OUString aURL;
+ mAny >>= aURL;
+
+ DBG(printf ("URL: %s\n", OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
+
+ if( !aURL.getLength() )
+ return;
+
+ mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
+
+ WriteBlip( rXPropSet, aURL );
+
+ if( sURLPropName == S( "FillBitmapURL" ) )
+ WriteBlipMode( rXPropSet );
+ else if( GetProperty( rXPropSet, S( "FillBitmapStretch" ) ) ) {
+ bool bStretch = false;
+ mAny >>= bStretch;
+
+ if( bStretch )
+ WriteStretch();
+ }
+
+ mpFS->endElementNS( nXmlNamespace, XML_blipFill );
+ }
+}
+
+void DrawingML::WriteStretch()
+{
+ mpFS->startElementNS( XML_a, XML_stretch, FSEND );
+ mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
+ mpFS->endElementNS( XML_a, XML_stretch );
+}
+
+void DrawingML::WriteTransformation( const Rectangle& rRect,
+ sal_Int32 nXmlNamespace, sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation )
+{
+ mpFS->startElementNS( nXmlNamespace, XML_xfrm,
+ XML_flipH, bFlipH ? "1" : NULL,
+ XML_flipV, bFlipV ? "1" : NULL,
+ XML_rot, nRotation ? I32S( nRotation ) : NULL,
+ FSEND );
+
+ mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( rRect.Left() ) ), XML_y, IS( MM100toEMU( rRect.Top() ) ), FSEND );
+ mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
+
+ mpFS->endElementNS( nXmlNamespace, XML_xfrm );
+}
+
+void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation )
+{
+ DBG(printf( "write shape transformation\n" ));
+
+ awt::Point aPos = rXShape->getPosition();
+ awt::Size aSize = rXShape->getSize();
+
+ WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, nRotation );
+}
+
+void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, sal_Bool bIsField )
+{
+ Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
+ Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
+ OUString usLanguage;
+ PropertyState eState;
+ sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
+ sal_Bool bComplex = ( nScriptType == ScriptType::COMPLEX );
+ const char* bold = NULL;
+ const char* italic = NULL;
+ const char* underline = NULL;
+ sal_Int32 nSize = 1800;
+
+ if( GETAD( CharHeight ) )
+ nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
+
+ if ( ( bComplex && GETAD( CharWeightComplex ) ) || GETAD( CharWeight ) )
+ if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
+ bold = "1";
+
+ if ( ( bComplex && GETAD( CharPostureComplex ) ) || GETAD( CharPosture ) )
+ switch ( *((awt::FontSlant*) mAny.getValue()) )
+ {
+ case awt::FontSlant_OBLIQUE :
+ case awt::FontSlant_ITALIC :
+ italic = "1";
+ break;
+ default:
+ break;
+ }
+
+ if ( GETAD( CharUnderline ) )
+ switch ( *((sal_Int16*) mAny.getValue()) )
+ {
+ case awt::FontUnderline::SINGLE :
+ underline = "sng";
+ break;
+ case awt::FontUnderline::DOUBLE :
+ underline = "dbl";
+ break;
+ case awt::FontUnderline::DOTTED :
+ underline = "dotted";
+ break;
+ case awt::FontUnderline::DASH :
+ underline = "dash";
+ break;
+ case awt::FontUnderline::LONGDASH :
+ underline = "dashLong";
+ break;
+ case awt::FontUnderline::DASHDOT :
+ underline = "dotDash";
+ break;
+ case awt::FontUnderline::DASHDOTDOT :
+ underline = "dotDotDash";
+ break;
+ case awt::FontUnderline::WAVE :
+ underline = "wavy";
+ break;
+ case awt::FontUnderline::DOUBLEWAVE :
+ underline = "wavyDbl";
+ break;
+ case awt::FontUnderline::BOLD :
+ underline = "heavy";
+ break;
+ case awt::FontUnderline::BOLDDOTTED :
+ underline = "dottedHeavy";
+ break;
+ case awt::FontUnderline::BOLDDASH :
+ underline = "dashHeavy";
+ break;
+ case awt::FontUnderline::BOLDLONGDASH :
+ underline = "dashLongHeavy";
+ break;
+ case awt::FontUnderline::BOLDDASHDOT :
+ underline = "dotDashHeavy";
+ break;
+ case awt::FontUnderline::BOLDDASHDOTDOT :
+ underline = "dotDotDashHeavy";
+ break;
+ case awt::FontUnderline::BOLDWAVE :
+ underline = "wavyHeavy";
+ break;
+ }
+
+ if( GETA( CharLocale ) ) {
+ com::sun::star::lang::Locale eLocale;
+ mAny >>= eLocale;
+
+ OUStringBuffer usLanguageBuffer = eLocale.Language;
+ if( eLocale.Country.getLength() ) {
+ usLanguageBuffer.appendAscii( "-" );
+ usLanguageBuffer.append( eLocale.Country );
+ }
+
+ if( usLanguageBuffer.getLength() )
+ usLanguage = usLanguageBuffer.makeStringAndClear();
+ }
+
+ mpFS->startElementNS( XML_a, XML_rPr,
+ XML_b, bold,
+ XML_i, italic,
+ XML_lang, usLanguage.getLength() ? USS( usLanguage ) : NULL,
+ XML_sz, nSize == 1800 ? NULL : IS( nSize ),
+ XML_u, underline,
+ FSEND );
+
+ // mso doesn't like text color to be placed after typeface
+ if( GETAD( CharColor ) ) {
+ sal_uInt32 color = *((sal_uInt32*) mAny.getValue());
+ DBG(printf("run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO )));
+
+ if( color == COL_AUTO ) { // nCharColor depends to the background color
+ sal_Bool bIsDark = sal_False;
+ GET( bIsDark, IsBackgroundDark );
+ color = bIsDark ? 0xffffff : 0x000000;
+ }
+ color &= 0xffffff;
+
+ // TODO: special handle embossed/engraved
+
+ WriteSolidFill( color );
+ }
+
+ if( GETAD( CharFontName ) ) {
+ const char* typeface = NULL;
+ const char* pitch = NULL;
+ const char* charset = NULL;
+ OUString usTypeface, usPitch, usCharset;
+
+ mAny >>= usTypeface;
+ String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
+ if( aSubstName.Len() )
+ typeface = ST( aSubstName );
+ else
+ typeface = USS( usTypeface );
+
+ mpFS->singleElementNS( XML_a, XML_latin,
+ XML_typeface, typeface,
+ XML_pitchFamily, pitch,
+ XML_charset, charset,
+ FSEND );
+ }
+
+ if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
+ const char* typeface = NULL;
+ const char* pitch = NULL;
+ const char* charset = NULL;
+ OUString usTypeface, usPitch, usCharset;
+
+ mAny >>= usTypeface;
+ String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
+ if( aSubstName.Len() )
+ typeface = ST( aSubstName );
+ else
+ typeface = USS( usTypeface );
+
+ mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
+ XML_typeface, typeface,
+ XML_pitchFamily, pitch,
+ XML_charset, charset,
+ FSEND );
+ }
+
+ if( bIsField ) {
+ Reference< XTextField > rXTextField;
+ GET( rXTextField, TextField );
+ if( rXTextField.is() )
+ rXPropSet.set( rXTextField, UNO_QUERY );
+ }
+
+ // field properties starts here
+ if( GETA( URL ) ) {
+ OUString sURL;
+
+ mAny >>= sURL;
+ if( sURL.getLength() ) {
+ OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
+ US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
+ sURL, true );
+
+ mpFS->singleElementNS( XML_a, XML_hlinkClick,
+ FSNS( XML_r,XML_id ), USS( sRelId ),
+ FSEND );
+ }
+ }
+
+ mpFS->endElementNS( XML_a, XML_rPr );
+}
+
+const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, sal_Bool& bIsField )
+{
+ const char* sType = NULL;
+ Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
+ String aFieldType;
+
+ if( GETA( TextPortionType ) ) {
+ aFieldType = String( *(::rtl::OUString*)mAny.getValue() );
+ DBG(printf ("field type: %s\n", ST(aFieldType) ));
+ }
+
+ if( aFieldType == S( "TextField" ) ) {
+ Reference< XTextField > rXTextField;
+ GET( rXTextField, TextField );
+ if( rXTextField.is() ) {
+ bIsField = sal_True;
+ rXPropSet.set( rXTextField, UNO_QUERY );
+ if( rXPropSet.is() ) {
+ String aFieldKind( rXTextField->getPresentation( sal_True ) );
+ DBG(printf ("field kind: %s\n", ST(aFieldKind) ));
+ if( aFieldKind == S( "Page" ) ) {
+ return "slidenum";
+ }
+ // else if( aFieldKind == S( "URL" ) ) {
+ // do not return here
+ // and make URL field text run with hyperlink property later
+ // }
+ }
+ }
+ }
+
+ return sType;
+}
+
+void DrawingML::GetUUID( OStringBuffer& rBuffer )
+{
+ Sequence< sal_uInt8 > aSeq( 16 );
+ static char cDigits[17] = "0123456789ABCDEF";
+ rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
+ int i;
+
+ rBuffer.append( '{' );
+ for( i = 0; i < 4; i++ ) {
+ rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
+ rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
+ }
+ rBuffer.append( '-' );
+ for( ; i < 6; i++ ) {
+ rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
+ rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
+ }
+ rBuffer.append( '-' );
+ for( ; i < 8; i++ ) {
+ rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
+ rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
+ }
+ rBuffer.append( '-' );
+ for( ; i < 10; i++ ) {
+ rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
+ rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
+ }
+ rBuffer.append( '-' );
+ for( ; i < 16; i++ ) {
+ rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
+ rBuffer.append( cDigits[ aSeq[i] && 0xf ] );
+ }
+ rBuffer.append( '}' );
+}
+
+void DrawingML::WriteRun( Reference< XTextRange > rRun )
+{
+ const char* sFieldType;
+ sal_Bool bIsField = sal_False;
+ OUString sText = rRun->getString();
+
+ if( sText.getLength() < 1) {
+ Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
+
+ try {
+ if( !xPropSet.is() || !( xPropSet->getPropertyValue( S( "PlaceholderText" ) ) >>= sText ) )
+ return;
+ if( sText.getLength() < 1 )
+ return;
+ }
+ catch (const Exception &) {
+ return;
+ }
+ }
+
+ if( ( sFieldType = GetFieldType( rRun, bIsField ) ) ) {
+ OStringBuffer sUUID(39);
+
+ GetUUID( sUUID );
+ mpFS->startElementNS( XML_a, XML_fld,
+ XML_id, sUUID.getStr(),
+ XML_type, sFieldType,
+ FSEND );
+ } else
+ mpFS->startElementNS( XML_a, XML_r, FSEND );
+
+ Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
+ WriteRunProperties( xPropSet, bIsField );
+
+ mpFS->startElementNS( XML_a, XML_t, FSEND );
+ mpFS->writeEscaped( sText );
+ mpFS->endElementNS( XML_a, XML_t );
+
+ if( sFieldType )
+ mpFS->endElementNS( XML_a, XML_fld );
+ else
+ mpFS->endElementNS( XML_a, XML_r );
+}
+
+#define AUTONUM(x) \
+ if( bPBoth ) \
+ pAutoNumType = #x "ParenBoth"; \
+ else if( bPBehind ) \
+ pAutoNumType = #x "ParenR"; \
+ else if( bSDot ) \
+ pAutoNumType = #x "Period";
+
+inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
+{
+ const char* pAutoNumType = NULL;
+
+ switch( (SvxExtNumType)nNumberingType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER_N :
+ case SVX_NUM_CHARS_UPPER_LETTER :
+ AUTONUM( alphaUc );
+ break;
+ case SVX_NUM_CHARS_LOWER_LETTER_N :
+ case SVX_NUM_CHARS_LOWER_LETTER :
+ AUTONUM( alphaLc );
+ break;
+ case SVX_NUM_ROMAN_UPPER :
+ AUTONUM( romanUc );
+ break;
+ case SVX_NUM_ROMAN_LOWER :
+ AUTONUM( romanLc );
+ break;
+ case SVX_NUM_ARABIC :
+ AUTONUM( arabic )
+ else
+ pAutoNumType = "arabicPlain";
+ break;
+ default:
+ break;
+ }
+
+ return pAutoNumType;
+}
+
+void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
+{
+ if( nLevel >= 0 && GETA( NumberingRules ) )
+ {
+ Reference< XIndexAccess > rXIndexAccess;
+
+ if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
+ {
+ DBG(printf ("numbering rules\n"));
+
+ Sequence< PropertyValue > aPropertySequence;
+ rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
+
+ const PropertyValue* pPropValue = aPropertySequence.getArray();
+
+ sal_Int32 nPropertyCount = aPropertySequence.getLength();
+
+ if ( nPropertyCount ) {
+
+ sal_Int16 nNumberingType = -1;
+ bool bSDot = false;
+ bool bPBehind = false;
+ bool bPBoth = false;
+ sal_Unicode aBulletChar = 0x2022; // a bullet
+ awt::FontDescriptor aFontDesc;
+ bool bHasFontDesc = false;
+ OUString aGraphicURL;
+ sal_Int16 nBulletRelSize = 0;
+
+ for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
+ const void* pValue = pPropValue[ i ].Value.getValue();
+ if ( pValue ) {
+ OUString aPropName( pPropValue[ i ].Name );
+ DBG(printf ("pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
+ if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "NumberingType" ) ) )
+ nNumberingType = *( (sal_Int16*)pValue );
+ else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Prefix" ) ) ) {
+ if( *(OUString*)pValue == US( ")" ) )
+ bPBoth = true;
+ } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Suffix" ) ) ) {
+ if( *(OUString*)pValue == US( "." ) )
+ bSDot = true;
+ else if( *(OUString*)pValue == US( ")" ) )
+ bPBehind = true;
+ } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletChar" ) ) )
+ {
+ aBulletChar = String ( *( (String*)pValue ) ).GetChar( 0 );
+ //printf ("bullet char: %d\n", aBulletChar.getStr());
+ }
+ else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletFont" ) ) )
+ {
+ aFontDesc = *( (awt::FontDescriptor*)pValue );
+ bHasFontDesc = true;
+
+ // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
+ // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
+ // Because there might exist a lot of damaged documemts I added this two lines
+ // which fixes the bullet problem for the export.
+ if ( aFontDesc.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StarSymbol" ) ) )
+ aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
+
+ } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletRelSize" ) ) ) {
+ nBulletRelSize = *( (sal_Int16*)pValue );
+ } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicURL" ) ) ) {
+ aGraphicURL = ( *(OUString*)pValue );
+ DBG(printf ("graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
+ } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicSize" ) ) )
+ {
+ if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) )
+ {
+ // don't cast awt::Size to Size as on 64-bits they are not the same.
+ ::com::sun::star::awt::Size aSize;
+ pPropValue[ i ].Value >>= aSize;
+ //aBuGraSize.nA = aSize.Width;
+ //aBuGraSize.nB = aSize.Height;
+ DBG(printf("graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height )));
+ }
+ }
+ }
+ }
+
+ const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
+
+ if( nLevel >= 0 ) {
+ if( aGraphicURL.getLength() > 0 ) {
+ OUString sRelId = WriteImage( aGraphicURL );
+
+ mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
+ mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
+ mpFS->endElementNS( XML_a, XML_buBlip );
+ } else {
+ if( nBulletRelSize && nBulletRelSize != 100 )
+ mpFS->singleElementNS( XML_a, XML_buSzPct,
+ XML_val, IS( 1000*( (sal_Int32)nBulletRelSize ) ), FSEND );
+ if( bHasFontDesc )
+ mpFS->singleElementNS( XML_a, XML_buFont,
+ XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
+ XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
+ FSEND );
+
+ if( pAutoNumType )
+ mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
+ else {
+ aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
+ mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
+{
+ const char* sAlignment = NULL;
+
+ switch( nAlignment ) {
+ case style::ParagraphAdjust_CENTER:
+ sAlignment = "ctr";
+ break;
+ case style::ParagraphAdjust_RIGHT:
+ sAlignment = "r";
+ break;
+ case style::ParagraphAdjust_BLOCK:
+ sAlignment = "just";
+ break;
+ default:
+ ;
+ }
+
+ return sAlignment;
+}
+
+void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
+{
+ if( rSpacing.Mode == LineSpacingMode::PROP )
+ mpFS->singleElementNS( XML_a, XML_spcPct,
+ XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
+ FSEND );
+ else
+ mpFS->singleElementNS( XML_a, XML_spcPts,
+ XML_val, I32S( rSpacing.Height ),
+ FSEND );
+}
+
+void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
+{
+ Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
+ Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
+ PropertyState eState;
+
+ if( !rXPropSet.is() || !rXPropState.is() )
+ return;
+
+ sal_Int16 nLevel = -1;
+ GET( nLevel, NumberingLevel );
+
+ sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
+ GET( nAlignment, ParaAdjust );
+
+ sal_Bool bHasLinespacing = sal_False;
+ LineSpacing aLineSpacing;
+ if( GETAD( ParaLineSpacing ) )
+ bHasLinespacing = ( mAny >>= aLineSpacing );
+
+ if( nLevel != -1
+ || nAlignment != style::ParagraphAdjust_LEFT
+ || bHasLinespacing ) {
+ mpFS->startElementNS( XML_a, XML_pPr,
+ XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
+ XML_marL, NULL,
+ XML_algn, GetAlignment( nAlignment ),
+ FSEND );
+
+ if( bHasLinespacing ) {
+ mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
+ WriteLinespacing( aLineSpacing );
+ mpFS->endElementNS( XML_a, XML_lnSpc );
+ }
+
+ WriteParagraphNumbering( rXPropSet, nLevel );
+
+ mpFS->endElementNS( XML_a, XML_pPr );
+ }
+}
+
+void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
+{
+ Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
+ if( !access.is() )
+ return;
+
+ Reference< XEnumeration > enumeration( access->createEnumeration() );
+ if( !enumeration.is() )
+ return;
+
+ mpFS->startElementNS( XML_a, XML_p, FSEND );
+
+ sal_Bool bPropertiesWritten = sal_False;
+ while( enumeration->hasMoreElements() ) {
+ Reference< XTextRange > run;
+ Any any ( enumeration->nextElement() );
+
+ if (any >>= run) {
+ if( !bPropertiesWritten ) {
+ WriteParagraphProperties( rParagraph );
+ bPropertiesWritten = sal_True;
+ }
+ WriteRun( run );
+ }
+ }
+ mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
+
+ mpFS->endElementNS( XML_a, XML_p );
+}
+
+void DrawingML::WriteText( Reference< XShape > rXShape )
+{
+ Reference< XText > xXText( rXShape, UNO_QUERY );
+ Reference< XPropertySet > rXPropSet( rXShape, UNO_QUERY );
+
+ if( !xXText.is() )
+ return;
+
+#define DEFLRINS 254
+#define DEFTBINS 127
+ sal_Int32 nLeft, nRight, nTop, nBottom;
+ nLeft = nRight = DEFLRINS;
+ nTop = nBottom = DEFTBINS;
+
+ // top inset looks a bit different compared to ppt export
+ // check if something related doesn't work as expected
+ GET( nLeft, TextLeftDistance );
+ GET( nRight, TextRightDistance );
+ GET( nTop, TextUpperDistance );
+ GET( nBottom, TextLowerDistance );
+
+ TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
+ const char* sVerticalAlignment = NULL;
+ GET( eVerticalAlignment, TextVerticalAdjust );
+ switch( eVerticalAlignment ) {
+ case TextVerticalAdjust_BOTTOM:
+ sVerticalAlignment = "b";
+ break;
+ case TextVerticalAdjust_CENTER:
+ sVerticalAlignment = "ctr";
+ break;
+ case TextVerticalAdjust_TOP:
+ default:
+ ;
+ }
+
+ const char* sWritingMode = NULL;
+ sal_Bool bVertical = sal_False;
+ if( GETA( TextWritingMode ) ) {
+ WritingMode eMode;
+
+ if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) {
+ sWritingMode = "vert";
+ bVertical = sal_True;
+ }
+ }
+
+ TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
+ bool bHorizontalCenter = false;
+ GET( eHorizontalAlignment, TextHorizontalAdjust );
+ if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
+ bHorizontalCenter = true;
+ else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
+ sVerticalAlignment = "b";
+
+ sal_Bool bHasWrap = sal_False;
+ sal_Bool bWrap = sal_False;
+ if( GETA( TextWordWrap ) ) {
+ mAny >>= bWrap;
+ bHasWrap = sal_True;
+ }
+
+ mpFS->singleElementNS( XML_a, XML_bodyPr,
+ XML_wrap, bHasWrap && !bWrap ? "none" : NULL,
+ XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
+ XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
+ XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
+ XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
+ XML_anchor, sVerticalAlignment,
+ XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
+ XML_vert, sWritingMode,
+ FSEND );
+
+ Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
+ if( !access.is() )
+ return;
+
+ Reference< XEnumeration > enumeration( access->createEnumeration() );
+ if( !enumeration.is() )
+ return;
+
+ while( enumeration->hasMoreElements() ) {
+ Reference< XTextContent > paragraph;
+ Any any ( enumeration->nextElement() );
+
+ if( any >>= paragraph)
+ WriteParagraph( paragraph );
+ }
+
+}
+
+void DrawingML::WritePresetShape( const char* pShape )
+{
+ mpFS->startElementNS( XML_a, XML_prstGeom,
+ XML_prst, pShape,
+ FSEND );
+ mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
+ mpFS->endElementNS( XML_a, XML_prstGeom );
+}
+
+void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, sal_Bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
+{
+ mpFS->startElementNS( XML_a, XML_prstGeom,
+ XML_prst, pShape,
+ FSEND );
+ mpFS->startElementNS( XML_a, XML_avLst, FSEND );
+
+ Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
+ if ( ( rProp.Value >>= aAdjustmentSeq )
+ && eShapeType != mso_sptActionButtonForwardNext // we have adjustments values for these type of shape, but MSO doesn't like them
+ && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
+ ) {
+ DBG(printf("adj seq len: %d\n", int( aAdjustmentSeq.getLength() )));
+ if ( bPredefinedHandlesUsed )
+ EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
+
+ sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
+ for( sal_Int32 i=0; i < nLength; i++ )
+ if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
+ mpFS->singleElementNS( XML_a, XML_gd,
+ XML_name, nLength > 1 ? ( OString( "adj" ) + OString::valueOf( i + 1 ) ).getStr() : "adj",
+ XML_fmla, (OString("val ") + OString::valueOf( nValue )).getStr(),
+ FSEND );
+ }
+
+ mpFS->endElementNS( XML_a, XML_avLst );
+ mpFS->endElementNS( XML_a, XML_prstGeom );
+}
+
+void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
+{
+ if( rPolyPolygon.Count() < 1 )
+ return;
+
+ mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
+ mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
+ mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
+ mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
+ mpFS->singleElementNS( XML_a, XML_rect,
+ XML_l, "0",
+ XML_t, "0",
+ XML_r, "r",
+ XML_b, "b",
+ FSEND );
+
+ mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
+
+ for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ ) {
+
+ const Polygon& rPoly = rPolyPolygon[ i ];
+ Rectangle aRect( rPoly.GetBoundRect() );
+ sal_Bool bBezier = sal_False;
+
+ mpFS->startElementNS( XML_a, XML_path,
+ XML_w, I64S( aRect.GetWidth() ),
+ XML_h, I64S( aRect.GetHeight() ),
+ FSEND );
+
+ if( rPoly.GetSize() > 0 )
+ {
+ mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
+
+ mpFS->singleElementNS( XML_a, XML_pt,
+ XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
+ XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
+ FSEND );
+
+ mpFS->endElementNS( XML_a, XML_moveTo );
+ }
+
+ for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
+ {
+ enum PolyFlags flags = rPoly.GetFlags(j);
+ if( flags == POLY_CONTROL && !bBezier )
+ {
+ mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
+ bBezier = sal_True;
+ }
+ else if( flags == POLY_NORMAL && !bBezier )
+ mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
+
+ mpFS->singleElementNS( XML_a, XML_pt,
+ XML_x, I64S( rPoly[j].X() - aRect.Left() ),
+ XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
+ FSEND );
+
+ if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR ) && bBezier )
+ {
+ mpFS->endElementNS( XML_a, XML_cubicBezTo );
+ bBezier = sal_False;
+ }
+ else if( flags == POLY_NORMAL && !bBezier )
+ mpFS->endElementNS( XML_a, XML_lnTo );
+ else if( bBezier && ( j % 3 ) == 0 )
+ {
+ // //a:cubicBezTo can only contain 3 //a:pt elements, so we
+ // need to break things up...
+ mpFS->endElementNS( XML_a, XML_cubicBezTo );
+ mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
+ }
+ }
+
+ mpFS->endElementNS( XML_a, XML_path );
+ }
+
+ mpFS->endElementNS( XML_a, XML_pathLst );
+
+ mpFS->endElementNS( XML_a, XML_custGeom );
+}
+
+void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
+{
+ if( nStartID != -1 )
+ mpFS->singleElementNS( XML_a, XML_stCxn,
+ XML_id, I32S( nStartID ),
+ XML_idx, I64S( rConnectorEntry.GetConnectorRule( sal_True ) ),
+ FSEND );
+ if( nEndID != -1 )
+ mpFS->singleElementNS( XML_a, XML_endCxn,
+ XML_id, I32S( nEndID ),
+ XML_idx, I64S( rConnectorEntry.GetConnectorRule( sal_False ) ),
+ FSEND );
+}
+
+// from sw/source/filter/ww8/wrtw8num.cxx for default bullets to export to MS intact
+static void lcl_SubstituteBullet(String& rNumStr, rtl_TextEncoding& rChrSet, String& rFontName)
+{
+ sal_Unicode cChar = rNumStr.GetChar(0);
+ StarSymbolToMSMultiFont *pConvert = CreateStarSymbolToMSMultiFont();
+ String sFont = pConvert->ConvertChar(cChar);
+ delete pConvert;
+ if (sFont.Len())
+ {
+ rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
+ rFontName = sFont;
+ rChrSet = RTL_TEXTENCODING_SYMBOL;
+ }
+ else if ( (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) )
+ {
+ /*
+ Ok we can't fit into a known windows unicode font, but
+ we are not in the private area, so we are a
+ standardized symbol, so turn off the symbol bit and
+ let words own font substitution kick in
+ */
+ rChrSet = RTL_TEXTENCODING_UNICODE;
+ rFontName = ::GetFontToken(rFontName, 0);
+ }
+ else
+ {
+ /*
+ Well we don't have an available substition, and we're
+ in our private area, so give up and show a standard
+ bullet symbol
+ */
+ rFontName.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Wingdings"));
+ rNumStr = static_cast< sal_Unicode >(0x6C);
+ }
+}
+
+sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
+{
+ String sNumStr = cBulletId;
+
+ if ( rFontDesc.Name.equalsIgnoreAsciiCaseAscii("starsymbol") ||
+ rFontDesc.Name.equalsIgnoreAsciiCaseAscii("opensymbol") ) {
+ String sFontName = rFontDesc.Name;
+ rtl_TextEncoding aCharSet = rFontDesc.CharSet;
+
+ lcl_SubstituteBullet( sNumStr, aCharSet, sFontName );
+
+ rFontDesc.Name = sFontName;
+ rFontDesc.CharSet = aCharSet;
+ }
+
+ return sNumStr.GetChar( 0 );
+}
+
+sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
+ const OUString& sFullStream,
+ const OUString& sRelativeStream,
+ const Reference< XOutputStream >& xParentRelation,
+ const char* sContentType,
+ const char* sRelationshipType,
+ ::rtl::OUString* pRelationshipId )
+{
+ OUString sRelationshipId;
+ if (xParentRelation.is())
+ sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
+ else
+ sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
+
+ if( pRelationshipId )
+ *pRelationshipId = sRelationshipId;
+
+ sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
+
+ return p;
+}
+
+void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
+{
+ if ( !GetProperty( xPropSet, S( "FillStyle" ) ) )
+ return;
+ FillStyle aFillStyle( FillStyle_NONE );
+ xPropSet->getPropertyValue( S( "FillStyle" ) ) >>= aFillStyle;
+
+ if( aFillStyle == FillStyle_NONE ||
+ aFillStyle == FillStyle_HATCH )
+ return;
+
+ switch( aFillStyle )
+ {
+ case ::com::sun::star::drawing::FillStyle_SOLID :
+ WriteSolidFill( xPropSet );
+ break;
+ case ::com::sun::star::drawing::FillStyle_GRADIENT :
+ WriteGradientFill( xPropSet );
+ break;
+ case ::com::sun::star::drawing::FillStyle_BITMAP :
+ WriteBlipFill( xPropSet, S( "FillBitmapURL" ) );
+ break;
+ default:
+ ;
+ }
+
+ return;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */