LCOV - code coverage report
Current view: top level - oox/source/export - drawingml.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1580 1738 90.9 %
Date: 2015-06-13 12:38:46 Functions: 61 62 98.4 %
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 <config_folders.h>
      21             : #include "rtl/bootstrap.hxx"
      22             : #include "oox/core/xmlfilterbase.hxx"
      23             : #include "oox/export/drawingml.hxx"
      24             : #include "oox/export/utils.hxx"
      25             : #include <oox/drawingml/color.hxx>
      26             : #include <oox/drawingml/fillproperties.hxx>
      27             : #include <oox/token/tokens.hxx>
      28             : #include <oox/drawingml/drawingmltypes.hxx>
      29             : 
      30             : #include <cstdio>
      31             : #include <com/sun/star/awt/CharSet.hpp>
      32             : #include <com/sun/star/awt/FontDescriptor.hpp>
      33             : #include <com/sun/star/awt/FontSlant.hpp>
      34             : #include <com/sun/star/awt/FontStrikeout.hpp>
      35             : #include <com/sun/star/awt/FontWeight.hpp>
      36             : #include <com/sun/star/awt/FontUnderline.hpp>
      37             : #include <com/sun/star/awt/Gradient.hpp>
      38             : #include <com/sun/star/beans/XPropertySet.hpp>
      39             : #include <com/sun/star/beans/XPropertyState.hpp>
      40             : #include <com/sun/star/beans/Property.hpp>
      41             : #include <com/sun/star/beans/XPropertySetInfo.hpp>
      42             : #include <com/sun/star/container/XEnumerationAccess.hpp>
      43             : #include <com/sun/star/container/XIndexAccess.hpp>
      44             : #include <com/sun/star/drawing/BitmapMode.hpp>
      45             : #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
      46             : #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
      47             : #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
      48             : #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
      49             : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
      50             : #include <com/sun/star/drawing/LineDash.hpp>
      51             : #include <com/sun/star/drawing/LineJoint.hpp>
      52             : #include <com/sun/star/drawing/LineStyle.hpp>
      53             : #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
      54             : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
      55             : #include <com/sun/star/drawing/XShape.hpp>
      56             : #include <com/sun/star/drawing/FillStyle.hpp>
      57             : #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
      58             : #include <com/sun/star/i18n/ScriptType.hpp>
      59             : #include <com/sun/star/io/XOutputStream.hpp>
      60             : #include <com/sun/star/style/LineSpacing.hpp>
      61             : #include <com/sun/star/style/LineSpacingMode.hpp>
      62             : #include <com/sun/star/style/ParagraphAdjust.hpp>
      63             : #include <com/sun/star/text/WritingMode.hpp>
      64             : #include <com/sun/star/text/WritingMode2.hpp>
      65             : #include <com/sun/star/text/GraphicCrop.hpp>
      66             : #include <com/sun/star/text/XText.hpp>
      67             : #include <com/sun/star/text/XTextContent.hpp>
      68             : #include <com/sun/star/text/XTextField.hpp>
      69             : #include <com/sun/star/text/XTextRange.hpp>
      70             : #include <com/sun/star/style/CaseMap.hpp>
      71             : #include <tools/stream.hxx>
      72             : #include <unotools/fontdefs.hxx>
      73             : #include <vcl/cvtgrf.hxx>
      74             : #include <vcl/graph.hxx>
      75             : #include <vcl/settings.hxx>
      76             : #include <svtools/grfmgr.hxx>
      77             : #include <rtl/strbuf.hxx>
      78             : #include <sfx2/app.hxx>
      79             : #include <svl/languageoptions.hxx>
      80             : #include <filter/msfilter/escherex.hxx>
      81             : #include <filter/msfilter/util.hxx>
      82             : #include <editeng/outlobj.hxx>
      83             : #include <editeng/svxenum.hxx>
      84             : #include <svx/unoapi.hxx>
      85             : #include <svx/svdoashp.hxx>
      86             : #include <svx/unoshape.hxx>
      87             : 
      88             : using namespace ::css;
      89             : using namespace ::css::beans;
      90             : using namespace ::css::drawing;
      91             : using namespace ::css::i18n;
      92             : using namespace ::css::style;
      93             : using namespace ::css::text;
      94             : using namespace ::css::uno;
      95             : using namespace ::css::container;
      96             : using namespace ::css::text;
      97             : 
      98             : using ::css::geometry::IntegerRectangle2D;
      99             : using ::css::io::XOutputStream;
     100             : using ::sax_fastparser::FSHelperPtr;
     101             : using ::sax_fastparser::FastSerializerHelper;
     102             : 
     103             : namespace oox {
     104             : namespace drawingml {
     105             : 
     106             : #define GETA(propName) \
     107             :     GetProperty( rXPropSet, OUString( #propName ) )
     108             : 
     109             : #define GETAD(propName) \
     110             :     ( GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
     111             : 
     112             : #define GET(variable, propName) \
     113             :     if ( GETA(propName) ) \
     114             :         mAny >>= variable;
     115             : 
     116             : // not thread safe
     117             : int DrawingML::mnImageCounter = 1;
     118             : int DrawingML::mnWdpImageCounter = 1;
     119          82 : std::map<OUString, OUString> DrawingML::maWdpCache;
     120             : 
     121         508 : void DrawingML::ResetCounters()
     122             : {
     123         508 :     mnImageCounter = 1;
     124         508 :     mnWdpImageCounter = 1;
     125         508 :     maWdpCache.clear();
     126         508 : }
     127             : 
     128       37257 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropertySet, const OUString& aName )
     129             : {
     130             :     try
     131             :     {
     132       37257 :         mAny = rXPropertySet->getPropertyValue(aName);
     133       33243 :         if (mAny.hasValue())
     134       31245 :             return true;
     135             :     }
     136        4014 :     catch( const Exception& )
     137             :     {
     138             :         /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
     139             :     }
     140        6012 :     return false;
     141             : }
     142             : 
     143        3790 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropertySet, Reference< XPropertyState > rXPropertyState, const OUString& aName, PropertyState& eState )
     144             : {
     145             :     try
     146             :     {
     147        3790 :         mAny = rXPropertySet->getPropertyValue(aName);
     148        3790 :         if (mAny.hasValue())
     149             :         {
     150        3778 :             eState = rXPropertyState->getPropertyState(aName);
     151        3778 :             return true;
     152             :         }
     153             :     }
     154           0 :     catch( const Exception& )
     155             :     {
     156             :         /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
     157             :     }
     158          12 :     return false;
     159             : }
     160             : 
     161        1815 : void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
     162             : {
     163             :     // Transparency is a separate element.
     164        1815 :     OString sColor = OString::number(  nColor & 0x00FFFFFF, 16 );
     165        1815 :     if( sColor.getLength() < 6 )
     166             :     {
     167         489 :         OStringBuffer sBuf( "0" );
     168         489 :         int remains = 5 - sColor.getLength();
     169             : 
     170        2766 :         while( remains > 0 )
     171             :         {
     172        1788 :             sBuf.append( "0" );
     173        1788 :             remains--;
     174             :         }
     175             : 
     176         489 :         sBuf.append( sColor );
     177             : 
     178         489 :         sColor = sBuf.getStr();
     179             :     }
     180        1815 :     if( nAlpha < MAX_PERCENT )
     181             :     {
     182          37 :         mpFS->startElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
     183          37 :         mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
     184          37 :         mpFS->endElementNS( XML_a, XML_srgbClr );
     185             : 
     186             :     }
     187             :     else
     188             :     {
     189        1778 :         mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
     190        1815 :     }
     191        1815 : }
     192             : 
     193         531 : void DrawingML::WriteColor( const OUString& sColorSchemeName, const Sequence< PropertyValue >& aTransformations )
     194             : {
     195             :     // prevent writing a tag with empty val attribute
     196         531 :     if( sColorSchemeName.isEmpty() )
     197         623 :         return;
     198             : 
     199         439 :     if( aTransformations.hasElements() )
     200             :     {
     201             :         mpFS->startElementNS( XML_a, XML_schemeClr,
     202             :                               XML_val, USS( sColorSchemeName ),
     203         130 :                               FSEND );
     204         130 :         WriteColorTransformations( aTransformations );
     205         130 :         mpFS->endElementNS( XML_a, XML_schemeClr );
     206             :     }
     207             :     else
     208             :     {
     209             :         mpFS->singleElementNS( XML_a, XML_schemeClr,
     210             :                               XML_val, USS( sColorSchemeName ),
     211         309 :                               FSEND );
     212             :     }
     213             : }
     214             : 
     215         130 : void DrawingML::WriteColorTransformations( const Sequence< PropertyValue >& aTransformations )
     216             : {
     217         338 :     for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
     218             :     {
     219         208 :         sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
     220         208 :         if( nToken != XML_TOKEN_INVALID && aTransformations[i].Value.hasValue() )
     221             :         {
     222         206 :             sal_Int32 nValue = aTransformations[i].Value.get<sal_Int32>();
     223         206 :             mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
     224             :         }
     225             :     }
     226         130 : }
     227             : 
     228        1562 : void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
     229             : {
     230        1562 :     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
     231        1562 :     WriteColor( nColor, nAlpha );
     232        1562 :     mpFS->endElementNS( XML_a, XML_solidFill );
     233        1562 : }
     234             : 
     235          84 : void DrawingML::WriteSolidFill( const OUString& sSchemeName, const Sequence< PropertyValue >& aTransformations )
     236             : {
     237          84 :     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
     238          84 :     WriteColor( sSchemeName, aTransformations );
     239          84 :     mpFS->endElementNS( XML_a, XML_solidFill );
     240          84 : }
     241             : 
     242         611 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
     243             : {
     244             :     // get fill color
     245         611 :     if ( !GetProperty( rXPropSet, "FillColor" ) )
     246         612 :         return;
     247         610 :     sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
     248             : 
     249             :     // get InteropGrabBag and search the relevant attributes
     250         610 :     OUString sColorFillScheme;
     251         610 :     sal_uInt32 nOriginalColor = 0;
     252        1220 :     Sequence< PropertyValue > aStyleProperties, aTransformations;
     253         610 :     if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     254             :     {
     255         319 :         Sequence< PropertyValue > aGrabBag;
     256         319 :         mAny >>= aGrabBag;
     257        1430 :         for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
     258             :         {
     259        1111 :             if( aGrabBag[i].Name == "SpPrSolidFillSchemeClr" )
     260          51 :                 aGrabBag[i].Value >>= sColorFillScheme;
     261        1060 :             else if( aGrabBag[i].Name == "OriginalSolidFillClr" )
     262         192 :                 aGrabBag[i].Value >>= nOriginalColor;
     263         868 :             else if( aGrabBag[i].Name == "StyleFillRef" )
     264          69 :                 aGrabBag[i].Value >>= aStyleProperties;
     265         799 :             else if( aGrabBag[i].Name == "SpPrSolidFillSchemeClrTransformations" )
     266          51 :                 aGrabBag[i].Value >>= aTransformations;
     267         319 :         }
     268             :     }
     269             : 
     270         610 :     sal_Int32 nAlpha = MAX_PERCENT;
     271         610 :     if( GetProperty( rXPropSet, "FillTransparence" ) )
     272             :     {
     273         610 :         sal_Int32 nTransparency = 0;
     274         610 :         mAny >>= nTransparency;
     275             :         // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
     276         610 :         nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
     277             :     }
     278             : 
     279             :     // write XML
     280         610 :     if ( nFillColor != nOriginalColor )
     281             :     {
     282             :         // the user has set a different color for the shape
     283         398 :         WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     284             :     }
     285         212 :     else if ( !sColorFillScheme.isEmpty() )
     286             :     {
     287             :         // the shape had a scheme color and the user didn't change it
     288          48 :         WriteSolidFill( sColorFillScheme, aTransformations );
     289             :     }
     290         164 :     else if ( aStyleProperties.hasElements() )
     291             :     {
     292          56 :         sal_uInt32 nThemeColor = 0;
     293         168 :         for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
     294             :         {
     295         168 :             if( aStyleProperties[i].Name == "Color" )
     296             :             {
     297          56 :                 aStyleProperties[i].Value >>= nThemeColor;
     298          56 :                 break;
     299             :             }
     300             :         }
     301          56 :         if ( nFillColor != nThemeColor )
     302             :             // the shape contains a theme but it wasn't being used
     303           3 :             WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     304             :         // in case the shape used the style color and the user didn't change it,
     305             :         // we must not write a <a: solidFill> tag.
     306             :     }
     307             :     else
     308             :     {
     309             :         // the shape had a custom color and the user didn't change it
     310         108 :         WriteSolidFill( nFillColor & 0xffffff, nAlpha );
     311         610 :     }
     312             : }
     313             : 
     314          15 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
     315             : {
     316             :     mpFS->startElementNS( XML_a, XML_gs,
     317             :                           XML_pos, I32S( nStop * 1000 ),
     318          15 :                           FSEND );
     319          15 :     WriteColor( nColor );
     320          15 :     mpFS->endElementNS( XML_a, XML_gs );
     321          15 : }
     322             : 
     323          15 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
     324             : {
     325          15 :     return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
     326          15 :         | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
     327          15 :         | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
     328             : }
     329             : 
     330          60 : bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
     331             : {
     332         116 :     return aGradient1.Style == aGradient2.Style &&
     333         110 :             aGradient1.StartColor == aGradient2.StartColor &&
     334         108 :             aGradient1.EndColor == aGradient2.EndColor &&
     335         108 :             aGradient1.Angle == aGradient2.Angle &&
     336         108 :             aGradient1.Border == aGradient2.Border &&
     337         108 :             aGradient1.XOffset == aGradient2.XOffset &&
     338         108 :             aGradient1.YOffset == aGradient2.YOffset &&
     339         108 :             aGradient1.StartIntensity == aGradient2.StartIntensity &&
     340         168 :             aGradient1.EndIntensity == aGradient2.EndIntensity &&
     341         114 :             aGradient1.StepCount == aGradient2.StepCount;
     342             : }
     343             : 
     344          60 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
     345             : {
     346          60 :     awt::Gradient aGradient;
     347          60 :     if( GETA( FillGradient ) )
     348             :     {
     349          60 :         aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
     350             : 
     351             :         // get InteropGrabBag and search the relevant attributes
     352          60 :         awt::Gradient aOriginalGradient;
     353          60 :         Sequence< PropertyValue > aGradientStops;
     354          60 :         if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
     355             :         {
     356          56 :             Sequence< PropertyValue > aGrabBag;
     357          56 :             mAny >>= aGrabBag;
     358         383 :             for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
     359         327 :                 if( aGrabBag[i].Name == "GradFillDefinition" )
     360          52 :                     aGrabBag[i].Value >>= aGradientStops;
     361         275 :                 else if( aGrabBag[i].Name == "OriginalGradFill" )
     362         110 :                     aGrabBag[i].Value >>= aOriginalGradient;
     363             :         }
     364             : 
     365             :         // check if an ooxml gradient had been imported and if the user has modified it
     366          60 :         if( EqualGradients( aOriginalGradient, aGradient ) )
     367             :         {
     368             :             // If we have no gradient stops that means original gradient were defined by a theme.
     369          54 :             if( aGradientStops.hasElements() )
     370             :             {
     371          52 :                 mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
     372          52 :                 WriteGrabBagGradientFill(aGradientStops, aGradient);
     373          52 :                 mpFS->endElementNS( XML_a, XML_gradFill );
     374             :             }
     375             :         }
     376             :         else
     377             :         {
     378           6 :             mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
     379           6 :             WriteGradientFill(aGradient);
     380           6 :             mpFS->endElementNS( XML_a, XML_gradFill );
     381          60 :         }
     382             :     }
     383          60 : }
     384             : 
     385          52 : void DrawingML::WriteGrabBagGradientFill( const Sequence< PropertyValue >& aGradientStops, awt::Gradient rGradient )
     386             : {
     387             :     // write back the original gradient
     388          52 :     mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     389             : 
     390             :     // get original stops and write them
     391         161 :     for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
     392             :     {
     393         109 :         Sequence< PropertyValue > aGradientStop;
     394         109 :         aGradientStops[i].Value >>= aGradientStop;
     395             : 
     396             :         // get values
     397         218 :         OUString sSchemeClr;
     398         109 :         double nPos = 0;
     399         109 :         sal_Int16 nTransparency = 0;
     400         109 :         sal_Int32 nRgbClr = 0;
     401         218 :         Sequence< PropertyValue > aTransformations;
     402         436 :         for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
     403             :         {
     404         327 :             if( aGradientStop[j].Name == "SchemeClr" )
     405          50 :                 aGradientStop[j].Value >>= sSchemeClr;
     406         277 :             else if( aGradientStop[j].Name == "RgbClr" )
     407          59 :                 aGradientStop[j].Value >>= nRgbClr;
     408         218 :             else if( aGradientStop[j].Name == "Pos" )
     409         109 :                 aGradientStop[j].Value >>= nPos;
     410         109 :             else if( aGradientStop[j].Name == "Transparency" )
     411           9 :                 aGradientStop[j].Value >>= nTransparency;
     412         100 :             else if( aGradientStop[j].Name == "Transformations" )
     413          50 :                 aGradientStop[j].Value >>= aTransformations;
     414             :         }
     415             :         // write stop
     416             :         mpFS->startElementNS( XML_a, XML_gs,
     417             :                               XML_pos, OString::number( nPos * 100000.0 ).getStr(),
     418         109 :                               FSEND );
     419         109 :         if( sSchemeClr.isEmpty() )
     420             :         {
     421             :             // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
     422          59 :             sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
     423          59 :             WriteColor( nRgbClr, nAlpha );
     424             :         }
     425             :         else
     426             :         {
     427          50 :             WriteColor( sSchemeClr, aTransformations );
     428             :         }
     429         109 :         mpFS->endElementNS( XML_a, XML_gs );
     430         109 :     }
     431          52 :     mpFS->endElementNS( XML_a, XML_gsLst );
     432             : 
     433             :     mpFS->singleElementNS( XML_a, XML_lin,
     434          52 :                            XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     435          52 :                            FSEND );
     436          52 : }
     437             : 
     438           6 : void DrawingML::WriteGradientFill( awt::Gradient rGradient )
     439             : {
     440           6 :     switch( rGradient.Style )
     441             :     {
     442             :         default:
     443             :         case GradientStyle_LINEAR:
     444           2 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     445           2 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     446           2 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     447           2 :             mpFS->endElementNS( XML_a, XML_gsLst );
     448             :             mpFS->singleElementNS( XML_a, XML_lin,
     449           2 :                     XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     450           2 :                     FSEND );
     451           2 :             break;
     452             : 
     453             :         case GradientStyle_AXIAL:
     454           3 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     455           3 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     456           3 :             WriteGradientStop( 50, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     457           3 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     458           3 :             mpFS->endElementNS( XML_a, XML_gsLst );
     459             :             mpFS->singleElementNS( XML_a, XML_lin,
     460           3 :                     XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
     461           3 :                     FSEND );
     462           3 :             break;
     463             : 
     464             :             /* I don't see how to apply transformation to gradients, so
     465             :              * elliptical will end as radial and square as
     466             :              * rectangular. also position offsets are not applied */
     467             :         case GradientStyle_RADIAL:
     468             :         case GradientStyle_ELLIPTICAL:
     469             :         case GradientStyle_RECT:
     470             :         case GradientStyle_SQUARE:
     471           1 :             mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
     472           1 :             WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
     473           1 :             WriteGradientStop( 100, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
     474           1 :             mpFS->endElementNS( XML_a, XML_gsLst );
     475             :             mpFS->singleElementNS( XML_a, XML_path,
     476           2 :                     XML_path, ( rGradient.Style == awt::GradientStyle_RADIAL || rGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
     477           1 :                     FSEND );
     478           1 :             break;
     479             :     }
     480           6 : }
     481             : 
     482        1362 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, bool bLineStart )
     483             : {
     484             :     ESCHER_LineEnd eLineEnd;
     485             :     sal_Int32 nArrowLength;
     486             :     sal_Int32 nArrowWidth;
     487             : 
     488        1362 :     if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
     489             :     {
     490             :         const char* len;
     491             :         const char* type;
     492             :         const char* width;
     493             : 
     494          27 :         switch( nArrowLength )
     495             :         {
     496             :             case ESCHER_LineShortArrow:
     497           1 :                 len = "sm";
     498           1 :                 break;
     499             :             default:
     500             :             case ESCHER_LineMediumLenArrow:
     501          26 :                 len = "med";
     502          26 :                 break;
     503             :             case ESCHER_LineLongArrow:
     504           0 :                 len = "lg";
     505           0 :                 break;
     506             :         }
     507             : 
     508          27 :         switch( eLineEnd )
     509             :         {
     510             :             default:
     511             :             case ESCHER_LineNoEnd:
     512           0 :                 type = "none";
     513           0 :                 break;
     514             :             case ESCHER_LineArrowEnd:
     515          21 :                 type = "triangle";
     516          21 :                 break;
     517             :             case ESCHER_LineArrowStealthEnd:
     518           1 :                 type = "stealth";
     519           1 :                 break;
     520             :             case ESCHER_LineArrowDiamondEnd:
     521           2 :                 type = "diamond";
     522           2 :                 break;
     523             :             case ESCHER_LineArrowOvalEnd:
     524           0 :                 type = "oval";
     525           0 :                 break;
     526             :             case ESCHER_LineArrowOpenEnd:
     527           3 :                 type = "arrow";
     528           3 :                 break;
     529             :         }
     530             : 
     531          27 :         switch( nArrowWidth )
     532             :         {
     533             :             case ESCHER_LineNarrowArrow:
     534           1 :                 width = "sm";
     535           1 :                 break;
     536             :             default:
     537             :             case ESCHER_LineMediumWidthArrow:
     538          26 :                 width = "med";
     539          26 :                 break;
     540             :             case ESCHER_LineWideArrow:
     541           0 :                 width = "lg";
     542           0 :                 break;
     543             :         }
     544             : 
     545             :         mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
     546             :                                XML_len, len,
     547             :                                XML_type, type,
     548             :                                XML_w, width,
     549          27 :                                FSEND );
     550             :     }
     551        1362 : }
     552             : 
     553        1286 : void DrawingML::WriteOutline( Reference<XPropertySet> rXPropSet )
     554             : {
     555        1286 :     drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
     556             : 
     557        1286 :     GET( aLineStyle, LineStyle );
     558             : 
     559        1286 :     sal_uInt32 nLineWidth = 0;
     560        1286 :     sal_uInt32 nColor = 0;
     561        1286 :     bool bColorSet = false;
     562        1286 :     const char* cap = NULL;
     563        1286 :     drawing::LineDash aLineDash;
     564        1286 :     bool bDashSet = false;
     565        1286 :     bool bNoFill = false;
     566             : 
     567             :     // get InteropGrabBag and search the relevant attributes
     568        1286 :     OUString sColorFillScheme;
     569             : 
     570        1286 :     sal_uInt32 nOriginalColor = 0;
     571        1286 :     sal_uInt32 nStyleColor = 0;
     572        1286 :     sal_uInt32 nStyleLineWidth = 0;
     573             : 
     574        2572 :     Sequence<PropertyValue> aStyleProperties;
     575        2572 :     Sequence<PropertyValue> aTransformations;
     576             : 
     577        1286 :     drawing::LineStyle aStyleLineStyle(drawing::LineStyle_NONE);
     578        1286 :     drawing::LineJoint aStyleLineJoint(drawing::LineJoint_NONE);
     579             : 
     580        1286 :     if (GetProperty(rXPropSet, "InteropGrabBag"))
     581             :     {
     582         633 :         Sequence<PropertyValue> aGrabBag;
     583         633 :         mAny >>= aGrabBag;
     584             : 
     585        2621 :         for (sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
     586             :         {
     587        1988 :             if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClr" )
     588          39 :                 aGrabBag[i].Value >>= sColorFillScheme;
     589        1949 :             else if( aGrabBag[i].Name == "OriginalLnSolidFillClr" )
     590         383 :                 aGrabBag[i].Value >>= nOriginalColor;
     591        1566 :             else if( aGrabBag[i].Name == "StyleLnRef" )
     592         144 :                 aGrabBag[i].Value >>= aStyleProperties;
     593        1422 :             else if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClrTransformations" )
     594          39 :                 aGrabBag[i].Value >>= aTransformations;
     595             :         }
     596         633 :         if (aStyleProperties.hasElements())
     597             :         {
     598        1152 :             for (sal_Int32 i=0; i < aStyleProperties.getLength(); ++i)
     599             :             {
     600        1008 :                 if( aStyleProperties[i].Name == "Color" )
     601         144 :                     aStyleProperties[i].Value >>= nStyleColor;
     602         864 :                 else if( aStyleProperties[i].Name == "LineStyle" )
     603         144 :                     aStyleProperties[i].Value >>= aStyleLineStyle;
     604         720 :                 else if( aStyleProperties[i].Name == "LineJoint" )
     605         144 :                     aStyleProperties[i].Value >>= aStyleLineJoint;
     606         576 :                 else if( aStyleProperties[i].Name == "LineWidth" )
     607         144 :                     aStyleProperties[i].Value >>= nStyleLineWidth;
     608             :             }
     609         633 :         }
     610             :     }
     611             : 
     612        1286 :     GET( nLineWidth, LineWidth );
     613             : 
     614        1286 :     switch (aLineStyle)
     615             :     {
     616             :         case drawing::LineStyle_NONE:
     617         605 :             bNoFill = true;
     618         605 :             break;
     619             :         case drawing::LineStyle_DASH:
     620          19 :             if (GetProperty(rXPropSet, "LineDash"))
     621             :             {
     622          19 :                 aLineDash = mAny.get<drawing::LineDash>();
     623          19 :                 bDashSet = true;
     624          19 :                 if (aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE)
     625             :                 {
     626           9 :                     cap = "rnd";
     627             :                 }
     628             : 
     629             :                 SAL_INFO("oox.shape", "dash dots: " << aLineDash.Dots << " dashes: " << aLineDash.Dashes
     630             :                         << " dotlen: " << aLineDash.DotLen << " dashlen: " << aLineDash.DashLen <<  " distance: " <<  aLineDash.Distance);
     631             :             }
     632             :             /* fallthru intended */
     633             :         case drawing::LineStyle_SOLID:
     634             :         default:
     635         681 :             if ( GETA( LineColor ) )
     636             :             {
     637         681 :                 nColor = mAny.get<sal_uInt32>() & 0xffffff;
     638         681 :                 bColorSet = true;
     639             :             }
     640         681 :             break;
     641             :     }
     642             : 
     643             :     mpFS->startElementNS( XML_a, XML_ln,
     644             :                           XML_cap, cap,
     645        1868 :                           XML_w, nLineWidth > 1 && nStyleLineWidth != nLineWidth ?
     646        2288 :                                   I64S( oox::drawingml::convertHmmToEmu( nLineWidth ) ) :NULL,
     647        3858 :                           FSEND );
     648             : 
     649        1286 :     if( bColorSet )
     650             :     {
     651         681 :         if( nColor != nOriginalColor )
     652             :         {
     653             :             // the user has set a different color for the line
     654         331 :             WriteSolidFill( nColor );
     655             :         }
     656         350 :         else if( !sColorFillScheme.isEmpty() )
     657             :         {
     658             :             // the line had a scheme color and the user didn't change it
     659          36 :             WriteSolidFill( sColorFillScheme, aTransformations );
     660             :         }
     661         314 :         else if( aStyleProperties.hasElements() )
     662             :         {
     663          80 :             if( nColor != nStyleColor )
     664             :                 // the line style defines some color but it wasn't being used
     665          11 :                 WriteSolidFill( nColor );
     666             :             // in case the shape used the style color and the user didn't change it,
     667             :             // we must not write a <a: solidFill> tag.
     668             :         }
     669             :         else
     670             :         {
     671         234 :             WriteSolidFill( nColor );
     672             :         }
     673             :     }
     674             : 
     675        1286 :     if( bDashSet && aStyleLineStyle != drawing::LineStyle_DASH )
     676             :     {
     677             :         // line style is a dash and it was not set by the shape style
     678             : 
     679          19 :         if (aLineDash.Dashes == 1 && aLineDash.DashLen == 564 && aLineDash.Distance == 423)
     680             :         {
     681             :             // That's exactly the predefined "dash" value.
     682             :             mpFS->singleElementNS(XML_a, XML_prstDash,
     683             :                                   XML_val, "dash",
     684           2 :                                   FSEND);
     685             :         }
     686             :         else
     687             :         {
     688          17 :             mpFS->startElementNS( XML_a, XML_custDash, FSEND );
     689             : 
     690             :             // Check that line-width is positive and distance between dashes\dots is positive
     691          17 :             if ( nLineWidth > 0 && aLineDash.Distance > 0 )
     692             :             {
     693             :                 // Write 'dashes' first, and then 'dots'
     694             :                 int i;
     695          17 :                 if ( aLineDash.Dashes > 0 )
     696             :                 {
     697          32 :                     for( i = 0; i < aLineDash.Dashes; i ++ )
     698             :                     {
     699             :                         mpFS->singleElementNS( XML_a , XML_ds,
     700          32 :                                                XML_d , write1000thOfAPercent( aLineDash.DashLen  > 0 ? aLineDash.DashLen  / nLineWidth * 100 : 100 ),
     701          32 :                                                XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ),
     702          64 :                                                FSEND );
     703             :                     }
     704             :                 }
     705          17 :                 if ( aLineDash.Dots > 0 )
     706             :                 {
     707          11 :                     for( i = 0; i < aLineDash.Dots; i ++ )
     708             :                     {
     709             :                         mpFS->singleElementNS( XML_a, XML_ds,
     710          14 :                                                XML_d , write1000thOfAPercent( aLineDash.DotLen   > 0 ? aLineDash.DotLen   / nLineWidth * 100 : 100 ),
     711          14 :                                                XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ),
     712          28 :                                                FSEND );
     713             :                     }
     714             :                 }
     715             :             }
     716             : 
     717             :             SAL_WARN_IF(nLineWidth <= 0,
     718             :                         "oox", "while writing outline - custom dash - line width was < 0  : " << nLineWidth);
     719             :             SAL_WARN_IF(aLineDash.Dashes < 0,
     720             :                         "oox", "while writing outline - custom dash - number of dashes was < 0  : " << aLineDash.Dashes);
     721             :             SAL_WARN_IF(aLineDash.Dashes > 0 && aLineDash.DashLen <= 0,
     722             :                         "oox", "while writing outline - custom dash - dash length was < 0  : " << aLineDash.DashLen);
     723             :             SAL_WARN_IF(aLineDash.Dots < 0,
     724             :                         "oox", "while writing outline - custom dash - number of dots was < 0  : " << aLineDash.Dots);
     725             :             SAL_WARN_IF(aLineDash.Dots > 0 && aLineDash.DotLen <= 0,
     726             :                         "oox", "while writing outline - custom dash - dot length was < 0  : " << aLineDash.DotLen);
     727             :             SAL_WARN_IF(aLineDash.Distance <= 0,
     728             :                         "oox", "while writing outline - custom dash - distance was < 0  : " << aLineDash.Distance);
     729             : 
     730          17 :             mpFS->endElementNS( XML_a, XML_custDash );
     731             :         }
     732             :     }
     733             : 
     734        1286 :     if( !bNoFill && nLineWidth > 1 && GETA( LineJoint ) )
     735             :     {
     736         524 :         LineJoint eLineJoint = mAny.get<LineJoint>();
     737             : 
     738         524 :         if( aStyleLineJoint == LineJoint_NONE || aStyleLineJoint != eLineJoint )
     739             :         {
     740             :             // style-defined line joint does not exist, or is different from the shape's joint
     741         520 :             switch( eLineJoint )
     742             :             {
     743             :                 case LineJoint_NONE:
     744             :                 case LineJoint_MIDDLE:
     745             :                 case LineJoint_BEVEL:
     746           1 :                     mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
     747           1 :                     break;
     748             :                 default:
     749             :                 case LineJoint_MITER:
     750          41 :                     mpFS->singleElementNS( XML_a, XML_miter, FSEND );
     751          41 :                     break;
     752             :                 case LineJoint_ROUND:
     753         478 :                     mpFS->singleElementNS( XML_a, XML_round, FSEND );
     754         478 :                     break;
     755             :             }
     756             :         }
     757             :     }
     758             : 
     759        1286 :     if( !bNoFill )
     760             :     {
     761         681 :         WriteLineArrow( rXPropSet, true );
     762         681 :         WriteLineArrow( rXPropSet, false );
     763             :     }
     764             :     else
     765             :     {
     766         605 :         mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
     767             :     }
     768             : 
     769        2572 :     mpFS->endElementNS( XML_a, XML_ln );
     770        1286 : }
     771             : 
     772         119 : OUString DrawingML::WriteImage( const OUString& rURL, bool bRelPathToMedia )
     773             : {
     774         119 :     OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
     775             : 
     776         119 :     const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
     777         119 :     sal_Int32 index = aURLBS.indexOf(aURLBegin);
     778             : 
     779         119 :     if ( index != -1 )
     780             :     {
     781             :         SAL_INFO("oox.shape", "begin: " << sizeof( aURLBegin ) << " " <<  USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ));
     782         117 :         Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
     783             : 
     784         117 :         return WriteImage( aGraphic , bRelPathToMedia );
     785             :     }
     786             :     else
     787             :     {
     788             :         // add link to relations
     789             :     }
     790             : 
     791           2 :     return OUString();
     792             : }
     793             : 
     794         257 : const char* DrawingML::GetComponentDir()
     795             : {
     796         257 :     switch ( meDocumentType )
     797             :     {
     798         185 :         case DOCUMENT_DOCX: return "word";
     799          62 :         case DOCUMENT_PPTX: return "ppt";
     800          10 :         case DOCUMENT_XLSX: return "xl";
     801             :     }
     802             : 
     803           0 :     return "unknown";
     804             : }
     805             : 
     806         257 : const char* DrawingML::GetRelationCompPrefix()
     807             : {
     808         257 :     switch ( meDocumentType )
     809             :     {
     810         185 :         case DOCUMENT_DOCX: return "";
     811             :         case DOCUMENT_PPTX:
     812          72 :         case DOCUMENT_XLSX: return "../";
     813             :     }
     814             : 
     815           0 :     return "unknown";
     816             : }
     817             : 
     818         277 : OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
     819             : {
     820         277 :     GfxLink aLink = rGraphic.GetLink ();
     821         554 :     OUString sMediaType;
     822         277 :     const char* pExtension = "";
     823         277 :     OUString sRelId;
     824             : 
     825         554 :     SvMemoryStream aStream;
     826         277 :     const void* aData = aLink.GetData();
     827         277 :     sal_Size nDataSize = aLink.GetDataSize();
     828             : 
     829         277 :     switch ( aLink.GetType() )
     830             :     {
     831             :         case GFX_LINK_TYPE_NATIVE_GIF:
     832          21 :             sMediaType = "image/gif";
     833          21 :             pExtension = ".gif";
     834          21 :             break;
     835             : 
     836             :         // #i15508# added BMP type for better exports
     837             :         // export not yet active, so adding for reference (not checked)
     838             :         case GFX_LINK_TYPE_NATIVE_BMP:
     839           0 :             sMediaType = "image/bmp";
     840           0 :             pExtension = ".bmp";
     841           0 :             break;
     842             : 
     843             :         case GFX_LINK_TYPE_NATIVE_JPG:
     844          49 :             sMediaType = "image/jpeg";
     845          49 :             pExtension = ".jpeg";
     846          49 :             break;
     847             :         case GFX_LINK_TYPE_NATIVE_PNG:
     848          76 :             sMediaType = "image/png";
     849          76 :             pExtension = ".png";
     850          76 :             break;
     851             :         case GFX_LINK_TYPE_NATIVE_TIF:
     852           1 :             sMediaType = "image/tif";
     853           1 :             pExtension = ".tif";
     854           1 :             break;
     855             :         case GFX_LINK_TYPE_NATIVE_WMF:
     856          30 :             sMediaType = "image/x-wmf";
     857          30 :             pExtension = ".wmf";
     858          30 :             break;
     859             :         case GFX_LINK_TYPE_NATIVE_MET:
     860           0 :             sMediaType = "image/x-met";
     861           0 :             pExtension = ".met";
     862           0 :             break;
     863             :         case GFX_LINK_TYPE_NATIVE_PCT:
     864           0 :             sMediaType = "image/x-pict";
     865           0 :             pExtension = ".pct";
     866           0 :             break;
     867             :         case GFX_LINK_TYPE_NATIVE_MOV:
     868           0 :             sMediaType = "application/movie";
     869           0 :             pExtension = ".MOV";
     870           0 :             break;
     871             :         default:
     872             :         {
     873         100 :             GraphicType aType = rGraphic.GetType();
     874         100 :             if ( aType == GRAPHIC_BITMAP || aType == GRAPHIC_GDIMETAFILE)
     875             :             {
     876         156 :                 if ( aType == GRAPHIC_BITMAP )
     877             :                 {
     878          59 :                     (void)GraphicConverter::Export( aStream, rGraphic, ConvertDataFormat::PNG );
     879          59 :                     sMediaType = "image/png";
     880          59 :                     pExtension = ".png";
     881             :                 }
     882             :                 else
     883             :                 {
     884          19 :                     (void)GraphicConverter::Export( aStream, rGraphic, ConvertDataFormat::EMF );
     885          19 :                     sMediaType = "image/x-emf";
     886          19 :                     pExtension = ".emf";
     887             :                 }
     888             :             }
     889             :             else
     890             :             {
     891             :                 OSL_TRACE( "unhandled graphic type" );
     892             :                 /*Earlier, even in case of unhandled graphic types we were
     893             :                   proceeding to write the image, which would eventually
     894             :                   write an empty image with a zero size, and return a valid
     895             :                   relationID, which is incorrect.
     896             :                   */
     897          22 :                 return sRelId;
     898             :             }
     899             : 
     900          78 :             aData = aStream.GetData();
     901          78 :             nDataSize = aStream.GetEndOfData();
     902          78 :             break;
     903             :         }
     904             :     }
     905             : 
     906             :     Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
     907         510 :                                                                       .appendAscii( GetComponentDir() )
     908         255 :                                                                       .appendAscii( "/media/image" )
     909         510 :                                                                       .append( (sal_Int32) mnImageCounter )
     910         255 :                                                                       .appendAscii( pExtension )
     911             :                                                                       .makeStringAndClear(),
     912         255 :                                                                       sMediaType );
     913         255 :     xOutStream->writeBytes( Sequence< sal_Int8 >( static_cast<const sal_Int8*>(aData), nDataSize ) );
     914         255 :     xOutStream->closeOutput();
     915             : 
     916         510 :     OString sRelPathToMedia = "media/image";
     917         255 :     if ( bRelPathToMedia )
     918           1 :         sRelPathToMedia = "../" + sRelPathToMedia;
     919         510 :     sRelId = mpFB->addRelation( mpFS->getOutputStream(),
     920             :                                 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
     921             :                                 OUStringBuffer()
     922         510 :                                 .appendAscii( GetRelationCompPrefix() )
     923         510 :                                 .appendAscii( sRelPathToMedia.getStr() )
     924         510 :                                 .append( (sal_Int32) mnImageCounter ++ )
     925         255 :                                 .appendAscii( pExtension )
     926         255 :                                 .makeStringAndClear() );
     927             : 
     928         787 :     return sRelId;
     929             : }
     930             : 
     931         116 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
     932             : {
     933         116 :     OUString sRelId = pGraphic ? WriteImage( *pGraphic, bRelPathToMedia ) : WriteImage( rURL, bRelPathToMedia );
     934         116 :     sal_Int16 nBright = 0;
     935         116 :     sal_Int32 nContrast = 0;
     936             : 
     937         116 :     GET( nBright, AdjustLuminance );
     938         116 :     GET( nContrast, AdjustContrast );
     939             : 
     940             :     mpFS->startElementNS( XML_a, XML_blip,
     941             :             FSNS( XML_r, XML_embed), sRelId.toUtf8().getStr(),
     942         116 :             FSEND );
     943         116 :     if( nBright || nContrast )
     944             :     {
     945             :         mpFS->singleElementNS( XML_a, XML_lum,
     946           0 :                    XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
     947           0 :                    XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
     948         116 :                    FSEND );
     949             :     }
     950         116 :     WriteArtisticEffect( rXPropSet );
     951             : 
     952         116 :     mpFS->endElementNS( XML_a, XML_blip );
     953             : 
     954         116 :     return sRelId;
     955             : }
     956             : 
     957           6 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet, const OUString& rURL )
     958             : {
     959           6 :     BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
     960           6 :     if (GetProperty( rXPropSet, "FillBitmapMode" ) )
     961           6 :         mAny >>= eBitmapMode;
     962             : 
     963             :     SAL_INFO("oox.shape", "fill bitmap mode: " << int(eBitmapMode));
     964             : 
     965           6 :     switch (eBitmapMode)
     966             :     {
     967             :     case BitmapMode_REPEAT:
     968           2 :         mpFS->singleElementNS( XML_a, XML_tile, FSEND );
     969           2 :         break;
     970             :     case BitmapMode_STRETCH:
     971           4 :         WriteStretch( rXPropSet, rURL );
     972           4 :         break;
     973             :     default:
     974           0 :         break;
     975             :     }
     976           6 : }
     977             : 
     978         104 : void DrawingML::WriteBlipOrNormalFill( Reference< XPropertySet > xPropSet, const OUString& rURLPropName )
     979             : {
     980             :     // check for blip and otherwise fall back to normal fill
     981             :     // we always store normal fill properties but OOXML
     982             :     // uses a choice between our fill props and BlipFill
     983         104 :     if (GetProperty ( xPropSet, rURLPropName ))
     984           0 :         WriteBlipFill( xPropSet, rURLPropName );
     985             :     else
     986         104 :         WriteFill(xPropSet);
     987         104 : }
     988             : 
     989         959 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName )
     990             : {
     991         959 :     WriteBlipFill( rXPropSet, sURLPropName, XML_a );
     992         959 : }
     993             : 
     994         959 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName, sal_Int32 nXmlNamespace )
     995             : {
     996         959 :     if ( GetProperty( rXPropSet, sURLPropName ) )
     997             :     {
     998           5 :         OUString aURL;
     999           5 :         mAny >>= aURL;
    1000           5 :         bool bWriteMode = false;
    1001           5 :         if( sURLPropName == "FillBitmapURL" || sURLPropName == "BackGraphicURL")
    1002           5 :             bWriteMode = true;
    1003           5 :         WriteBlipFill( rXPropSet, aURL, nXmlNamespace, bWriteMode );
    1004             :     }
    1005         959 : }
    1006             : 
    1007           6 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sBitmapURL, sal_Int32 nXmlNamespace, bool bWriteMode, bool bRelPathToMedia )
    1008             : {
    1009           6 :     if ( !sBitmapURL.isEmpty() )
    1010             :     {
    1011             :         SAL_INFO("oox.shape", "URL: " << sBitmapURL);
    1012             : 
    1013           6 :         mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
    1014             : 
    1015           6 :         WriteBlip( rXPropSet, sBitmapURL, bRelPathToMedia );
    1016             : 
    1017           6 :         if( bWriteMode )
    1018             :         {
    1019           6 :             WriteBlipMode( rXPropSet, sBitmapURL );
    1020             :         }
    1021           0 :         else if( GetProperty( rXPropSet, "FillBitmapStretch" ) )
    1022             :         {
    1023           0 :                 bool bStretch = false;
    1024           0 :                 mAny >>= bStretch;
    1025             : 
    1026           0 :                 if( bStretch )
    1027           0 :                     WriteStretch( rXPropSet, sBitmapURL );
    1028             :         }
    1029           6 :         mpFS->endElementNS( nXmlNamespace, XML_blipFill );
    1030             :     }
    1031           6 : }
    1032             : 
    1033          14 : void DrawingML::WritePattFill( Reference< XPropertySet > rXPropSet )
    1034             : {
    1035          14 :     if ( GetProperty( rXPropSet, "FillHatch" ) )
    1036             :     {
    1037          14 :         drawing::Hatch aHatch;
    1038          14 :         mAny >>= aHatch;
    1039             : 
    1040          14 :         mpFS->startElementNS( XML_a , XML_pattFill, XML_prst, GetHatchPattern(aHatch), FSEND );
    1041             : 
    1042          14 :         mpFS->startElementNS( XML_a , XML_fgClr, FSEND );
    1043          14 :         WriteColor(aHatch.Color);
    1044          14 :         mpFS->endElementNS( XML_a , XML_fgClr );
    1045             : 
    1046             :         // In Writer hatching has no background so use white as a default value.
    1047          14 :         mpFS->startElementNS( XML_a , XML_bgClr, FSEND );
    1048          14 :         WriteColor(COL_WHITE);
    1049          14 :         mpFS->endElementNS( XML_a , XML_bgClr );
    1050             : 
    1051          14 :         mpFS->endElementNS( XML_a , XML_pattFill );
    1052             :     }
    1053          14 : }
    1054             : 
    1055         110 : void DrawingML::WriteSrcRect( Reference< XPropertySet > rXPropSet, const OUString& rURL )
    1056             : {
    1057         110 :     GraphicObject aGraphicObject = GraphicObject::CreateGraphicObjectFromURL(rURL);
    1058         110 :     Size aOriginalSize = aGraphicObject.GetPrefSize();
    1059         110 :     const MapMode& rMapMode = aGraphicObject.GetPrefMapMode();
    1060             : 
    1061             :     // GraphicCrop is in mm100, so in case the original size is in pixels, convert it over.
    1062         110 :     if (rMapMode.GetMapUnit() == MAP_PIXEL)
    1063          75 :         aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, MapMode(MAP_100TH_MM));
    1064             : 
    1065         110 :     if ( GetProperty( rXPropSet, "GraphicCrop" ) )
    1066             :     {
    1067         110 :         ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
    1068         110 :         mAny >>= aGraphicCropStruct;
    1069             : 
    1070         110 :         if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
    1071             :         {
    1072             :             mpFS->singleElementNS( XML_a, XML_srcRect,
    1073           1 :                           XML_l, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Left) * 100000 / aOriginalSize.Width())),
    1074           1 :                           XML_t, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Top) * 100000 / aOriginalSize.Height())),
    1075           1 :                           XML_r, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Right) * 100000 / aOriginalSize.Width())),
    1076           1 :                           XML_b, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Bottom) * 100000 / aOriginalSize.Height())),
    1077           4 :                           FSEND );
    1078             :         }
    1079         110 :     }
    1080         110 : }
    1081             : 
    1082           4 : void DrawingML::WriteStretch( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, const OUString& rURL )
    1083             : {
    1084           4 :     mpFS->startElementNS( XML_a, XML_stretch, FSEND );
    1085             : 
    1086           4 :     bool bCrop = false;
    1087           4 :     if ( GetProperty( rXPropSet, "GraphicCrop" ) )
    1088             :     {
    1089           3 :         ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
    1090           3 :         mAny >>= aGraphicCropStruct;
    1091             : 
    1092           3 :         if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
    1093             :         {
    1094           1 :             Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
    1095             :             mpFS->singleElementNS( XML_a, XML_fillRect,
    1096           2 :                           XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
    1097           2 :                           XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
    1098           2 :                           XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
    1099           2 :                           XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
    1100           8 :                           FSEND );
    1101           1 :             bCrop = true;
    1102             :         }
    1103             :     }
    1104             : 
    1105           4 :     if( !bCrop )
    1106             :     {
    1107           3 :         mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
    1108             :     }
    1109             : 
    1110           4 :     mpFS->endElementNS( XML_a, XML_stretch );
    1111           4 : }
    1112             : 
    1113        1759 : void DrawingML::WriteTransformation( const Rectangle& rRect,
    1114             :         sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation )
    1115             : {
    1116             :     mpFS->startElementNS( nXmlNamespace, XML_xfrm,
    1117             :                           XML_flipH, bFlipH ? "1" : NULL,
    1118             :                           XML_flipV, bFlipV ? "1" : NULL,
    1119        3560 :                           XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
    1120        3518 :                           FSEND );
    1121             : 
    1122        1759 :     sal_Int32 nLeft = rRect.Left();
    1123        1759 :     sal_Int32 nTop = rRect.Top();
    1124        1759 :     if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
    1125             :     {
    1126         336 :         nLeft = 0;
    1127         336 :         nTop = 0;
    1128             :     }
    1129             : 
    1130        1759 :     mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( oox::drawingml::convertHmmToEmu( nLeft ) ), XML_y, IS( oox::drawingml::convertHmmToEmu( nTop ) ), FSEND );
    1131        1759 :     mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( oox::drawingml::convertHmmToEmu( rRect.GetWidth() ) ), XML_cy, IS( oox::drawingml::convertHmmToEmu( rRect.GetHeight() ) ), FSEND );
    1132             : 
    1133        1759 :     mpFS->endElementNS( nXmlNamespace, XML_xfrm );
    1134        1759 : }
    1135             : 
    1136        1715 : void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation  )
    1137             : {
    1138             :     SAL_INFO("oox.shape",  "write shape transformation");
    1139             : 
    1140        1715 :     sal_Int32 nRotation=0;
    1141        1715 :     awt::Point aPos = rXShape->getPosition();
    1142        1715 :     awt::Size aSize = rXShape->getSize();
    1143             : 
    1144        1715 :     if (m_xParent.is())
    1145             :     {
    1146         277 :         awt::Point aParentPos = m_xParent->getPosition();
    1147         277 :         aPos.X -= aParentPos.X;
    1148         277 :         aPos.Y -= aParentPos.Y;
    1149             :     }
    1150             : 
    1151        1715 :     if ( aSize.Width < 0 )
    1152          26 :         aSize.Width = 1000;
    1153        1715 :     if ( aSize.Height < 0 )
    1154          11 :         aSize.Height = 1000;
    1155        1715 :     if (!bSuppressRotation)
    1156             :     {
    1157        1699 :         SdrObject* pShape = GetSdrObjectFromXShape( rXShape );
    1158        1699 :         nRotation = pShape ? pShape->GetRotateAngle() : 0;
    1159        1699 :         if (nRotation != 0 && nRotation != 18000)
    1160             :         {
    1161          15 :             int faccos=bFlipV ? -1 : 1;
    1162          15 :             int facsin=bFlipH ? -1 : 1;
    1163          15 :             aPos.X-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Width/2-facsin*sin(nRotation*F_PI18000)*aSize.Height/2;
    1164          15 :             aPos.Y-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Height/2+facsin*sin(nRotation*F_PI18000)*aSize.Width/2;
    1165             :         }
    1166             : 
    1167             :         // The RotateAngle property's value is independent from any flipping, and that's exactly what we need here.
    1168        1699 :         uno::Reference<beans::XPropertySet> xPropertySet(rXShape, uno::UNO_QUERY);
    1169        3398 :         uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
    1170        1699 :         if (xPropertySetInfo->hasPropertyByName("RotateAngle"))
    1171        3394 :             xPropertySet->getPropertyValue("RotateAngle") >>= nRotation;
    1172             :     }
    1173        1715 :     WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
    1174        1715 : }
    1175             : 
    1176         447 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, bool bIsField, sal_Int32 nElement /*= XML_rPr*/ )
    1177             : {
    1178         447 :     Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
    1179         894 :     Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
    1180         894 :     OUString usLanguage;
    1181             :     PropertyState eState;
    1182         447 :     SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
    1183         447 :     bool bComplex = ( nScriptType == SvtScriptType::COMPLEX );
    1184         447 :     const char* bold = NULL;
    1185         447 :     const char* italic = NULL;
    1186         447 :     const char* underline = NULL;
    1187         447 :     const char* strikeout = NULL;
    1188         447 :     const char* cap = NULL;
    1189         447 :     sal_Int32 nSize = 1800;
    1190         447 :     sal_Int32 nCharEscapement = 0;
    1191         447 :     sal_Int32 nCharKerning = 0;
    1192             : 
    1193         447 :     if( GETA( CharHeight ) )
    1194         447 :         nSize = (sal_Int32) (100*(*static_cast<float const *>(mAny.getValue())));
    1195             : 
    1196         447 :      if( GETA( CharKerning ) )
    1197         447 :         nCharKerning = (sal_Int32)(*static_cast<short const *>(mAny.getValue()));
    1198             :     /**  While setting values in propertymap,
    1199             :     *    CharKerning converted using GetTextSpacingPoint
    1200             :     *    i.e set @ http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/textcharacterproperties.cxx#129
    1201             :     *    therefore to get original value CharKerning need to be convert.
    1202             :     *    http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/drawingmltypes.cxx#95
    1203             :     **/
    1204         447 :     nCharKerning = ((nCharKerning * 720)-360) / 254;
    1205             : 
    1206         447 :     if ( ( bComplex && GETA( CharWeightComplex ) ) || GETA( CharWeight ) )
    1207             :     {
    1208         447 :         if ( *static_cast<float const *>(mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
    1209          78 :             bold = "1";
    1210             :     }
    1211             : 
    1212         447 :     if ( ( bComplex && GETA( CharPostureComplex ) ) || GETA( CharPosture ) )
    1213         447 :         switch ( *static_cast<awt::FontSlant const *>(mAny.getValue()) )
    1214             :         {
    1215             :             case awt::FontSlant_OBLIQUE :
    1216             :             case awt::FontSlant_ITALIC :
    1217          10 :                 italic = "1";
    1218          10 :                 break;
    1219             :             default:
    1220         437 :                 break;
    1221             :         }
    1222             : 
    1223         447 :     if ( GETAD( CharUnderline ) )
    1224             :     {
    1225         122 :         switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
    1226             :         {
    1227             :             case awt::FontUnderline::SINGLE :
    1228           2 :                 underline = "sng";
    1229           2 :                 break;
    1230             :             case awt::FontUnderline::DOUBLE :
    1231           1 :                 underline = "dbl";
    1232           1 :                 break;
    1233             :             case awt::FontUnderline::DOTTED :
    1234           0 :                 underline = "dotted";
    1235           0 :                 break;
    1236             :             case awt::FontUnderline::DASH :
    1237           0 :                 underline = "dash";
    1238           0 :                 break;
    1239             :             case awt::FontUnderline::LONGDASH :
    1240           0 :                 underline = "dashLong";
    1241           0 :                 break;
    1242             :             case awt::FontUnderline::DASHDOT :
    1243           0 :                 underline = "dotDash";
    1244           0 :                 break;
    1245             :             case awt::FontUnderline::DASHDOTDOT :
    1246           0 :                 underline = "dotDotDash";
    1247           0 :                 break;
    1248             :             case awt::FontUnderline::WAVE :
    1249           0 :                 underline = "wavy";
    1250           0 :                 break;
    1251             :             case awt::FontUnderline::DOUBLEWAVE :
    1252           0 :                 underline = "wavyDbl";
    1253           0 :                 break;
    1254             :             case awt::FontUnderline::BOLD :
    1255           0 :                 underline = "heavy";
    1256           0 :                 break;
    1257             :             case awt::FontUnderline::BOLDDOTTED :
    1258           0 :                 underline = "dottedHeavy";
    1259           0 :                 break;
    1260             :             case awt::FontUnderline::BOLDDASH :
    1261           0 :                 underline = "dashHeavy";
    1262           0 :                 break;
    1263             :             case awt::FontUnderline::BOLDLONGDASH :
    1264           0 :                 underline = "dashLongHeavy";
    1265           0 :                 break;
    1266             :             case awt::FontUnderline::BOLDDASHDOT :
    1267           0 :                 underline = "dotDashHeavy";
    1268           0 :                 break;
    1269             :             case awt::FontUnderline::BOLDDASHDOTDOT :
    1270           0 :                 underline = "dotDotDashHeavy";
    1271           0 :                 break;
    1272             :             case awt::FontUnderline::BOLDWAVE :
    1273           0 :                 underline = "wavyHeavy";
    1274           0 :                 break;
    1275             :         }
    1276             :     }
    1277             : 
    1278         447 :     if ( GETAD( CharStrikeout ) )
    1279             :     {
    1280         122 :         switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
    1281             :         {
    1282             :             case awt::FontStrikeout::NONE :
    1283         121 :                strikeout = "noStrike";
    1284         121 :                break;
    1285             :             case awt::FontStrikeout::SINGLE :
    1286             :             // LibO supports further values of character
    1287             :             // strikeout, OOXML standard (20.1.10.78,
    1288             :             // ST_TextStrikeType) however specifies only
    1289             :             // 3 - single, double and none. Approximate
    1290             :             // the remaining ones by single strike (better
    1291             :             // some strike than none at all).
    1292             :             // TODO: figure out how to do this better
    1293             :             case awt::FontStrikeout::BOLD :
    1294             :             case awt::FontStrikeout::SLASH :
    1295             :             case awt::FontStrikeout::X :
    1296           1 :                strikeout = "sngStrike";
    1297           1 :                break;
    1298             :             case awt::FontStrikeout::DOUBLE :
    1299           0 :                strikeout = "dblStrike";
    1300           0 :                break;
    1301             :         }
    1302             :     }
    1303             : 
    1304         447 :     if( GETA( CharLocale ) )
    1305             :     {
    1306         447 :         com::sun::star::lang::Locale aLocale;
    1307         447 :         mAny >>= aLocale;
    1308         894 :         LanguageTag aLanguageTag( aLocale);
    1309         447 :         if (!aLanguageTag.isSystemLocale())
    1310         700 :             usLanguage = aLanguageTag.getBcp47();
    1311             :     }
    1312             : 
    1313         447 :     if( GETAD( CharEscapement ) )
    1314         303 :         mAny >>= nCharEscapement;
    1315             : 
    1316         447 :     if( nCharEscapement && GETAD( CharEscapementHeight ) )
    1317             :     {
    1318           1 :         sal_uInt32 nCharEscapementHeight = 0;
    1319           1 :         mAny >>= nCharEscapementHeight;
    1320           1 :         nSize = (nSize * nCharEscapementHeight) / 100;
    1321             :         // MSO uses default ~58% size
    1322           1 :         nSize = (nSize / 0.58);
    1323             :     }
    1324             : 
    1325         447 :     if( GETA( CharCaseMap ) )
    1326             :     {
    1327         253 :         switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
    1328             :         {
    1329             :             case CaseMap::UPPERCASE :
    1330           0 :                 cap = "all";
    1331           0 :                 break;
    1332             :             case CaseMap::SMALLCAPS :
    1333           0 :                 cap = "small";
    1334           0 :                 break;
    1335             :         }
    1336             :     }
    1337             : 
    1338             :     mpFS->startElementNS( XML_a, nElement,
    1339             :                           XML_b, bold,
    1340             :                           XML_i, italic,
    1341        1147 :                           XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
    1342             :                           XML_sz, IS( nSize ),
    1343             :             // For Condensed character spacing spc value is negative.
    1344         894 :                           XML_spc, nCharKerning ? IS(nCharKerning) : NULL,
    1345             :                           XML_strike, strikeout,
    1346             :                           XML_u, underline,
    1347         896 :                           XML_baseline, nCharEscapement == 0 ? NULL : IS( nCharEscapement*1000 ),
    1348             :                           XML_cap, cap,
    1349        2488 :                           FSEND );
    1350             : 
    1351             :     // mso doesn't like text color to be placed after typeface
    1352         447 :     if( GETAD( CharColor ) )
    1353             :     {
    1354         305 :         sal_uInt32 color = *static_cast<sal_uInt32 const *>(mAny.getValue());
    1355             :         SAL_INFO("oox.shape", "run color: " << color << " auto: " << COL_AUTO);
    1356             : 
    1357         305 :         if( color == COL_AUTO )  // nCharColor depends to the background color
    1358             :         {
    1359           0 :             bool bIsDark = false;
    1360           0 :             GET( bIsDark, IsBackgroundDark );
    1361           0 :             color = bIsDark ? 0xffffff : 0x000000;
    1362             :         }
    1363         305 :         color &= 0xffffff;
    1364             : 
    1365             :         // TODO: special handle embossed/engraved
    1366             : 
    1367         305 :         WriteSolidFill( color );
    1368             :     }
    1369             : 
    1370         447 :     if( GETAD( CharUnderlineColor ) )
    1371             :     {
    1372         122 :         sal_uInt32 color = *static_cast<sal_uInt32 const *>(mAny.getValue());
    1373             : 
    1374         122 :         mpFS->startElementNS( XML_a, XML_uFill,FSEND);
    1375         122 :         WriteSolidFill( color );
    1376         122 :         mpFS->endElementNS( XML_a, XML_uFill );
    1377             :     }
    1378             : 
    1379         447 :     if( GETA( CharFontName ) )
    1380             :     {
    1381         447 :         const char* pitch = NULL;
    1382         447 :         const char* charset = NULL;
    1383         447 :         OUString usTypeface;
    1384             : 
    1385         447 :         mAny >>= usTypeface;
    1386         894 :         OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
    1387             : 
    1388             :         mpFS->singleElementNS( XML_a, XML_latin,
    1389         447 :                                XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
    1390             :                                XML_pitchFamily, pitch,
    1391             :                                XML_charset, charset,
    1392         894 :                                FSEND );
    1393             :     }
    1394             : 
    1395         447 :     if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) )
    1396             :     {
    1397          30 :         const char* pitch = NULL;
    1398          30 :         const char* charset = NULL;
    1399          30 :         OUString usTypeface;
    1400             : 
    1401          30 :         mAny >>= usTypeface;
    1402          60 :         OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
    1403             : 
    1404             :         mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
    1405          30 :                                XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
    1406             :                                XML_pitchFamily, pitch,
    1407             :                                XML_charset, charset,
    1408          60 :                                FSEND );
    1409             :     }
    1410             : 
    1411         447 :     if( bIsField )
    1412             :     {
    1413          55 :         Reference< XTextField > rXTextField;
    1414          55 :         GET( rXTextField, TextField );
    1415          55 :         if( rXTextField.is() )
    1416          55 :             rRun.set( rXTextField, UNO_QUERY );
    1417             :     }
    1418             : 
    1419             :     // field properties starts here
    1420         447 :     if( GETA( URL ) )
    1421             :     {
    1422           0 :         OUString sURL;
    1423             : 
    1424           0 :         mAny >>= sURL;
    1425           0 :         if( !sURL.isEmpty() ) {
    1426             :             OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
    1427             :                                   "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
    1428           0 :                                   sURL, true );
    1429             : 
    1430             :             mpFS->singleElementNS( XML_a, XML_hlinkClick,
    1431             :                        FSNS( XML_r,XML_id ), USS( sRelId ),
    1432           0 :                        FSEND );
    1433           0 :         }
    1434             :     }
    1435             : 
    1436         894 :     mpFS->endElementNS( XML_a, nElement );
    1437         447 : }
    1438             : 
    1439         253 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, bool& bIsField )
    1440             : {
    1441         253 :     const char* sType = NULL;
    1442         253 :     Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
    1443         506 :     OUString aFieldType;
    1444             : 
    1445         253 :     if( GETA( TextPortionType ) )
    1446             :     {
    1447         253 :         aFieldType = OUString( *static_cast<OUString const *>(mAny.getValue()) );
    1448             :         SAL_INFO("oox.shape", "field type: " << aFieldType);
    1449             :     }
    1450             : 
    1451         253 :     if( aFieldType == "TextField" )
    1452             :     {
    1453          55 :         Reference< XTextField > rXTextField;
    1454          55 :         GET( rXTextField, TextField );
    1455          55 :         if( rXTextField.is() )
    1456             :         {
    1457          55 :             bIsField = true;
    1458          55 :             rXPropSet.set( rXTextField, UNO_QUERY );
    1459          55 :             if( rXPropSet.is() )
    1460             :             {
    1461          55 :                 OUString aFieldKind( rXTextField->getPresentation( true ) );
    1462             :                 SAL_INFO("oox.shape", "field kind: " << aFieldKind);
    1463          55 :                 if( aFieldKind == "Page" )
    1464             :                 {
    1465          22 :                     return "slidenum";
    1466          33 :                 }
    1467             :         // else if( aFieldKind == "URL" ) {
    1468             :         // do not return here
    1469             :         // and make URL field text run with hyperlink property later
    1470             :         // }
    1471             :             }
    1472          33 :         }
    1473             :     }
    1474             : 
    1475         484 :     return sType;
    1476             : }
    1477             : 
    1478          22 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
    1479             : {
    1480          22 :     Sequence< sal_uInt8 > aSeq( 16 );
    1481             :     static const char cDigits[17] = "0123456789ABCDEF";
    1482          22 :     rtl_createUuid( aSeq.getArray(), 0, true );
    1483             :     int i;
    1484             : 
    1485          22 :     rBuffer.append( '{' );
    1486         110 :     for( i = 0; i < 4; i++ )
    1487             :     {
    1488          88 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1489          88 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1490             :     }
    1491          22 :     rBuffer.append( '-' );
    1492          66 :     for( ; i < 6; i++ )
    1493             :     {
    1494          44 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1495          44 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1496             :     }
    1497          22 :     rBuffer.append( '-' );
    1498          66 :     for( ; i < 8; i++ )
    1499             :     {
    1500          44 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1501          44 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1502             :     }
    1503          22 :     rBuffer.append( '-' );
    1504          66 :     for( ; i < 10; i++ )
    1505             :     {
    1506          44 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1507          44 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1508             :     }
    1509          22 :     rBuffer.append( '-' );
    1510         154 :     for( ; i < 16; i++ )
    1511             :     {
    1512         132 :         rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
    1513         132 :         rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
    1514             :     }
    1515          22 :     rBuffer.append( '}' );
    1516          22 : }
    1517             : 
    1518        1111 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
    1519             : {
    1520        1111 :     Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
    1521        1111 :     sal_Int16 nLevel = -1;
    1522        1111 :     GET( nLevel, NumberingLevel );
    1523             : 
    1524             :     const char* sFieldType;
    1525        1111 :     bool bIsField = false;
    1526        1364 :     OUString sText = rRun->getString();
    1527             : 
    1528             :     //if there is no text following the bullet, add a space after the bullet
    1529        1111 :     if (nLevel !=-1 && sText.isEmpty() )
    1530           1 :          sText=" ";
    1531             : 
    1532        1111 :     if( sText.isEmpty())
    1533             :     {
    1534         858 :         Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
    1535             : 
    1536             :         try
    1537             :         {
    1538        1716 :             if( !xPropSet.is() || !( xPropSet->getPropertyValue( "PlaceholderText" ) >>= sText ) )
    1539           0 :                 return;
    1540           0 :             if( sText.isEmpty() )
    1541           0 :                 return;
    1542             :         }
    1543        1716 :         catch (const Exception &)
    1544             :         {
    1545         858 :             return;
    1546           0 :         }
    1547             :     }
    1548             : 
    1549         253 :     sFieldType = GetFieldType( rRun, bIsField );
    1550         253 :     if( ( sFieldType != NULL ) )
    1551             :     {
    1552          22 :         OStringBuffer sUUID(39);
    1553             : 
    1554          22 :         GetUUID( sUUID );
    1555             :         mpFS->startElementNS( XML_a, XML_fld,
    1556             :                               XML_id, sUUID.getStr(),
    1557             :                               XML_type, sFieldType,
    1558          22 :                               FSEND );
    1559             :     }
    1560             :     else
    1561             :     {
    1562         231 :         mpFS->startElementNS( XML_a, XML_r, FSEND );
    1563             :     }
    1564             : 
    1565         506 :     Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
    1566         253 :     WriteRunProperties( xPropSet, bIsField );
    1567             : 
    1568         253 :     mpFS->startElementNS( XML_a, XML_t, FSEND );
    1569         253 :     mpFS->writeEscaped( sText );
    1570         253 :     mpFS->endElementNS( XML_a, XML_t );
    1571             : 
    1572         253 :     if( sFieldType )
    1573          22 :         mpFS->endElementNS( XML_a, XML_fld );
    1574             :     else
    1575         484 :         mpFS->endElementNS( XML_a, XML_r );
    1576             : }
    1577             : 
    1578         120 : OUString GetAutoNumType(sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth)
    1579             : {
    1580         120 :     OUString sPrefixSuffix;
    1581             : 
    1582         120 :     if (bPBoth)
    1583           0 :         sPrefixSuffix = "ParenBoth";
    1584         120 :     else if (bPBehind)
    1585           2 :         sPrefixSuffix = "ParenR";
    1586         118 :     else if (bSDot)
    1587           8 :         sPrefixSuffix = "Period";
    1588             : 
    1589         120 :     switch( (SvxExtNumType)nNumberingType )
    1590             :     {
    1591             :         case SVX_NUM_CHARS_UPPER_LETTER_N :
    1592             :         case SVX_NUM_CHARS_UPPER_LETTER :
    1593           2 :             return "alphaUc" + sPrefixSuffix;
    1594             : 
    1595             :         case SVX_NUM_CHARS_LOWER_LETTER_N :
    1596             :         case SVX_NUM_CHARS_LOWER_LETTER :
    1597           2 :             return "alphaLc" + sPrefixSuffix;
    1598             : 
    1599             :         case SVX_NUM_ROMAN_UPPER :
    1600           2 :             return "romanUc" + sPrefixSuffix;
    1601             : 
    1602             :         case SVX_NUM_ROMAN_LOWER :
    1603           2 :             return "romanLc" + sPrefixSuffix;
    1604             : 
    1605             :         case SVX_NUM_ARABIC :
    1606             :         {
    1607           2 :             if (sPrefixSuffix.isEmpty())
    1608           0 :                 return OUString("arabicPlain");
    1609             :             else
    1610           2 :                 return "arabic" + sPrefixSuffix;
    1611             :         }
    1612             :         default:
    1613         110 :             break;
    1614             :     }
    1615             : 
    1616         110 :     return OUString();
    1617             : }
    1618             : 
    1619         400 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
    1620             : {
    1621         400 :     if( nLevel < 0 || !GETA( NumberingRules ) )
    1622         545 :         return;
    1623             : 
    1624         132 :     Reference< XIndexAccess > rXIndexAccess;
    1625             : 
    1626         132 :     if (!(mAny >>= rXIndexAccess) || nLevel >= rXIndexAccess->getCount())
    1627           0 :         return;
    1628             : 
    1629             :     SAL_INFO("oox.shape", "numbering rules");
    1630             : 
    1631         255 :     Sequence<PropertyValue> aPropertySequence;
    1632         132 :     rXIndexAccess->getByIndex(nLevel) >>= aPropertySequence;
    1633             : 
    1634         132 :     if (!aPropertySequence.hasElements())
    1635           0 :         return;
    1636             : 
    1637         132 :     sal_Int32 nPropertyCount = aPropertySequence.getLength();
    1638             : 
    1639         132 :     const PropertyValue* pPropValue = aPropertySequence.getArray();
    1640             : 
    1641         132 :     sal_Int16 nNumberingType = SVX_NUM_NUMBER_NONE;
    1642         132 :     bool bSDot = false;
    1643         132 :     bool bPBehind = false;
    1644         132 :     bool bPBoth = false;
    1645         132 :     sal_Unicode aBulletChar = 0x2022; // a bullet
    1646         255 :     awt::FontDescriptor aFontDesc;
    1647         132 :     bool bHasFontDesc = false;
    1648         255 :     OUString aGraphicURL;
    1649         132 :     sal_Int16 nBulletRelSize = 0;
    1650         132 :     sal_Int16 nStartWith = 1;
    1651         132 :     sal_Int32 nBulletColor = 0;
    1652             : 
    1653        1829 :     for ( sal_Int32 i = 0; i < nPropertyCount; i++ )
    1654             :     {
    1655        1697 :         const void* pValue = pPropValue[ i ].Value.getValue();
    1656        1697 :         if ( pValue )
    1657             :         {
    1658        1697 :             OUString aPropName( pPropValue[ i ].Name );
    1659             :             SAL_INFO("oox.shape", "pro name: " << aPropName);
    1660        1697 :             if ( aPropName == "NumberingType" )
    1661             :             {
    1662         132 :                 nNumberingType = *( static_cast<sal_Int16 const *>(pValue) );
    1663             :             }
    1664        1565 :             else if ( aPropName == "Prefix" )
    1665             :             {
    1666         132 :                 if( *static_cast<OUString const *>(pValue) == ")")
    1667           0 :                     bPBoth = true;
    1668             :             }
    1669        1433 :             else if ( aPropName == "Suffix" )
    1670             :             {
    1671         132 :                 if( *static_cast<OUString const *>(pValue) == ".")
    1672           8 :                     bSDot = true;
    1673         124 :                 else if( *static_cast<OUString const *>(pValue) == ")")
    1674           2 :                     bPBehind = true;
    1675             :             }
    1676        1301 :             else if(aPropName == "BulletColor")
    1677             :             {
    1678         132 :                 nBulletColor = *static_cast<sal_Int32 const *>(pValue);
    1679             :             }
    1680        1169 :             else if ( aPropName == "BulletChar" )
    1681             :             {
    1682         110 :                 aBulletChar = OUString ( *( static_cast<OUString const *>(pValue) ) )[ 0 ];
    1683             :             }
    1684        1059 :             else if ( aPropName == "BulletFont" )
    1685             :             {
    1686         132 :                 aFontDesc = *static_cast<awt::FontDescriptor const *>(pValue);
    1687         132 :                 bHasFontDesc = true;
    1688             : 
    1689             :                 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
    1690             :                 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
    1691             :                 // Because there might exist a lot of damaged documemts I added this two lines
    1692             :                 // which fixes the bullet problem for the export.
    1693         132 :                 if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
    1694          98 :                     aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
    1695             : 
    1696             :             }
    1697         927 :             else if ( aPropName == "BulletRelSize" )
    1698             :             {
    1699         132 :                 nBulletRelSize = *static_cast<sal_Int16 const *>(pValue);
    1700             :             }
    1701         795 :             else if ( aPropName == "StartWith" )
    1702             :             {
    1703         132 :                 nStartWith = *static_cast<sal_Int16 const *>(pValue);
    1704             :             }
    1705         663 :             else if ( aPropName == "GraphicURL" )
    1706             :             {
    1707           3 :                 aGraphicURL = *static_cast<OUString const *>(pValue);
    1708             :                 SAL_INFO("oox.shape", "graphic url: " << aGraphicURL);
    1709             :             }
    1710         660 :             else if ( aPropName == "GraphicSize" )
    1711             :             {
    1712         132 :                 if ( pPropValue[ i ].Value.getValueType() == cppu::UnoType<awt::Size>::get())
    1713             :                 {
    1714             :                     // don't cast awt::Size to Size as on 64-bits they are not the same.
    1715         132 :                     css::awt::Size aSize;
    1716         132 :                     pPropValue[ i ].Value >>= aSize;
    1717             :                     //aBuGraSize.nA = aSize.Width;
    1718             :                     //aBuGraSize.nB = aSize.Height;
    1719             :                     SAL_INFO("oox.shape", "graphic size: " << aSize.Width << "x" << aSize.Height);
    1720             :                 }
    1721        1697 :             }
    1722             :         }
    1723             :     }
    1724             : 
    1725         132 :     if (nNumberingType == SVX_NUM_NUMBER_NONE)
    1726           9 :         return;
    1727             : 
    1728         123 :     if( !aGraphicURL.isEmpty() )
    1729             :     {
    1730           3 :         OUString sRelId = WriteImage( aGraphicURL );
    1731             : 
    1732           3 :         mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
    1733           3 :         mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
    1734           3 :         mpFS->endElementNS( XML_a, XML_buBlip );
    1735             :     }
    1736             :     else
    1737             :     {
    1738         120 :         if(nBulletColor)
    1739             :         {
    1740          89 :                mpFS->startElementNS( XML_a, XML_buClr, FSEND );
    1741          89 :                WriteColor( nBulletColor );
    1742          89 :                mpFS->endElementNS( XML_a, XML_buClr );
    1743             :         }
    1744             : 
    1745         120 :         if( nBulletRelSize && nBulletRelSize != 100 )
    1746             :             mpFS->singleElementNS( XML_a, XML_buSzPct,
    1747          93 :                                    XML_val, IS( std::max( (sal_Int32)25000, std::min( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
    1748         120 :         if( bHasFontDesc )
    1749             :             mpFS->singleElementNS( XML_a, XML_buFont,
    1750             :                                    XML_typeface, aFontDesc.Name.toUtf8().getStr(),
    1751         120 :                                    XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
    1752         120 :                                    FSEND );
    1753             : 
    1754         120 :         OUString pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
    1755             : 
    1756         120 :         if (!pAutoNumType.isEmpty())
    1757             :         {
    1758             :             mpFS->singleElementNS(XML_a, XML_buAutoNum,
    1759             :                                   XML_type, OUStringToOString(pAutoNumType, RTL_TEXTENCODING_UTF8).getStr(),
    1760          30 :                                   XML_startAt, nStartWith > 1 ? IS(nStartWith) : NULL,
    1761          20 :                                   FSEND);
    1762             :         }
    1763             :         else
    1764             :         {
    1765         110 :             aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
    1766         110 :             mpFS->singleElementNS(XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND);
    1767         120 :         }
    1768         123 :     }
    1769             : }
    1770             : 
    1771        2214 : sal_Int32 DrawingML::getBulletMarginIndentation (Reference< XPropertySet > rXPropSet,sal_Int16 nLevel, const OUString& propName)
    1772             : {
    1773        2214 :     if( nLevel < 0 || !GETA( NumberingRules ) )
    1774        1950 :         return 0;
    1775             : 
    1776         264 :     Reference< XIndexAccess > rXIndexAccess;
    1777             : 
    1778         264 :     if (!(mAny >>= rXIndexAccess) || nLevel >= rXIndexAccess->getCount())
    1779           0 :         return 0;
    1780             : 
    1781             :     SAL_INFO("oox.shape", "numbering rules");
    1782             : 
    1783         528 :     Sequence<PropertyValue> aPropertySequence;
    1784         264 :     rXIndexAccess->getByIndex(nLevel) >>= aPropertySequence;
    1785             : 
    1786         264 :     if (!aPropertySequence.hasElements())
    1787           0 :         return 0;
    1788             : 
    1789         264 :     sal_Int32 nPropertyCount = aPropertySequence.getLength();
    1790             : 
    1791         264 :     const PropertyValue* pPropValue = aPropertySequence.getArray();
    1792             : 
    1793        2470 :     for ( sal_Int32 i = 0; i < nPropertyCount; i++ )
    1794             :     {
    1795        2470 :         const void* pValue = pPropValue[ i ].Value.getValue();
    1796        2470 :         if ( pValue )
    1797             :         {
    1798        2470 :             OUString aPropName( pPropValue[ i ].Name );
    1799             :             SAL_INFO("oox.shape", "pro name: " << aPropName);
    1800        2470 :             if ( aPropName == propName )
    1801         264 :                 return *( static_cast<sal_Int32 const *>(pValue) );
    1802             :         }
    1803             :     }
    1804             : 
    1805         264 :     return 0;
    1806             : }
    1807             : 
    1808         400 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
    1809             : {
    1810         400 :     const char* sAlignment = NULL;
    1811             : 
    1812         400 :     switch( nAlignment )
    1813             :     {
    1814             :         case style::ParagraphAdjust_CENTER:
    1815         226 :             sAlignment = "ctr";
    1816         226 :             break;
    1817             :         case style::ParagraphAdjust_RIGHT:
    1818          29 :             sAlignment = "r";
    1819          29 :             break;
    1820             :         case style::ParagraphAdjust_BLOCK:
    1821           0 :             sAlignment = "just";
    1822           0 :             break;
    1823             :         default:
    1824             :             ;
    1825             :     }
    1826             : 
    1827         400 :     return sAlignment;
    1828             : }
    1829             : 
    1830         100 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
    1831             : {
    1832         100 :     if( rSpacing.Mode == LineSpacingMode::PROP )
    1833             :     {
    1834             :         mpFS->singleElementNS( XML_a, XML_spcPct,
    1835             :                                XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
    1836         100 :                                FSEND );
    1837             :     }
    1838             :     else
    1839             :     {
    1840             :         mpFS->singleElementNS( XML_a, XML_spcPts,
    1841             :                                XML_val, I32S( rSpacing.Height ),
    1842           0 :                                FSEND );
    1843             :     }
    1844         100 : }
    1845             : 
    1846        1107 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
    1847             : {
    1848        1107 :     Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
    1849        2214 :     Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
    1850             :     PropertyState eState;
    1851             : 
    1852        1107 :     if( !rXPropSet.is() || !rXPropState.is() )
    1853        1107 :         return;
    1854             : 
    1855        1107 :     sal_Int16 nLevel = -1;
    1856        1107 :     GET( nLevel, NumberingLevel );
    1857             : 
    1858        1107 :     sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
    1859        1107 :     GET( nAlignment, ParaAdjust );
    1860             : 
    1861        1107 :     bool bHasLinespacing = false;
    1862        1107 :     LineSpacing aLineSpacing;
    1863        1107 :     if( GETAD( ParaLineSpacing ) )
    1864         100 :         bHasLinespacing = ( mAny >>= aLineSpacing );
    1865             : 
    1866        1107 :     bool bRtl = false;
    1867        1107 :     if( GETA( WritingMode ) )
    1868             :     {
    1869             :         sal_Int16 nWritingMode;
    1870        1107 :         if( ( mAny >>= nWritingMode ) && nWritingMode == text::WritingMode2::RL_TB )
    1871             :         {
    1872           1 :             bRtl = true;
    1873             :         }
    1874             :     }
    1875             : 
    1876        1107 :     sal_Int32 nParaLeftMargin = 0;
    1877        1107 :     sal_Int32 nParaFirstLineIndent = 0;
    1878             : 
    1879        1107 :     GET( nParaLeftMargin, ParaLeftMargin );
    1880        1107 :     GET( nParaFirstLineIndent,ParaFirstLineIndent);
    1881             : 
    1882        1107 :     sal_Int32 nLeftMargin =  getBulletMarginIndentation ( rXPropSet, nLevel,"LeftMargin");
    1883        1107 :     sal_Int32 nLineIndentation = getBulletMarginIndentation ( rXPropSet, nLevel,"FirstLineOffset");
    1884             : 
    1885        1107 :     if( nLevel != -1
    1886         975 :         || nAlignment != style::ParagraphAdjust_LEFT
    1887         727 :         || bHasLinespacing )
    1888             :     {
    1889         400 :         if (nParaLeftMargin) // For Paraghraph
    1890             :             mpFS->startElementNS( XML_a, XML_pPr,
    1891          28 :                                XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
    1892          33 :                                XML_marL, nParaLeftMargin > 0 ? I32S( oox::drawingml::convertHmmToEmu( nParaLeftMargin ) ) : NULL,
    1893          31 :                                XML_indent, nParaFirstLineIndent ? I32S( oox::drawingml::convertHmmToEmu( nParaFirstLineIndent ) ) : NULL,
    1894             :                                XML_algn, GetAlignment( nAlignment ),
    1895             :                                XML_rtl, bRtl ? BS(bRtl) : NULL,
    1896          61 :                                FSEND );
    1897             :         else
    1898             :             mpFS->startElementNS( XML_a, XML_pPr,
    1899         861 :                                XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
    1900         506 :                                XML_marL, nLeftMargin > 0 ? I32S( oox::drawingml::convertHmmToEmu( nLeftMargin ) ) : NULL,
    1901         623 :                                XML_indent, nLineIndentation ? I32S( oox::drawingml::convertHmmToEmu( nLineIndentation ) ) : NULL,
    1902             :                                XML_algn, GetAlignment( nAlignment ),
    1903             :                                XML_rtl, bRtl ? BS(bRtl) : NULL,
    1904        1367 :                                FSEND );
    1905             : 
    1906             : 
    1907             : 
    1908         400 :         if( bHasLinespacing )
    1909             :         {
    1910         100 :             mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
    1911         100 :             WriteLinespacing( aLineSpacing );
    1912         100 :             mpFS->endElementNS( XML_a, XML_lnSpc );
    1913             :         }
    1914             : 
    1915         400 :         WriteParagraphNumbering( rXPropSet, nLevel );
    1916             : 
    1917         400 :         mpFS->endElementNS( XML_a, XML_pPr );
    1918        1107 :     }
    1919             : }
    1920             : 
    1921        1107 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
    1922             : {
    1923        1107 :     Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
    1924        1107 :     if( !access.is() )
    1925           0 :         return;
    1926             : 
    1927        2214 :     Reference< XEnumeration > enumeration( access->createEnumeration() );
    1928        1107 :     if( !enumeration.is() )
    1929           0 :         return;
    1930             : 
    1931        1107 :     mpFS->startElementNS( XML_a, XML_p, FSEND );
    1932             : 
    1933        1107 :     bool bPropertiesWritten = false;
    1934        3325 :     while( enumeration->hasMoreElements() )
    1935             :     {
    1936        1111 :         Reference< XTextRange > run;
    1937        2222 :         Any any ( enumeration->nextElement() );
    1938             : 
    1939        1111 :         if (any >>= run)
    1940             :         {
    1941        1111 :             if( !bPropertiesWritten )
    1942             :             {
    1943        1107 :                 WriteParagraphProperties( rParagraph );
    1944        1107 :                 bPropertiesWritten = true;
    1945             :             }
    1946        1111 :             WriteRun( run );
    1947             :         }
    1948        1111 :     }
    1949        1107 :     mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
    1950             : 
    1951        2214 :     mpFS->endElementNS( XML_a, XML_p );
    1952             : }
    1953             : 
    1954        1377 : void DrawingML::WriteText( Reference< XInterface > rXIface, const OUString& presetWarp, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
    1955             : {
    1956        1377 :     Reference< XText > xXText( rXIface, UNO_QUERY );
    1957        2378 :     Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
    1958             : 
    1959        1377 :     if( !xXText.is() )
    1960           0 :         return;
    1961             : 
    1962             : #define DEFLRINS 254
    1963             : #define DEFTBINS 127
    1964             :     sal_Int32 nLeft, nRight, nTop, nBottom;
    1965        1377 :     nLeft = nRight = DEFLRINS;
    1966        1377 :     nTop = nBottom = DEFTBINS;
    1967             : 
    1968             :     // top inset looks a bit different compared to ppt export
    1969             :     // check if something related doesn't work as expected
    1970        1377 :     GET( nLeft, TextLeftDistance );
    1971        1377 :     GET( nRight, TextRightDistance );
    1972        1377 :     GET( nTop, TextUpperDistance );
    1973        1377 :     GET( nBottom, TextLowerDistance );
    1974             : 
    1975        1377 :     TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
    1976        1377 :     const char* sVerticalAlignment = NULL;
    1977        1377 :     GET( eVerticalAlignment, TextVerticalAdjust );
    1978        1377 :     if( eVerticalAlignment != TextVerticalAdjust_TOP )
    1979         520 :         sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
    1980             : 
    1981        1377 :     const char* sWritingMode = NULL;
    1982        1377 :     bool bVertical = false;
    1983        1377 :     if( GETA( TextWritingMode ) )
    1984             :     {
    1985             :         WritingMode eMode;
    1986             : 
    1987        1377 :         if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL )
    1988             :         {
    1989           0 :             sWritingMode = "vert";
    1990           0 :             bVertical = true;
    1991             :         }
    1992             :     }
    1993             : 
    1994        1377 :     if ( GETA( CustomShapeGeometry ) )
    1995             :     {
    1996         224 :         Sequence< PropertyValue > aProps;
    1997         224 :         if ( mAny >>= aProps )
    1998             :         {
    1999        1851 :             for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
    2000             :             {
    2001        1831 :                 sal_Int32 nTextRotateAngle = 0;
    2002        1831 :                 if ( aProps[ i ].Name == "TextPreRotateAngle" && ( aProps[ i ].Value >>= nTextRotateAngle ) )
    2003             :                 {
    2004         204 :                     if ( nTextRotateAngle == -90 )
    2005             :                     {
    2006           0 :                         sWritingMode = "vert";
    2007           0 :                         bVertical = true;
    2008             :                     }
    2009         204 :                     else if ( nTextRotateAngle == -270 )
    2010             :                     {
    2011           2 :                         sWritingMode = "vert270";
    2012           2 :                         bVertical = true;
    2013             :                     }
    2014         204 :                     break;
    2015             :                 }
    2016             :             }
    2017         224 :         }
    2018             :     }
    2019             : 
    2020        1377 :     TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
    2021        1377 :     bool bHorizontalCenter = false;
    2022        1377 :     GET( eHorizontalAlignment, TextHorizontalAdjust );
    2023        1377 :     if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
    2024           2 :         bHorizontalCenter = true;
    2025        1375 :     else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
    2026           0 :         sVerticalAlignment = "b";
    2027             : 
    2028        1377 :     bool bHasWrap = false;
    2029        1377 :     bool bWrap = false;
    2030             :     // Only custom shapes obey the TextWordWrap option, normal text always wraps.
    2031        1377 :     if( dynamic_cast<SvxCustomShape*>(rXIface.get()) && GETA( TextWordWrap ) )
    2032             :     {
    2033          26 :         mAny >>= bWrap;
    2034          26 :         bHasWrap = true;
    2035             :     }
    2036             : 
    2037        1377 :     if (bBodyPr)
    2038             :     {
    2039        1247 :         const char* pWrap = bHasWrap && !bWrap ? "none" : NULL;
    2040        1247 :         if (GetDocumentType() == DOCUMENT_DOCX)
    2041             :         {
    2042             :             // In case of DOCX, if we want to have the same effect as
    2043             :             // TextShape's automatic word wrapping, then we need to set
    2044             :             // wrapping to square.
    2045         246 :             uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY);
    2046         246 :             if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
    2047          88 :                 pWrap = "square";
    2048             :         }
    2049             :         mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
    2050             :                                XML_wrap, pWrap,
    2051        3550 :                                XML_lIns, (nLeft != DEFLRINS) ? IS( oox::drawingml::convertHmmToEmu( nLeft ) ) : NULL,
    2052        3549 :                                XML_rIns, (nRight != DEFLRINS) ? IS( oox::drawingml::convertHmmToEmu( nRight ) ) : NULL,
    2053        3546 :                                XML_tIns, (nTop != DEFTBINS) ? IS( oox::drawingml::convertHmmToEmu( nTop ) ) : NULL,
    2054        4598 :                                XML_bIns, (nBottom != DEFTBINS) ? IS( oox::drawingml::convertHmmToEmu( nBottom ) ) : NULL,
    2055             :                                XML_anchor, sVerticalAlignment,
    2056             :                                XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
    2057             :                                XML_vert, sWritingMode,
    2058       10645 :                                FSEND );
    2059        1247 :         if( presetWarp != NULL  && !presetWarp.isEmpty())
    2060             :         {
    2061             :             mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp.toUtf8().getStr(),
    2062          33 :                 FSEND );
    2063             :         }
    2064        1247 :         if (GetDocumentType() == DOCUMENT_DOCX)
    2065             :         {
    2066         246 :             sal_Bool bTextAutoGrowHeight = sal_False;
    2067         246 :             GET(bTextAutoGrowHeight, TextAutoGrowHeight);
    2068         246 :             mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit), FSEND);
    2069             :         }
    2070        1247 :         mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr);
    2071             :     }
    2072             : 
    2073        2378 :     Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
    2074        1377 :     if( !access.is() || !bText )
    2075         246 :         return;
    2076             : 
    2077        2132 :     Reference< XEnumeration > enumeration( access->createEnumeration() );
    2078        1131 :     if( !enumeration.is() )
    2079           0 :         return;
    2080             : 
    2081        2132 :     uno::Reference<drawing::XShape> xShape(rXIface, uno::UNO_QUERY);
    2082        1131 :     SdrObject* pSdrObject = xShape.is() ? GetSdrObjectFromXShape(xShape) : 0;
    2083        1131 :     const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, pSdrObject);
    2084        1131 :     if (pTxtObj && mpTextExport)
    2085             :     {
    2086         130 :         const OutlinerParaObject* pParaObj = 0;
    2087         130 :         bool bOwnParaObj = false;
    2088             : 
    2089             :         /*
    2090             :         #i13885#
    2091             :         When the object is actively being edited, that text is not set into
    2092             :         the objects normal text object, but lives in a separate object.
    2093             :         */
    2094         130 :         if (pTxtObj->IsTextEditActive())
    2095             :         {
    2096           0 :             pParaObj = pTxtObj->GetEditOutlinerParaObject();
    2097           0 :             bOwnParaObj = true;
    2098             :         }
    2099             :         else
    2100         130 :             pParaObj = pTxtObj->GetOutlinerParaObject();
    2101             : 
    2102         130 :         if (pParaObj)
    2103             :         {
    2104             :             // this is reached only in case some text is attached to the shape
    2105         130 :             mpTextExport->WriteOutliner(*pParaObj);
    2106         130 :             if (bOwnParaObj)
    2107           0 :                 delete pParaObj;
    2108             :         }
    2109         130 :         return;
    2110             :     }
    2111             : 
    2112        3109 :     while( enumeration->hasMoreElements() )
    2113             :     {
    2114        1107 :         Reference< XTextContent > paragraph;
    2115        2214 :         Any any ( enumeration->nextElement() );
    2116             : 
    2117        1107 :         if( any >>= paragraph)
    2118        1107 :             WriteParagraph( paragraph );
    2119        2108 :     }
    2120             : 
    2121             : }
    2122             : 
    2123        1234 : void DrawingML::WritePresetShape( const char* pShape )
    2124             : {
    2125             :     mpFS->startElementNS( XML_a, XML_prstGeom,
    2126             :                           XML_prst, pShape,
    2127        1234 :                           FSEND );
    2128        1234 :     mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
    2129        1234 :     mpFS->endElementNS(  XML_a, XML_prstGeom );
    2130        1234 : }
    2131             : 
    2132          13 : std::map< OString, std::vector<OString> > lcl_getAdjNames()
    2133             : {
    2134          13 :     std::map< OString, std::vector<OString> > aRet;
    2135             : 
    2136          26 :     OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-adj-names");
    2137          13 :     rtl::Bootstrap::expandMacros(aPath);
    2138          26 :     SvFileStream aStream(aPath, StreamMode::READ);
    2139          13 :     if (aStream.GetError() != ERRCODE_NONE)
    2140             :         SAL_WARN("oox", "failed to open oox-drawingml-adj-names");
    2141          26 :     OString aLine;
    2142          13 :     bool bNotDone = aStream.ReadLine(aLine);
    2143        4550 :     while (bNotDone)
    2144             :     {
    2145        4524 :         sal_Int32 nIndex = 0;
    2146             :         // Each line is in a "key\tvalue" format: read the key, the rest is the value.
    2147        4524 :         OString aKey = aLine.getToken(0, '\t', nIndex);
    2148        9048 :         OString aValue = aLine.copy(nIndex);
    2149        4524 :         aRet[aKey].push_back(aValue);
    2150        4524 :         bNotDone = aStream.ReadLine(aLine);
    2151        4524 :     }
    2152          26 :     return aRet;
    2153             : }
    2154             : 
    2155         298 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
    2156             : {
    2157         298 :     static std::map< OString, std::vector<OString> > aAdjMap = lcl_getAdjNames();
    2158             :     // If there are predefined adj names for this shape type, look them up now.
    2159         298 :     std::vector<OString> aAdjustments;
    2160         298 :     if (aAdjMap.find(OString(pShape)) != aAdjMap.end())
    2161         113 :         aAdjustments = aAdjMap[OString(pShape)];
    2162             : 
    2163             :     mpFS->startElementNS( XML_a, XML_prstGeom,
    2164             :                           XML_prst, pShape,
    2165         298 :                           FSEND );
    2166         298 :     mpFS->startElementNS( XML_a, XML_avLst, FSEND );
    2167             : 
    2168         596 :     Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
    2169         894 :     if ( ( rProp.Value >>= aAdjustmentSeq )
    2170         298 :          && eShapeType != mso_sptActionButtonForwardNext  // we have adjustments values for these type of shape, but MSO doesn't like them
    2171         298 :          && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
    2172        1490 :          && OString(pShape) != "rect" //some shape types are commented out in pCustomShapeTypeTranslationTable[] & are being defaulted to rect & rect does not have adjustment values/name.
    2173             :         )
    2174             :     {
    2175             :         SAL_INFO("oox.shape", "adj seq len: " << aAdjustmentSeq.getLength());
    2176         134 :         if ( bPredefinedHandlesUsed )
    2177           8 :             EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
    2178             : 
    2179         134 :         sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
    2180             :         //aAdjustments will give info about the number of adj values for a particular geometry. For example for hexagon aAdjustments.size() will be 2 and for circular arrow it will be 5 as per lcl_getAdjNames.
    2181         134 :         if(aAdjustments.size() == static_cast<sal_uInt32>(nLength))// In case there is a mismatch do not write the XML_gd tag.
    2182             :         {
    2183         266 :             for( sal_Int32 i=0; i < nLength; i++ )
    2184             :             {
    2185         132 :                 if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
    2186             :                 {
    2187             :                     // If the document model doesn't have an adjustment name (e.g. shape was created from VML), then take it from the predefined list.
    2188         132 :                     OString aAdjName;
    2189         132 :                     if (aAdjustmentSeq[i].Name.isEmpty() && static_cast<sal_uInt32>(i) < aAdjustments.size())
    2190          11 :                         aAdjName = aAdjustments[i];
    2191             : 
    2192             :                     mpFS->singleElementNS( XML_a, XML_gd,
    2193         385 :                                        XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : aAdjName.getStr(),
    2194         264 :                                        XML_fmla, OString("val " + OString::number( nValue )).getStr(),
    2195         649 :                                        FSEND );
    2196             :                 }
    2197             :             }
    2198             :         }
    2199             :     }
    2200             : 
    2201         298 :     mpFS->endElementNS( XML_a, XML_avLst );
    2202         596 :     mpFS->endElementNS(  XML_a, XML_prstGeom );
    2203         298 : }
    2204             : 
    2205         115 : void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape )
    2206             : {
    2207         115 :     uno::Reference< beans::XPropertySet > aXPropSet;
    2208         223 :     uno::Any aAny( rXShape->queryInterface(cppu::UnoType<beans::XPropertySet>::get()));
    2209             : 
    2210         115 :     if ( ! (aAny >>= aXPropSet) )
    2211           0 :         return;
    2212             : 
    2213             :     try
    2214             :     {
    2215         115 :         aAny = aXPropSet->getPropertyValue( "CustomShapeGeometry" );
    2216         115 :         if ( !aAny.hasValue() )
    2217           0 :             return;
    2218             :     }
    2219           0 :     catch( const ::uno::Exception& )
    2220             :     {
    2221           0 :         return;
    2222             :     }
    2223             : 
    2224             : 
    2225             : 
    2226             :     uno::Sequence< beans::PropertyValue > const * pGeometrySeq =
    2227         115 :         static_cast<uno::Sequence< beans::PropertyValue > const *>(aAny.getValue());
    2228             : 
    2229         115 :     if ( pGeometrySeq )
    2230             :     {
    2231         876 :         for( int i = 0; i < pGeometrySeq->getLength(); ++i )
    2232             :         {
    2233         768 :             const beans::PropertyValue& rProp = (*pGeometrySeq)[ i ];
    2234         768 :             if ( rProp.Name == "Path" )
    2235             :             {
    2236         113 :                 uno::Sequence<beans::PropertyValue> aPathProp;
    2237         113 :                 rProp.Value >>= aPathProp;
    2238             : 
    2239         219 :                 uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs;
    2240         219 :                 uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
    2241         219 :                 uno::Sequence<awt::Size> aPathSize;
    2242         390 :                 for (int j = 0; j < aPathProp.getLength(); ++j )
    2243             :                 {
    2244         277 :                     const beans::PropertyValue& rPathProp = aPathProp[j];
    2245         277 :                     if (rPathProp.Name == "Coordinates")
    2246         113 :                         rPathProp.Value >>= aPairs;
    2247         164 :                     else if (rPathProp.Name == "Segments")
    2248         106 :                         rPathProp.Value >>= aSegments;
    2249          58 :                     else if (rPathProp.Name == "SubViewSize")
    2250          26 :                         rPathProp.Value >>= aPathSize;
    2251             :                 }
    2252             : 
    2253         113 :                 if ( !aPairs.hasElements() || !aSegments.hasElements() )
    2254           7 :                     return;
    2255             : 
    2256         106 :                 int nExpectedPairCount = 0;
    2257         685 :                 for( int j = 0; j < aSegments.getLength(); ++j )
    2258             :                 {
    2259         579 :                     nExpectedPairCount += aSegments[j].Count;
    2260             :                 }
    2261             : 
    2262         106 :                 if ( nExpectedPairCount > aPairs.getLength() )
    2263             :                 {
    2264             :                     SAL_WARN("oox", "Segments need " << nExpectedPairCount << " coordinates, but Coordinates have only " << aPairs.getLength() << " pairs.");
    2265           0 :                     return;
    2266             :                 }
    2267             : 
    2268         106 :                 mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
    2269         106 :                 mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
    2270         106 :                 mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
    2271         106 :                 mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
    2272             :                 mpFS->singleElementNS( XML_a, XML_rect, XML_l, "l", XML_t, "t",
    2273         106 :                         XML_r, "r", XML_b, "b", FSEND );
    2274         106 :                 mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
    2275             : 
    2276         106 :                 if ( aPathSize.hasElements() )
    2277             :                 {
    2278             :                     mpFS->startElementNS( XML_a, XML_path,
    2279          26 :                           XML_w, I64S( aPathSize[0].Width ),
    2280          26 :                           XML_h, I64S( aPathSize[0].Height ),
    2281          52 :                           FSEND );
    2282             :                 }
    2283             :                 else
    2284             :                 {
    2285          80 :                     sal_Int32 nXMin(0);
    2286          80 :                     aPairs[0].First.Value >>= nXMin;
    2287          80 :                     sal_Int32 nXMax = nXMin;
    2288          80 :                     sal_Int32 nYMin(0);
    2289          80 :                     aPairs[0].Second.Value >>= nYMin;
    2290          80 :                     sal_Int32 nYMax = nYMin;
    2291             : 
    2292        2192 :                     for ( int j = 0; j < aPairs.getLength(); ++j )
    2293             :                     {
    2294        2112 :                         sal_Int32 nCandidate(0);
    2295        2112 :                         if ((aPairs[j].First.Value >>= nCandidate) && nCandidate < nXMin)
    2296           2 :                             nXMin = nCandidate;
    2297        2112 :                         if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate < nYMin)
    2298           0 :                             nYMin = nCandidate;
    2299        2112 :                         if ((aPairs[j].First.Value >>= nCandidate) && nCandidate > nXMax)
    2300          72 :                             nXMax = nCandidate;
    2301        2112 :                         if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate > nYMax)
    2302          64 :                             nYMax = nCandidate;
    2303             :                     }
    2304             :                     mpFS->startElementNS( XML_a, XML_path,
    2305             :                           XML_w, I64S( nXMax - nXMin ),
    2306             :                           XML_h, I64S( nYMax - nYMin ),
    2307          80 :                           FSEND );
    2308             :                 }
    2309             : 
    2310             : 
    2311         106 :                 int nPairIndex = 0;
    2312         685 :                 for( int j = 0; j < aSegments.getLength(); ++j )
    2313             :                 {
    2314         579 :                     if ( aSegments[ j ].Command == drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
    2315             :                     {
    2316          15 :                         mpFS->singleElementNS( XML_a, XML_close, FSEND );
    2317             :                     }
    2318        1974 :                     for ( int k = 0; k < aSegments[j].Count; ++k )
    2319             :                     {
    2320        1395 :                         switch( aSegments[ j ].Command )
    2321             :                         {
    2322             :                             case drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
    2323             :                             {
    2324         158 :                                 mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
    2325             : 
    2326         158 :                                 sal_Int32 nX(0), nY(0);
    2327         158 :                                 aPairs[nPairIndex].First.Value >>= nX;
    2328         158 :                                 aPairs[nPairIndex].Second.Value >>= nY;
    2329             : 
    2330             :                                 mpFS->singleElementNS( XML_a, XML_pt,
    2331             :                                    XML_x, I64S(nX),
    2332             :                                    XML_y, I64S(nY),
    2333         158 :                                    FSEND );
    2334             : 
    2335         158 :                                 mpFS->endElementNS( XML_a, XML_moveTo );
    2336         158 :                                 nPairIndex++;
    2337         158 :                                 break;
    2338             :                             }
    2339             :                             case drawing::EnhancedCustomShapeSegmentCommand::LINETO :
    2340             :                             {
    2341         672 :                                 mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
    2342             : 
    2343         672 :                                 sal_Int32 nX(0), nY(0);
    2344         672 :                                 aPairs[nPairIndex].First.Value >>= nX;
    2345         672 :                                 aPairs[nPairIndex].Second.Value >>= nY;
    2346             : 
    2347             :                                 mpFS->singleElementNS( XML_a, XML_pt,
    2348             :                                    XML_x, I64S(nX),
    2349             :                                    XML_y, I64S(nY),
    2350         672 :                                    FSEND );
    2351         672 :                                 mpFS->endElementNS( XML_a, XML_lnTo );
    2352         672 :                                 nPairIndex++;
    2353         672 :                                 break;
    2354             :                             }
    2355             :                             case drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
    2356             :                             {
    2357         562 :                                 mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
    2358        2248 :                                 for( sal_uInt8 l = 0; l <= 2; ++l )
    2359             :                                 {
    2360        1686 :                                     sal_Int32 nX(0), nY(0);
    2361        1686 :                                     aPairs[nPairIndex+l].First.Value >>= nX;
    2362        1686 :                                     aPairs[nPairIndex+l].Second.Value >>= nY;
    2363             : 
    2364             :                                     mpFS->singleElementNS( XML_a, XML_pt,
    2365             :                                     XML_x, I64S( nX ),
    2366             :                                     XML_y, I64S( nY ),
    2367        1686 :                                     FSEND );
    2368             : 
    2369             :                                 }
    2370         562 :                                 mpFS->endElementNS( XML_a, XML_cubicBezTo );
    2371         562 :                                 nPairIndex += 3;
    2372         562 :                                 break;
    2373             :                             }
    2374             :                             case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
    2375             :                             case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
    2376             :                             {
    2377           1 :                                 nPairIndex += 3;
    2378           1 :                                 break;
    2379             :                             }
    2380             :                             case drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
    2381             :                             case drawing::EnhancedCustomShapeSegmentCommand::ARC :
    2382             :                             case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
    2383             :                             case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
    2384             :                             {
    2385           2 :                                 nPairIndex += 4;
    2386           2 :                                 break;
    2387             :                             }
    2388             :                             case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
    2389             :                             case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
    2390             :                             {
    2391           0 :                                 nPairIndex++;
    2392           0 :                                 break;
    2393             :                             }
    2394             :                             case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO :
    2395             :                             {
    2396           0 :                                 mpFS->startElementNS( XML_a, XML_quadBezTo, FSEND );
    2397           0 :                                 for( sal_uInt8 l = 0; l < 2; ++l )
    2398             :                                 {
    2399           0 :                                     sal_Int32 nX(0), nY(0);
    2400           0 :                                     aPairs[nPairIndex+l].First.Value >>= nX;
    2401           0 :                                     aPairs[nPairIndex+l].Second.Value >>= nY;
    2402             : 
    2403             :                                     mpFS->singleElementNS( XML_a, XML_pt,
    2404             :                                         XML_x, I64S( nX ),
    2405             :                                         XML_y, I64S( nY ),
    2406           0 :                                         FSEND );
    2407             : 
    2408             :                                 }
    2409           0 :                                 mpFS->endElementNS( XML_a, XML_quadBezTo );
    2410           0 :                                 nPairIndex += 2;
    2411           0 :                                 break;
    2412             :                             }
    2413             :                             case drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO :
    2414             :                             {
    2415           0 :                                 nPairIndex += 2;
    2416           0 :                                 break;
    2417             :                             }
    2418             :                             default:
    2419             :                                 // do nothing
    2420           0 :                                 break;
    2421             :                         }
    2422             :                     }
    2423             :                 }
    2424         106 :                 mpFS->endElementNS( XML_a, XML_path );
    2425         106 :                 mpFS->endElementNS( XML_a, XML_pathLst );
    2426         212 :                 mpFS->endElementNS( XML_a, XML_custGeom );
    2427             :             }
    2428             :         }
    2429         108 :     }
    2430             : 
    2431             : }
    2432             : 
    2433          44 : void DrawingML::WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon )
    2434             : {
    2435          44 :     if( rPolyPolygon.Count() < 1 )
    2436          44 :         return;
    2437             : 
    2438          44 :     mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
    2439          44 :     mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
    2440          44 :     mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
    2441          44 :     mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
    2442             :     mpFS->singleElementNS( XML_a, XML_rect,
    2443             :                            XML_l, "0",
    2444             :                            XML_t, "0",
    2445             :                            XML_r, "r",
    2446             :                            XML_b, "b",
    2447          44 :                            FSEND );
    2448             : 
    2449          44 :     mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
    2450             : 
    2451         126 :     for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ )
    2452             :     {
    2453             : 
    2454          82 :         const Polygon& rPoly = rPolyPolygon[ i ];
    2455          82 :         Rectangle aRect( rPoly.GetBoundRect() );
    2456             : 
    2457             :         mpFS->startElementNS( XML_a, XML_path,
    2458             :                               XML_w, I64S( aRect.GetWidth() ),
    2459             :                               XML_h, I64S( aRect.GetHeight() ),
    2460          82 :                               FSEND );
    2461             : 
    2462          82 :         if( rPoly.GetSize() > 0 )
    2463             :         {
    2464          82 :             mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
    2465             : 
    2466             :             mpFS->singleElementNS( XML_a, XML_pt,
    2467          82 :                                    XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
    2468          82 :                                    XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
    2469         164 :                                    FSEND );
    2470             : 
    2471          82 :             mpFS->endElementNS( XML_a, XML_moveTo );
    2472             :         }
    2473             : 
    2474         755 :         for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
    2475             :         {
    2476         673 :             enum PolyFlags flags = rPoly.GetFlags(j);
    2477         673 :             if( flags == POLY_CONTROL )
    2478             :             {
    2479             :                 // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
    2480         210 :                 if( j+2 < rPoly.GetSize() && rPoly.GetFlags(j+1) == POLY_CONTROL && rPoly.GetFlags(j+2) != POLY_CONTROL )
    2481             :                 {
    2482             : 
    2483         210 :                     mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
    2484         840 :                     for( sal_uInt8 k = 0; k <= 2; ++k )
    2485             :                     {
    2486             :                         mpFS->singleElementNS( XML_a, XML_pt,
    2487         630 :                                                XML_x, I64S( rPoly[j+k].X() - aRect.Left() ),
    2488         630 :                                                XML_y, I64S( rPoly[j+k].Y() - aRect.Top() ),
    2489        1260 :                                                FSEND );
    2490             : 
    2491             :                     }
    2492         210 :                     mpFS->endElementNS( XML_a, XML_cubicBezTo );
    2493         210 :                     j += 2;
    2494             :                 }
    2495             :             }
    2496         463 :             else if( flags == POLY_NORMAL )
    2497             :             {
    2498         463 :                 mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
    2499             :                 mpFS->singleElementNS( XML_a, XML_pt,
    2500         463 :                                        XML_x, I64S( rPoly[j].X() - aRect.Left() ),
    2501         463 :                                        XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
    2502         926 :                                        FSEND );
    2503         463 :                 mpFS->endElementNS( XML_a, XML_lnTo );
    2504             :             }
    2505             :         }
    2506             : 
    2507          82 :         mpFS->endElementNS( XML_a, XML_path );
    2508             :     }
    2509             : 
    2510          44 :     mpFS->endElementNS( XML_a, XML_pathLst );
    2511             : 
    2512          44 :     mpFS->endElementNS( XML_a, XML_custGeom );
    2513             : }
    2514             : 
    2515           0 : void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
    2516             : {
    2517           0 :     if( nStartID != -1 )
    2518             :     {
    2519             :         mpFS->singleElementNS( XML_a, XML_stCxn,
    2520             :                                XML_id, I32S( nStartID ),
    2521           0 :                                XML_idx, I64S( rConnectorEntry.GetConnectorRule( true ) ),
    2522           0 :                                FSEND );
    2523             :     }
    2524           0 :     if( nEndID != -1 )
    2525             :     {
    2526             :         mpFS->singleElementNS( XML_a, XML_endCxn,
    2527             :                                XML_id, I32S( nEndID ),
    2528           0 :                                XML_idx, I64S( rConnectorEntry.GetConnectorRule( false ) ),
    2529           0 :                                FSEND );
    2530             :     }
    2531           0 : }
    2532             : 
    2533         110 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
    2534             : {
    2535         110 :     if ( IsStarSymbol(rFontDesc.Name) )
    2536             :     {
    2537          86 :         rtl_TextEncoding eCharSet = rFontDesc.CharSet;
    2538          86 :         cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
    2539          86 :         rFontDesc.CharSet = eCharSet;
    2540             :     }
    2541             : 
    2542         110 :     return cBulletId;
    2543             : }
    2544             : 
    2545          24 : sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
    2546             :     const OUString& sFullStream,
    2547             :     const OUString& sRelativeStream,
    2548             :     const Reference< XOutputStream >& xParentRelation,
    2549             :     const char* sContentType,
    2550             :     const char* sRelationshipType,
    2551             :     OUString* pRelationshipId )
    2552             : {
    2553          24 :     OUString sRelationshipId;
    2554          24 :     if (xParentRelation.is())
    2555          24 :         sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
    2556             :     else
    2557           0 :         sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
    2558             : 
    2559          24 :     if( pRelationshipId )
    2560          24 :         *pRelationshipId = sRelationshipId;
    2561             : 
    2562          24 :     sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
    2563             : 
    2564          24 :     return p;
    2565             : }
    2566             : 
    2567        1186 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
    2568             : {
    2569        1186 :     if ( !GetProperty( xPropSet, "FillStyle" ) )
    2570         194 :         return;
    2571         992 :     FillStyle aFillStyle( FillStyle_NONE );
    2572         992 :     xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
    2573             : 
    2574         992 :     if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ) )
    2575             :     {
    2576             :         // map full transparent background to no fill
    2577         613 :         sal_Int16 nVal = 0;
    2578         613 :         xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
    2579         613 :         if ( nVal == 100 )
    2580           3 :             aFillStyle = FillStyle_NONE;
    2581             :     }
    2582             : 
    2583         992 :     switch( aFillStyle )
    2584             :     {
    2585             :     case FillStyle_SOLID :
    2586         611 :         WriteSolidFill( xPropSet );
    2587         611 :         break;
    2588             :     case FillStyle_GRADIENT :
    2589          57 :         WriteGradientFill( xPropSet );
    2590          57 :         break;
    2591             :     case FillStyle_BITMAP :
    2592           5 :         WriteBlipFill( xPropSet, "FillBitmapURL" );
    2593           5 :         break;
    2594             :     case FillStyle_HATCH :
    2595          14 :         WritePattFill( xPropSet );
    2596          14 :         break;
    2597             :     case FillStyle_NONE:
    2598         305 :         mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
    2599         305 :         break;
    2600             :     default:
    2601             :         ;
    2602             :     }
    2603             : 
    2604         992 :     return;
    2605             : }
    2606             : 
    2607        1287 : void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, const Sequence< PropertyValue >& aProperties )
    2608             : {
    2609        1287 :     if( aProperties.getLength() > 0 )
    2610             :     {
    2611         386 :         OUString sSchemeClr;
    2612         386 :         sal_uInt32 nIdx = 0;
    2613         772 :         Sequence< PropertyValue > aTransformations;
    2614        2218 :         for( sal_Int32 i=0; i < aProperties.getLength(); ++i)
    2615             :         {
    2616        1832 :             if( aProperties[i].Name == "SchemeClr" )
    2617         386 :                 aProperties[i].Value >>= sSchemeClr;
    2618        1446 :             else if( aProperties[i].Name == "Idx" )
    2619         386 :                 aProperties[i].Value >>= nIdx;
    2620        1060 :             else if( aProperties[i].Name == "Transformations" )
    2621         386 :                 aProperties[i].Value >>= aTransformations;
    2622             :         }
    2623         386 :         mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
    2624         386 :         WriteColor( sSchemeClr, aTransformations );
    2625         772 :         mpFS->endElementNS( XML_a, nTokenId );
    2626             :     }
    2627             :     else
    2628             :     {
    2629             :         // write mock <a:*Ref> tag
    2630         901 :         mpFS->singleElementNS( XML_a, nTokenId, XML_idx, I32S( 0 ), FSEND );
    2631             :     }
    2632        1287 : }
    2633             : 
    2634         429 : void DrawingML::WriteShapeStyle( Reference< XPropertySet > xPropSet )
    2635             : {
    2636             :     // check existence of the grab bag
    2637         429 :     if ( !GetProperty( xPropSet, "InteropGrabBag" ) )
    2638         429 :         return;
    2639             : 
    2640             :     // extract the relevant properties from the grab bag
    2641         429 :     Sequence< PropertyValue > aGrabBag;
    2642         858 :     Sequence< PropertyValue > aFillRefProperties, aLnRefProperties, aEffectRefProperties;
    2643         429 :     mAny >>= aGrabBag;
    2644        2348 :     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
    2645             :     {
    2646        1919 :         if( aGrabBag[i].Name == "StyleFillRef" )
    2647          98 :             aGrabBag[i].Value >>= aFillRefProperties;
    2648        1821 :         else if( aGrabBag[i].Name == "StyleLnRef" )
    2649         144 :             aGrabBag[i].Value >>= aLnRefProperties;
    2650        1677 :         else if( aGrabBag[i].Name == "StyleEffectRef" )
    2651         144 :             aGrabBag[i].Value >>= aEffectRefProperties;
    2652             :     }
    2653             : 
    2654         429 :     WriteStyleProperties( XML_lnRef, aLnRefProperties );
    2655         429 :     WriteStyleProperties( XML_fillRef, aFillRefProperties );
    2656         429 :     WriteStyleProperties( XML_effectRef, aEffectRefProperties );
    2657             : 
    2658             :     // write mock <a:fontRef>
    2659         858 :     mpFS->singleElementNS( XML_a, XML_fontRef, XML_idx, "minor", FSEND );
    2660             : }
    2661             : 
    2662          78 : void DrawingML::WriteShapeEffect( const OUString& sName, const Sequence< PropertyValue >& aEffectProps )
    2663             : {
    2664          78 :     if( aEffectProps.getLength() == 0 )
    2665          78 :         return;
    2666             : 
    2667             :     // assign the proper tag and enable bContainsColor if necessary
    2668          78 :     sal_Int32 nEffectToken = 0;
    2669          78 :     bool bContainsColor = false;
    2670          78 :     if( sName == "outerShdw" )
    2671             :     {
    2672          59 :         nEffectToken = FSNS( XML_a, XML_outerShdw );
    2673          59 :         bContainsColor = true;
    2674             :     }
    2675          19 :     else if( sName == "innerShdw" )
    2676             :     {
    2677           2 :         nEffectToken = FSNS( XML_a, XML_innerShdw );
    2678           2 :         bContainsColor = true;
    2679             :     }
    2680          17 :     else if( sName == "glow" )
    2681             :     {
    2682           8 :         nEffectToken = FSNS( XML_a, XML_glow );
    2683           8 :         bContainsColor = true;
    2684             :     }
    2685           9 :     else if( sName == "softEdge" )
    2686           2 :         nEffectToken = FSNS( XML_a, XML_softEdge );
    2687           7 :     else if( sName == "reflection" )
    2688           7 :         nEffectToken = FSNS( XML_a, XML_reflection );
    2689           0 :     else if( sName == "blur" )
    2690           0 :         nEffectToken = FSNS( XML_a, XML_blur );
    2691             : 
    2692          78 :     OUString sSchemeClr;
    2693          78 :     sal_uInt32 nRgbClr = 0;
    2694          78 :     sal_Int32 nAlpha = MAX_PERCENT;
    2695         156 :     Sequence< PropertyValue > aTransformations;
    2696          78 :     sax_fastparser::FastAttributeList *aOuterShdwAttrList = FastSerializerHelper::createAttrList();
    2697         156 :     sax_fastparser::XFastAttributeListRef xOuterShdwAttrList( aOuterShdwAttrList );
    2698         312 :     for( sal_Int32 i=0; i < aEffectProps.getLength(); ++i )
    2699             :     {
    2700         234 :         if( aEffectProps[i].Name == "Attribs" )
    2701             :         {
    2702             :             // read tag attributes
    2703          78 :             uno::Sequence< beans::PropertyValue > aOuterShdwProps;
    2704          78 :             aEffectProps[i].Value >>= aOuterShdwProps;
    2705         355 :             for( sal_Int32 j=0; j < aOuterShdwProps.getLength(); ++j )
    2706             :             {
    2707         277 :                 if( aOuterShdwProps[j].Name == "algn" )
    2708             :                 {
    2709          57 :                     OUString sVal;
    2710          57 :                     aOuterShdwProps[j].Value >>= sVal;
    2711          57 :                     aOuterShdwAttrList->add( XML_algn, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
    2712             :                 }
    2713         220 :                 else if( aOuterShdwProps[j].Name == "blurRad" )
    2714             :                 {
    2715          27 :                     sal_Int32 nVal = 0;
    2716          27 :                     aOuterShdwProps[j].Value >>= nVal;
    2717          27 :                     aOuterShdwAttrList->add( XML_blurRad, OString::number( nVal ).getStr() );
    2718             :                 }
    2719         193 :                 else if( aOuterShdwProps[j].Name == "dir" )
    2720             :                 {
    2721          30 :                     sal_Int32 nVal = 0;
    2722          30 :                     aOuterShdwProps[j].Value >>= nVal;
    2723          30 :                     aOuterShdwAttrList->add( XML_dir, OString::number( nVal ).getStr() );
    2724             :                 }
    2725         163 :                 else if( aOuterShdwProps[j].Name == "dist" )
    2726             :                 {
    2727          63 :                     sal_Int32 nVal = 0;
    2728          63 :                     aOuterShdwProps[j].Value >>= nVal;
    2729          63 :                     aOuterShdwAttrList->add( XML_dist, OString::number( nVal ).getStr() );
    2730             :                 }
    2731         100 :                 else if( aOuterShdwProps[j].Name == "kx" )
    2732             :                 {
    2733           0 :                     sal_Int32 nVal = 0;
    2734           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2735           0 :                     aOuterShdwAttrList->add( XML_kx, OString::number( nVal ).getStr() );
    2736             :                 }
    2737         100 :                 else if( aOuterShdwProps[j].Name == "ky" )
    2738             :                 {
    2739           0 :                     sal_Int32 nVal = 0;
    2740           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2741           0 :                     aOuterShdwAttrList->add( XML_ky, OString::number( nVal ).getStr() );
    2742             :                 }
    2743         100 :                 else if( aOuterShdwProps[j].Name == "rotWithShape" )
    2744             :                 {
    2745          63 :                     sal_Int32 nVal = 0;
    2746          63 :                     aOuterShdwProps[j].Value >>= nVal;
    2747          63 :                     aOuterShdwAttrList->add( XML_rotWithShape, OString::number( nVal ).getStr() );
    2748             :                 }
    2749          37 :                 else if( aOuterShdwProps[j].Name == "sx" )
    2750             :                 {
    2751           0 :                     sal_Int32 nVal = 0;
    2752           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2753           0 :                     aOuterShdwAttrList->add( XML_sx, OString::number( nVal ).getStr() );
    2754             :                 }
    2755          37 :                 else if( aOuterShdwProps[j].Name == "sy" )
    2756             :                 {
    2757           7 :                     sal_Int32 nVal = 0;
    2758           7 :                     aOuterShdwProps[j].Value >>= nVal;
    2759           7 :                     aOuterShdwAttrList->add( XML_sy, OString::number( nVal ).getStr() );
    2760             :                 }
    2761          30 :                 else if( aOuterShdwProps[j].Name == "rad" )
    2762             :                 {
    2763          10 :                     sal_Int32 nVal = 0;
    2764          10 :                     aOuterShdwProps[j].Value >>= nVal;
    2765          10 :                     aOuterShdwAttrList->add( XML_rad, OString::number( nVal ).getStr() );
    2766             :                 }
    2767          20 :                 else if( aOuterShdwProps[j].Name == "endA" )
    2768             :                 {
    2769           6 :                     sal_Int32 nVal = 0;
    2770           6 :                     aOuterShdwProps[j].Value >>= nVal;
    2771           6 :                     aOuterShdwAttrList->add( XML_endA, OString::number( nVal ).getStr() );
    2772             :                 }
    2773          14 :                 else if( aOuterShdwProps[j].Name == "endPos" )
    2774             :                 {
    2775           7 :                     sal_Int32 nVal = 0;
    2776           7 :                     aOuterShdwProps[j].Value >>= nVal;
    2777           7 :                     aOuterShdwAttrList->add( XML_endPos, OString::number( nVal ).getStr() );
    2778             :                 }
    2779           7 :                 else if( aOuterShdwProps[j].Name == "fadeDir" )
    2780             :                 {
    2781           0 :                     sal_Int32 nVal = 0;
    2782           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2783           0 :                     aOuterShdwAttrList->add( XML_fadeDir, OString::number( nVal ).getStr() );
    2784             :                 }
    2785           7 :                 else if( aOuterShdwProps[j].Name == "stA" )
    2786             :                 {
    2787           7 :                     sal_Int32 nVal = 0;
    2788           7 :                     aOuterShdwProps[j].Value >>= nVal;
    2789           7 :                     aOuterShdwAttrList->add( XML_stA, OString::number( nVal ).getStr() );
    2790             :                 }
    2791           0 :                 else if( aOuterShdwProps[j].Name == "stPos" )
    2792             :                 {
    2793           0 :                     sal_Int32 nVal = 0;
    2794           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2795           0 :                     aOuterShdwAttrList->add( XML_stPos, OString::number( nVal ).getStr() );
    2796             :                 }
    2797           0 :                 else if( aOuterShdwProps[j].Name == "grow" )
    2798             :                 {
    2799           0 :                     sal_Int32 nVal = 0;
    2800           0 :                     aOuterShdwProps[j].Value >>= nVal;
    2801           0 :                     aOuterShdwAttrList->add( XML_grow, OString::number( nVal ).getStr() );
    2802             :                 }
    2803          78 :             }
    2804             :         }
    2805         156 :         else if(aEffectProps[i].Name == "RgbClr")
    2806             :         {
    2807          69 :             aEffectProps[i].Value >>= nRgbClr;
    2808             :         }
    2809          87 :         else if(aEffectProps[i].Name == "RgbClrTransparency")
    2810             :         {
    2811             :             sal_Int32 nTransparency;
    2812          69 :             if (aEffectProps[i].Value >>= nTransparency)
    2813             :                 // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
    2814          69 :                 nAlpha = MAX_PERCENT - ( PER_PERCENT * nTransparency );
    2815             :         }
    2816          18 :         else if(aEffectProps[i].Name == "SchemeClr")
    2817             :         {
    2818           9 :             aEffectProps[i].Value >>= sSchemeClr;
    2819             :         }
    2820           9 :         else if(aEffectProps[i].Name == "SchemeClrTransformations")
    2821             :         {
    2822           9 :             aEffectProps[i].Value >>= aTransformations;
    2823             :         }
    2824             :     }
    2825             : 
    2826          78 :     if( nEffectToken > 0 )
    2827             :     {
    2828          78 :         mpFS->startElement( nEffectToken, xOuterShdwAttrList );
    2829             : 
    2830          78 :         if( bContainsColor )
    2831             :         {
    2832          69 :             if( sSchemeClr.isEmpty() )
    2833          60 :                 WriteColor( nRgbClr, nAlpha );
    2834             :             else
    2835           9 :                 WriteColor( sSchemeClr, aTransformations );
    2836             :         }
    2837             : 
    2838          78 :         mpFS->endElement( nEffectToken );
    2839          78 :     }
    2840             : }
    2841             : 
    2842         523 : void DrawingML::WriteShapeEffects( Reference< XPropertySet > rXPropSet )
    2843             : {
    2844         523 :     if( !GetProperty( rXPropSet, "InteropGrabBag" ) )
    2845         456 :         return;
    2846             : 
    2847         590 :     Sequence< PropertyValue > aGrabBag, aEffects;
    2848         523 :     mAny >>= aGrabBag;
    2849        2114 :     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
    2850             :     {
    2851        1658 :         if( aGrabBag[i].Name == "EffectProperties" )
    2852             :         {
    2853          67 :             aGrabBag[i].Value >>= aEffects;
    2854          67 :             break;
    2855             :         }
    2856             :     }
    2857         523 :     if( aEffects.getLength() == 0 )
    2858             :     {
    2859         456 :         bool bHasShadow = false;
    2860         456 :         rXPropSet->getPropertyValue( "Shadow" ) >>= bHasShadow;
    2861         456 :         if( bHasShadow )
    2862             :         {
    2863           2 :             Sequence< PropertyValue > aShadowGrabBag( 3 );
    2864           4 :             Sequence< PropertyValue > aShadowAttribsGrabBag( 2 );
    2865             : 
    2866           2 :             double dX = +0.0, dY = +0.0;
    2867           2 :             rXPropSet->getPropertyValue( "ShadowXDistance" ) >>= dX;
    2868           2 :             rXPropSet->getPropertyValue( "ShadowYDistance" ) >>= dY;
    2869             : 
    2870           2 :             aShadowAttribsGrabBag[0].Name = "dist";
    2871           2 :             aShadowAttribsGrabBag[0].Value = Any(static_cast< sal_Int32 >(sqrt(dX*dX + dY*dY) * 360));
    2872           2 :             aShadowAttribsGrabBag[1].Name = "dir";
    2873           2 :             aShadowAttribsGrabBag[1].Value = Any(static_cast< sal_Int32 >(atan2(dY,dX) * 180 * 60000 / M_PI));
    2874             : 
    2875           2 :             aShadowGrabBag[0].Name = "Attribs";
    2876           2 :             aShadowGrabBag[0].Value = Any(aShadowAttribsGrabBag);
    2877           2 :             aShadowGrabBag[1].Name = "RgbClr";
    2878           2 :             aShadowGrabBag[1].Value = rXPropSet->getPropertyValue( "ShadowColor" );
    2879           2 :             aShadowGrabBag[2].Name = "RgbClrTransparency";
    2880           2 :             aShadowGrabBag[2].Value = rXPropSet->getPropertyValue( "ShadowTransparence" );
    2881             : 
    2882           2 :             mpFS->startElementNS(XML_a, XML_effectLst, FSEND);
    2883           2 :             WriteShapeEffect( "outerShdw", aShadowGrabBag );
    2884           4 :             mpFS->endElementNS(XML_a, XML_effectLst);
    2885             :         }
    2886         456 :         return;
    2887             :     }
    2888             : 
    2889          67 :     mpFS->startElementNS(XML_a, XML_effectLst, FSEND);
    2890             : 
    2891         143 :     for( sal_Int32 i=0; i < aEffects.getLength(); ++i )
    2892             :     {
    2893          76 :         Sequence< PropertyValue > aEffectProps;
    2894          76 :         aEffects[i].Value >>= aEffectProps;
    2895          76 :         WriteShapeEffect( aEffects[i].Name, aEffectProps );
    2896          76 :     }
    2897             : 
    2898         134 :     mpFS->endElementNS(XML_a, XML_effectLst);
    2899             : }
    2900             : 
    2901         523 : void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
    2902             : {
    2903             :     // check existence of the grab bag
    2904         523 :     if( !GetProperty( xPropSet, "InteropGrabBag" ) )
    2905         515 :         return;
    2906             : 
    2907             :     // extract the relevant properties from the grab bag
    2908         531 :     Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps, aShape3DProps;
    2909         523 :     mAny >>= aGrabBag;
    2910        2387 :     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
    2911             :     {
    2912        1873 :         if( aGrabBag[i].Name == "3DEffectProperties" )
    2913             :         {
    2914           9 :             Sequence< PropertyValue > a3DEffectProps;
    2915           9 :             aGrabBag[i].Value >>= a3DEffectProps;
    2916          36 :             for( sal_Int32 j=0; j < a3DEffectProps.getLength(); ++j )
    2917             :             {
    2918          27 :                 if( a3DEffectProps[j].Name == "Camera" )
    2919           9 :                     a3DEffectProps[j].Value >>= aEffectProps;
    2920          18 :                 else if( a3DEffectProps[j].Name == "LightRig" )
    2921           9 :                     a3DEffectProps[j].Value >>= aLightRigProps;
    2922           9 :                 else if( a3DEffectProps[j].Name == "Shape3D" )
    2923           9 :                     a3DEffectProps[j].Value >>= aShape3DProps;
    2924             :             }
    2925           9 :             break;
    2926             :         }
    2927             :     }
    2928         523 :     if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 && aShape3DProps.getLength() == 0 )
    2929         514 :         return;
    2930             : 
    2931           9 :     bool bCameraRotationPresent = false;
    2932           9 :     sax_fastparser::FastAttributeList *aCameraAttrList = FastSerializerHelper::createAttrList();
    2933          17 :     sax_fastparser::XFastAttributeListRef xCameraAttrList( aCameraAttrList );
    2934           9 :     sax_fastparser::FastAttributeList *aCameraRotationAttrList = FastSerializerHelper::createAttrList();
    2935          17 :     sax_fastparser::XFastAttributeListRef xRotAttrList( aCameraRotationAttrList );
    2936          25 :     for( sal_Int32 i=0; i < aEffectProps.getLength(); ++i )
    2937             :     {
    2938          16 :         if( aEffectProps[i].Name == "prst" )
    2939             :         {
    2940           9 :             OUString sVal;
    2941           9 :             aEffectProps[i].Value >>= sVal;
    2942           9 :             aCameraAttrList->add( XML_prst, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
    2943             :         }
    2944           7 :         else if( aEffectProps[i].Name == "fov" )
    2945             :         {
    2946           0 :             float fVal = 0;
    2947           0 :             aEffectProps[i].Value >>= fVal;
    2948           0 :             aCameraAttrList->add( XML_fov, OString::number( fVal * 60000 ).getStr() );
    2949             :         }
    2950           7 :         else if( aEffectProps[i].Name == "zoom" )
    2951             :         {
    2952           1 :             float fVal = 1;
    2953           1 :             aEffectProps[i].Value >>= fVal;
    2954           1 :             aCameraAttrList->add( XML_zoom, OString::number( fVal * 100000 ).getStr() );
    2955             :         }
    2956          16 :         else if( aEffectProps[i].Name == "rotLat" ||
    2957           8 :                 aEffectProps[i].Name == "rotLon" ||
    2958           2 :                 aEffectProps[i].Name == "rotRev" )
    2959             :         {
    2960           6 :             sal_Int32 nVal = 0, nToken = XML_none;
    2961           6 :             aEffectProps[i].Value >>= nVal;
    2962           6 :             if( aEffectProps[i].Name == "rotLat" )
    2963           2 :                 nToken = XML_lat;
    2964           4 :             else if( aEffectProps[i].Name == "rotLon" )
    2965           2 :                 nToken = XML_lon;
    2966           2 :             else if( aEffectProps[i].Name == "rotRev" )
    2967           2 :                 nToken = XML_rev;
    2968           6 :             aCameraRotationAttrList->add( nToken, OString::number( nVal ).getStr() );
    2969           6 :             bCameraRotationPresent = true;
    2970             :         }
    2971             :     }
    2972             : 
    2973           9 :     bool bLightRigRotationPresent = false;
    2974           9 :     sax_fastparser::FastAttributeList *aLightRigAttrList = FastSerializerHelper::createAttrList();
    2975          17 :     sax_fastparser::XFastAttributeListRef xLightAttrList( aLightRigAttrList );
    2976           9 :     sax_fastparser::FastAttributeList *aLightRigRotationAttrList = FastSerializerHelper::createAttrList();
    2977          17 :     sax_fastparser::XFastAttributeListRef xLightRotAttrList( aLightRigRotationAttrList );
    2978          42 :     for( sal_Int32 i=0; i < aLightRigProps.getLength(); ++i )
    2979             :     {
    2980          33 :         if( aLightRigProps[i].Name == "rig" || aLightRigProps[i].Name == "dir" )
    2981             :         {
    2982          18 :             OUString sVal;
    2983          18 :             sal_Int32 nToken = XML_none;
    2984          18 :             aLightRigProps[i].Value >>= sVal;
    2985          18 :             if( aLightRigProps[i].Name == "rig" )
    2986           9 :                 nToken = XML_rig;
    2987           9 :             else if( aLightRigProps[i].Name == "dir" )
    2988           9 :                 nToken = XML_dir;
    2989          18 :             aLightRigAttrList->add( nToken, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
    2990             :         }
    2991          40 :         else if( aLightRigProps[i].Name == "rotLat" ||
    2992          20 :                 aLightRigProps[i].Name == "rotLon" ||
    2993           5 :                 aLightRigProps[i].Name == "rotRev" )
    2994             :         {
    2995          15 :             sal_Int32 nVal = 0, nToken = XML_none;
    2996          15 :             aLightRigProps[i].Value >>= nVal;
    2997          15 :             if( aLightRigProps[i].Name == "rotLat" )
    2998           5 :                 nToken = XML_lat;
    2999          10 :             else if( aLightRigProps[i].Name == "rotLon" )
    3000           5 :                 nToken = XML_lon;
    3001           5 :             else if( aLightRigProps[i].Name == "rotRev" )
    3002           5 :                 nToken = XML_rev;
    3003          15 :             aLightRigRotationAttrList->add( nToken, OString::number( nVal ).getStr() );
    3004          15 :             bLightRigRotationPresent = true;
    3005             :         }
    3006             :     }
    3007             : 
    3008           9 :     mpFS->startElementNS( XML_a, XML_scene3d, FSEND );
    3009             : 
    3010           9 :     if( aEffectProps.getLength() > 0 )
    3011             :     {
    3012           9 :         mpFS->startElementNS( XML_a, XML_camera, xCameraAttrList );
    3013           9 :         if( bCameraRotationPresent )
    3014             :         {
    3015           2 :             mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
    3016             :         }
    3017           9 :         mpFS->endElementNS( XML_a, XML_camera );
    3018             :     }
    3019             :     else
    3020             :     {
    3021             :         // a:camera with Word default values - Word won't open the document if this is not present
    3022           0 :         mpFS->singleElementNS( XML_a, XML_camera, XML_prst, "orthographicFront", FSEND );
    3023             :     }
    3024             : 
    3025           9 :     if( aEffectProps.getLength() > 0 )
    3026             :     {
    3027           9 :         mpFS->startElementNS( XML_a, XML_lightRig, xLightAttrList );
    3028           9 :         if( bLightRigRotationPresent )
    3029             :         {
    3030           5 :             mpFS->singleElementNS( XML_a, XML_rot, xLightRotAttrList );
    3031             :         }
    3032           9 :         mpFS->endElementNS( XML_a, XML_lightRig );
    3033             :     }
    3034             :     else
    3035             :     {
    3036             :         // a:lightRig with Word default values - Word won't open the document if this is not present
    3037           0 :         mpFS->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
    3038             :     }
    3039             : 
    3040           9 :     mpFS->endElementNS( XML_a, XML_scene3d );
    3041             : 
    3042           9 :     if( aShape3DProps.getLength() == 0 )
    3043           1 :         return;
    3044             : 
    3045           8 :     bool bBevelTPresent = false, bBevelBPresent = false;
    3046          16 :     Sequence< PropertyValue > aExtrusionColorProps, aContourColorProps;
    3047           8 :     sax_fastparser::FastAttributeList *aBevelTAttrList = FastSerializerHelper::createAttrList();
    3048          16 :     sax_fastparser::XFastAttributeListRef xBevelTAttrList( aBevelTAttrList );
    3049           8 :     sax_fastparser::FastAttributeList *aBevelBAttrList = FastSerializerHelper::createAttrList();
    3050          16 :     sax_fastparser::XFastAttributeListRef xBevelBAttrList( aBevelBAttrList );
    3051           8 :     sax_fastparser::FastAttributeList *aShape3DAttrList = FastSerializerHelper::createAttrList();
    3052          29 :     for( sal_Int32 i=0; i < aShape3DProps.getLength(); ++i )
    3053             :     {
    3054          21 :         if( aShape3DProps[i].Name == "extrusionH" || aShape3DProps[i].Name == "contourW" || aShape3DProps[i].Name == "z" )
    3055             :         {
    3056           6 :             sal_Int32 nVal = 0, nToken = XML_none;
    3057           6 :             aShape3DProps[i].Value >>= nVal;
    3058           6 :             if( aShape3DProps[i].Name == "extrusionH" )
    3059           4 :                 nToken = XML_extrusionH;
    3060           2 :             else if( aShape3DProps[i].Name == "contourW" )
    3061           1 :                 nToken = XML_contourW;
    3062           1 :             else if( aShape3DProps[i].Name == "z" )
    3063           1 :                 nToken = XML_z;
    3064           6 :             aShape3DAttrList->add( nToken, OString::number( nVal ).getStr() );
    3065             :         }
    3066          15 :         else if( aShape3DProps[i].Name == "prstMaterial" )
    3067             :         {
    3068           6 :             OUString sVal;
    3069           6 :             aShape3DProps[i].Value >>= sVal;
    3070           6 :             aShape3DAttrList->add( XML_prstMaterial, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
    3071             :         }
    3072           9 :         else if( aShape3DProps[i].Name == "extrusionClr" )
    3073             :         {
    3074           2 :             aShape3DProps[i].Value >>= aExtrusionColorProps;
    3075             :         }
    3076           7 :         else if( aShape3DProps[i].Name == "contourClr" )
    3077             :         {
    3078           2 :             aShape3DProps[i].Value >>= aContourColorProps;
    3079             :         }
    3080           5 :         else if( aShape3DProps[i].Name == "bevelT" || aShape3DProps[i].Name == "bevelB" )
    3081             :         {
    3082           5 :             Sequence< PropertyValue > aBevelProps;
    3083           5 :             aShape3DProps[i].Value >>= aBevelProps;
    3084           5 :             if ( aBevelProps.getLength() == 0 )
    3085           0 :                 continue;
    3086             : 
    3087           5 :             sax_fastparser::FastAttributeList *aBevelAttrList = NULL;
    3088           5 :             if( aShape3DProps[i].Name == "bevelT" )
    3089             :             {
    3090           4 :                 bBevelTPresent = true;
    3091           4 :                 aBevelAttrList = aBevelTAttrList;
    3092             :             }
    3093             :             else
    3094             :             {
    3095           1 :                 bBevelBPresent = true;
    3096           1 :                 aBevelAttrList = aBevelBAttrList;
    3097             :             }
    3098          19 :             for( sal_Int32 j=0; j < aBevelProps.getLength(); ++j )
    3099             :             {
    3100          14 :                 if( aBevelProps[j].Name == "w" || aBevelProps[j].Name == "h" )
    3101             :                 {
    3102           9 :                     sal_Int32 nVal = 0, nToken = XML_none;
    3103           9 :                     aBevelProps[j].Value >>= nVal;
    3104           9 :                     if( aBevelProps[j].Name == "w" )
    3105           4 :                         nToken = XML_w;
    3106           5 :                     else if( aBevelProps[j].Name == "h" )
    3107           5 :                         nToken = XML_h;
    3108           9 :                     aBevelAttrList->add( nToken, OString::number( nVal ).getStr() );
    3109             :                 }
    3110           5 :                 else  if( aBevelProps[j].Name == "prst" )
    3111             :                 {
    3112           5 :                     OUString sVal;
    3113           5 :                     aBevelProps[j].Value >>= sVal;
    3114           5 :                     aBevelAttrList->add( XML_prst, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
    3115             :                 }
    3116           5 :             }
    3117             : 
    3118             :         }
    3119             :     }
    3120             : 
    3121          16 :     sax_fastparser::XFastAttributeListRef xAttrList( aShape3DAttrList );
    3122           8 :     mpFS->startElementNS( XML_a, XML_sp3d, xAttrList );
    3123           8 :     if( bBevelTPresent )
    3124             :     {
    3125           4 :         mpFS->singleElementNS( XML_a, XML_bevelT, xBevelTAttrList );
    3126             :     }
    3127           8 :     if( bBevelBPresent )
    3128             :     {
    3129           1 :         mpFS->singleElementNS( XML_a, XML_bevelB, xBevelBAttrList );
    3130             :     }
    3131           8 :     if( aExtrusionColorProps.getLength() > 0 )
    3132             :     {
    3133           2 :         OUString sSchemeClr;
    3134           2 :         sal_Int32 nColor(0);
    3135           2 :         sal_Int32 nTransparency(0);
    3136           4 :         Sequence< PropertyValue > aColorTransformations;
    3137           6 :         for( sal_Int32 i=0; i < aExtrusionColorProps.getLength(); ++i )
    3138             :         {
    3139           4 :             if( aExtrusionColorProps[i].Name == "schemeClr" )
    3140           1 :                 aExtrusionColorProps[i].Value >>= sSchemeClr;
    3141           3 :             else if( aExtrusionColorProps[i].Name == "schemeClrTransformations" )
    3142           1 :                 aExtrusionColorProps[i].Value >>= aColorTransformations;
    3143           2 :             else if( aExtrusionColorProps[i].Name == "rgbClr" )
    3144           1 :                 aExtrusionColorProps[i].Value >>= nColor;
    3145           1 :             else if( aExtrusionColorProps[i].Name == "rgbClrTransparency" )
    3146           1 :                 aExtrusionColorProps[i].Value >>= nTransparency;
    3147             :         }
    3148           2 :         mpFS->startElementNS( XML_a, XML_extrusionClr, FSEND );
    3149             : 
    3150           2 :         if( sSchemeClr.isEmpty() )
    3151           1 :             WriteColor( nColor, MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
    3152             :         else
    3153           1 :             WriteColor( sSchemeClr, aColorTransformations );
    3154             : 
    3155           4 :         mpFS->endElementNS( XML_a, XML_extrusionClr );
    3156             :     }
    3157           8 :     if( aContourColorProps.getLength() > 0 )
    3158             :     {
    3159           2 :         OUString sSchemeClr;
    3160           2 :         sal_Int32 nColor(0);
    3161           2 :         sal_Int32 nTransparency(0);
    3162           4 :         Sequence< PropertyValue > aColorTransformations;
    3163           6 :         for( sal_Int32 i=0; i < aContourColorProps.getLength(); ++i )
    3164             :         {
    3165           4 :             if( aContourColorProps[i].Name == "schemeClr" )
    3166           1 :                 aContourColorProps[i].Value >>= sSchemeClr;
    3167           3 :             else if( aContourColorProps[i].Name == "schemeClrTransformations" )
    3168           1 :                 aContourColorProps[i].Value >>= aColorTransformations;
    3169           2 :             else if( aContourColorProps[i].Name == "rgbClr" )
    3170           1 :                 aContourColorProps[i].Value >>= nColor;
    3171           1 :             else if( aContourColorProps[i].Name == "rgbClrTransparency" )
    3172           1 :                 aContourColorProps[i].Value >>= nTransparency;
    3173             :         }
    3174           2 :         mpFS->startElementNS( XML_a, XML_contourClr, FSEND );
    3175             : 
    3176           2 :         if( sSchemeClr.isEmpty() )
    3177           1 :             WriteColor( nColor, MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
    3178             :         else
    3179           1 :             WriteColor( sSchemeClr, aContourColorProps );
    3180             : 
    3181           4 :         mpFS->endElementNS( XML_a, XML_contourClr );
    3182             :     }
    3183          16 :     mpFS->endElementNS( XML_a, XML_sp3d );
    3184             : }
    3185             : 
    3186         116 : void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
    3187             : {
    3188         116 :     if( !GetProperty( rXPropSet, "InteropGrabBag" ) )
    3189         112 :         return;
    3190             : 
    3191         114 :     PropertyValue aEffect;
    3192         120 :     Sequence< PropertyValue > aGrabBag;
    3193         114 :     mAny >>= aGrabBag;
    3194         186 :     for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
    3195             :     {
    3196          78 :         if( aGrabBag[i].Name == "ArtisticEffectProperties" )
    3197             :         {
    3198           6 :             aGrabBag[i].Value >>= aEffect;
    3199           6 :             break;
    3200             :         }
    3201             :     }
    3202         114 :     sal_Int32 nEffectToken = ArtisticEffectProperties::getEffectToken( aEffect.Name );
    3203         114 :     if( nEffectToken == XML_none )
    3204         108 :         return;
    3205             : 
    3206          12 :     Sequence< PropertyValue > aAttrs;
    3207           6 :     aEffect.Value >>= aAttrs;
    3208           6 :     sax_fastparser::FastAttributeList *aAttrList = FastSerializerHelper::createAttrList();
    3209          12 :     OString sRelId;
    3210          21 :     for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
    3211             :     {
    3212          15 :         sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
    3213          15 :         if( nToken != XML_none )
    3214             :         {
    3215           9 :             sal_Int32 nVal = 0;
    3216           9 :             aAttrs[i].Value >>= nVal;
    3217           9 :             aAttrList->add( nToken, OString::number( nVal ).getStr() );
    3218             :         }
    3219           6 :         else if( aAttrs[i].Name == "OriginalGraphic" )
    3220             :         {
    3221           6 :             Sequence< PropertyValue > aGraphic;
    3222           6 :             aAttrs[i].Value >>= aGraphic;
    3223          12 :             Sequence< sal_Int8 > aGraphicData;
    3224          12 :             OUString sGraphicId;
    3225          18 :             for( sal_Int32 j=0; j < aGraphic.getLength(); ++j )
    3226             :             {
    3227          12 :                 if( aGraphic[j].Name == "Id" )
    3228           6 :                     aGraphic[j].Value >>= sGraphicId;
    3229           6 :                 else if( aGraphic[j].Name == "Data" )
    3230           6 :                     aGraphic[j].Value >>= aGraphicData;
    3231             :             }
    3232          12 :             sRelId = WriteWdpPicture( sGraphicId, aGraphicData );
    3233             :         }
    3234             :     }
    3235             : 
    3236           6 :     mpFS->startElementNS( XML_a, XML_extLst, FSEND );
    3237             :     mpFS->startElementNS( XML_a, XML_ext,
    3238             :                           XML_uri, "{BEBA8EAE-BF5A-486C-A8C5-ECC9F3942E4B}",
    3239           6 :                           FSEND );
    3240             :     mpFS->startElementNS( XML_a14, XML_imgProps,
    3241             :                           FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
    3242           6 :                           FSEND );
    3243             :     mpFS->startElementNS( XML_a14, XML_imgLayer,
    3244             :                           FSNS( XML_r, XML_embed), sRelId.getStr(),
    3245           6 :                           FSEND );
    3246           6 :     mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
    3247             : 
    3248          12 :     sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
    3249           6 :     mpFS->singleElementNS( XML_a14, nEffectToken, xAttrList );
    3250             : 
    3251           6 :     mpFS->endElementNS( XML_a14, XML_imgEffect );
    3252           6 :     mpFS->endElementNS( XML_a14, XML_imgLayer );
    3253           6 :     mpFS->endElementNS( XML_a14, XML_imgProps );
    3254           6 :     mpFS->endElementNS( XML_a, XML_ext );
    3255          12 :     mpFS->endElementNS( XML_a, XML_extLst );
    3256             : }
    3257             : 
    3258           6 : OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< sal_Int8 >& rPictureData )
    3259             : {
    3260           6 :     std::map<OUString, OUString>::iterator aCachedItem = maWdpCache.find( rFileId );
    3261           6 :     if( aCachedItem != maWdpCache.end() )
    3262           4 :         return OUStringToOString( aCachedItem->second, RTL_TEXTENCODING_UTF8 );
    3263             : 
    3264           2 :     OUString sFileName = "media/hdphoto" + OUString::number( mnWdpImageCounter++ ) + ".wdp";
    3265             :     uno::Reference< io::XOutputStream > xOutStream =
    3266           4 :             mpFB->openFragmentStream( "word/" + sFileName,
    3267           8 :                                       "image/vnd.ms-photo" );
    3268           4 :     OUString sId;
    3269           2 :     xOutStream->writeBytes( rPictureData );
    3270           2 :     xOutStream->closeOutput();
    3271             : 
    3272           4 :     sId = mpFB->addRelation( mpFS->getOutputStream(),
    3273             :                              "http://schemas.microsoft.com/office/2007/relationships/hdphoto",
    3274           2 :                              sFileName, false );
    3275             : 
    3276           2 :     maWdpCache[rFileId] = sId;
    3277           4 :     return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
    3278             : }
    3279             : 
    3280             : }
    3281         246 : }
    3282             : 
    3283             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11