LCOV - code coverage report
Current view: top level - oox/source/export - vmlexport.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 564 618 91.3 %
Date: 2014-11-03 Functions: 32 33 97.0 %
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/export/vmlexport.hxx>
      23             : 
      24             : #include <oox/token/tokens.hxx>
      25             : 
      26             : #include <rtl/strbuf.hxx>
      27             : #include <rtl/ustring.hxx>
      28             : 
      29             : #include <tools/stream.hxx>
      30             : #include <comphelper/sequenceashashmap.hxx>
      31             : #include <svx/svdotext.hxx>
      32             : #include <vcl/cvtgrf.hxx>
      33             : #include <filter/msfilter/msdffimp.hxx>
      34             : #include <filter/msfilter/util.hxx>
      35             : #include <filter/msfilter/escherex.hxx>
      36             : 
      37             : #include <com/sun/star/drawing/XShape.hpp>
      38             : #include <com/sun/star/text/HoriOrientation.hpp>
      39             : #include <com/sun/star/text/VertOrientation.hpp>
      40             : #include <com/sun/star/text/RelOrientation.hpp>
      41             : 
      42             : #include <cstdio>
      43             : 
      44             : using namespace sax_fastparser;
      45             : using namespace oox::vml;
      46             : using namespace com::sun::star;
      47             : 
      48         860 : VMLExport::VMLExport( ::sax_fastparser::FSHelperPtr pSerializer, VMLTextExport* pTextExport )
      49         860 :     : EscherEx( EscherExGlobalRef(new EscherExGlobal(0)), 0, /*bOOXML=*/true )
      50             :     , m_pSerializer( pSerializer )
      51             :     , m_pTextExport( pTextExport )
      52             :     , m_eHOri( 0 )
      53             :     , m_eVOri( 0 )
      54             :     , m_eHRel( 0 )
      55             :     , m_eVRel( 0 )
      56             :     , m_pNdTopLeft( 0 )
      57             :     , m_pSdrObject( 0 )
      58             :     , m_pShapeAttrList( NULL )
      59             :     , m_nShapeType( ESCHER_ShpInst_Nil )
      60             :     , m_nShapeFlags(0)
      61         860 :     , m_pShapeStyle( new OStringBuffer( 200 ) )
      62        2580 :     , m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
      63             : {
      64         860 :     mnGroupLevel = 1;
      65         860 :     memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
      66         860 : }
      67             : 
      68        1056 : void VMLExport::SetFS( ::sax_fastparser::FSHelperPtr pSerializer )
      69             : {
      70        1056 :     m_pSerializer = pSerializer;
      71        1056 : }
      72             : 
      73        2580 : VMLExport::~VMLExport()
      74             : {
      75         860 :     delete mpOutStrm, mpOutStrm = NULL;
      76         860 :     delete m_pShapeStyle, m_pShapeStyle = NULL;
      77         860 :     delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
      78        1720 : }
      79             : 
      80        1378 : void VMLExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
      81             : {
      82        1378 :     EscherEx::OpenContainer( nEscherContainer, nRecInstance );
      83             : 
      84        1378 :     if ( nEscherContainer == ESCHER_SpContainer )
      85             :     {
      86             :         // opening a shape container
      87             : #if OSL_DEBUG_LEVEL > 0
      88             :         if ( m_nShapeType != ESCHER_ShpInst_Nil )
      89             :             fprintf( stderr, "Warning!  VMLExport::OpenContainer(): opening shape inside a shape.\n" );
      90             : #endif
      91        1378 :         m_nShapeType = ESCHER_ShpInst_Nil;
      92        1378 :         m_pShapeAttrList = m_pSerializer->createAttrList();
      93             : 
      94        1378 :         if ( !m_pShapeStyle->isEmpty() )
      95           2 :             m_pShapeStyle->makeStringAndClear();
      96             : 
      97        1378 :         m_pShapeStyle->ensureCapacity( 200 );
      98             : 
      99             :         // postpone the output so that we are able to write even the elements
     100             :         // that we learn inside Commit()
     101        1378 :         m_pSerializer->mark();
     102             :     }
     103        1378 : }
     104             : 
     105        1378 : void VMLExport::CloseContainer()
     106             : {
     107        1378 :     if ( mRecTypes.back() == ESCHER_SpContainer )
     108             :     {
     109             :         // write the shape now when we have all the info
     110        1378 :         sal_Int32 nShapeElement = StartShape();
     111             : 
     112        1378 :         m_pSerializer->mergeTopMarks();
     113             : 
     114        1378 :         EndShape( nShapeElement );
     115             : 
     116             :         // cleanup
     117        1378 :         m_nShapeType = ESCHER_ShpInst_Nil;
     118        1378 :         m_pShapeAttrList = NULL;
     119             :     }
     120             : 
     121        1378 :     EscherEx::CloseContainer();
     122        1378 : }
     123             : 
     124          60 : sal_uInt32 VMLExport::EnterGroup( const OUString& rShapeName, const Rectangle* pRect )
     125             : {
     126          60 :     sal_uInt32 nShapeId = GenerateShapeId();
     127             : 
     128          60 :     OStringBuffer aStyle( 200 );
     129          60 :     FastAttributeList *pAttrList = m_pSerializer->createAttrList();
     130             : 
     131          60 :     pAttrList->add( XML_id, ShapeIdString( nShapeId ) );
     132             : 
     133          60 :     if ( rShapeName.getLength() )
     134          34 :         pAttrList->add( XML_alt, OUStringToOString( rShapeName, RTL_TEXTENCODING_UTF8 ) );
     135             : 
     136          60 :     bool rbAbsolutePos = true;
     137             :     //editAs
     138         120 :     OUString rEditAs = EscherEx::GetEditAs();
     139          60 :     if (!rEditAs.isEmpty())
     140             :     {
     141           8 :         pAttrList->add(XML_editas, OUStringToOString( rEditAs, RTL_TEXTENCODING_UTF8 ));
     142           8 :         rbAbsolutePos = false;
     143             :     }
     144             : 
     145             :     // style
     146          60 :     if ( pRect )
     147          60 :         AddRectangleDimensions( aStyle, *pRect, rbAbsolutePos );
     148             : 
     149          60 :     if ( !aStyle.isEmpty() )
     150          60 :         pAttrList->add( XML_style, aStyle.makeStringAndClear() );
     151             : 
     152             :     // coordorigin/coordsize
     153          60 :     if ( pRect && ( mnGroupLevel == 1 ) )
     154             :     {
     155             :         pAttrList->add( XML_coordorigin,
     156         100 :                 OStringBuffer( 20 ).append( sal_Int32( pRect->Left() ) )
     157         100 :                 .append( "," ).append( sal_Int32( pRect->Top() ) )
     158          50 :                 .makeStringAndClear() );
     159             : 
     160             :         pAttrList->add( XML_coordsize,
     161         100 :                 OStringBuffer( 20 ).append( sal_Int32( pRect->Right() ) - sal_Int32( pRect->Left() ) )
     162         100 :                 .append( "," ).append( sal_Int32( pRect->Bottom() ) - sal_Int32( pRect->Top() ) )
     163          50 :                 .makeStringAndClear() );
     164             :     }
     165             : 
     166          60 :     m_pSerializer->startElementNS( XML_v, XML_group, XFastAttributeListRef( pAttrList ) );
     167             : 
     168          60 :     mnGroupLevel++;
     169         120 :     return nShapeId;
     170             : }
     171             : 
     172          60 : void VMLExport::LeaveGroup()
     173             : {
     174          60 :     --mnGroupLevel;
     175          60 :     m_pSerializer->endElementNS( XML_v, XML_group );
     176          60 : }
     177             : 
     178        1378 : void VMLExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 nShapeId )
     179             : {
     180        1378 :     m_nShapeType = nShapeType;
     181        1378 :     m_nShapeFlags = nShapeFlags;
     182             :     // If shape is a watermark object - should keep the original shape's name
     183             :     // because Microsoft detects if it is a watermark by the actual name
     184        1378 :     if (!IsWaterMarkShape(m_pSdrObject->GetName()))
     185             :     {
     186             :         // Not a watermark object
     187        1368 :         m_pShapeAttrList->add( XML_id, ShapeIdString( nShapeId ) );
     188             :     }
     189             :     else
     190             :     {
     191             :         // A watermark object - store the optional shape ID also ('o:spid')
     192          10 :         m_pShapeAttrList->add( XML_id, OUStringToOString(m_pSdrObject->GetName(), RTL_TEXTENCODING_UTF8) );
     193             :     }
     194        1378 : }
     195             : 
     196        4448 : bool VMLExport::IsWaterMarkShape(const OUString& rStr)
     197             : {
     198        4448 :      if (rStr.isEmpty() )  return false;
     199             : 
     200        2960 :      if (rStr.match(OUString("PowerPlusWaterMarkObject")) || rStr.match(OUString("WordPictureWatermark")))
     201          42 :         return true;
     202             :      else
     203        2918 :         return false;
     204             : }
     205             : 
     206          54 : static void impl_AddArrowHead( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
     207             : {
     208          54 :     if ( !pAttrList )
     209          54 :         return;
     210             : 
     211          54 :     const char *pArrowHead = NULL;
     212          54 :     switch ( nValue )
     213             :     {
     214           0 :         case ESCHER_LineNoEnd:           pArrowHead = "none"; break;
     215          42 :         case ESCHER_LineArrowEnd:        pArrowHead = "block"; break;
     216           2 :         case ESCHER_LineArrowStealthEnd: pArrowHead = "classic"; break;
     217           4 :         case ESCHER_LineArrowDiamondEnd: pArrowHead = "diamond"; break;
     218           0 :         case ESCHER_LineArrowOvalEnd:    pArrowHead = "oval"; break;
     219           6 :         case ESCHER_LineArrowOpenEnd:    pArrowHead = "open"; break;
     220             :     }
     221             : 
     222          54 :     if ( pArrowHead )
     223          54 :         pAttrList->add( nElement, pArrowHead );
     224             : }
     225             : 
     226          54 : static void impl_AddArrowLength( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
     227             : {
     228          54 :     if ( !pAttrList )
     229          54 :         return;
     230             : 
     231          54 :     const char *pArrowLength = NULL;
     232          54 :     switch ( nValue )
     233             :     {
     234           2 :         case ESCHER_LineShortArrow:     pArrowLength = "short"; break;
     235          52 :         case ESCHER_LineMediumLenArrow: pArrowLength = "medium"; break;
     236           0 :         case ESCHER_LineLongArrow:      pArrowLength = "long"; break;
     237             :     }
     238             : 
     239          54 :     if ( pArrowLength )
     240          54 :         pAttrList->add( nElement, pArrowLength );
     241             : }
     242             : 
     243          54 : static void impl_AddArrowWidth( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
     244             : {
     245          54 :     if ( !pAttrList )
     246          54 :         return;
     247             : 
     248          54 :     const char *pArrowWidth = NULL;
     249          54 :     switch ( nValue )
     250             :     {
     251           2 :         case ESCHER_LineNarrowArrow:      pArrowWidth = "narrow"; break;
     252          52 :         case ESCHER_LineMediumWidthArrow: pArrowWidth = "medium"; break;
     253           0 :         case ESCHER_LineWideArrow:        pArrowWidth = "wide"; break;
     254             :     }
     255             : 
     256          54 :     if ( pArrowWidth )
     257          54 :         pAttrList->add( nElement, pArrowWidth );
     258             : }
     259             : 
     260        2328 : static void impl_AddBool( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, bool bValue )
     261             : {
     262        2328 :     if ( !pAttrList )
     263        2328 :         return;
     264             : 
     265        2328 :     pAttrList->add( nElement, bValue? "t": "f" );
     266             : }
     267             : 
     268        2620 : static void impl_AddColor( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nColor )
     269             : {
     270             : #if OSL_DEBUG_LEVEL > 0
     271             :     if ( nColor & 0xFF000000 )
     272             :         fprintf( stderr, "TODO: this is not a RGB value!\n" );
     273             : #endif
     274             : 
     275        2620 :     if ( !pAttrList || ( nColor & 0xFF000000 ) )
     276        2620 :         return;
     277             : 
     278        2620 :     nColor = ( ( nColor & 0xFF ) << 16 ) + ( nColor & 0xFF00 ) + ( ( nColor & 0xFF0000 ) >> 16 );
     279             : 
     280        2620 :     const char *pColor = NULL;
     281             :     char pRgbColor[10];
     282        2620 :     switch ( nColor )
     283             :     {
     284         414 :         case 0x000000: pColor = "black"; break;
     285           6 :         case 0xC0C0C0: pColor = "silver"; break;
     286           6 :         case 0x808080: pColor = "gray"; break;
     287         188 :         case 0xFFFFFF: pColor = "white"; break;
     288           0 :         case 0x800000: pColor = "maroon"; break;
     289          68 :         case 0xFF0000: pColor = "red"; break;
     290           0 :         case 0x800080: pColor = "purple"; break;
     291           0 :         case 0xFF00FF: pColor = "fuchsia"; break;
     292          34 :         case 0x008000: pColor = "green"; break;
     293           4 :         case 0x00FF00: pColor = "lime"; break;
     294           0 :         case 0x808000: pColor = "olive"; break;
     295          10 :         case 0xFFFF00: pColor = "yellow"; break;
     296           0 :         case 0x000080: pColor = "navy"; break;
     297          32 :         case 0x0000FF: pColor = "blue"; break;
     298           0 :         case 0x008080: pColor = "teal"; break;
     299          44 :         case 0x00FFFF: pColor = "aqua"; break;
     300             :         default:
     301             :             {
     302        1814 :                 snprintf( pRgbColor, sizeof( pRgbColor ), "#%06x", static_cast< unsigned int >( nColor ) ); // not too handy to use OString::valueOf() here :-(
     303        1814 :                 pColor = pRgbColor;
     304             :             }
     305        1814 :             break;
     306             :     }
     307             : 
     308        2620 :     pAttrList->add( nElement, pColor );
     309             : }
     310             : 
     311         372 : static void impl_AddInt( sax_fastparser::FastAttributeList *pAttrList, sal_Int32 nElement, sal_uInt32 nValue )
     312             : {
     313         372 :     if ( !pAttrList )
     314         372 :         return;
     315             : 
     316         372 :     pAttrList->add( nElement, OString::number( nValue ).getStr() );
     317             : }
     318             : 
     319       29400 : inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
     320             : {
     321       29400 :     sal_uInt16 nRet = *pVal++;
     322       29400 :     nRet += ( *pVal++ ) << 8;
     323       29400 :     return nRet;
     324             : }
     325             : 
     326       30836 : inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_uInt16 nPointSize )
     327             : {
     328       30836 :     sal_Int32 nRet = 0;
     329       30836 :     if ( ( nPointSize == 0xfff0 ) || ( nPointSize == 4 ) )
     330             :     {
     331       28444 :         sal_uInt16 nUnsigned = *pVal++;
     332       28444 :         nUnsigned += ( *pVal++ ) << 8;
     333             : 
     334       28444 :         nRet = sal_Int16( nUnsigned );
     335             :     }
     336        2392 :     else if ( nPointSize == 8 )
     337             :     {
     338        2392 :         sal_uInt32 nUnsigned = *pVal++;
     339        2392 :         nUnsigned += ( *pVal++ ) << 8;
     340        2392 :         nUnsigned += ( *pVal++ ) << 16;
     341        2392 :         nUnsigned += ( *pVal++ ) << 24;
     342             : 
     343        2392 :         nRet = nUnsigned;
     344             :     }
     345             : 
     346       30836 :     return nRet;
     347             : }
     348             : 
     349        1378 : void  VMLExport::AddSdrObjectVMLObject( const SdrObject& rObj)
     350             : {
     351        1378 :    m_pSdrObject = &rObj;
     352        1378 : }
     353        1378 : void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
     354             : {
     355        1378 :     if ( m_nShapeType == ESCHER_ShpInst_Nil )
     356        1600 :         return;
     357             : 
     358             :     // postpone the output of the embedded elements so that they are written
     359             :     // inside the shapes
     360        1156 :     m_pSerializer->mark();
     361             : 
     362             :     // dimensions
     363        1156 :     if ( m_nShapeType == ESCHER_ShpInst_Line )
     364          22 :         AddLineDimensions( rRect );
     365             :     else
     366        1134 :         AddRectangleDimensions( *m_pShapeStyle, rRect );
     367             : 
     368             :     // properties
     369             :     bool bAlreadyWritten[ 0xFFF ];
     370        1156 :     memset( bAlreadyWritten, 0, sizeof( bAlreadyWritten ) );
     371        1156 :     const EscherProperties &rOpts = rProps.GetOpts();
     372       23156 :     for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
     373             :     {
     374       22000 :         sal_uInt16 nId = ( it->nPropId & 0x0FFF );
     375             : 
     376       22000 :         if ( bAlreadyWritten[ nId ] )
     377        6948 :             continue;
     378             : 
     379       15052 :         switch ( nId )
     380             :         {
     381             :             case ESCHER_Prop_WrapText: // 133
     382             :                 {
     383        1128 :                     const char *pWrapType = NULL;
     384        1128 :                     switch ( it->nPropValue )
     385             :                     {
     386             :                         case ESCHER_WrapSquare:
     387         296 :                         case ESCHER_WrapByPoints:  pWrapType = "square"; break; // these two are equivalent according to the docu
     388         832 :                         case ESCHER_WrapNone:      pWrapType = "none"; break;
     389           0 :                         case ESCHER_WrapTopBottom: pWrapType = "topAndBottom"; break;
     390           0 :                         case ESCHER_WrapThrough:   pWrapType = "through"; break;
     391             :                     }
     392        1128 :                     if ( pWrapType )
     393             :                         m_pSerializer->singleElementNS( XML_w10, XML_wrap,
     394             :                                 XML_type, pWrapType,
     395        1128 :                                 FSEND );
     396             :                 }
     397        1128 :                 bAlreadyWritten[ ESCHER_Prop_WrapText ] = true;
     398        1128 :                 break;
     399             : 
     400             :             // coordorigin
     401             :             case ESCHER_Prop_geoLeft: // 320
     402             :             case ESCHER_Prop_geoTop: // 321
     403             :                 {
     404         326 :                     sal_uInt32 nLeft = 0, nTop = 0;
     405             : 
     406         326 :                     if ( nId == ESCHER_Prop_geoLeft )
     407             :                     {
     408         326 :                         nLeft = it->nPropValue;
     409         326 :                         rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
     410             :                     }
     411             :                     else
     412             :                     {
     413           0 :                         nTop = it->nPropValue;
     414           0 :                         rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
     415             :                     }
     416         326 :                     if(nTop!=0 && nLeft!=0)
     417             :                         m_pShapeAttrList->add( XML_coordorigin,
     418           0 :                                 OStringBuffer( 20 ).append( sal_Int32( nLeft ) )
     419           0 :                                 .append( "," ).append( sal_Int32( nTop ) )
     420           0 :                                 .makeStringAndClear() );
     421             :                 }
     422         326 :                 bAlreadyWritten[ ESCHER_Prop_geoLeft ] = true;
     423         326 :                 bAlreadyWritten[ ESCHER_Prop_geoTop ] = true;
     424         326 :                 break;
     425             : 
     426             :             // coordsize
     427             :             case ESCHER_Prop_geoRight: // 322
     428             :             case ESCHER_Prop_geoBottom: // 323
     429             :                 {
     430         670 :                     sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
     431         670 :                     rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
     432         670 :                     rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
     433             : 
     434         670 :                     if ( nId == ESCHER_Prop_geoRight )
     435             :                     {
     436         670 :                         nRight = it->nPropValue;
     437         670 :                         rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
     438             :                     }
     439             :                     else
     440             :                     {
     441           0 :                         nBottom = it->nPropValue;
     442           0 :                         rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
     443             :                     }
     444             : 
     445         670 :                     if(nTop!=0 && nLeft!=0 &&  nBottom!=0 &&  nRight!=0 )
     446             :                         m_pShapeAttrList->add( XML_coordsize,
     447           0 :                                 OStringBuffer( 20 ).append( sal_Int32( nRight ) - sal_Int32( nLeft ) )
     448           0 :                                 .append( "," ).append( sal_Int32( nBottom ) - sal_Int32( nTop ) )
     449           0 :                                 .makeStringAndClear() );
     450             :                 }
     451         670 :                 bAlreadyWritten[ ESCHER_Prop_geoRight ] = true;
     452         670 :                 bAlreadyWritten[ ESCHER_Prop_geoBottom ] = true;
     453         670 :                 break;
     454             : 
     455             :             case ESCHER_Prop_pVertices: // 325
     456             :             case ESCHER_Prop_pSegmentInfo: // 326
     457             :                 {
     458             :                     EscherPropSortStruct aVertices;
     459             :                     EscherPropSortStruct aSegments;
     460             : 
     461        1340 :                     if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
     462         670 :                          rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
     463             :                     {
     464         670 :                         const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
     465         670 :                         const sal_uInt8 *pSegmentIt = aSegments.pBuf;
     466         670 :                         OStringBuffer aPath( 512 );
     467             : 
     468         670 :                         sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
     469             : 
     470             :                         // number of segments
     471         670 :                         sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
     472         670 :                         pSegmentIt += 4;
     473             : 
     474       29400 :                         for ( ; nSegments; --nSegments )
     475             :                         {
     476       28730 :                             sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
     477       28730 :                             switch ( nSeg )
     478             :                             {
     479             :                                 case 0x4000: // moveto
     480             :                                     {
     481         758 :                                         sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
     482         758 :                                         sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
     483         758 :                                         if (nX >= 0 && nY >= 0 )
     484         686 :                                             aPath.append( "m" ).append( nX ).append( "," ).append( nY );
     485             :                                     }
     486         758 :                                     break;
     487             :                                 case 0xb300:
     488             :                                 case 0xac00:
     489       13430 :                                     break;
     490             :                                 case 0x0001: // lineto
     491             :                                     {
     492       12622 :                                         sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
     493       12622 :                                         sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
     494       12622 :                                         aPath.append( "l" ).append( nX ).append( "," ).append( nY );
     495             :                                     }
     496       12622 :                                     break;
     497             :                                 case 0x2001: // curveto
     498             :                                     {
     499         414 :                                         sal_Int32 nX1 = impl_GetPointComponent( pVerticesIt, nPointSize );
     500         414 :                                         sal_Int32 nY1 = impl_GetPointComponent( pVerticesIt, nPointSize );
     501         414 :                                         sal_Int32 nX2 = impl_GetPointComponent( pVerticesIt, nPointSize );
     502         414 :                                         sal_Int32 nY2 = impl_GetPointComponent( pVerticesIt, nPointSize );
     503         414 :                                         sal_Int32 nX3 = impl_GetPointComponent( pVerticesIt, nPointSize );
     504         414 :                                         sal_Int32 nY3 = impl_GetPointComponent( pVerticesIt, nPointSize );
     505         414 :                                         aPath.append( "c" ).append( nX1 ).append( "," ).append( nY1 ).append( "," )
     506         414 :                                             .append( nX2 ).append( "," ).append( nY2 ).append( "," )
     507         414 :                                             .append( nX3 ).append( "," ).append( nY3 );
     508             :                                     }
     509         414 :                                     break;
     510             :                                 case 0xaa00: // nofill
     511           4 :                                     aPath.append( "nf" );
     512           4 :                                     break;
     513             :                                 case 0xab00: // nostroke
     514           4 :                                     aPath.append( "ns" );
     515           4 :                                     break;
     516             :                                 case 0x6001: // close
     517         486 :                                     aPath.append( "x" );
     518         486 :                                     break;
     519             :                                 case 0x8000: // end
     520         674 :                                     aPath.append( "e" );
     521         674 :                                     break;
     522             :                                 default:
     523             :                                     // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
     524             :                                     // FIXME: we miss out a significant amount of complexity from
     525             :                                     // the above method here, and do some rather odd things to match.
     526         338 :                                     int nElems = aVertices.nPropSize / ( nPointSize * 2);
     527         338 :                                     if (nSeg > nElems)
     528             :                                     {
     529             :                                         SAL_WARN("oox", "Busted escher export " << nSeg << "vs . " << nElems << " truncating point stream");
     530         292 :                                         nSeg = nElems;
     531             :                                     }
     532        1134 :                                     for (int i = 0; i < nSeg; ++i)
     533             :                                     {
     534         796 :                                         sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nPointSize);
     535         796 :                                         sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nPointSize);
     536         796 :                                         if (nX >= 0 && nY >= 0 )
     537          52 :                                             aPath.append("l").append(nX).append(",").append(nY);
     538             :                                     }
     539         338 :                                     break;
     540             :                             }
     541             :                         }
     542         670 :                         OString pathString = aPath.makeStringAndClear();
     543         670 :                         if ( !aPath.isEmpty() && pathString != "xe" )
     544           0 :                             m_pShapeAttrList->add( XML_path, pathString );
     545             :                     }
     546             : #if OSL_DEBUG_LEVEL > 0
     547             :                     else
     548             :                         fprintf( stderr, "TODO: unhandled shape path, missing either pVertices or pSegmentInfo.\n" );
     549             : #endif
     550             :                 }
     551         670 :                 bAlreadyWritten[ ESCHER_Prop_pVertices ] = true;
     552         670 :                 bAlreadyWritten[ ESCHER_Prop_pSegmentInfo ] = true;
     553         670 :                 break;
     554             : 
     555             :             case ESCHER_Prop_fillType: // 384
     556             :             case ESCHER_Prop_fillColor: // 385
     557             :             case ESCHER_Prop_fillBackColor: // 387
     558             :             case ESCHER_Prop_fillBlip: // 390
     559             :             case ESCHER_Prop_fNoFillHitTest: // 447
     560             :             case ESCHER_Prop_fillOpacity: // 386
     561             :                 {
     562             :                     sal_uInt32 nValue;
     563        1156 :                     sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
     564             : 
     565        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fillType, nValue ) )
     566             :                     {
     567         814 :                         const char *pFillType = NULL;
     568         814 :                         switch ( nValue )
     569             :                         {
     570         674 :                             case ESCHER_FillSolid:       pFillType = "solid"; break;
     571             :                             // TODO case ESCHER_FillPattern:     pFillType = ""; break;
     572          28 :                             case ESCHER_FillTexture:     pFillType = "tile"; break;
     573             :                             // TODO case ESCHER_FillPicture:     pFillType = ""; break;
     574             :                             // TODO case ESCHER_FillShade:       pFillType = ""; break;
     575             :                             // TODO case ESCHER_FillShadeCenter: pFillType = ""; break;
     576             :                             // TODO case ESCHER_FillShadeShape:  pFillType = ""; break;
     577             :                             // TODO case ESCHER_FillShadeScale:  pFillType = ""; break;
     578             :                             // TODO case ESCHER_FillShadeTitle:  pFillType = ""; break;
     579             :                             // TODO case ESCHER_FillBackground:  pFillType = ""; break;
     580             :                             default:
     581             : #if OSL_DEBUG_LEVEL > 0
     582             :                                 fprintf( stderr, "TODO: unhandled fill type\n" );
     583             : #endif
     584         112 :                                 break;
     585             :                         }
     586         814 :                         if ( pFillType )
     587         702 :                             pAttrList->add( XML_type, pFillType );
     588             :                     }
     589         342 :                     else if (!rProps.GetOpt(ESCHER_Prop_fillColor, nValue))
     590         334 :                         pAttrList->add( XML_on, "false" );
     591             : 
     592        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fillColor, nValue ) )
     593         718 :                         impl_AddColor( m_pShapeAttrList, XML_fillcolor, nValue );
     594             : 
     595        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fillBackColor, nValue ) )
     596         724 :                         impl_AddColor( pAttrList, XML_color2, nValue );
     597             : 
     598        1156 :                     bool imageData = false;
     599             :                     EscherPropSortStruct aStruct;
     600        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fillBlip, aStruct ) && m_pTextExport)
     601             :                     {
     602         106 :                         SvMemoryStream aStream;
     603         106 :                         int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
     604         106 :                         aStream.Write(aStruct.pBuf + nHeaderSize, aStruct.nPropSize - nHeaderSize);
     605         106 :                         aStream.Seek(0);
     606         212 :                         Graphic aGraphic;
     607         106 :                         GraphicConverter::Import(aStream, aGraphic);
     608         212 :                         OUString aImageId = m_pTextExport->GetDrawingML().WriteImage( aGraphic );
     609         106 :                         pAttrList->add(FSNS(XML_r, XML_id), OUStringToOString(aImageId, RTL_TEXTENCODING_UTF8));
     610         212 :                         imageData = true;
     611             :                     }
     612             : 
     613        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fNoFillHitTest, nValue ) )
     614        1128 :                         impl_AddBool( pAttrList, FSNS(XML_o, XML_detectmouseclick), nValue != 0 );
     615             : 
     616        1156 :                     if (rProps.GetOpt(ESCHER_Prop_fillOpacity, nValue))
     617             :                         // Partly undo the transformation at the end of EscherPropertyContainer::CreateFillProperties(): VML opacity is 0..1.
     618          18 :                         pAttrList->add(XML_opacity, OString::number(double((nValue * 100) >> 16) / 100));
     619             : 
     620        1156 :                     if (imageData)
     621         106 :                         m_pSerializer->singleElementNS( XML_v, XML_imagedata, XFastAttributeListRef( pAttrList ) );
     622             :                     else
     623        1050 :                         m_pSerializer->singleElementNS( XML_v, XML_fill, XFastAttributeListRef( pAttrList ) );
     624             :                 }
     625        1156 :                 bAlreadyWritten[ ESCHER_Prop_fillType ] = true;
     626        1156 :                 bAlreadyWritten[ ESCHER_Prop_fillColor ] = true;
     627        1156 :                 bAlreadyWritten[ ESCHER_Prop_fillBackColor ] = true;
     628        1156 :                 bAlreadyWritten[ ESCHER_Prop_fillBlip ] = true;
     629        1156 :                 bAlreadyWritten[ ESCHER_Prop_fNoFillHitTest ] = true;
     630        1156 :                 bAlreadyWritten[ ESCHER_Prop_fillOpacity ] = true;
     631        1156 :                 break;
     632             : 
     633             :             case ESCHER_Prop_lineColor: // 448
     634             :             case ESCHER_Prop_lineWidth: // 459
     635             :             case ESCHER_Prop_lineDashing: // 462
     636             :             case ESCHER_Prop_lineStartArrowhead: // 464
     637             :             case ESCHER_Prop_lineEndArrowhead: // 465
     638             :             case ESCHER_Prop_lineStartArrowWidth: // 466
     639             :             case ESCHER_Prop_lineStartArrowLength: // 467
     640             :             case ESCHER_Prop_lineEndArrowWidth: // 468
     641             :             case ESCHER_Prop_lineEndArrowLength: // 469
     642             :             case ESCHER_Prop_lineJoinStyle: // 470
     643             :             case ESCHER_Prop_lineEndCapStyle: // 471
     644             :                 {
     645             :                     sal_uInt32 nValue;
     646        1156 :                     sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
     647             : 
     648        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineColor, nValue ) )
     649        1156 :                         impl_AddColor( pAttrList, XML_color, nValue );
     650             : 
     651        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineWidth, nValue ) )
     652         372 :                         impl_AddInt( pAttrList, XML_weight, nValue );
     653             : 
     654        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineDashing, nValue ) )
     655             :                     {
     656          28 :                         const char *pDashStyle = NULL;
     657          28 :                         switch ( nValue )
     658             :                         {
     659           0 :                             case ESCHER_LineSolid:             pDashStyle = "solid"; break;
     660           0 :                             case ESCHER_LineDashSys:           pDashStyle = "shortdash"; break;
     661           0 :                             case ESCHER_LineDotSys:            pDashStyle = "shortdot"; break;
     662           0 :                             case ESCHER_LineDashDotSys:        pDashStyle = "shortdashdot"; break;
     663           0 :                             case ESCHER_LineDashDotDotSys:     pDashStyle = "shortdashdotdot"; break;
     664           0 :                             case ESCHER_LineDotGEL:            pDashStyle = "dot"; break;
     665          14 :                             case ESCHER_LineDashGEL:           pDashStyle = "dash"; break;
     666           8 :                             case ESCHER_LineLongDashGEL:       pDashStyle = "longdash"; break;
     667           0 :                             case ESCHER_LineDashDotGEL:        pDashStyle = "dashdot"; break;
     668           0 :                             case ESCHER_LineLongDashDotGEL:    pDashStyle = "longdashdot"; break;
     669           6 :                             case ESCHER_LineLongDashDotDotGEL: pDashStyle = "longdashdotdot"; break;
     670             :                         }
     671          28 :                         if ( pDashStyle )
     672          28 :                             pAttrList->add( XML_dashstyle, pDashStyle );
     673             :                     }
     674             : 
     675        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowhead, nValue ) )
     676          12 :                         impl_AddArrowHead( pAttrList, XML_startarrow, nValue );
     677             : 
     678        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowhead, nValue ) )
     679          42 :                         impl_AddArrowHead( pAttrList, XML_endarrow, nValue );
     680             : 
     681        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowWidth, nValue ) )
     682          12 :                         impl_AddArrowWidth( pAttrList, XML_startarrowwidth, nValue );
     683             : 
     684        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineStartArrowLength, nValue ) )
     685          12 :                         impl_AddArrowLength( pAttrList, XML_startarrowlength, nValue );
     686             : 
     687        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowWidth, nValue ) )
     688          42 :                         impl_AddArrowWidth( pAttrList, XML_endarrowwidth, nValue );
     689             : 
     690        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineEndArrowLength, nValue ) )
     691          42 :                         impl_AddArrowLength( pAttrList, XML_endarrowlength, nValue );
     692             : 
     693        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineJoinStyle, nValue ) )
     694             :                     {
     695        1156 :                         const char *pJoinStyle = NULL;
     696        1156 :                         switch ( nValue )
     697             :                         {
     698          84 :                             case ESCHER_LineJoinBevel: pJoinStyle = "bevel"; break;
     699         106 :                             case ESCHER_LineJoinMiter: pJoinStyle = "miter"; break;
     700         966 :                             case ESCHER_LineJoinRound: pJoinStyle = "round"; break;
     701             :                         }
     702        1156 :                         if ( pJoinStyle )
     703        1156 :                             pAttrList->add( XML_joinstyle, pJoinStyle );
     704             :                     }
     705             : 
     706        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_lineEndCapStyle, nValue ) )
     707             :                     {
     708        1156 :                         const char *pEndCap = NULL;
     709        1156 :                         switch ( nValue )
     710             :                         {
     711           8 :                             case ESCHER_LineEndCapRound:  pEndCap = "round"; break;
     712          10 :                             case ESCHER_LineEndCapSquare: pEndCap = "square"; break;
     713        1138 :                             case ESCHER_LineEndCapFlat:   pEndCap = "flat"; break;
     714             :                         }
     715        1156 :                         if ( pEndCap )
     716        1156 :                             pAttrList->add( XML_endcap, pEndCap );
     717             :                     }
     718             : 
     719        1156 :                     m_pSerializer->singleElementNS( XML_v, XML_stroke, XFastAttributeListRef( pAttrList ) );
     720             :                 }
     721        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineColor ] = true;
     722        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineWidth ] = true;
     723        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineDashing ] = true;
     724        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineStartArrowhead ] = true;
     725        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineEndArrowhead ] = true;
     726        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineStartArrowWidth ] = true;
     727        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineStartArrowLength ] = true;
     728        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineEndArrowWidth ] = true;
     729        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineEndArrowLength ] = true;
     730        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineJoinStyle ] = true;
     731        1156 :                 bAlreadyWritten[ ESCHER_Prop_lineEndCapStyle ] = true;
     732        1156 :                 break;
     733             : 
     734             :             case ESCHER_Prop_fHidden:
     735           0 :                 if ( !it->nPropValue )
     736           0 :                     m_pShapeStyle->append( ";visibility:hidden" );
     737           0 :                 break;
     738             :             case ESCHER_Prop_shadowColor:
     739             :             case ESCHER_Prop_fshadowObscured:
     740             :                 {
     741        1156 :                     sal_uInt32 nValue = 0;
     742        1156 :                     bool bShadow = false;
     743        1156 :                     bool bObscured = false;
     744        1156 :                     if ( rProps.GetOpt( ESCHER_Prop_fshadowObscured, nValue ) )
     745             :                     {
     746        1156 :                         bShadow = (( nValue & 0x20002 ) == 0x20002 );
     747        1156 :                         bObscured = (( nValue & 0x10001 ) == 0x10001 );
     748             :                     }
     749        1156 :                     if ( bShadow )
     750             :                     {
     751          22 :                         sax_fastparser::FastAttributeList *pAttrList = m_pSerializer->createAttrList();
     752          22 :                         impl_AddBool( pAttrList, XML_on, bShadow );
     753          22 :                         impl_AddBool( pAttrList, XML_obscured, bObscured );
     754             : 
     755          22 :                         if ( rProps.GetOpt( ESCHER_Prop_shadowColor, nValue ) )
     756          22 :                             impl_AddColor( pAttrList, XML_color, nValue );
     757             : 
     758          22 :                         m_pSerializer->singleElementNS( XML_v, XML_shadow, XFastAttributeListRef( pAttrList ) );
     759          22 :                         bAlreadyWritten[ ESCHER_Prop_fshadowObscured ] = true;
     760          22 :                         bAlreadyWritten[ ESCHER_Prop_shadowColor ] = true;
     761             :                     }
     762             :                 }
     763        1156 :                 break;
     764             :             case ESCHER_Prop_gtextUNICODE:
     765             :             case ESCHER_Prop_gtextFont:
     766             :                 {
     767             :                     EscherPropSortStruct aUnicode;
     768          34 :                     if (rProps.GetOpt(ESCHER_Prop_gtextUNICODE, aUnicode))
     769             :                     {
     770          34 :                         SvMemoryStream aStream;
     771          34 :                         aStream.Write(it->pBuf, it->nPropSize);
     772          34 :                         aStream.Seek(0);
     773          68 :                         OUString aTextPathString = SvxMSDffManager::MSDFFReadZString(aStream, it->nPropSize, true);
     774          34 :                         aStream.Seek(0);
     775             : 
     776             :                         m_pSerializer->singleElementNS( XML_v, XML_path,
     777             :                                 XML_textpathok, "t",
     778          34 :                                 FSEND );
     779             : 
     780          34 :                         sax_fastparser::FastAttributeList* pAttrList = m_pSerializer->createAttrList();
     781          34 :                         pAttrList->add(XML_on, "t");
     782          34 :                         pAttrList->add(XML_fitshape, "t");
     783          34 :                         pAttrList->add(XML_string, OUStringToOString(aTextPathString, RTL_TEXTENCODING_UTF8));
     784             :                         EscherPropSortStruct aFont;
     785          68 :                         OUString aStyle;
     786          34 :                         if (rProps.GetOpt(ESCHER_Prop_gtextFont, aFont))
     787             :                         {
     788          34 :                             aStream.Write(aFont.pBuf, aFont.nPropSize);
     789          34 :                             aStream.Seek(0);
     790          34 :                             OUString aTextPathFont = SvxMSDffManager::MSDFFReadZString(aStream, aFont.nPropSize, true);
     791          34 :                             aStyle += "font-family:\"" + aTextPathFont + "\"";
     792             :                         }
     793          34 :                         if (!aStyle.isEmpty())
     794          34 :                             pAttrList->add(XML_style, OUStringToOString(aStyle, RTL_TEXTENCODING_UTF8));
     795          68 :                         m_pSerializer->singleElementNS(XML_v, XML_textpath, XFastAttributeListRef(pAttrList));
     796             :                     }
     797             : 
     798          34 :                     bAlreadyWritten[ESCHER_Prop_gtextUNICODE] = true;
     799          34 :                     bAlreadyWritten[ESCHER_Prop_gtextFont] = true;
     800             :                 }
     801          34 :                 break;
     802             :             case ESCHER_Prop_Rotation:
     803             :                 {
     804             :                     // The higher half of the variable contains the angle.
     805          46 :                     m_pShapeStyle->append(";rotation:").append(double(it->nPropValue >> 16));
     806          46 :                     bAlreadyWritten[ESCHER_Prop_Rotation] = true;
     807             :                 }
     808          46 :                 break;
     809             :             case ESCHER_Prop_fNoLineDrawDash:
     810             :                 {
     811             :                     // See DffPropertyReader::ApplyLineAttributes().
     812        1156 :                     impl_AddBool( m_pShapeAttrList, XML_stroked, (it->nPropValue & 8) != 0 );
     813        1156 :                     bAlreadyWritten[ESCHER_Prop_fNoLineDrawDash] = true;
     814             :                 }
     815        1156 :                 break;
     816             :             case ESCHER_Prop_wzName:
     817             :                 {
     818         738 :                     SvMemoryStream aStream;
     819         738 :                     aStream.Write(it->pBuf, it->nPropSize);
     820         738 :                     aStream.Seek(0);
     821        1476 :                     OUString idStr = SvxMSDffManager::MSDFFReadZString(aStream, it->nPropSize, true);
     822         738 :                     aStream.Seek(0);
     823         738 :                     if (!IsWaterMarkShape(m_pSdrObject->GetName()))
     824         728 :                          m_pShapeAttrList->add(XML_ID, OUStringToOString(idStr, RTL_TEXTENCODING_UTF8).getStr());
     825             : 
     826        1476 :                     bAlreadyWritten[ESCHER_Prop_wzName] = true;
     827             :                 }
     828         738 :                 break;
     829             :             default:
     830             : #if OSL_DEBUG_LEVEL > 0
     831             :                 fprintf( stderr, "TODO VMLExport::Commit(), unimplemented id: %d, value: %" SAL_PRIuUINT32 ", data: [%" SAL_PRIuUINT32 ", %p]\n",
     832             :                         nId, it->nPropValue, it->nPropSize, it->pBuf );
     833             :                 if ( it->nPropSize )
     834             :                 {
     835             :                     const sal_uInt8 *pIt = it->pBuf;
     836             :                     fprintf( stderr, "    ( " );
     837             :                     for ( int nCount = it->nPropSize; nCount; --nCount )
     838             :                     {
     839             :                         fprintf( stderr, "%02x ", *pIt );
     840             :                         ++pIt;
     841             :                     }
     842             :                     fprintf( stderr, ")\n" );
     843             :                 }
     844             : #endif
     845        6816 :                 break;
     846             :         }
     847             :     }
     848             : 
     849        1156 :     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
     850             : }
     851             : 
     852        1428 : OString VMLExport::ShapeIdString( sal_uInt32 nId )
     853             : {
     854        1428 :     return OStringBuffer( 20 ).append( "shape_" ).append( sal_Int64( nId ) ).makeStringAndClear();
     855             : }
     856             : 
     857        1216 : void VMLExport::AddFlipXY( )
     858             : {
     859        1216 :     const sal_uInt32 nFlipHandV = SHAPEFLAG_FLIPH + SHAPEFLAG_FLIPV;
     860        1216 :     switch ( m_nShapeFlags & nFlipHandV )
     861             :     {
     862           4 :         case SHAPEFLAG_FLIPH:   m_pShapeStyle->append( ";flip:x" );  break;
     863          66 :         case SHAPEFLAG_FLIPV:   m_pShapeStyle->append( ";flip:y" );  break;
     864           4 :         case (nFlipHandV):      m_pShapeStyle->append( ";flip:xy" ); break;
     865             :     }
     866        1216 : }
     867             : 
     868          22 : void VMLExport::AddLineDimensions( const Rectangle& rRectangle )
     869             : {
     870             :     // style
     871          22 :     if ( !m_pShapeStyle->isEmpty() )
     872           0 :         m_pShapeStyle->append( ";" );
     873             : 
     874          22 :     m_pShapeStyle->append( "position:absolute" );
     875             : 
     876          22 :     AddFlipXY();
     877             : 
     878             :     // the actual dimensions
     879          44 :     OString aLeft, aTop, aRight, aBottom;
     880             : 
     881          22 :     if ( mnGroupLevel == 1 )
     882             :     {
     883          16 :         const OString aPt( "pt" );
     884          16 :         aLeft = OString::number( double( rRectangle.Left() ) / 20 ) + aPt;
     885          16 :         aTop = OString::number( double( rRectangle.Top() ) / 20 ) + aPt;
     886          16 :         aRight = OString::number( double( rRectangle.Right() ) / 20 ) + aPt;
     887          16 :         aBottom = OString::number( double( rRectangle.Bottom() ) / 20 ) + aPt;
     888             :     }
     889             :     else
     890             :     {
     891           6 :         aLeft = OString::number( rRectangle.Left() );
     892           6 :         aTop = OString::number( rRectangle.Top() );
     893           6 :         aRight = OString::number( rRectangle.Right() );
     894           6 :         aBottom = OString::number( rRectangle.Bottom() );
     895             :     }
     896             : 
     897             :     m_pShapeAttrList->add( XML_from,
     898          44 :             OStringBuffer( 20 ).append( aLeft )
     899          22 :             .append( "," ).append( aTop )
     900          22 :             .makeStringAndClear() );
     901             : 
     902             :     m_pShapeAttrList->add( XML_to,
     903          44 :             OStringBuffer( 20 ).append( aRight )
     904          22 :             .append( "," ).append( aBottom )
     905          44 :             .makeStringAndClear() );
     906          22 : }
     907             : 
     908        1194 : void VMLExport::AddRectangleDimensions( OStringBuffer& rBuffer, const Rectangle& rRectangle, bool rbAbsolutePos)
     909             : {
     910        1194 :     if ( !rBuffer.isEmpty() )
     911           0 :         rBuffer.append( ";" );
     912             : 
     913        1194 :     if (rbAbsolutePos)
     914             :     {
     915        1186 :         rBuffer.append( "position:absolute;" );
     916             :     }
     917             : 
     918        1194 :     if ( mnGroupLevel == 1 )
     919             :     {
     920         560 :         rBuffer.append( "margin-left:" ).append( double( rRectangle.Left() ) / 20 )
     921        1120 :             .append( "pt;margin-top:" ).append( double( rRectangle.Top() ) / 20 )
     922        1120 :             .append( "pt;width:" ).append( double( rRectangle.Right() - rRectangle.Left() ) / 20 )
     923        1120 :             .append( "pt;height:" ).append( double( rRectangle.Bottom() - rRectangle.Top() ) / 20 )
     924         560 :             .append( "pt" );
     925             :     }
     926             :     else
     927             :     {
     928         634 :         rBuffer.append( "left:" ).append( rRectangle.Left() )
     929        1268 :             .append( ";top:" ).append( rRectangle.Top() )
     930        1268 :             .append( ";width:" ).append( rRectangle.Right() - rRectangle.Left() )
     931        1268 :             .append( ";height:" ).append( rRectangle.Bottom() - rRectangle.Top() );
     932             :     }
     933             : 
     934        1194 :     AddFlipXY();
     935        1194 : }
     936             : 
     937           0 : void VMLExport::AddShapeAttribute( sal_Int32 nAttribute, const OString& rValue )
     938             : {
     939           0 :     m_pShapeAttrList->add( nAttribute, rValue );
     940           0 : }
     941             : 
     942          14 : std::vector<OString> lcl_getShapeTypes()
     943             : {
     944          14 :     std::vector<OString> aRet;
     945             : 
     946          28 :     OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/vml-shape-types");
     947          14 :     rtl::Bootstrap::expandMacros(aPath);
     948          28 :     SvFileStream aStream(aPath, STREAM_READ);
     949          14 :     if (aStream.GetError() != ERRCODE_NONE)
     950             :         SAL_WARN("oox", "failed to open vml-shape-types");
     951          28 :     OString aLine;
     952          14 :     bool bNotDone = aStream.ReadLine(aLine);
     953        5712 :     while (bNotDone)
     954             :     {
     955             :         // Filter out comments.
     956        5684 :         if (!aLine.startsWith("/"))
     957        2842 :             aRet.push_back(aLine);
     958        5684 :         bNotDone = aStream.ReadLine(aLine);
     959             :     }
     960          28 :     return aRet;
     961             : }
     962             : 
     963        2286 : bool lcl_isTextBox(const SdrObject* pSdrObject)
     964             : {
     965        2286 :     uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY);
     966        2286 :     if (xPropertySet.is())
     967             :     {
     968        2286 :         uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
     969        2286 :         return xPropertySetInfo->hasPropertyByName("TextBox") && xPropertySet->getPropertyValue("TextBox").get<bool>();
     970             :     }
     971           0 :     return false;
     972             : }
     973             : 
     974        1156 : OUString lcl_getAnchorIdFromGrabBag(const SdrObject* pSdrObject)
     975             : {
     976        1156 :     OUString aResult;
     977             : 
     978        2312 :     uno::Reference<beans::XPropertySet> xShape(const_cast<SdrObject*>(pSdrObject)->getUnoShape(), uno::UNO_QUERY);
     979        1156 :     if (xShape->getPropertySetInfo()->hasPropertyByName("InteropGrabBag"))
     980             :     {
     981         996 :         comphelper::SequenceAsHashMap aInteropGrabBag(xShape->getPropertyValue("InteropGrabBag"));
     982         996 :         if (aInteropGrabBag.find("AnchorId") != aInteropGrabBag.end())
     983         316 :             aInteropGrabBag["AnchorId"] >>= aResult;
     984             :     }
     985             : 
     986        2312 :     return aResult;
     987             : }
     988             : 
     989        1378 : sal_Int32 VMLExport::StartShape()
     990             : {
     991        1378 :     if ( m_nShapeType == ESCHER_ShpInst_Nil )
     992         222 :         return -1;
     993             : 
     994             :     // some of the shapes have their own name ;-)
     995        1156 :     sal_Int32 nShapeElement = -1;
     996        1156 :     bool bReferToShapeType = false;
     997        1156 :     switch ( m_nShapeType )
     998             :     {
     999         344 :         case ESCHER_ShpInst_NotPrimitive:   nShapeElement = XML_shape;     break;
    1000         310 :         case ESCHER_ShpInst_Rectangle:      nShapeElement = XML_rect;      break;
    1001           0 :         case ESCHER_ShpInst_RoundRectangle: nShapeElement = XML_roundrect; break;
    1002          32 :         case ESCHER_ShpInst_Ellipse:        nShapeElement = XML_oval;      break;
    1003           0 :         case ESCHER_ShpInst_Arc:            nShapeElement = XML_arc;       break;
    1004          22 :         case ESCHER_ShpInst_Line:           nShapeElement = XML_line;      break;
    1005             :         default:
    1006         448 :             if ( m_nShapeType < ESCHER_ShpInst_COUNT )
    1007             :             {
    1008         448 :                 nShapeElement = XML_shape;
    1009             : 
    1010             :                 // a predefined shape?
    1011         448 :                 static std::vector<OString> aShapeTypes = lcl_getShapeTypes();
    1012         448 :                 OString aShapeType = aShapeTypes[ m_nShapeType ];
    1013         448 :                 if ( aShapeType != "NULL" )
    1014             :                 {
    1015         358 :                     bReferToShapeType = true;
    1016         358 :                     if ( !m_pShapeTypeWritten[ m_nShapeType ] )
    1017             :                     {
    1018          72 :                         m_pSerializer->write( aShapeType.getStr() );
    1019          72 :                         m_pShapeTypeWritten[ m_nShapeType ] = true;
    1020             :                     }
    1021             :                 }
    1022             :                 else
    1023             :                 {
    1024             :                     // rectangle is probably the best fallback...
    1025          90 :                     nShapeElement = XML_rect;
    1026         448 :                 }
    1027             :             }
    1028         448 :             break;
    1029             :     }
    1030             : 
    1031             :     // anchoring
    1032        1156 :     switch (m_eHOri)
    1033             :     {
    1034             :         case text::HoriOrientation::LEFT:
    1035           2 :             m_pShapeStyle->append(";mso-position-horizontal:left");
    1036           2 :             break;
    1037             :         case text::HoriOrientation::CENTER:
    1038          22 :             m_pShapeStyle->append(";mso-position-horizontal:center");
    1039          22 :             break;
    1040             :         case text::HoriOrientation::RIGHT:
    1041           2 :             m_pShapeStyle->append(";mso-position-horizontal:right");
    1042           2 :             break;
    1043             :         case text::HoriOrientation::INSIDE:
    1044           0 :             m_pShapeStyle->append(";mso-position-horizontal:inside");
    1045           0 :             break;
    1046             :         case text::HoriOrientation::OUTSIDE:
    1047           0 :             m_pShapeStyle->append(";mso-position-horizontal:outside");
    1048           0 :             break;
    1049             :         default:
    1050             :         case text::HoriOrientation::NONE:
    1051        1130 :             break;
    1052             :     }
    1053        1156 :     switch (m_eHRel)
    1054             :     {
    1055             :         case text::RelOrientation::PAGE_PRINT_AREA:
    1056          10 :             m_pShapeStyle->append(";mso-position-horizontal-relative:margin");
    1057          10 :             break;
    1058             :         case text::RelOrientation::PAGE_FRAME:
    1059             :         case text::RelOrientation::PAGE_LEFT:
    1060             :         case text::RelOrientation::PAGE_RIGHT:
    1061          66 :             m_pShapeStyle->append(";mso-position-horizontal-relative:page");
    1062          66 :             break;
    1063             :         case text::RelOrientation::CHAR:
    1064           0 :             m_pShapeStyle->append(";mso-position-horizontal-relative:char");
    1065           0 :             break;
    1066             :         default:
    1067        1080 :             break;
    1068             :     }
    1069             : 
    1070        1156 :     switch (m_eVOri)
    1071             :     {
    1072             :         case text::VertOrientation::TOP:
    1073             :         case text::VertOrientation::LINE_TOP:
    1074             :         case text::VertOrientation::CHAR_TOP:
    1075          14 :             m_pShapeStyle->append(";mso-position-vertical:top");
    1076          14 :             break;
    1077             :         case text::VertOrientation::CENTER:
    1078             :         case text::VertOrientation::LINE_CENTER:
    1079          16 :             m_pShapeStyle->append(";mso-position-vertical:center");
    1080          16 :             break;
    1081             :         case text::VertOrientation::BOTTOM:
    1082             :         case text::VertOrientation::LINE_BOTTOM:
    1083             :         case text::VertOrientation::CHAR_BOTTOM:
    1084           0 :             m_pShapeStyle->append(";mso-position-vertical:bottom");
    1085           0 :             break;
    1086             :         default:
    1087             :         case text::VertOrientation::NONE:
    1088        1126 :             break;
    1089             :     }
    1090        1156 :     switch (m_eVRel)
    1091             :     {
    1092             :         case text::RelOrientation::PAGE_PRINT_AREA:
    1093          18 :             m_pShapeStyle->append(";mso-position-vertical-relative:margin");
    1094          18 :             break;
    1095             :         case text::RelOrientation::PAGE_FRAME:
    1096          68 :             m_pShapeStyle->append(";mso-position-vertical-relative:page");
    1097          68 :             break;
    1098             :         default:
    1099        1070 :             break;
    1100             :     }
    1101             : 
    1102             :     // add style
    1103        1156 :     m_pShapeAttrList->add( XML_style, m_pShapeStyle->makeStringAndClear() );
    1104             : 
    1105        1156 :     OUString sAnchorId = lcl_getAnchorIdFromGrabBag(m_pSdrObject);
    1106        1156 :     if (!sAnchorId.isEmpty())
    1107         316 :         m_pShapeAttrList->addNS(XML_wp14, XML_anchorId, OUStringToOString(sAnchorId, RTL_TEXTENCODING_UTF8));
    1108             : 
    1109        1156 :     if ( nShapeElement >= 0 && !m_pShapeAttrList->hasAttribute( XML_type ) )
    1110             :     {
    1111        1156 :         if ( bReferToShapeType )
    1112             :         {
    1113             :             m_pShapeAttrList->add( XML_type, OStringBuffer( 20 )
    1114         716 :                     .append( "shapetype_" ).append( sal_Int32( m_nShapeType ) )
    1115         358 :                     .makeStringAndClear() );
    1116             :         }
    1117             : 
    1118             :         // start of the shape
    1119        1156 :         m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
    1120             :     }
    1121             :     else
    1122             :     {
    1123             :         // start of the shape
    1124           0 :         m_pSerializer->startElementNS( XML_v, nShapeElement, XFastAttributeListRef( m_pShapeAttrList ) );
    1125             :     }
    1126             : 
    1127             :     // now check if we have some editeng text (not associated textbox) and we have a text exporter registered
    1128        1156 :     const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
    1129        1156 :     if (pTxtObj && m_pTextExport && msfilter::util::HasTextBoxContent(m_nShapeType) && !IsWaterMarkShape(m_pSdrObject->GetName()) && !lcl_isTextBox(m_pSdrObject))
    1130             :     {
    1131        1000 :         const OutlinerParaObject* pParaObj = 0;
    1132        1000 :         bool bOwnParaObj = false;
    1133             : 
    1134             :         /*
    1135             :         #i13885#
    1136             :         When the object is actively being edited, that text is not set into
    1137             :         the objects normal text object, but lives in a separate object.
    1138             :         */
    1139        1000 :         if (pTxtObj->IsTextEditActive())
    1140             :         {
    1141           0 :             pParaObj = pTxtObj->GetEditOutlinerParaObject();
    1142           0 :             bOwnParaObj = true;
    1143             :         }
    1144             :         else
    1145             :         {
    1146        1000 :             pParaObj = pTxtObj->GetOutlinerParaObject();
    1147             :         }
    1148             : 
    1149        1000 :         if( pParaObj )
    1150             :         {
    1151             :             // this is reached only in case some text is attached to the shape
    1152         242 :             m_pSerializer->startElementNS(XML_v, XML_textbox, FSEND);
    1153         242 :             m_pTextExport->WriteOutliner(*pParaObj);
    1154         242 :             m_pSerializer->endElementNS(XML_v, XML_textbox);
    1155         242 :             if( bOwnParaObj )
    1156           0 :                 delete pParaObj;
    1157             :         }
    1158             :     }
    1159             : 
    1160        1156 :     return nShapeElement;
    1161             : }
    1162             : 
    1163        1378 : void VMLExport::EndShape( sal_Int32 nShapeElement )
    1164             : {
    1165        1378 :     if ( nShapeElement >= 0 )
    1166             :     {
    1167        1156 :         if (m_pTextExport && lcl_isTextBox(m_pSdrObject))
    1168             :         {
    1169         130 :             uno::Reference<beans::XPropertySet> xPropertySet(const_cast<SdrObject*>(m_pSdrObject)->getUnoShape(), uno::UNO_QUERY);
    1170         260 :             comphelper::SequenceAsHashMap aCustomShapeProperties(xPropertySet->getPropertyValue("CustomShapeGeometry"));
    1171         130 :             sax_fastparser::FastAttributeList* pTextboxAttrList = m_pSerializer->createAttrList();
    1172         130 :             if (aCustomShapeProperties.find("TextPreRotateAngle") != aCustomShapeProperties.end())
    1173             :             {
    1174         130 :                 sal_Int32 nTextRotateAngle = aCustomShapeProperties["TextPreRotateAngle"].get<sal_Int32>();
    1175         130 :                 if (nTextRotateAngle == -270)
    1176           4 :                     pTextboxAttrList->add(XML_style, "mso-layout-flow-alt:bottom-to-top");
    1177             :             }
    1178         260 :             sax_fastparser::XFastAttributeListRef xTextboxAttrList(pTextboxAttrList);
    1179         130 :             pTextboxAttrList = 0;
    1180         130 :             m_pSerializer->startElementNS(XML_v, XML_textbox, xTextboxAttrList);
    1181             : 
    1182         130 :             m_pTextExport->WriteVMLTextBox(uno::Reference<drawing::XShape>(xPropertySet, uno::UNO_QUERY_THROW));
    1183             : 
    1184         260 :             m_pSerializer->endElementNS(XML_v, XML_textbox);
    1185             :         }
    1186             : 
    1187             :         // end of the shape
    1188        1156 :         m_pSerializer->endElementNS( XML_v, nShapeElement );
    1189             :     }
    1190        1378 : }
    1191             : 
    1192         672 : sal_uInt32 VMLExport::AddSdrObject( const SdrObject& rObj, sal_Int16 eHOri, sal_Int16 eVOri, sal_Int16 eHRel, sal_Int16 eVRel, const Point* pNdTopLeft, const bool bOOxmlExport )
    1193             : {
    1194         672 :     m_pSdrObject = &rObj;
    1195         672 :     m_eHOri = eHOri;
    1196         672 :     m_eVOri = eVOri;
    1197         672 :     m_eHRel = eHRel;
    1198         672 :     m_eVRel = eVRel;
    1199         672 :     m_pNdTopLeft = pNdTopLeft;
    1200         672 :     return EscherEx::AddSdrObject(rObj, bOOxmlExport);
    1201         408 : }
    1202             : 
    1203             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10