|  | /************************************************************** | 
|  | * | 
|  | * Licensed to the Apache Software Foundation (ASF) under one | 
|  | * or more contributor license agreements.  See the NOTICE file | 
|  | * distributed with this work for additional information | 
|  | * regarding copyright ownership.  The ASF licenses this file | 
|  | * to you under the Apache License, Version 2.0 (the | 
|  | * "License"); you may not use this file except in compliance | 
|  | * with the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, | 
|  | * software distributed under the License is distributed on an | 
|  | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | * KIND, either express or implied.  See the License for the | 
|  | * specific language governing permissions and limitations | 
|  | * under the License. | 
|  | * | 
|  | *************************************************************/ | 
|  |  | 
|  |  | 
|  |  | 
|  | #include "oox/core/xmlfilterbase.hxx" | 
|  | #include "oox/export/drawingml.hxx" | 
|  | #include "oox/export/utils.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/container/XEnumerationAccess.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/i18n/ScriptType.hpp> | 
|  | #include <com/sun/star/io/XOutputStream.hpp> | 
|  | #include <com/sun/star/style/ParagraphAdjust.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 <vcl/graph.hxx> | 
|  | #include <svtools/grfmgr.hxx> | 
|  | #include <rtl/strbuf.hxx> | 
|  | #include <sfx2/app.hxx> | 
|  | #include <svl/languageoptions.hxx> | 
|  | #include <svx/escherex.hxx> | 
|  | #include <svx/svxenum.hxx> | 
|  |  | 
|  | using namespace ::com::sun::star; | 
|  | using namespace ::com::sun::star::uno; | 
|  | using namespace ::com::sun::star::drawing; | 
|  | using namespace ::com::sun::star::i18n; | 
|  | 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::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; | 
|  |  | 
|  | // 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( 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( 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 = FALSE; | 
|  | const char* cap = NULL; | 
|  | drawing::LineDash aLineDash; | 
|  | sal_Bool bDashSet = FALSE; | 
|  |  | 
|  | GET( nLineWidth, LineWidth ); | 
|  |  | 
|  | switch( aLineStyle ) { | 
|  | case drawing::LineStyle_DASH: | 
|  | if( GETA( LineDash ) ) { | 
|  | aLineDash = *(drawing::LineDash*) mAny.getValue(); | 
|  | bDashSet = 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 = 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; | 
|  |  | 
|  | // #15508# added BMP type for better exports | 
|  | // export not yet active, so adding for reference (not checked) | 
|  | case GFX_LINK_TYPE_NATIVE_BMP: | 
|  | sMediaType = US( "image/bmp" ); | 
|  | sExtension = ".bmp"; | 
|  | 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.GetSize(); | 
|  | 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->openOutputStream( 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( OUString& rURL ) | 
|  | { | 
|  | OUString sRelId = WriteImage( rURL ); | 
|  |  | 
|  | mpFS->singleElementNS( XML_a, XML_blip, | 
|  | FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(), | 
|  | FSEND ); | 
|  |  | 
|  | 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( 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_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation ) | 
|  | { | 
|  | mpFS->startElementNS( XML_a, 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( XML_a, XML_xfrm ); | 
|  | } | 
|  |  | 
|  | void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, 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 ) ), bFlipH, bFlipV, nRotation ); | 
|  | } | 
|  |  | 
|  | void DrawingML::WriteRunProperties( Reference< XTextRange > rRun ) | 
|  | { | 
|  | 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 ); | 
|  | } | 
|  |  | 
|  | mpFS->endElementNS( XML_a, XML_rPr ); | 
|  | } | 
|  |  | 
|  | const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun ) | 
|  | { | 
|  | 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() ) { | 
|  | rXPropSet.set( rXTextField, UNO_QUERY ); | 
|  | if( rXPropSet.is() ) { | 
|  | String aFieldKind( rXTextField->getPresentation( TRUE ) ); | 
|  | DBG(printf ("field kind: %s\n", ST(aFieldKind) )); | 
|  | if( aFieldKind == S( "Page" ) ) { | 
|  | return "slidenum"; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | 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; | 
|  | bool bIsField = false; | 
|  | OUString sText = rRun->getString(); | 
|  |  | 
|  | if( sText.getLength() < 1) | 
|  | return; | 
|  |  | 
|  | if( ( sFieldType = GetFieldType( rRun ) ) ) { | 
|  | OStringBuffer sUUID(39); | 
|  |  | 
|  | GetUUID( sUUID ); | 
|  | mpFS->startElementNS( XML_a, XML_fld, | 
|  | XML_id, sUUID.getStr(), | 
|  | XML_type, sFieldType, | 
|  | FSEND ); | 
|  | bIsField = true; | 
|  | } else | 
|  | mpFS->startElementNS( XML_a, XML_r, FSEND ); | 
|  |  | 
|  | WriteRunProperties( rRun ); | 
|  |  | 
|  | mpFS->startElementNS( XML_a, XML_t, FSEND ); | 
|  | mpFS->writeEscaped( sText ); | 
|  | mpFS->endElementNS( XML_a, XML_t ); | 
|  |  | 
|  | if( bIsField ) | 
|  | 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::WriteParagraphProperties( Reference< XTextContent > rParagraph ) | 
|  | { | 
|  | Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY ); | 
|  | Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY ); | 
|  |  | 
|  | if( !rXPropSet.is() || !rXPropState.is() ) | 
|  | return; | 
|  |  | 
|  | sal_Int16 nLevel = -1; | 
|  | GET( nLevel, NumberingLevel ); | 
|  |  | 
|  | sal_Int32 nLeftMargin = 0; | 
|  | // fix coordinates | 
|  | //GET( nLeftMargin, ParaLeftMargin ); | 
|  |  | 
|  | sal_Int16 nAlignment( style::ParagraphAdjust_LEFT ); | 
|  | GET( nAlignment, ParaAdjust ); | 
|  |  | 
|  | if( nLevel != -1 | 
|  | || nLeftMargin > 0 | 
|  | || nAlignment != style::ParagraphAdjust_LEFT ) { | 
|  | mpFS->startElementNS( XML_a, XML_pPr, | 
|  | XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL, | 
|  | XML_marL, nLeftMargin > 0 ? IS( nLeftMargin ) : NULL, | 
|  | XML_algn, GetAlignment( nAlignment ), | 
|  | FSEND ); | 
|  |  | 
|  | 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 = FALSE; | 
|  | while( enumeration->hasMoreElements() ) { | 
|  | Reference< XTextRange > run; | 
|  | Any any ( enumeration->nextElement() ); | 
|  |  | 
|  | if (any >>= run) { | 
|  | if( !bPropertiesWritten && run->getString().getLength() ) { | 
|  | WriteParagraphProperties( rParagraph ); | 
|  | bPropertiesWritten = 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: | 
|  | ; | 
|  | } | 
|  |  | 
|  | TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER ); | 
|  | bool bHorizontalCenter = false; | 
|  | GET( eHorizontalAlignment, TextHorizontalAdjust ); | 
|  | if( eHorizontalAlignment == TextHorizontalAdjust_CENTER ) | 
|  | bHorizontalCenter = true; | 
|  |  | 
|  | sal_Bool bHasWrap = FALSE; | 
|  | sal_Bool bWrap = FALSE; | 
|  | if( GETA( TextWordWrap ) ) { | 
|  | mAny >>= bWrap; | 
|  | bHasWrap = TRUE; | 
|  | //DBG(printf("wrap: %d\n", bWrap)); | 
|  | } | 
|  |  | 
|  | 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, | 
|  | 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 ) { | 
|  | 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( USHORT i = 0; i < rPolyPolygon.Count(); i ++ ) { | 
|  |  | 
|  | const Polygon& rPoly = rPolyPolygon[ i ]; | 
|  | Rectangle aRect( rPoly.GetBoundRect() ); | 
|  | sal_Bool bBezier = 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( USHORT 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 = 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 = 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 ); | 
|  | } | 
|  | //             switch( rPoly.GetFlags(j) ) { | 
|  | //                 case POLY_NORMAL: | 
|  | //                     DBG(printf("normal\n")); | 
|  | //                     break; | 
|  | //                 case POLY_SMOOTH: | 
|  | //                     DBG(printf("smooth\n")); | 
|  | //                     break; | 
|  | //                 case POLY_CONTROL: | 
|  | //                     DBG(printf("control\n")); | 
|  | //                     break; | 
|  | //                 case POLY_SYMMTR: | 
|  | //                     DBG(printf("symmtr\n")); | 
|  | //                         break; | 
|  | //             } | 
|  | //             DBG(printf("point %ld %ld\n", rPoly[j].X() - aRect.Left(), rPoly[j].Y() - aRect.Top())); | 
|  | } | 
|  |  | 
|  | 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 ) | 
|  | { | 
|  | mpFS->singleElementNS( XML_a, XML_stCxn, | 
|  | XML_id, I32S( nStartID ), | 
|  | XML_idx, I64S( rConnectorEntry.GetConnectorRule( TRUE ) ), | 
|  | FSEND ); | 
|  | mpFS->singleElementNS( XML_a, XML_endCxn, | 
|  | XML_id, I32S( nEndID ), | 
|  | XML_idx, I64S( rConnectorEntry.GetConnectorRule( 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 ); | 
|  | } | 
|  |  | 
|  | } | 
|  | } |