LCOV - code coverage report
Current view: top level - oox/source/export - drawingml.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 948 1091 86.9 %
Date: 2014-04-11 Functions: 53 54 98.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "oox/core/xmlfilterbase.hxx"
      21             : #include "oox/export/drawingml.hxx"
      22             : #include "oox/export/utils.hxx"
      23             : #include <oox/drawingml/color.hxx>
      24             : #include <oox/token/tokens.hxx>
      25             : #include <oox/drawingml/drawingmltypes.hxx>
      26             : 
      27             : #include <cstdio>
      28             : #include <com/sun/star/awt/CharSet.hpp>
      29             : #include <com/sun/star/awt/FontDescriptor.hpp>
      30             : #include <com/sun/star/awt/FontSlant.hpp>
      31             : #include <com/sun/star/awt/FontWeight.hpp>
      32             : #include <com/sun/star/awt/FontUnderline.hpp>
      33             : #include <com/sun/star/awt/Gradient.hpp>
      34             : #include <com/sun/star/beans/XPropertySet.hpp>
      35             : #include <com/sun/star/beans/XPropertyState.hpp>
      36             : #include <com/sun/star/beans/Property.hpp>
      37             : #include <com/sun/star/beans/XPropertySetInfo.hpp>
      38             : #include <com/sun/star/container/XEnumerationAccess.hpp>
      39             : #include <com/sun/star/container/XIndexAccess.hpp>
      40             : #include <com/sun/star/drawing/BitmapMode.hpp>
      41             : #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
      42             : #include <com/sun/star/drawing/LineDash.hpp>
      43             : #include <com/sun/star/drawing/LineJoint.hpp>
      44             : #include <com/sun/star/drawing/LineStyle.hpp>
      45             : #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
      46             : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
      47             : #include <com/sun/star/drawing/XShape.hpp>
      48             : #include <com/sun/star/drawing/FillStyle.hpp>
      49             : #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
      50             : #include <com/sun/star/i18n/ScriptType.hpp>
      51             : #include <com/sun/star/io/XOutputStream.hpp>
      52             : #include <com/sun/star/style/LineSpacing.hpp>
      53             : #include <com/sun/star/style/LineSpacingMode.hpp>
      54             : #include <com/sun/star/style/ParagraphAdjust.hpp>
      55             : #include <com/sun/star/text/WritingMode.hpp>
      56             : #include <com/sun/star/text/GraphicCrop.hpp>
      57             : #include <com/sun/star/text/XText.hpp>
      58             : #include <com/sun/star/text/XTextContent.hpp>
      59             : #include <com/sun/star/text/XTextField.hpp>
      60             : #include <com/sun/star/text/XTextRange.hpp>
      61             : #include <tools/stream.hxx>
      62             : #include <unotools/fontdefs.hxx>
      63             : #include <vcl/cvtgrf.hxx>
      64             : #include <vcl/graph.hxx>
      65             : #include <vcl/settings.hxx>
      66             : #include <svtools/grfmgr.hxx>
      67             : #include <rtl/strbuf.hxx>
      68             : #include <sfx2/app.hxx>
      69             : #include <svl/languageoptions.hxx>
      70             : #include <filter/msfilter/escherex.hxx>
      71             : #include <filter/msfilter/util.hxx>
      72             : #include <editeng/outlobj.hxx>
      73             : #include <editeng/svxenum.hxx>
      74             : #include <svx/unoapi.hxx>
      75             : #include <svx/svdoashp.hxx>
      76             : #include <svx/unoshape.hxx>
      77             : 
      78             : using namespace ::com::sun::star;
      79             : using namespace ::com::sun::star::beans;
      80             : using namespace ::com::sun::star::drawing;
      81             : using namespace ::com::sun::star::i18n;
      82             : using namespace ::com::sun::star::style;
      83             : using namespace ::com::sun::star::text;
      84             : using namespace ::com::sun::star::uno;
      85             : using ::com::sun::star::beans::PropertyState;
      86             : using ::com::sun::star::beans::PropertyValue;
      87             : using ::com::sun::star::beans::XPropertySet;
      88             : using ::com::sun::star::beans::XPropertyState;
      89             : using ::com::sun::star::container::XEnumeration;
      90             : using ::com::sun::star::container::XEnumerationAccess;
      91             : using ::com::sun::star::container::XIndexAccess;
      92             : using ::com::sun::star::geometry::IntegerRectangle2D;
      93             : using ::com::sun::star::io::XOutputStream;
      94             : using ::com::sun::star::style::LineSpacing;
      95             : using ::com::sun::star::text::XText;
      96             : using ::com::sun::star::text::XTextContent;
      97             : using ::com::sun::star::text::XTextField;
      98             : using ::com::sun::star::text::XTextRange;
      99             : using ::sax_fastparser::FSHelperPtr;
     100             : 
     101             : DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet));
     102             : 
     103             : // Defined in generated code.
     104             : extern std::map< OString, std::vector<OString> > ooxDrawingMLGetAdjNames();
     105             : 
     106             : namespace oox {
     107             : namespace drawingml {
     108             : 
     109             : #define GETA(propName) \
     110             :     GetProperty( rXPropSet, OUString( #propName ) )
     111             : 
     112             : #define GETAD(propName) \
     113             :     ( GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
     114             : 
     115             : #define GET(variable, propName) \
     116             :     if ( GETA(propName) ) \
     117             :         mAny >>= variable;
     118             : 
     119             : // not thread safe
     120             : int DrawingML::mnImageCounter = 1;
     121             : 
     122         276 : void DrawingML::ResetCounters()
     123             : {
     124         276 :     mnImageCounter = 1;
     125         276 : }
     126             : 
     127        9680 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
     128             : {
     129        9680 :     bool bRetValue = false;
     130             : 
     131             :     try {
     132        9680 :         mAny = rXPropSet->getPropertyValue( aName );
     133        8471 :         if ( mAny.hasValue() )
     134        8297 :             bRetValue = true;
     135        1209 :     } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
     136             : 
     137        9680 :     return bRetValue;
     138             : }
     139             : 
     140         506 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, const OUString& aName, PropertyState& eState )
     141             : {
     142         506 :     bool bRetValue = false;
     143             : 
     144             :     try {
     145         506 :         mAny = rXPropSet->getPropertyValue( aName );
     146         506 :         if ( mAny.hasValue() ) {
     147         506 :             bRetValue = true;
     148         506 :             eState = rXPropState->getPropertyState( aName );
     149             :         }
     150           0 :     } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
     151             : 
     152         506 :     return bRetValue;
     153             : }
     154             : 
     155         611 : void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
     156             : {
     157         611 :     OString sColor = OString::number(  nColor, 16 );
     158         611 :     if( sColor.getLength() < 6 ) {
     159         150 :         OStringBuffer sBuf( "0" );
     160         150 :         int remains = 5 - sColor.getLength();
     161             : 
     162         848 :         while( remains > 0 ) {
     163         548 :             sBuf.append( "0" );
     164         548 :             remains--;
     165             :         }
     166             : 
     167         150 :         sBuf.append( sColor );
     168             : 
     169         150 :         sColor = sBuf.getStr();
     170             :     }
     171         611 :     if( nAlpha < MAX_PERCENT )
     172             :     {
     173           2 :         mpFS->startElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
     174           2 :         mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
     175           2 :         mpFS->endElementNS( XML_a, XML_srgbClr );
     176             : 
     177             :     }
     178             :     else
     179             :     {
     180         609 :         mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
     181         611 :     }
     182         611 : }
     183             : 
     184         199 : void DrawingML::WriteColor( const OUString& sColorSchemeName, Sequence< PropertyValue > aTransformations )
     185             : {
     186             :     // prevent writing a tag with empty val attribute
     187         199 :     if( sColorSchemeName.isEmpty() )
     188         247 :         return;
     189             : 
     190         151 :     if( aTransformations.hasElements() )
     191             :     {
     192             :         mpFS->startElementNS( XML_a, XML_schemeClr,
     193             :                               XML_val, USS( sColorSchemeName ),
     194          52 :                               FSEND );
     195          52 :         WriteColorTransformations( aTransformations );
     196          52 :         mpFS->endElementNS( XML_a, XML_schemeClr );
     197             :     }
     198             :     else
     199             :         mpFS->singleElementNS( XML_a, XML_schemeClr,
     200             :                               XML_val, USS( sColorSchemeName ),
     201          99 :                               FSEND );
     202             : }
     203             : 
     204          52 : void DrawingML::WriteColorTransformations( Sequence< PropertyValue > aTransformations )
     205             : {
     206         106 :     for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
     207             :     {
     208          54 :         sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
     209          54 :         if( nToken != XML_TOKEN_INVALID && aTransformations[i].Value.hasValue() )
     210             :         {
     211          54 :             sal_Int32 nValue = aTransformations[i].Value.get<sal_Int32>();
     212          54 :             mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
     213             :         }
     214             :     }
     215          52 : }
     216             : 
     217         552 : void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
     218             : {
     219         552 :     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
     220         552 :     WriteColor( nColor, nAlpha );
     221         552 :     mpFS->endElementNS( XML_a, XML_solidFill );
     222         552 : }
     223             : 
     224          55 : void DrawingML::WriteSolidFill( const OUString& sSchemeName, Sequence< PropertyValue > aTransformations )
     225             : {
     226          55 :     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
     227          55 :     WriteColor( sSchemeName, aTransformations );
     228          55 :     mpFS->endElementNS( XML_a, XML_solidFill );
     229          55 : }
     230             : 
     231         262 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
     232             : {
     233             :     // get fill color
     234         262 :     if ( !GetProperty( rXPropSet, "FillColor" ) )
     235         263 :         return;
     236         261 :     sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
     237             : 
     238             :     // get InteropGrabBag and search the relevant attributes
     239         261 :     OUString sColorFillScheme;
     240         261 :     sal_uInt32 nOriginalColor = 0;
     241         522 :     Sequence< PropertyValue > aStyleProperties, aTransformations;
     242         261 :     if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     243             :     {
     244         138 :         Sequence< PropertyValue > aGrabBag;
     245         138 :         mAny >>= aGrabBag;
     246         506 :         for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
     247         368 :             if( aGrabBag[i].Name == "SpPrSolidFillSchemeClr" )
     248          30 :                 aGrabBag[i].Value >>= sColorFillScheme;
     249         338 :             else if( aGrabBag[i].Name == "OriginalSolidFillClr" )
     250          66 :                 aGrabBag[i].Value >>= nOriginalColor;
     251         272 :             else if( aGrabBag[i].Name == "StyleFillRef" )
     252          26 :                 aGrabBag[i].Value >>= aStyleProperties;
     253         246 :             else if( aGrabBag[i].Name == "SpPrSolidFillSchemeClrTransformations" )
     254         168 :                 aGrabBag[i].Value >>= aTransformations;
     255             :     }
     256             : 
     257         261 :     sal_Int32 nAlpha = MAX_PERCENT;
     258         261 :     if( GetProperty( rXPropSet, "FillTransparence" ) )
     259             :     {
     260         261 :         sal_Int32 nTransparency = 0;
     261         261 :         mAny >>= nTransparency;
     262             :         // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
     263         261 :         nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
     264             :     }
     265             : 
     266             :     // write XML
     267         261 :     if ( nFillColor != nOriginalColor )
     268             :         // the user has set a different color for the shape
     269         192 :         WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     270          69 :     else if ( !sColorFillScheme.isEmpty() )
     271             :         // the shape had a scheme color and the user didn't change it
     272          30 :         WriteSolidFill( sColorFillScheme, aTransformations );
     273          39 :     else if ( aStyleProperties.hasElements() )
     274             :     {
     275          21 :         sal_uInt32 nThemeColor = 0;
     276          63 :         for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
     277          63 :             if( aStyleProperties[i].Name == "Color" )
     278             :             {
     279          21 :                 aStyleProperties[i].Value >>= nThemeColor;
     280          21 :                 break;
     281             :             }
     282          21 :         if ( nFillColor != nThemeColor )
     283             :             // the shape contains a theme but it wasn't being used
     284           2 :             WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     285             :         // in case the shape used the style color and the user didn't change it,
     286             :         // we must not write a <a: solidFill> tag.
     287             :     }
     288             :     else
     289             :         // the shape had a custom color and the user didn't change it
     290         279 :         WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     291             : }
     292             : 
     293          28 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
     294             : {
     295             :     mpFS->startElementNS( XML_a, XML_gs,
     296             :                           XML_pos, I32S( nStop * 1000 ),
     297          28 :                           FSEND );
     298          28 :     WriteColor( nColor );
     299          28 :     mpFS->endElementNS( XML_a, XML_gs );
     300          28 : }
     301             : 
     302          28 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
     303             : {
     304          28 :     return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
     305          28 :         | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
     306          28 :         | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
     307             : }
     308             : 
     309          15 : bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
     310             : {
     311          26 :     return aGradient1.Style == aGradient2.Style &&
     312          14 :             aGradient1.StartColor == aGradient2.StartColor &&
     313           6 :             aGradient1.EndColor == aGradient2.EndColor &&
     314           6 :             aGradient1.Angle == aGradient2.Angle &&
     315           6 :             aGradient1.Border == aGradient2.Border &&
     316           6 :             aGradient1.XOffset == aGradient2.XOffset &&
     317           6 :             aGradient1.YOffset == aGradient2.YOffset &&
     318           6 :             aGradient1.StartIntensity == aGradient2.StartIntensity &&
     319          21 :             aGradient1.EndIntensity == aGradient2.EndIntensity &&
     320          18 :             aGradient1.StepCount == aGradient2.StepCount;
     321             : }
     322             : 
     323          15 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
     324             : {
     325          15 :     awt::Gradient aGradient;
     326          15 :     if( GETA( FillGradient ) ) {
     327          15 :         aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
     328             : 
     329             :         // get InteropGrabBag and search the relevant attributes
     330          15 :         awt::Gradient aOriginalGradient;
     331          15 :         Sequence< PropertyValue > aGradientStops;
     332          15 :         if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     333             :         {
     334           4 :             Sequence< PropertyValue > aGrabBag;
     335           4 :             mAny >>= aGrabBag;
     336          24 :             for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
     337          20 :                 if( aGrabBag[i].Name == "GradFillDefinition" )
     338           2 :                     aGrabBag[i].Value >>= aGradientStops;
     339          18 :                 else if( aGrabBag[i].Name == "OriginalGradFill" )
     340           7 :                     aGrabBag[i].Value >>= aOriginalGradient;
     341             :         }
     342             : 
     343             :         // check if an ooxml gradient had been imported and if the user has modified it
     344          15 :         if( EqualGradients( aOriginalGradient, aGradient ) )
     345             :         {
     346             :             // If we have no gradient stops that means original gradient were defined by a theme.
     347           3 :             if( aGradientStops.hasElements() )
     348             :             {
     349           2 :                 mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
     350           2 :                 WriteGrabBagGradientFill(aGradientStops, aGradient);
     351           2 :                 mpFS->endElementNS( XML_a, XML_gradFill );
     352             :             }
     353             :         }
     354             :         else
     355             :         {
     356          12 :             mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
     357          12 :             WriteGradientFill(aGradient);
     358          12 :             mpFS->endElementNS( XML_a, XML_gradFill );
     359          15 :         }
     360             :     }
     361          15 : }
     362             : 
     363           2 : void DrawingML::WriteGrabBagGradientFill( Sequence< PropertyValue > aGradientStops, awt::Gradient rGradient )
     364             : {
     365             :     // write back the original gradient
     366           2 :     mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     367             : 
     368             :     // get original stops and write them
     369           8 :     for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
     370             :     {
     371           6 :         Sequence< PropertyValue > aGradientStop;
     372           6 :         aGradientStops[i].Value >>= aGradientStop;
     373             : 
     374             :         // get values
     375          12 :         OUString sSchemeClr;
     376           6 :         double nPos = 0;
     377           6 :         sal_Int16 nTransparency = 0;
     378           6 :         sal_Int32 nRgbClr = 0;
     379          12 :         Sequence< PropertyValue > aTransformations;
     380          24 :         for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
     381          18 :             if( aGradientStop[j].Name == "SchemeClr" )
     382           3 :                 aGradientStop[j].Value >>= sSchemeClr;
     383          15 :             else if( aGradientStop[j].Name == "RgbClr" )
     384           3 :                 aGradientStop[j].Value >>= nRgbClr;
     385          12 :             else if( aGradientStop[j].Name == "Pos" )
     386           6 :                 aGradientStop[j].Value >>= nPos;
     387           6 :             else if( aGradientStop[j].Name == "Transparency" )
     388           1 :                 aGradientStop[j].Value >>= nTransparency;
     389           5 :             else if( aGradientStop[j].Name == "Transformations" )
     390           3 :                 aGradientStop[j].Value >>= aTransformations;
     391             : 
     392             :         // write stop
     393             :         mpFS->startElementNS( XML_a, XML_gs,
     394             :                               XML_pos, OString::number( nPos * 100000.0 ).getStr(),
     395           6 :                               FSEND );
     396           6 :         if( sSchemeClr.isEmpty() )
     397             :         {
     398             :             // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
     399           3 :             sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
     400           3 :             WriteColor( nRgbClr, nAlpha );
     401             :         }
     402             :         else
     403           3 :             WriteColor( sSchemeClr, aTransformations );
     404           6 :         mpFS->endElementNS( XML_a, XML_gs );
     405           6 :     }
     406           2 :     mpFS->endElementNS( XML_a, XML_gsLst );
     407             : 
     408             :     mpFS->singleElementNS( XML_a, XML_lin,
     409           2 :                            XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     410           2 :                            FSEND );
     411           2 : }
     412             : 
     413          12 : void DrawingML::WriteGradientFill( awt::Gradient rGradient )
     414             : {
     415          12 :     switch( rGradient.Style ) {
     416             :         default:
     417             :         case GradientStyle_LINEAR:
     418           8 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     419           8 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     420           8 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     421           8 :             mpFS->endElementNS( XML_a, XML_gsLst );
     422             :             mpFS->singleElementNS( XML_a, XML_lin,
     423           8 :                     XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     424           8 :                     FSEND );
     425           8 :             break;
     426             : 
     427             :         case GradientStyle_AXIAL:
     428           4 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     429           4 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     430           4 :             WriteGradientStop( 50, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     431           4 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     432           4 :             mpFS->endElementNS( XML_a, XML_gsLst );
     433             :             mpFS->singleElementNS( XML_a, XML_lin,
     434           4 :                     XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     435           4 :                     FSEND );
     436           4 :             break;
     437             : 
     438             :             /* I don't see how to apply transformation to gradients, so
     439             :              * elliptical will end as radial and square as
     440             :              * rectangular. also position offsets are not applied */
     441             :         case GradientStyle_RADIAL:
     442             :         case GradientStyle_ELLIPTICAL:
     443             :         case GradientStyle_RECT:
     444             :         case GradientStyle_SQUARE:
     445           0 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     446           0 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     447           0 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     448           0 :             mpFS->endElementNS( XML_a, XML_gsLst );
     449             :             mpFS->singleElementNS( XML_a, XML_path,
     450           0 :                     XML_path, ( rGradient.Style == awt::GradientStyle_RADIAL || rGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
     451           0 :                     FSEND );
     452           0 :             break;
     453             :     }
     454          12 : }
     455             : 
     456         712 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, bool bLineStart )
     457             : {
     458             :     ESCHER_LineEnd eLineEnd;
     459             :     sal_Int32 nArrowLength;
     460             :     sal_Int32 nArrowWidth;
     461             : 
     462         712 :     if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
     463             :         const char* len;
     464             :         const char* type;
     465             :         const char* width;
     466             : 
     467          24 :         switch( nArrowLength ) {
     468             :             case ESCHER_LineShortArrow:
     469           0 :                 len = "sm";
     470           0 :                 break;
     471             :             default:
     472             :             case ESCHER_LineMediumLenArrow:
     473          24 :                 len = "med";
     474          24 :                 break;
     475             :             case ESCHER_LineLongArrow:
     476           0 :                 len = "lg";
     477           0 :                 break;
     478             :         }
     479             : 
     480          24 :         switch( eLineEnd ) {
     481             :             default:
     482             :             case ESCHER_LineNoEnd:
     483           0 :                 type = "none";
     484           0 :                 break;
     485             :             case ESCHER_LineArrowEnd:
     486          20 :                 type = "triangle";
     487          20 :                 break;
     488             :             case ESCHER_LineArrowStealthEnd:
     489           1 :                 type = "stealth";
     490           1 :                 break;
     491             :             case ESCHER_LineArrowDiamondEnd:
     492           2 :                 type = "diamond";
     493           2 :                 break;
     494             :             case ESCHER_LineArrowOvalEnd:
     495           0 :                 type = "oval";
     496           0 :                 break;
     497             :             case ESCHER_LineArrowOpenEnd:
     498           1 :                 type = "arrow";
     499           1 :                 break;
     500             :         }
     501             : 
     502          24 :         switch( nArrowWidth ) {
     503             :             case ESCHER_LineNarrowArrow:
     504           0 :                 width = "sm";
     505           0 :                 break;
     506             :             default:
     507             :             case ESCHER_LineMediumWidthArrow:
     508          24 :                 width = "med";
     509          24 :                 break;
     510             :             case ESCHER_LineWideArrow:
     511           0 :                 width = "lg";
     512           0 :                 break;
     513             :         }
     514             : 
     515             :         mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
     516             :                                XML_len, len,
     517             :                                XML_type, type,
     518             :                                XML_w, width,
     519          24 :                                FSEND );
     520             :     }
     521         712 : }
     522             : 
     523         617 : void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
     524             : {
     525         617 :     drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
     526             : 
     527         617 :     GET( aLineStyle, LineStyle );
     528             : 
     529         617 :     sal_uInt32 nLineWidth = 0;
     530         617 :     sal_uInt32 nColor = 0;
     531         617 :     bool bColorSet = false;
     532         617 :     const char* cap = NULL;
     533         617 :     drawing::LineDash aLineDash;
     534         617 :     bool bDashSet = false;
     535         617 :     bool bNoFill = false;
     536             : 
     537             :     // get InteropGrabBag and search the relevant attributes
     538         617 :     OUString sColorFillScheme;
     539         617 :     sal_uInt32 nOriginalColor( 0 ), nStyleColor( 0 ), nStyleLineWidth( 0 );
     540        1234 :     Sequence< PropertyValue > aStyleProperties, aTransformations;
     541         617 :     drawing::LineStyle aStyleLineStyle( drawing::LineStyle_NONE );
     542         617 :     drawing::LineJoint aStyleLineJoint( drawing::LineJoint_NONE );
     543         617 :     if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     544             :     {
     545         264 :         Sequence< PropertyValue > aGrabBag;
     546         264 :         mAny >>= aGrabBag;
     547         804 :         for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
     548         540 :             if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClr" )
     549          25 :                 aGrabBag[i].Value >>= sColorFillScheme;
     550         515 :             else if( aGrabBag[i].Name == "OriginalLnSolidFillClr" )
     551         141 :                 aGrabBag[i].Value >>= nOriginalColor;
     552         374 :             else if( aGrabBag[i].Name == "StyleLnRef" )
     553          55 :                 aGrabBag[i].Value >>= aStyleProperties;
     554         319 :             else if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClrTransformations" )
     555          25 :                 aGrabBag[i].Value >>= aTransformations;
     556         264 :         if( aStyleProperties.hasElements() )
     557             :         {
     558         440 :             for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
     559         385 :                 if( aStyleProperties[i].Name == "Color" )
     560          55 :                     aStyleProperties[i].Value >>= nStyleColor;
     561         330 :                 else if( aStyleProperties[i].Name == "LineStyle" )
     562          55 :                     aStyleProperties[i].Value >>= aStyleLineStyle;
     563         275 :                 else if( aStyleProperties[i].Name == "LineJoint" )
     564          55 :                     aStyleProperties[i].Value >>= aStyleLineJoint;
     565         220 :                 else if( aStyleProperties[i].Name == "LineWidth" )
     566          55 :                     aStyleProperties[i].Value >>= nStyleLineWidth;
     567         264 :         }
     568             :     }
     569             : 
     570         617 :     GET( nLineWidth, LineWidth );
     571             : 
     572         617 :     switch( aLineStyle ) {
     573             :         case drawing::LineStyle_NONE:
     574         261 :             bNoFill = true;
     575         261 :             break;
     576             :         case drawing::LineStyle_DASH:
     577           5 :             if( GETA( LineDash ) ) {
     578           5 :                 aLineDash = *(drawing::LineDash*) mAny.getValue();
     579           5 :                 bDashSet = true;
     580           5 :                 if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
     581           2 :                     cap = "rnd";
     582             : 
     583             :                 DBG(fprintf(stderr, "dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
     584             :                             int( aLineDash.Dots ), int( aLineDash.Dashes ), int( aLineDash.DotLen ), int( aLineDash.DashLen ), int( aLineDash.Distance )));
     585             :             }
     586             :             /* fallthru intended */
     587             :         case drawing::LineStyle_SOLID:
     588             :         default:
     589         356 :             if ( GETA( LineColor ) ) {
     590         356 :                 nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
     591         356 :                 bColorSet = true;
     592             :             }
     593         356 :             break;
     594             :     }
     595             : 
     596             :     mpFS->startElementNS( XML_a, XML_ln,
     597             :                           XML_cap, cap,
     598         854 :                           XML_w, nLineWidth > 1 && nStyleLineWidth != nLineWidth ?
     599        1035 :                                   I64S( MM100toEMU( nLineWidth ) ) :NULL,
     600        1851 :                           FSEND );
     601             : 
     602         617 :     if( bColorSet )
     603             :     {
     604         356 :         if( nColor != nOriginalColor )
     605             :             // the user has set a different color for the line
     606         182 :             WriteSolidFill( nColor );
     607         174 :         else if( !sColorFillScheme.isEmpty() )
     608             :             // the line had a scheme color and the user didn't change it
     609          25 :             WriteSolidFill( sColorFillScheme, aTransformations );
     610         149 :         else if( aStyleProperties.hasElements() )
     611             :         {
     612          26 :             if( nColor != nStyleColor )
     613             :                 // the line style defines some color but it wasn't being used
     614           2 :                 WriteSolidFill( nColor );
     615             :             // in case the shape used the style color and the user didn't change it,
     616             :             // we must not write a <a: solidFill> tag.
     617             :         }
     618             :         else
     619         123 :             WriteSolidFill( nColor );
     620             :     }
     621             : 
     622         617 :     if( bDashSet && aStyleLineStyle != drawing::LineStyle_DASH ) {
     623             :         // line style is a dash and it was not set by the shape style
     624             :         // TODO: the XML_d and XML_sp values seem insane
     625           5 :         mpFS->startElementNS( XML_a, XML_custDash, FSEND );
     626             :         int i;
     627           5 :         for( i = 0; i < aLineDash.Dots; i ++ )
     628             :             mpFS->singleElementNS( XML_a, XML_ds,
     629             :                                    XML_d, aLineDash.DotLen ? writePercentage( aLineDash.DotLen*1000 ) : "100000%",
     630             :                                    XML_sp, writePercentage( aLineDash.Distance*1000 ),
     631           0 :                                    FSEND );
     632          10 :         for( i = 0; i < aLineDash.Dashes; i ++ )
     633             :             mpFS->singleElementNS( XML_a, XML_ds,
     634             :                                    XML_d, aLineDash.DashLen ? writePercentage( aLineDash.DashLen*1000 ) : "100000%",
     635             :                                    XML_sp, writePercentage( aLineDash.Distance*1000 ),
     636           5 :                                    FSEND );
     637           5 :         mpFS->endElementNS( XML_a, XML_custDash );
     638             :     }
     639             : 
     640         617 :     if( !bNoFill && nLineWidth > 1 && GETA( LineJoint ) ) {
     641             :         LineJoint eLineJoint;
     642             : 
     643         220 :         mAny >>= eLineJoint;
     644         220 :         if( aStyleLineJoint == LineJoint_NONE || aStyleLineJoint != eLineJoint )
     645             :             // style-defined line joint does not exist, or is different from the shape's joint
     646         216 :             switch( eLineJoint ) {
     647             :                 case LineJoint_NONE:
     648             :                 case LineJoint_MIDDLE:
     649             :                 case LineJoint_BEVEL:
     650           1 :                     mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
     651           1 :                     break;
     652             :                 default:
     653             :                 case LineJoint_MITER:
     654          21 :                     mpFS->singleElementNS( XML_a, XML_miter, FSEND );
     655          21 :                     break;
     656             :                 case LineJoint_ROUND:
     657         194 :                     mpFS->singleElementNS( XML_a, XML_round, FSEND );
     658         194 :                     break;
     659             :             }
     660             :     }
     661             : 
     662         617 :     if( !bNoFill )
     663             :     {
     664         356 :         WriteLineArrow( rXPropSet, true );
     665         356 :         WriteLineArrow( rXPropSet, false );
     666             :     }
     667             :     else
     668             :     {
     669         261 :         mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
     670             :     }
     671             : 
     672        1234 :     mpFS->endElementNS( XML_a, XML_ln );
     673         617 : }
     674             : 
     675          38 : OUString DrawingML::WriteImage( const OUString& rURL, bool bRelPathToMedia )
     676             : {
     677          38 :     OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
     678             : 
     679          38 :     const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
     680          38 :     sal_Int32 index = aURLBS.indexOf(aURLBegin);
     681             : 
     682          38 :     if ( index != -1 )
     683             :     {
     684             :         DBG(fprintf (stderr, "begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ) ));
     685          38 :         Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
     686             : 
     687          38 :         return WriteImage( aGraphic , bRelPathToMedia );
     688             :     } else {
     689             :         // add link to relations
     690             :     }
     691             : 
     692           0 :     return OUString();
     693             : }
     694             : 
     695         109 : const char* DrawingML::GetComponentDir()
     696             : {
     697         109 :     switch ( meDocumentType )
     698             :     {
     699          99 :         case DOCUMENT_DOCX: return "word";
     700           8 :         case DOCUMENT_PPTX: return "ppt";
     701           2 :         case DOCUMENT_XLSX: return "xl";
     702             :     }
     703             : 
     704           0 :     return "unknown";
     705             : }
     706             : 
     707         109 : const char* DrawingML::GetRelationCompPrefix()
     708             : {
     709         109 :     switch ( meDocumentType )
     710             :     {
     711          99 :         case DOCUMENT_DOCX: return "";
     712             :         case DOCUMENT_PPTX:
     713          10 :         case DOCUMENT_XLSX: return "../";
     714             :     }
     715             : 
     716           0 :     return "unknown";
     717             : }
     718             : 
     719         110 : OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
     720             : {
     721         110 :     GfxLink aLink = rGraphic.GetLink ();
     722         220 :     OUString sMediaType;
     723         110 :     const char* pExtension = "";
     724         110 :     OUString sRelId;
     725             : 
     726         220 :     SvMemoryStream aStream;
     727         110 :     const void* aData = aLink.GetData();
     728         110 :     sal_Size nDataSize = aLink.GetDataSize();
     729             : 
     730         110 :     switch ( aLink.GetType() ) {
     731             :         case GFX_LINK_TYPE_NATIVE_GIF:
     732          11 :             sMediaType = "image/gif";
     733          11 :             pExtension = ".gif";
     734          11 :             break;
     735             : 
     736             :         // #i15508# added BMP type for better exports
     737             :         // export not yet active, so adding for reference (not checked)
     738             :         case GFX_LINK_TYPE_NATIVE_BMP:
     739           2 :             sMediaType = "image/bmp";
     740           2 :             pExtension = ".bmp";
     741           2 :             break;
     742             : 
     743             :         case GFX_LINK_TYPE_NATIVE_JPG:
     744          22 :             sMediaType = "image/jpeg";
     745          22 :             pExtension = ".jpeg";
     746          22 :             break;
     747             :         case GFX_LINK_TYPE_NATIVE_PNG:
     748          32 :             sMediaType = "image/png";
     749          32 :             pExtension = ".png";
     750          32 :             break;
     751             :         case GFX_LINK_TYPE_NATIVE_TIF:
     752           0 :             sMediaType = "image/tiff";
     753           0 :             pExtension = ".tiff";
     754           0 :             break;
     755             :         case GFX_LINK_TYPE_NATIVE_WMF:
     756          26 :             sMediaType = "image/x-wmf";
     757          26 :             pExtension = ".wmf";
     758          26 :             break;
     759             :         case GFX_LINK_TYPE_NATIVE_MET:
     760           0 :             sMediaType = "image/x-met";
     761           0 :             pExtension = ".met";
     762           0 :             break;
     763             :         case GFX_LINK_TYPE_NATIVE_PCT:
     764           0 :             sMediaType = "image/x-pict";
     765           0 :             pExtension = ".pct";
     766           0 :             break;
     767             :         case GFX_LINK_TYPE_NATIVE_MOV:
     768           0 :             sMediaType = "application/movie";
     769           0 :             pExtension = ".MOV";
     770           0 :             break;
     771             :         default: {
     772          17 :             GraphicType aType = rGraphic.GetType();
     773          17 :             if ( aType == GRAPHIC_BITMAP ) {
     774          11 :                 GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
     775          11 :                 sMediaType = "image/png";
     776          11 :                 pExtension = ".png";
     777           6 :             } else if ( aType == GRAPHIC_GDIMETAFILE ) {
     778           5 :                 GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
     779           5 :                 sMediaType = "image/x-emf";
     780           5 :                 pExtension = ".emf";
     781             :             } else {
     782             :                 OSL_TRACE( "unhandled graphic type" );
     783             :                 /*Earlier, even in case of unhandled graphic types we were
     784             :                   proceeding to write the image, which would eventually
     785             :                   write an empty image with a zero size, and return a valid
     786             :                   relationID, which is incorrect.
     787             :                   */
     788           1 :                 return sRelId;
     789             :             }
     790             : 
     791          16 :             aData = aStream.GetData();
     792          16 :             nDataSize = aStream.GetEndOfData();
     793          16 :             break;
     794             :             }
     795             :     }
     796             : 
     797             :     Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
     798         218 :                                                                       .appendAscii( GetComponentDir() )
     799         109 :                                                                       .appendAscii( "/media/image" )
     800         218 :                                                                       .append( (sal_Int32) mnImageCounter )
     801         109 :                                                                       .appendAscii( pExtension )
     802             :                                                                       .makeStringAndClear(),
     803         109 :                                                                       sMediaType );
     804         109 :     xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
     805         109 :     xOutStream->closeOutput();
     806             : 
     807         218 :     OString sRelPathToMedia = "media/image";
     808         109 :     if ( bRelPathToMedia )
     809           1 :         sRelPathToMedia = "../" + sRelPathToMedia;
     810         218 :     sRelId = mpFB->addRelation( mpFS->getOutputStream(),
     811             :                                 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
     812             :                                 OUStringBuffer()
     813         218 :                                 .appendAscii( GetRelationCompPrefix() )
     814         218 :                                 .appendAscii( sRelPathToMedia.getStr() )
     815         218 :                                 .append( (sal_Int32) mnImageCounter ++ )
     816         109 :                                 .appendAscii( pExtension )
     817         109 :                                 .makeStringAndClear() );
     818             : 
     819         328 :     return sRelId;
     820             : }
     821             : 
     822          38 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
     823             : {
     824          38 :     OUString sRelId = pGraphic ? WriteImage( *pGraphic, bRelPathToMedia ) : WriteImage( rURL, bRelPathToMedia );
     825          38 :     sal_Int16 nBright = 0;
     826          38 :     sal_Int32 nContrast = 0;
     827             : 
     828          38 :     GET( nBright, AdjustLuminance );
     829          38 :     GET( nContrast, AdjustContrast );
     830             : 
     831             :     mpFS->startElementNS( XML_a, XML_blip,
     832             :             FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
     833          38 :                   FSEND );
     834          38 :     if( nBright || nContrast )
     835             :         mpFS->singleElementNS( XML_a, XML_lum,
     836           0 :                    XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
     837           0 :                    XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
     838          38 :                    FSEND );
     839             : 
     840          38 :     mpFS->endElementNS( XML_a, XML_blip );
     841             : 
     842          38 :     return sRelId;
     843             : }
     844             : 
     845           4 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet, const OUString& rURL )
     846             : {
     847           4 :     BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
     848           4 :     if (GetProperty( rXPropSet, "FillBitmapMode" ) )
     849           4 :         mAny >>= eBitmapMode;
     850             : 
     851             :     DBG(fprintf(stderr, "fill bitmap mode: %d\n", eBitmapMode));
     852             : 
     853           4 :     switch (eBitmapMode) {
     854             :     case BitmapMode_REPEAT:
     855           0 :         mpFS->singleElementNS( XML_a, XML_tile, FSEND );
     856           0 :         break;
     857             :     case BitmapMode_STRETCH:
     858           4 :         WriteStretch( rXPropSet, rURL );
     859           4 :         break;
     860             :     default:
     861             :         ;
     862             :     }
     863           4 : }
     864             : 
     865          85 : void DrawingML::WriteBlipOrNormalFill( Reference< XPropertySet > xPropSet, const OUString& rURLPropName )
     866             : {
     867             :     // check for blip and otherwise fall back to normal fill
     868             :     // we always store normal fill properties but OOXML
     869             :     // uses a choice between our fill props and BlipFill
     870          85 :     if (GetProperty ( xPropSet, rURLPropName ))
     871           0 :         WriteBlipFill( xPropSet, rURLPropName );
     872             :     else
     873          85 :         WriteFill(xPropSet);
     874          85 : }
     875             : 
     876         154 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName )
     877             : {
     878         154 :     WriteBlipFill( rXPropSet, sURLPropName, XML_a );
     879         154 : }
     880             : 
     881         154 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName, sal_Int32 nXmlNamespace )
     882             : {
     883         154 :     if ( GetProperty( rXPropSet, sURLPropName ) ) {
     884           3 :         OUString aURL;
     885           3 :         mAny >>= aURL;
     886           3 :         bool bWriteMode = false;
     887           3 :         if( sURLPropName == "FillBitmapURL" || sURLPropName == "BackGraphicURL")
     888           3 :             bWriteMode = true;
     889           3 :         WriteBlipFill( rXPropSet, aURL, nXmlNamespace, bWriteMode );
     890             :     }
     891         154 : }
     892             : 
     893           4 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sBitmapURL, sal_Int32 nXmlNamespace, bool bWriteMode, bool bRelPathToMedia )
     894             : {
     895           4 :     if ( !sBitmapURL.isEmpty() ) {
     896             :         DBG(fprintf (stderr, "URL: %s\n", OUStringToOString( sBitmapURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
     897             : 
     898           4 :         mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
     899             : 
     900           4 :         WriteBlip( rXPropSet, sBitmapURL, bRelPathToMedia );
     901             : 
     902           4 :         if( bWriteMode )
     903           4 :             WriteBlipMode( rXPropSet, sBitmapURL );
     904           0 :         else if( GetProperty( rXPropSet, "FillBitmapStretch" ) ) {
     905           0 :                 bool bStretch = false;
     906           0 :                 mAny >>= bStretch;
     907             : 
     908           0 :                 if( bStretch )
     909           0 :                     WriteStretch( rXPropSet, sBitmapURL );
     910             :         }
     911           4 :         mpFS->endElementNS( nXmlNamespace, XML_blipFill );
     912             :     }
     913           4 : }
     914             : 
     915          14 : void DrawingML::WritePattFill( Reference< XPropertySet > rXPropSet )
     916             : {
     917          14 :     if ( GetProperty( rXPropSet, "FillHatch" ) )
     918             :     {
     919          14 :         drawing::Hatch aHatch;
     920          14 :         mAny >>= aHatch;
     921             : 
     922          14 :         mpFS->startElementNS( XML_a , XML_pattFill, XML_prst, GetHatchPattern(aHatch), FSEND );
     923             : 
     924          14 :         mpFS->startElementNS( XML_a , XML_fgClr, FSEND );
     925          14 :         WriteColor(aHatch.Color);
     926          14 :         mpFS->endElementNS( XML_a , XML_fgClr );
     927             : 
     928             :         // In Writer hatching has no background so use white as a default value.
     929          14 :         mpFS->startElementNS( XML_a , XML_bgClr, FSEND );
     930          14 :         WriteColor(COL_WHITE);
     931          14 :         mpFS->endElementNS( XML_a , XML_bgClr );
     932             : 
     933          14 :         mpFS->endElementNS( XML_a , XML_pattFill );
     934             :     }
     935          14 : }
     936             : 
     937          34 : void DrawingML::WriteSrcRect( Reference< XPropertySet > rXPropSet, const OUString& rURL )
     938             : {
     939          34 :     Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
     940             : 
     941          34 :     if ( GetProperty( rXPropSet, "GraphicCrop" ) )
     942             :     {
     943          34 :         ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
     944          34 :         mAny >>= aGraphicCropStruct;
     945             : 
     946          34 :         if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
     947             :         {
     948             :             mpFS->singleElementNS( XML_a, XML_srcRect,
     949           0 :                           XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
     950           0 :                           XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
     951           0 :                           XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
     952           0 :                           XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
     953           0 :                           FSEND );
     954             :         }
     955             :     }
     956          34 : }
     957             : 
     958           4 : void DrawingML::WriteStretch( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, const OUString& rURL )
     959             : {
     960           4 :     mpFS->startElementNS( XML_a, XML_stretch, FSEND );
     961             : 
     962           4 :     bool bCrop = false;
     963           4 :     if ( GetProperty( rXPropSet, "GraphicCrop" ) )
     964             :     {
     965           2 :         ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
     966           2 :         mAny >>= aGraphicCropStruct;
     967             : 
     968           2 :         if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
     969             :         {
     970           1 :             Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
     971             :             mpFS->singleElementNS( XML_a, XML_fillRect,
     972           1 :                           XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
     973           1 :                           XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
     974           1 :                           XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
     975           1 :                           XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
     976           4 :                           FSEND );
     977           1 :             bCrop = true;
     978             :         }
     979             :     }
     980             : 
     981           4 :     if( !bCrop )
     982             :     {
     983           3 :         mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
     984             :     }
     985             : 
     986           4 :     mpFS->endElementNS( XML_a, XML_stretch );
     987           4 : }
     988             : 
     989         527 : void DrawingML::WriteTransformation( const Rectangle& rRect,
     990             :         sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation )
     991             : {
     992             :     mpFS->startElementNS( nXmlNamespace, XML_xfrm,
     993             :                           XML_flipH, bFlipH ? "1" : NULL,
     994             :                           XML_flipV, bFlipV ? "1" : NULL,
     995        1118 :                           XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
     996        1054 :                           FSEND );
     997             : 
     998         527 :     sal_Int32 nLeft = rRect.Left();
     999         527 :     sal_Int32 nTop = rRect.Top();
    1000         527 :     if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
    1001             :     {
    1002         160 :         nLeft = 0;
    1003         160 :         nTop = 0;
    1004             :     }
    1005             : 
    1006         527 :     mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( nLeft ) ), XML_y, IS( MM100toEMU( nTop ) ), FSEND );
    1007         527 :     mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
    1008             : 
    1009         527 :     mpFS->endElementNS( nXmlNamespace, XML_xfrm );
    1010         527 : }
    1011             : 
    1012         486 : void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation  )
    1013             : {
    1014             :     DBG(fprintf(stderr,  "write shape transformation\n" ));
    1015             : 
    1016         486 :     sal_Int32 nRotation=0;
    1017         486 :     awt::Point aPos = rXShape->getPosition();
    1018         486 :     awt::Size aSize = rXShape->getSize();
    1019             : 
    1020         486 :     if (m_xParent.is())
    1021             :     {
    1022         152 :         awt::Point aParentPos = m_xParent->getPosition();
    1023         152 :         aPos.X -= aParentPos.X;
    1024         152 :         aPos.Y -= aParentPos.Y;
    1025             :     }
    1026             : 
    1027         486 :     if ( aSize.Width < 0 )
    1028          24 :         aSize.Width = 1000;
    1029         486 :     if ( aSize.Height < 0 )
    1030          11 :         aSize.Height = 1000;
    1031         486 :     if (!bSuppressRotation)
    1032             :     {
    1033         482 :         SdrObject* pShape = (SdrObject*) GetSdrObjectFromXShape( rXShape );
    1034         482 :         nRotation=pShape->GetRotateAngle();
    1035         482 :         if (nRotation != 0 && nRotation != 18000)
    1036             :         {
    1037           6 :             int faccos=bFlipV ? -1 : 1;
    1038           6 :             int facsin=bFlipH ? -1 : 1;
    1039           6 :             aPos.X-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Width/2-facsin*sin(nRotation*F_PI18000)*aSize.Height/2;
    1040           6 :             aPos.Y-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Height/2+facsin*sin(nRotation*F_PI18000)*aSize.Width/2;
    1041             :         }
    1042             :     }
    1043         486 :     if (!bSuppressRotation)
    1044             :     {
    1045         482 :         if (bFlipV) {nRotation=(nRotation+18000)%36000;}
    1046             :     }
    1047         486 :     WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, PPTX_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
    1048         486 : }
    1049             : 
    1050          80 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, bool bIsField )
    1051             : {
    1052          80 :     Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
    1053         160 :     Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
    1054         160 :     OUString usLanguage;
    1055             :     PropertyState eState;
    1056          80 :     sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
    1057          80 :     bool bComplex = ( nScriptType == ScriptType::COMPLEX );
    1058          80 :     const char* bold = NULL;
    1059          80 :     const char* italic = NULL;
    1060          80 :     const char* underline = NULL;
    1061          80 :     sal_Int32 nSize = 1800;
    1062          80 :     sal_Int32 nCharEscapement = 0;
    1063             : 
    1064          80 :     if( GETA( CharHeight ) )
    1065          80 :         nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
    1066             : 
    1067          80 :     if ( ( bComplex && GETA( CharWeightComplex ) ) || GETA( CharWeight ) )
    1068          80 :         if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
    1069          23 :             bold = "1";
    1070             : 
    1071          80 :     if ( ( bComplex && GETA( CharPostureComplex ) ) || GETA( CharPosture ) )
    1072          80 :         switch ( *((awt::FontSlant*) mAny.getValue()) )
    1073             :         {
    1074             :             case awt::FontSlant_OBLIQUE :
    1075             :             case awt::FontSlant_ITALIC :
    1076           0 :                 italic = "1";
    1077           0 :                 break;
    1078             :             default:
    1079          80 :                 break;
    1080             :         }
    1081             : 
    1082          80 :     if ( GETAD( CharUnderline ) )
    1083           6 :         switch ( *((sal_Int16*) mAny.getValue()) )
    1084             :         {
    1085             :             case awt::FontUnderline::SINGLE :
    1086           0 :                 underline = "sng";
    1087           0 :                 break;
    1088             :             case awt::FontUnderline::DOUBLE :
    1089           0 :                 underline = "dbl";
    1090           0 :                 break;
    1091             :             case awt::FontUnderline::DOTTED :
    1092           0 :                 underline = "dotted";
    1093           0 :                 break;
    1094             :             case awt::FontUnderline::DASH :
    1095           0 :                 underline = "dash";
    1096           0 :                 break;
    1097             :             case awt::FontUnderline::LONGDASH :
    1098           0 :                 underline = "dashLong";
    1099           0 :                 break;
    1100             :             case awt::FontUnderline::DASHDOT :
    1101           0 :                 underline = "dotDash";
    1102           0 :                 break;
    1103             :             case awt::FontUnderline::DASHDOTDOT :
    1104           0 :                 underline = "dotDotDash";
    1105           0 :                 break;
    1106             :             case awt::FontUnderline::WAVE :
    1107           0 :                 underline = "wavy";
    1108           0 :                 break;
    1109             :             case awt::FontUnderline::DOUBLEWAVE :
    1110           0 :                 underline = "wavyDbl";
    1111           0 :                 break;
    1112             :             case awt::FontUnderline::BOLD :
    1113           0 :                 underline = "heavy";
    1114           0 :                 break;
    1115             :             case awt::FontUnderline::BOLDDOTTED :
    1116           0 :                 underline = "dottedHeavy";
    1117           0 :                 break;
    1118             :             case awt::FontUnderline::BOLDDASH :
    1119           0 :                 underline = "dashHeavy";
    1120           0 :                 break;
    1121             :             case awt::FontUnderline::BOLDLONGDASH :
    1122           0 :                 underline = "dashLongHeavy";
    1123           0 :                 break;
    1124             :             case awt::FontUnderline::BOLDDASHDOT :
    1125           0 :                 underline = "dotDashHeavy";
    1126           0 :                 break;
    1127             :             case awt::FontUnderline::BOLDDASHDOTDOT :
    1128           0 :                 underline = "dotDotDashHeavy";
    1129           0 :                 break;
    1130             :             case awt::FontUnderline::BOLDWAVE :
    1131           0 :                 underline = "wavyHeavy";
    1132           0 :                 break;
    1133             :         }
    1134             : 
    1135          80 :     if( GETA( CharLocale ) ) {
    1136          80 :         com::sun::star::lang::Locale aLocale;
    1137          80 :         mAny >>= aLocale;
    1138         160 :         LanguageTag aLanguageTag( aLocale);
    1139          80 :         if (!aLanguageTag.isSystemLocale())
    1140         138 :             usLanguage = aLanguageTag.getBcp47();
    1141             :     }
    1142             : 
    1143          80 :     if( GETAD( CharEscapement ) )
    1144          28 :         mAny >>= nCharEscapement;
    1145             : 
    1146          80 :     if( nCharEscapement && GETAD( CharEscapementHeight ) ) {
    1147           1 :         sal_uInt32 nCharEscapementHeight = 0;
    1148           1 :         mAny >>= nCharEscapementHeight;
    1149           1 :         nSize = (nSize * nCharEscapementHeight) / 100;
    1150             :         // MSO uses default ~58% size
    1151           1 :         nSize = (nSize / 0.58);
    1152             :     }
    1153             : 
    1154             :     mpFS->startElementNS( XML_a, XML_rPr,
    1155             :                           XML_b, bold,
    1156             :                           XML_i, italic,
    1157         218 :                           XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
    1158         147 :                           XML_sz, nSize == 1800 ? NULL : IS( nSize ),
    1159             :                           XML_u, underline,
    1160         162 :                           XML_baseline, nCharEscapement == 0 ? NULL : IS( nCharEscapement*1000 ),
    1161         365 :                           FSEND );
    1162             : 
    1163             :     // mso doesn't like text color to be placed after typeface
    1164          80 :     if( GETAD( CharColor ) ) {
    1165          28 :         sal_uInt32 color = *((sal_uInt32*) mAny.getValue());
    1166             :         DBG(fprintf(stderr, "run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO )));
    1167             : 
    1168          28 :         if( color == COL_AUTO ) { // nCharColor depends to the background color
    1169           0 :             bool bIsDark = false;
    1170           0 :             GET( bIsDark, IsBackgroundDark );
    1171           0 :             color = bIsDark ? 0xffffff : 0x000000;
    1172             :         }
    1173          28 :         color &= 0xffffff;
    1174             : 
    1175             :         // TODO: special handle embossed/engraved
    1176             : 
    1177          28 :         WriteSolidFill( color );
    1178             :     }
    1179             : 
    1180          80 :     if( GETA( CharFontName ) ) {
    1181          80 :         const char* pitch = NULL;
    1182          80 :         const char* charset = NULL;
    1183          80 :         OUString usTypeface;
    1184             : 
    1185          80 :         mAny >>= usTypeface;
    1186         160 :         OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
    1187             : 
    1188             :         mpFS->singleElementNS( XML_a, XML_latin,
    1189          80 :                                XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
    1190             :                                XML_pitchFamily, pitch,
    1191             :                                XML_charset, charset,
    1192         160 :                                FSEND );
    1193             :     }
    1194             : 
    1195          80 :     if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
    1196           1 :         const char* pitch = NULL;
    1197           1 :         const char* charset = NULL;
    1198           1 :         OUString usTypeface;
    1199             : 
    1200           1 :         mAny >>= usTypeface;
    1201           2 :         OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
    1202             : 
    1203             :         mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
    1204           1 :                                XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
    1205             :                                XML_pitchFamily, pitch,
    1206             :                                XML_charset, charset,
    1207           2 :                                FSEND );
    1208             :     }
    1209             : 
    1210          80 :     if( bIsField ) {
    1211          12 :         Reference< XTextField > rXTextField;
    1212          12 :         GET( rXTextField, TextField );
    1213          12 :         if( rXTextField.is() )
    1214          12 :             rRun.set( rXTextField, UNO_QUERY );
    1215             :     }
    1216             : 
    1217             :     // field properties starts here
    1218          80 :     if( GETA( URL ) ) {
    1219           0 :     OUString sURL;
    1220             : 
    1221           0 :     mAny >>= sURL;
    1222           0 :     if( !sURL.isEmpty() ) {
    1223             :         OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
    1224             :                               "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
    1225           0 :                               sURL, true );
    1226             : 
    1227             :         mpFS->singleElementNS( XML_a, XML_hlinkClick,
    1228             :                    FSNS( XML_r,XML_id ), USS( sRelId ),
    1229           0 :                    FSEND );
    1230           0 :     }
    1231             :     }
    1232             : 
    1233         160 :     mpFS->endElementNS( XML_a, XML_rPr );
    1234          80 : }
    1235             : 
    1236          58 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, bool& bIsField )
    1237             : {
    1238          58 :     const char* sType = NULL;
    1239          58 :     Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
    1240         116 :     OUString aFieldType;
    1241             : 
    1242          58 :     if( GETA( TextPortionType ) ) {
    1243          58 :         aFieldType = OUString( *(OUString*)mAny.getValue() );
    1244             :         DBG(fprintf (stderr, "field type: %s\n", USS(aFieldType) ));
    1245             :     }
    1246             : 
    1247          58 :     if( aFieldType == "TextField" ) {
    1248          12 :         Reference< XTextField > rXTextField;
    1249          12 :         GET( rXTextField, TextField );
    1250          12 :         if( rXTextField.is() ) {
    1251          12 :         bIsField = true;
    1252          12 :             rXPropSet.set( rXTextField, UNO_QUERY );
    1253          12 :             if( rXPropSet.is() ) {
    1254          12 :                 OUString aFieldKind( rXTextField->getPresentation( true ) );
    1255             :                 DBG(fprintf (stderr, "field kind: %s\n", USS(aFieldKind) ));
    1256          12 :                 if( aFieldKind == "Page" ) {
    1257           4 :                     return "slidenum";
    1258           8 :                 }
    1259             :         // else if( aFieldKind == "URL" ) {
    1260             :         // do not return here
    1261             :         // and make URL field text run with hyperlink property later
    1262             :         // }
    1263             :             }
    1264           8 :         }
    1265             :     }
    1266             : 
    1267         112 :     return sType;
    1268             : }
    1269             : 
    1270           4 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
    1271             : {
    1272           4 :     Sequence< sal_uInt8 > aSeq( 16 );
    1273             :     static const char cDigits[17] = "0123456789ABCDEF";
    1274           4 :     rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, true );
    1275             :     int i;
    1276             : 
    1277           4 :     rBuffer.append( '{' );
    1278          20 :     for( i = 0; i < 4; i++ ) {
    1279          16 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1280          16 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1281             :     }
    1282           4 :     rBuffer.append( '-' );
    1283          12 :     for( ; i < 6; i++ ) {
    1284           8 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1285           8 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1286             :     }
    1287           4 :     rBuffer.append( '-' );
    1288          12 :     for( ; i < 8; i++ ) {
    1289           8 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1290           8 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1291             :     }
    1292           4 :     rBuffer.append( '-' );
    1293          12 :     for( ; i < 10; i++ ) {
    1294           8 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1295           8 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1296             :     }
    1297           4 :     rBuffer.append( '-' );
    1298          28 :     for( ; i < 16; i++ ) {
    1299          24 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1300          24 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1301             :     }
    1302           4 :     rBuffer.append( '}' );
    1303           4 : }
    1304             : 
    1305         189 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
    1306             : {
    1307             :     const char* sFieldType;
    1308         189 :     bool bIsField = false;
    1309         189 :     OUString sText = rRun->getString();
    1310             : 
    1311         189 :     if( sText.isEmpty()) {
    1312         131 :         Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
    1313             : 
    1314             :         try {
    1315         262 :         if( !xPropSet.is() || !( xPropSet->getPropertyValue( "PlaceholderText" ) >>= sText ) )
    1316           0 :             return;
    1317           0 :         if( sText.isEmpty() )
    1318           0 :             return;
    1319             :         }
    1320         262 :         catch (const Exception &) {
    1321         131 :             return;
    1322           0 :         }
    1323             :     }
    1324             : 
    1325          58 :     sFieldType = GetFieldType( rRun, bIsField );
    1326          58 :     if( ( sFieldType != NULL ) ) {
    1327           4 :         OStringBuffer sUUID(39);
    1328             : 
    1329           4 :         GetUUID( sUUID );
    1330             :         mpFS->startElementNS( XML_a, XML_fld,
    1331             :                               XML_id, sUUID.getStr(),
    1332             :                               XML_type, sFieldType,
    1333           4 :                               FSEND );
    1334             :     } else
    1335          54 :         mpFS->startElementNS( XML_a, XML_r, FSEND );
    1336             : 
    1337         116 :     Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
    1338          58 :     WriteRunProperties( xPropSet, bIsField );
    1339             : 
    1340          58 :     mpFS->startElementNS( XML_a, XML_t, FSEND );
    1341          58 :     mpFS->writeEscaped( sText );
    1342          58 :     mpFS->endElementNS( XML_a, XML_t );
    1343             : 
    1344          58 :     if( sFieldType )
    1345           4 :         mpFS->endElementNS( XML_a, XML_fld );
    1346             :     else
    1347         112 :         mpFS->endElementNS( XML_a, XML_r );
    1348             : }
    1349             : 
    1350             : #define AUTONUM(x) \
    1351             :                         if( bPBoth ) \
    1352             :                             pAutoNumType = #x "ParenBoth"; \
    1353             :                         else if( bPBehind ) \
    1354             :                             pAutoNumType = #x "ParenR"; \
    1355             :                         else if( bSDot ) \
    1356             :                             pAutoNumType = #x "Period";
    1357             : 
    1358          32 : inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
    1359             : {
    1360          32 :     const char* pAutoNumType = NULL;
    1361             : 
    1362          32 :     switch( (SvxExtNumType)nNumberingType )
    1363             :         {
    1364             :         case SVX_NUM_CHARS_UPPER_LETTER_N :
    1365             :         case SVX_NUM_CHARS_UPPER_LETTER :
    1366           0 :             AUTONUM( alphaUc );
    1367           0 :             break;
    1368             :         case SVX_NUM_CHARS_LOWER_LETTER_N :
    1369             :         case SVX_NUM_CHARS_LOWER_LETTER :
    1370           0 :             AUTONUM( alphaLc );
    1371           0 :             break;
    1372             :         case SVX_NUM_ROMAN_UPPER :
    1373           0 :             AUTONUM( romanUc );
    1374           0 :             break;
    1375             :         case SVX_NUM_ROMAN_LOWER :
    1376           0 :             AUTONUM( romanLc );
    1377           0 :             break;
    1378             :         case SVX_NUM_ARABIC :
    1379           0 :             AUTONUM( arabic )
    1380             :             else
    1381           0 :                 pAutoNumType = "arabicPlain";
    1382           0 :                         break;
    1383             :         default:
    1384          32 :             break;
    1385             :         }
    1386             : 
    1387          32 :     return pAutoNumType;
    1388             : }
    1389             : 
    1390          76 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
    1391             : {
    1392          76 :     if( nLevel >= 0 && GETA( NumberingRules ) )
    1393             :     {
    1394          32 :         Reference< XIndexAccess > rXIndexAccess;
    1395             : 
    1396          32 :         if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
    1397             :         {
    1398             :             DBG(fprintf (stderr, "numbering rules\n"));
    1399             : 
    1400          32 :             Sequence< PropertyValue > aPropertySequence;
    1401          32 :             rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
    1402             : 
    1403          32 :             const PropertyValue* pPropValue = aPropertySequence.getArray();
    1404             : 
    1405          32 :             sal_Int32 nPropertyCount = aPropertySequence.getLength();
    1406             : 
    1407          32 :             if ( nPropertyCount ) {
    1408             : 
    1409          32 :                 sal_Int16 nNumberingType = -1;
    1410          32 :                 bool bSDot = false;
    1411          32 :                 bool bPBehind = false;
    1412          32 :                 bool bPBoth = false;
    1413          32 :                 sal_Unicode aBulletChar = 0x2022; // a bullet
    1414          32 :                 awt::FontDescriptor aFontDesc;
    1415          32 :                 bool bHasFontDesc = false;
    1416          64 :                 OUString aGraphicURL;
    1417          32 :                 sal_Int16 nBulletRelSize = 0;
    1418             : 
    1419         448 :                 for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
    1420         416 :                     const void* pValue = pPropValue[ i ].Value.getValue();
    1421         416 :                     if ( pValue ) {
    1422         416 :                         OUString aPropName( pPropValue[ i ].Name );
    1423             :                         DBG(fprintf (stderr, "pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
    1424         416 :                         if ( aPropName == "NumberingType" )
    1425          32 :                             nNumberingType = *( (sal_Int16*)pValue );
    1426         384 :                         else if ( aPropName == "Prefix" ) {
    1427          32 :                             if( *(OUString*)pValue == ")")
    1428           0 :                                 bPBoth = true;
    1429         352 :                         } else if ( aPropName == "Suffix" ) {
    1430          32 :                             if( *(OUString*)pValue == ".")
    1431           0 :                                 bSDot = true;
    1432          32 :                             else if( *(OUString*)pValue == ")")
    1433           0 :                                 bPBehind = true;
    1434         320 :                         } else if ( aPropName == "BulletChar" )
    1435             :                         {
    1436          32 :                             aBulletChar = OUString ( *( (OUString*)pValue ) )[ 0 ];
    1437             :                             //printf ("bullet char: %d\n", aBulletChar.getStr());
    1438             :                         }
    1439         288 :                         else if ( aPropName == "BulletFont" )
    1440             :                         {
    1441          32 :                             aFontDesc = *( (awt::FontDescriptor*)pValue );
    1442          32 :                             bHasFontDesc = true;
    1443             : 
    1444             :                             // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
    1445             :                             // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
    1446             :                             // Because there might exist a lot of damaged documemts I added this two lines
    1447             :                             // which fixes the bullet problem for the export.
    1448          32 :                             if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
    1449          25 :                                 aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
    1450             : 
    1451         256 :                         } else if ( aPropName == "BulletRelSize" ) {
    1452          32 :                             nBulletRelSize = *( (sal_Int16*)pValue );
    1453         224 :                         } else if ( aPropName == "GraphicURL" ) {
    1454           0 :                             aGraphicURL = ( *(OUString*)pValue );
    1455             :                             DBG(fprintf (stderr, "graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
    1456         224 :                         } else if ( aPropName == "GraphicSize" )
    1457             :                         {
    1458          32 :                             if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) )
    1459             :                             {
    1460             :                                 // don't cast awt::Size to Size as on 64-bits they are not the same.
    1461          32 :                                 ::com::sun::star::awt::Size aSize;
    1462          32 :                                 pPropValue[ i ].Value >>= aSize;
    1463             :                                 //aBuGraSize.nA = aSize.Width;
    1464             :                                 //aBuGraSize.nB = aSize.Height;
    1465             :                                 DBG(fprintf(stderr, "graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height )));
    1466             :                             }
    1467         416 :                         }
    1468             :                     }
    1469             :                 }
    1470             : 
    1471          32 :                 const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
    1472             : 
    1473          32 :                 if( nLevel >= 0 ) {
    1474          32 :                     if( !aGraphicURL.isEmpty() ) {
    1475           0 :                         OUString sRelId = WriteImage( aGraphicURL );
    1476             : 
    1477           0 :                         mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
    1478           0 :                         mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
    1479           0 :                         mpFS->endElementNS( XML_a, XML_buBlip );
    1480             :                     } else {
    1481          32 :                         if( nBulletRelSize && nBulletRelSize != 100 )
    1482             :                             mpFS->singleElementNS( XML_a, XML_buSzPct,
    1483          32 :                                                    XML_val, IS( std::max( (sal_Int32)25000, std::min( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
    1484          32 :                         if( bHasFontDesc )
    1485             :                             mpFS->singleElementNS( XML_a, XML_buFont,
    1486             :                                                    XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
    1487          32 :                                                    XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
    1488          32 :                                                    FSEND );
    1489             : 
    1490          32 :                         if( pAutoNumType )
    1491           0 :                             mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
    1492             :                         else {
    1493          32 :                             aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
    1494          32 :                             mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
    1495             :                         }
    1496             :                     }
    1497          32 :                 }
    1498          32 :             }
    1499          32 :         }
    1500             :     }
    1501          76 : }
    1502             : 
    1503          76 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
    1504             : {
    1505          76 :     const char* sAlignment = NULL;
    1506             : 
    1507          76 :     switch( nAlignment ) {
    1508             :         case style::ParagraphAdjust_CENTER:
    1509          37 :             sAlignment = "ctr";
    1510          37 :             break;
    1511             :         case style::ParagraphAdjust_RIGHT:
    1512           5 :             sAlignment = "r";
    1513           5 :             break;
    1514             :         case style::ParagraphAdjust_BLOCK:
    1515           0 :             sAlignment = "just";
    1516           0 :             break;
    1517             :         default:
    1518             :             ;
    1519             :     }
    1520             : 
    1521          76 :     return sAlignment;
    1522             : }
    1523             : 
    1524           4 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
    1525             : {
    1526           4 :     if( rSpacing.Mode == LineSpacingMode::PROP )
    1527             :         mpFS->singleElementNS( XML_a, XML_spcPct,
    1528             :                                XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
    1529           4 :                                FSEND );
    1530             :     else
    1531             :         mpFS->singleElementNS( XML_a, XML_spcPts,
    1532             :                                XML_val, I32S( rSpacing.Height ),
    1533           0 :                                FSEND );
    1534           4 : }
    1535             : 
    1536         185 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
    1537             : {
    1538         185 :     Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
    1539         370 :     Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
    1540             :     PropertyState eState;
    1541             : 
    1542         185 :     if( !rXPropSet.is() || !rXPropState.is() )
    1543         185 :         return;
    1544             : 
    1545         185 :     sal_Int16 nLevel = -1;
    1546         185 :     GET( nLevel, NumberingLevel );
    1547             : 
    1548         185 :     sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
    1549         185 :     GET( nAlignment, ParaAdjust );
    1550             : 
    1551         185 :     bool bHasLinespacing = false;
    1552         185 :     LineSpacing aLineSpacing;
    1553         185 :     if( GETAD( ParaLineSpacing ) )
    1554           4 :         bHasLinespacing = ( mAny >>= aLineSpacing );
    1555             : 
    1556         185 :     if( nLevel != -1
    1557         153 :         || nAlignment != style::ParagraphAdjust_LEFT
    1558         111 :         || bHasLinespacing ) {
    1559             :         mpFS->startElementNS( XML_a, XML_pPr,
    1560         206 :                               XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
    1561             :                               XML_marL, NULL,
    1562             :                               XML_algn, GetAlignment( nAlignment ),
    1563         228 :                               FSEND );
    1564             : 
    1565          76 :         if( bHasLinespacing ) {
    1566           4 :             mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
    1567           4 :             WriteLinespacing( aLineSpacing );
    1568           4 :             mpFS->endElementNS( XML_a, XML_lnSpc );
    1569             :         }
    1570             : 
    1571          76 :         WriteParagraphNumbering( rXPropSet, nLevel );
    1572             : 
    1573          76 :         mpFS->endElementNS( XML_a, XML_pPr );
    1574         185 :     }
    1575             : }
    1576             : 
    1577         185 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
    1578             : {
    1579         185 :     Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
    1580         185 :     if( !access.is() )
    1581           0 :         return;
    1582             : 
    1583         370 :     Reference< XEnumeration > enumeration( access->createEnumeration() );
    1584         185 :     if( !enumeration.is() )
    1585           0 :         return;
    1586             : 
    1587         185 :     mpFS->startElementNS( XML_a, XML_p, FSEND );
    1588             : 
    1589         185 :     bool bPropertiesWritten = false;
    1590         559 :     while( enumeration->hasMoreElements() ) {
    1591         189 :         Reference< XTextRange > run;
    1592         378 :         Any any ( enumeration->nextElement() );
    1593             : 
    1594         189 :         if (any >>= run) {
    1595         189 :             if( !bPropertiesWritten ) {
    1596         185 :                 WriteParagraphProperties( rParagraph );
    1597         185 :                 bPropertiesWritten = true;
    1598             :             }
    1599         189 :             WriteRun( run );
    1600             :         }
    1601         189 :     }
    1602         185 :     mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
    1603             : 
    1604         370 :     mpFS->endElementNS( XML_a, XML_p );
    1605             : }
    1606             : 
    1607         352 : void DrawingML::WriteText( Reference< XInterface > rXIface, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
    1608             : {
    1609         352 :     Reference< XText > xXText( rXIface, UNO_QUERY );
    1610         510 :     Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
    1611             : 
    1612         352 :     if( !xXText.is() )
    1613           0 :         return;
    1614             : 
    1615             : #define DEFLRINS 254
    1616             : #define DEFTBINS 127
    1617             :     sal_Int32 nLeft, nRight, nTop, nBottom;
    1618         352 :     nLeft = nRight = DEFLRINS;
    1619         352 :     nTop = nBottom = DEFTBINS;
    1620             : 
    1621             :     // top inset looks a bit different compared to ppt export
    1622             :     // check if something related doesn't work as expected
    1623         352 :     GET( nLeft, TextLeftDistance );
    1624         352 :     GET( nRight, TextRightDistance );
    1625         352 :     GET( nTop, TextUpperDistance );
    1626         352 :     GET( nBottom, TextLowerDistance );
    1627             : 
    1628         352 :     TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
    1629         352 :     const char* sVerticalAlignment = NULL;
    1630         352 :     GET( eVerticalAlignment, TextVerticalAdjust );
    1631         352 :     if( eVerticalAlignment != TextVerticalAdjust_TOP )
    1632          72 :         sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
    1633             : 
    1634         352 :     const char* sWritingMode = NULL;
    1635         352 :     bool bVertical = false;
    1636         352 :     if( GETA( TextWritingMode ) ) {
    1637             :         WritingMode eMode;
    1638             : 
    1639         352 :         if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) {
    1640           0 :             sWritingMode = "vert";
    1641           0 :             bVertical = true;
    1642             :         }
    1643             :     }
    1644             : 
    1645         352 :     if ( GETA( CustomShapeGeometry ) )
    1646             :     {
    1647          34 :         Sequence< PropertyValue > aProps;
    1648          34 :         if ( mAny >>= aProps )
    1649             :         {
    1650         252 :             for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
    1651             :             {
    1652         242 :                 sal_Int32 nTextRotateAngle = 0;
    1653         242 :                 if ( aProps[ i ].Name.equals( "TextPreRotateAngle" ) && ( aProps[ i ].Value >>= nTextRotateAngle ) )
    1654             :                 {
    1655          24 :                     if ( nTextRotateAngle == -90 )
    1656             :                     {
    1657           0 :                         sWritingMode = "vert";
    1658           0 :                         bVertical = true;
    1659             :                     }
    1660          24 :                     break;
    1661             :                 }
    1662             :             }
    1663          34 :         }
    1664             :     }
    1665             : 
    1666         352 :     TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
    1667         352 :     bool bHorizontalCenter = false;
    1668         352 :     GET( eHorizontalAlignment, TextHorizontalAdjust );
    1669         352 :     if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
    1670           2 :         bHorizontalCenter = true;
    1671         350 :     else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
    1672           0 :         sVerticalAlignment = "b";
    1673             : 
    1674         352 :     bool bHasWrap = false;
    1675         352 :     bool bWrap = false;
    1676             :     // Only custom shapes obey the TextWordWrap option, normal text always wraps.
    1677         352 :     if( dynamic_cast<SvxCustomShape*>(rXIface.get()) && GETA( TextWordWrap ) ) {
    1678           2 :         mAny >>= bWrap;
    1679           2 :         bHasWrap = true;
    1680             :     }
    1681             : 
    1682         352 :     if (bBodyPr)
    1683             :     {
    1684         255 :         const char* pWrap = bHasWrap && !bWrap ? "none" : NULL;
    1685         255 :         if (GetDocumentType() == DOCUMENT_DOCX)
    1686             :         {
    1687             :             // In case of DOCX, if we want to have the same effect as
    1688             :             // TextShape's automatic word wrapping, then we need to set
    1689             :             // wrapping to square.
    1690          97 :             uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY);
    1691          97 :             if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
    1692          80 :                 pWrap = "square";
    1693             :         }
    1694             :         mpFS->singleElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
    1695             :                                XML_wrap, pWrap,
    1696         733 :                                XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
    1697         732 :                                XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
    1698         732 :                                XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
    1699         954 :                                XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
    1700             :                                XML_anchor, sVerticalAlignment,
    1701             :                                XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
    1702             :                                XML_vert, sWritingMode,
    1703        2197 :                                FSEND );
    1704             :     }
    1705             : 
    1706         510 :     Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
    1707         352 :     if( !access.is() || !bText )
    1708          97 :         return;
    1709             : 
    1710         413 :     Reference< XEnumeration > enumeration( access->createEnumeration() );
    1711         255 :     if( !enumeration.is() )
    1712           0 :         return;
    1713             : 
    1714         255 :     SdrObject* pSdrObject = GetSdrObjectFromXShape(uno::Reference<drawing::XShape>(rXIface, uno::UNO_QUERY_THROW));
    1715         255 :     const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, pSdrObject);
    1716         255 :     if (pTxtObj && mpTextExport)
    1717             :     {
    1718          97 :         const OutlinerParaObject* pParaObj = 0;
    1719          97 :         bool bOwnParaObj = false;
    1720             : 
    1721             :         /*
    1722             :         #i13885#
    1723             :         When the object is actively being edited, that text is not set into
    1724             :         the objects normal text object, but lives in a separate object.
    1725             :         */
    1726          97 :         if (pTxtObj->IsTextEditActive())
    1727             :         {
    1728           0 :             pParaObj = pTxtObj->GetEditOutlinerParaObject();
    1729           0 :             bOwnParaObj = true;
    1730             :         }
    1731             :         else
    1732          97 :             pParaObj = pTxtObj->GetOutlinerParaObject();
    1733             : 
    1734          97 :         if (pParaObj)
    1735             :         {
    1736             :             // this is reached only in case some text is attached to the shape
    1737          97 :             mpTextExport->WriteOutliner(*pParaObj);
    1738          97 :             if (bOwnParaObj)
    1739           0 :                 delete pParaObj;
    1740             :         }
    1741          97 :         return;
    1742             :     }
    1743             : 
    1744         501 :     while( enumeration->hasMoreElements() ) {
    1745         185 :         Reference< XTextContent > paragraph;
    1746         370 :         Any any ( enumeration->nextElement() );
    1747             : 
    1748         185 :         if( any >>= paragraph)
    1749         185 :             WriteParagraph( paragraph );
    1750         343 :     }
    1751             : 
    1752             : }
    1753             : 
    1754         296 : void DrawingML::WritePresetShape( const char* pShape )
    1755             : {
    1756             :     mpFS->startElementNS( XML_a, XML_prstGeom,
    1757             :                           XML_prst, pShape,
    1758         296 :                           FSEND );
    1759         296 :     mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
    1760         296 :     mpFS->endElementNS(  XML_a, XML_prstGeom );
    1761         296 : }
    1762             : 
    1763         139 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
    1764             : {
    1765         139 :     static std::map< OString, std::vector<OString> > aAdjMap = ooxDrawingMLGetAdjNames();
    1766             :     // If there are predefined adj names for this shape type, look them up now.
    1767         139 :     std::vector<OString> aAdjustments;
    1768         139 :     if (aAdjMap.find(OString(pShape)) != aAdjMap.end())
    1769          26 :         aAdjustments = aAdjMap[OString(pShape)];
    1770             : 
    1771             :     mpFS->startElementNS( XML_a, XML_prstGeom,
    1772             :                           XML_prst, pShape,
    1773         139 :                           FSEND );
    1774         139 :     mpFS->startElementNS( XML_a, XML_avLst, FSEND );
    1775             : 
    1776         278 :     Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
    1777         417 :     if ( ( rProp.Value >>= aAdjustmentSeq )
    1778         139 :          && eShapeType != mso_sptActionButtonForwardNext  // we have adjustments values for these type of shape, but MSO doesn't like them
    1779         139 :          && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
    1780         695 :          && OString(pShape) != "rect" //some shape types are commented out in pCustomShapeTypeTranslationTable[] & are being defaulted to rect & rect does not have adjustment values/name.
    1781             :         ) {
    1782             :         DBG(fprintf(stderr, "adj seq len: %d\n", int( aAdjustmentSeq.getLength() )));
    1783          78 :         if ( bPredefinedHandlesUsed )
    1784          60 :             EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
    1785             : 
    1786          78 :         sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
    1787             :         //aAdjustments will give info about the number of adj values for a particular geomtery.For example for hexagon aAdjustments.size() will be 2 and for circular arrow it will be 5 as per ooxDrawingMLGetAdjNames.
    1788          78 :         if(aAdjustments.size() == static_cast<sal_uInt32>(nLength))// In case there is a mismatch do not write the XML_gd tag.
    1789             :         {
    1790         121 :             for( sal_Int32 i=0; i < nLength; i++ )
    1791          44 :                 if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
    1792             :                 {
    1793             :                     // If the document model doesn't have an adjustment name (e.g. shape was created from VML), then take it from the predefined list.
    1794          44 :                     OString aAdjName;
    1795          44 :                     if (aAdjustmentSeq[i].Name.isEmpty() && static_cast<sal_uInt32>(i) < aAdjustments.size())
    1796          13 :                         aAdjName = aAdjustments[i];
    1797             : 
    1798             :                     mpFS->singleElementNS( XML_a, XML_gd,
    1799         119 :                                        XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : aAdjName.getStr(),
    1800          88 :                                        XML_fmla, OString("val " + OString::number( nValue )).getStr(),
    1801         207 :                                        FSEND );
    1802             :             }
    1803             :         }
    1804             :     }
    1805             : 
    1806         139 :     mpFS->endElementNS( XML_a, XML_avLst );
    1807         278 :     mpFS->endElementNS(  XML_a, XML_prstGeom );
    1808         139 : }
    1809             : 
    1810          65 : void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
    1811             : {
    1812          65 :     if( rPolyPolygon.Count() < 1 )
    1813          65 :         return;
    1814             : 
    1815          65 :     mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
    1816          65 :     mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
    1817          65 :     mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
    1818          65 :     mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
    1819             :     mpFS->singleElementNS( XML_a, XML_rect,
    1820             :                            XML_l, "0",
    1821             :                            XML_t, "0",
    1822             :                            XML_r, "r",
    1823             :                            XML_b, "b",
    1824          65 :                            FSEND );
    1825             : 
    1826          65 :     mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
    1827             : 
    1828         168 :     for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ ) {
    1829             : 
    1830         103 :         const Polygon& rPoly = rPolyPolygon[ i ];
    1831         103 :         Rectangle aRect( rPoly.GetBoundRect() );
    1832             : 
    1833             :         mpFS->startElementNS( XML_a, XML_path,
    1834         103 :                               XML_w, I64S( aRect.GetWidth() ),
    1835         103 :                               XML_h, I64S( aRect.GetHeight() ),
    1836         206 :                               FSEND );
    1837             : 
    1838         103 :         if( rPoly.GetSize() > 0 )
    1839             :         {
    1840         103 :             mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
    1841             : 
    1842             :             mpFS->singleElementNS( XML_a, XML_pt,
    1843         206 :                                    XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
    1844         206 :                                    XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
    1845         412 :                                    FSEND );
    1846             : 
    1847         103 :             mpFS->endElementNS( XML_a, XML_moveTo );
    1848             :         }
    1849             : 
    1850        1016 :         for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
    1851             :         {
    1852         913 :             enum PolyFlags flags = rPoly.GetFlags(j);
    1853         913 :             if( flags == POLY_CONTROL )
    1854             :             {
    1855             :                 // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
    1856         203 :                 if( j+2 < rPoly.GetSize() && rPoly.GetFlags(j+1) == POLY_CONTROL && rPoly.GetFlags(j+2) != POLY_CONTROL )
    1857             :                 {
    1858             : 
    1859         203 :                     mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
    1860         812 :                     for( sal_uInt8 k = 0; k <= 2; ++k )
    1861             :                     {
    1862             :                         mpFS->singleElementNS( XML_a, XML_pt,
    1863        1218 :                                                XML_x, I64S( rPoly[j+k].X() - aRect.Left() ),
    1864        1218 :                                                XML_y, I64S( rPoly[j+k].Y() - aRect.Top() ),
    1865        2436 :                                                FSEND );
    1866             : 
    1867             :                     }
    1868         203 :                     mpFS->endElementNS( XML_a, XML_cubicBezTo );
    1869         203 :                     j += 2;
    1870             :                 }
    1871             :             }
    1872         710 :             else if( flags == POLY_NORMAL )
    1873             :             {
    1874         710 :                 mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
    1875             :                 mpFS->singleElementNS( XML_a, XML_pt,
    1876        1420 :                                        XML_x, I64S( rPoly[j].X() - aRect.Left() ),
    1877        1420 :                                        XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
    1878        2840 :                                        FSEND );
    1879         710 :                 mpFS->endElementNS( XML_a, XML_lnTo );
    1880             :             }
    1881             :         }
    1882             : 
    1883         103 :         mpFS->endElementNS( XML_a, XML_path );
    1884             :     }
    1885             : 
    1886          65 :     mpFS->endElementNS( XML_a, XML_pathLst );
    1887             : 
    1888          65 :     mpFS->endElementNS(  XML_a, XML_custGeom );
    1889             : }
    1890             : 
    1891           0 : void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
    1892             : {
    1893           0 :     if( nStartID != -1 )
    1894             :         mpFS->singleElementNS( XML_a, XML_stCxn,
    1895             :                                XML_id, I32S( nStartID ),
    1896           0 :                                XML_idx, I64S( rConnectorEntry.GetConnectorRule( true ) ),
    1897           0 :                                FSEND );
    1898           0 :     if( nEndID != -1 )
    1899             :         mpFS->singleElementNS( XML_a, XML_endCxn,
    1900             :                                XML_id, I32S( nEndID ),
    1901           0 :                                XML_idx, I64S( rConnectorEntry.GetConnectorRule( false ) ),
    1902           0 :                                FSEND );
    1903           0 : }
    1904             : 
    1905          32 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
    1906             : {
    1907          32 :     if ( IsStarSymbol(rFontDesc.Name) )
    1908             :     {
    1909          25 :         rtl_TextEncoding eCharSet = rFontDesc.CharSet;
    1910          25 :         cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
    1911          25 :         rFontDesc.CharSet = eCharSet;
    1912             :     }
    1913             : 
    1914          32 :     return cBulletId;
    1915             : }
    1916             : 
    1917           6 : sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
    1918             :     const OUString& sFullStream,
    1919             :     const OUString& sRelativeStream,
    1920             :     const Reference< XOutputStream >& xParentRelation,
    1921             :     const char* sContentType,
    1922             :     const char* sRelationshipType,
    1923             :     OUString* pRelationshipId )
    1924             : {
    1925           6 :     OUString sRelationshipId;
    1926           6 :     if (xParentRelation.is())
    1927           6 :         sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
    1928             :     else
    1929           0 :         sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
    1930             : 
    1931           6 :     if( pRelationshipId )
    1932           6 :         *pRelationshipId = sRelationshipId;
    1933             : 
    1934           6 :     sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
    1935             : 
    1936           6 :     return p;
    1937             : }
    1938             : 
    1939         578 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
    1940             : {
    1941         578 :     if ( !GetProperty( xPropSet, "FillStyle" ) )
    1942          82 :         return;
    1943         496 :     FillStyle aFillStyle( FillStyle_NONE );
    1944         496 :     xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
    1945             : 
    1946         496 :     if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ) )
    1947             :     {
    1948             :         // map full transparent background to no fill
    1949         261 :         sal_Int16 nVal = 0;
    1950         261 :         xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
    1951         261 :         if ( nVal == 100 )
    1952           0 :             aFillStyle = FillStyle_NONE;
    1953             :     }
    1954             : 
    1955         496 :     switch( aFillStyle )
    1956             :     {
    1957             :     case FillStyle_SOLID :
    1958         262 :         WriteSolidFill( xPropSet );
    1959         262 :         break;
    1960             :     case FillStyle_GRADIENT :
    1961           4 :         WriteGradientFill( xPropSet );
    1962           4 :         break;
    1963             :     case FillStyle_BITMAP :
    1964           2 :         WriteBlipFill( xPropSet, "FillBitmapURL" );
    1965           2 :         break;
    1966             :     case FillStyle_HATCH :
    1967          14 :         WritePattFill( xPropSet );
    1968          14 :         break;
    1969             :     case FillStyle_NONE:
    1970         214 :         mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
    1971         214 :         break;
    1972             :     default:
    1973             :         ;
    1974             :     }
    1975             : 
    1976         496 :     return;
    1977             : }
    1978             : 
    1979         489 : void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, Sequence< PropertyValue > aProperties )
    1980             : {
    1981         489 :     if( aProperties.getLength() > 0 )
    1982             :     {
    1983         141 :         OUString sSchemeClr;
    1984         141 :         sal_uInt32 nIdx = 0;
    1985         282 :         Sequence< PropertyValue > aTransformations;
    1986         815 :         for( sal_Int32 i=0; i < aProperties.getLength(); ++i)
    1987         674 :             if( aProperties[i].Name == "SchemeClr" )
    1988         141 :                 aProperties[i].Value >>= sSchemeClr;
    1989         533 :             else if( aProperties[i].Name == "Idx" )
    1990         141 :                 aProperties[i].Value >>= nIdx;
    1991         392 :             else if( aProperties[i].Name == "Transformations" )
    1992         141 :                 aProperties[i].Value >>= aTransformations;
    1993         141 :         mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
    1994         141 :         WriteColor( sSchemeClr, aTransformations );
    1995         282 :         mpFS->endElementNS( XML_a, nTokenId );
    1996             :     }
    1997             :     else
    1998             :         // write mock <a:*Ref> tag
    1999         348 :         mpFS->singleElementNS( XML_a, nTokenId, XML_idx, I32S( 0 ), FSEND );
    2000         489 : }
    2001             : 
    2002         163 : void DrawingML::WriteShapeStyle( Reference< XPropertySet > xPropSet )
    2003             : {
    2004             :     // check existence of the grab bag
    2005         163 :     if ( !GetProperty( xPropSet, "InteropGrabBag" ) )
    2006         163 :         return;
    2007             : 
    2008             :     // extract the relevant properties from the grab bag
    2009         163 :     Sequence< PropertyValue > aGrabBag;
    2010         326 :     Sequence< PropertyValue > aFillRefProperties, aLnRefProperties, aEffectRefProperties;
    2011         163 :     mAny >>= aGrabBag;
    2012         699 :     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
    2013         536 :         if( aGrabBag[i].Name == "StyleFillRef" )
    2014          31 :             aGrabBag[i].Value >>= aFillRefProperties;
    2015         505 :         else if( aGrabBag[i].Name == "StyleLnRef" )
    2016          55 :             aGrabBag[i].Value >>= aLnRefProperties;
    2017         450 :         else if( aGrabBag[i].Name == "StyleEffectRef" )
    2018          55 :             aGrabBag[i].Value >>= aEffectRefProperties;
    2019             : 
    2020         163 :     WriteStyleProperties( XML_lnRef, aLnRefProperties );
    2021         163 :     WriteStyleProperties( XML_fillRef, aFillRefProperties );
    2022         163 :     WriteStyleProperties( XML_effectRef, aEffectRefProperties );
    2023             : 
    2024             :     // write mock <a:fontRef>
    2025         326 :     mpFS->singleElementNS( XML_a, XML_fontRef, XML_idx, "minor", FSEND );
    2026             : }
    2027             : 
    2028             : }
    2029         177 : }
    2030             : 
    2031             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10