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

Generated by: LCOV version 1.10