LCOV - code coverage report
Current view: top level - sw/source/filter/ww8 - rtfsdrexport.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 253 306 82.7 %
Date: 2014-04-11 Functions: 18 19 94.7 %
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 "rtfsdrexport.hxx"
      21             : #include "rtfattributeoutput.hxx"
      22             : #include "rtfexportfilter.hxx"
      23             : 
      24             : #include <svtools/rtfkeywd.hxx>
      25             : #include <filter/msfilter/rtfutil.hxx>
      26             : #include <editeng/editobj.hxx>
      27             : #include <svx/svdotext.hxx>
      28             : #include <svx/unoapi.hxx>
      29             : #include <vcl/cvtgrf.hxx>
      30             : 
      31             : #include <algorithm>
      32             : 
      33             : using namespace sw::util;
      34             : using namespace css;
      35             : 
      36          56 : RtfSdrExport::RtfSdrExport( RtfExport &rExport )
      37          56 :     : EscherEx( EscherExGlobalRef( new EscherExGlobal ), 0 ),
      38             :       m_rExport( rExport ),
      39          56 :       m_rAttrOutput( (RtfAttributeOutput&)m_rExport.AttrOutput() ),
      40             :       m_pSdrObject( NULL ),
      41             :       m_nShapeType( ESCHER_ShpInst_Nil ),
      42             :       m_nShapeFlags ( 0 ) ,
      43          56 :       m_pShapeStyle( new OStringBuffer( 200 ) ),
      44         224 :       m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
      45             : {
      46          56 :     mnGroupLevel = 1;
      47          56 :     memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
      48          56 : }
      49             : 
      50         168 : RtfSdrExport::~RtfSdrExport()
      51             : {
      52          56 :     delete mpOutStrm, mpOutStrm = NULL;
      53          56 :     delete m_pShapeStyle, m_pShapeStyle = NULL;
      54          56 :     delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
      55         112 : }
      56             : 
      57          63 : void RtfSdrExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
      58             : {
      59             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
      60             : 
      61          63 :     EscherEx::OpenContainer( nEscherContainer, nRecInstance );
      62             : 
      63          63 :     if ( nEscherContainer == ESCHER_SpContainer )
      64             :     {
      65          63 :         m_nShapeType = ESCHER_ShpInst_Nil;
      66          63 :         if ( !m_pShapeStyle->isEmpty() )
      67           0 :             m_pShapeStyle->makeStringAndClear();
      68          63 :         m_pShapeStyle->ensureCapacity( 200 );
      69          63 :         m_aShapeProps.clear();
      70             :     }
      71          63 : }
      72             : 
      73          63 : void RtfSdrExport::CloseContainer()
      74             : {
      75             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
      76             : 
      77          63 :     if ( mRecTypes.back() == ESCHER_SpContainer )
      78             :     {
      79             :         // write the shape now when we have all the info
      80          63 :         sal_Int32 nShapeElement = StartShape();
      81          63 :         EndShape( nShapeElement );
      82             : 
      83             :         // cleanup
      84          63 :         m_nShapeType = ESCHER_ShpInst_Nil;
      85             :     }
      86             : 
      87          63 :     EscherEx::CloseContainer();
      88          63 : }
      89             : 
      90           2 : sal_uInt32 RtfSdrExport::EnterGroup( const OUString& /*rShapeName*/, const Rectangle* /*pRect*/ )
      91             : {
      92             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
      93             : 
      94           2 :     return GenerateShapeId();
      95             : }
      96             : 
      97           2 : void RtfSdrExport::LeaveGroup()
      98             : {
      99             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     100             : 
     101             :     /* noop */
     102           2 : }
     103             : 
     104          63 : void RtfSdrExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 /*nShapeId*/ )
     105             : {
     106             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     107             : 
     108          63 :     m_nShapeType = nShapeType;
     109          63 :     m_nShapeFlags = nShapeFlags;
     110          63 : }
     111             : 
     112          22 : inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
     113             : {
     114          22 :     sal_uInt16 nRet = *pVal++;
     115          22 :     nRet += ( *pVal++ ) << 8;
     116          22 :     return nRet;
     117             : }
     118             : 
     119          96 : inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_Size& rVerticesPos, sal_uInt16 nPointSize )
     120             : {
     121          96 :     sal_Int32 nRet = 0;
     122          96 :     if ( ( nPointSize == 0xfff0 ) || ( nPointSize == 4 ) )
     123             :     {
     124           0 :         sal_uInt16 nUnsigned = *pVal++;
     125           0 :         nUnsigned += ( *pVal++ ) << 8;
     126           0 :         rVerticesPos += 2;
     127             : 
     128           0 :         nRet = sal_Int16( nUnsigned );
     129             :     }
     130          96 :     else if ( nPointSize == 8 )
     131             :     {
     132          96 :         sal_uInt32 nUnsigned = *pVal++;
     133          96 :         nUnsigned += ( *pVal++ ) << 8;
     134          96 :         nUnsigned += ( *pVal++ ) << 16;
     135          96 :         nUnsigned += ( *pVal++ ) << 24;
     136          96 :         rVerticesPos += 4;
     137             : 
     138          96 :         nRet = nUnsigned;
     139             :     }
     140             : 
     141          96 :     return nRet;
     142             : }
     143             : 
     144          63 : void RtfSdrExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
     145             : {
     146             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     147             : 
     148          63 :     if ( m_nShapeType == ESCHER_ShpInst_Nil )
     149          63 :         return;
     150             : 
     151          63 :     if ( m_nShapeType == ESCHER_ShpInst_Line )
     152           0 :         AddLineDimensions( rRect );
     153             :     else
     154          63 :         AddRectangleDimensions( *m_pShapeStyle, rRect );
     155             : 
     156             :     // properties
     157          63 :     const EscherProperties &rOpts = rProps.GetOpts();
     158        1008 :     for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
     159             :     {
     160         945 :         sal_uInt16 nId = ( it->nPropId & 0x0FFF );
     161             : 
     162         945 :         switch ( nId )
     163             :         {
     164             :             case ESCHER_Prop_WrapText:
     165             :                 {
     166          36 :                     int nWrapType = 0;
     167          36 :                     switch ( it->nPropValue )
     168             :                     {
     169          13 :                         case ESCHER_WrapSquare:    nWrapType = 2; break;
     170           0 :                         case ESCHER_WrapByPoints:  nWrapType = 4; break;
     171          23 :                         case ESCHER_WrapNone:      nWrapType = 3; break;
     172           0 :                         case ESCHER_WrapTopBottom: nWrapType = 1; break;
     173           0 :                         case ESCHER_WrapThrough:   nWrapType = 5; break;
     174             :                     }
     175          36 :                     if ( nWrapType )
     176          36 :                         m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPWR).append((sal_Int32)nWrapType);
     177             :                 }
     178          36 :                 break;
     179             :             case ESCHER_Prop_fillColor:
     180          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("fillColor", OString::number(it->nPropValue)));
     181          17 :                 break;
     182             :             case ESCHER_Prop_fillBackColor:
     183          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("fillBackColor", OString::number(it->nPropValue)));
     184          17 :                 break;
     185             :             case ESCHER_Prop_AnchorText:
     186          36 :                 m_aShapeProps.insert(std::pair<OString,OString>("anchorText", OString::number(it->nPropValue)));
     187          36 :                 break;
     188             :             case ESCHER_Prop_fNoFillHitTest:
     189          63 :                 if (it->nPropValue)
     190          63 :                     m_aShapeProps.insert(std::pair<OString,OString>("fNoFillHitTest", OString::number(1)));
     191          63 :                 break;
     192             :             case ESCHER_Prop_fNoLineDrawDash:
     193             :                 // for some reason the value is set to 0x90000 if lines are switched off
     194          63 :                 if( it->nPropValue == 0x90000 )
     195          15 :                     m_aShapeProps.insert(std::pair<OString,OString>("fLine", OString::number(0)));
     196          63 :                 break;
     197             :             case ESCHER_Prop_lineColor:
     198          63 :                 m_aShapeProps.insert(std::pair<OString,OString>("lineColor", OString::number(it->nPropValue)));
     199          63 :                 break;
     200             :             case ESCHER_Prop_lineBackColor:
     201          63 :                 m_aShapeProps.insert(std::pair<OString,OString>("lineBackColor", OString::number(it->nPropValue)));
     202          63 :                 break;
     203             :             case ESCHER_Prop_lineJoinStyle:
     204          63 :                 m_aShapeProps.insert(std::pair<OString,OString>("lineJoinStyle", OString::number(it->nPropValue)));
     205          63 :                 break;
     206             :             case ESCHER_Prop_fshadowObscured:
     207          63 :                 if (it->nPropValue)
     208          63 :                     m_aShapeProps.insert(std::pair<OString,OString>("fshadowObscured", "1"));
     209          63 :                 break;
     210             :             case ESCHER_Prop_geoLeft:
     211             :             case ESCHER_Prop_geoTop:
     212             :                 {
     213           4 :                     sal_uInt32 nLeft = 0, nTop = 0;
     214             : 
     215           4 :                     if ( nId == ESCHER_Prop_geoLeft )
     216             :                     {
     217           2 :                         nLeft = it->nPropValue;
     218           2 :                         rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
     219             :                     }
     220             :                     else
     221             :                     {
     222           2 :                         nTop = it->nPropValue;
     223           2 :                         rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
     224             :                     }
     225             : 
     226             :                     m_aShapeProps.insert(std::pair<OString,OString>("geoLeft",
     227           4 :                                 OString::number(sal_Int32( nLeft ))));
     228             :                     m_aShapeProps.insert(std::pair<OString,OString>("geoTop",
     229           4 :                                 OString::number(sal_Int32( nTop ))));
     230             :                 }
     231           4 :                 break;
     232             : 
     233             :             case ESCHER_Prop_geoRight:
     234             :             case ESCHER_Prop_geoBottom:
     235             :                 {
     236           4 :                     sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
     237           4 :                     rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
     238           4 :                     rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
     239             : 
     240           4 :                     if ( nId == ESCHER_Prop_geoRight )
     241             :                     {
     242           2 :                         nRight = it->nPropValue;
     243           2 :                         rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
     244             :                     }
     245             :                     else
     246             :                     {
     247           2 :                         nBottom = it->nPropValue;
     248           2 :                         rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
     249             :                     }
     250             : 
     251             :                     m_aShapeProps.insert(std::pair<OString,OString>("geoRight",
     252           4 :                                 OString::number(sal_Int32( nRight ) - sal_Int32( nLeft ))));
     253             :                     m_aShapeProps.insert(std::pair<OString,OString>("geoBottom",
     254           4 :                                 OString::number(sal_Int32( nBottom ) - sal_Int32( nTop ))));
     255             :                 }
     256           4 :                 break;
     257             :             case ESCHER_Prop_pVertices:
     258             :             case ESCHER_Prop_pSegmentInfo:
     259             :                 {
     260             :                     EscherPropSortStruct aVertices;
     261             :                     EscherPropSortStruct aSegments;
     262             : 
     263           8 :                     if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
     264           4 :                          rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
     265             :                     {
     266           4 :                         const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
     267           4 :                         sal_Size nVerticesPos = 0;
     268           4 :                         const sal_uInt8 *pSegmentIt = aSegments.pBuf;
     269             : 
     270           4 :                         OStringBuffer aSegmentInfo( 512 );
     271           8 :                         OStringBuffer aVerticies( 512 );
     272             : 
     273           4 :                         sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
     274             : 
     275             :                         // number of segments
     276           4 :                         sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
     277           4 :                         sal_Int32 nVertices = 0;
     278           4 :                         aSegmentInfo.append("2;").append((sal_Int32)nSegments);
     279           4 :                         pSegmentIt += 4;
     280             : 
     281          22 :                         for ( ; nSegments; --nSegments )
     282             :                         {
     283          18 :                             sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
     284          18 :                             aSegmentInfo.append(';').append((sal_Int32)nSeg);
     285          18 :                             switch ( nSeg )
     286             :                             {
     287             :                                 case 0x0001: // lineto
     288             :                                 case 0x4000: // moveto
     289             :                                     {
     290           4 :                                         sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
     291           4 :                                         sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
     292           4 :                                         aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
     293           4 :                                         nVertices ++;
     294             :                                     }
     295           4 :                                     break;
     296             :                                 case 0x2001: // curveto
     297             :                                     {
     298           0 :                                         for (int i = 0; i < 3; i++)
     299             :                                         {
     300           0 :                                             sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
     301           0 :                                             sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nVerticesPos, nPointSize );
     302           0 :                                             aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
     303           0 :                                             nVertices ++;
     304             :                                         }
     305             :                                     }
     306           0 :                                     break;
     307             :                                 case 0xb300:
     308             :                                 case 0xac00:
     309             :                                 case 0xaa00: // nofill
     310             :                                 case 0xab00: // nostroke
     311             :                                 case 0x6001: // close
     312             :                                 case 0x8000: // end
     313           6 :                                     break;
     314             :                                 default:
     315             :                                     // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points.
     316          52 :                                     for (int i = 0; i < nSeg; ++i)
     317             :                                     {
     318          50 :                                         if (nVerticesPos >= aVertices.nPropSize)
     319           6 :                                             break;
     320          44 :                                         sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
     321          44 :                                         sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize);
     322          44 :                                         aVerticies.append(";(").append(nX).append(",").append(nY).append(")");
     323          44 :                                         ++nVertices;
     324             :                                     }
     325           8 :                                     break;
     326             :                             }
     327             :                         }
     328             : 
     329           4 :                         if (!aVerticies.isEmpty() )
     330             :                         {
     331             :                             // We know the number of vertices at the end only, so we have to prepend them here.
     332           4 :                             m_aShapeProps.insert(std::pair<OString,OString>("pVerticies", "8;" + OString::number(nVertices) + aVerticies.makeStringAndClear()));
     333             :                         }
     334           4 :                         if ( !aSegmentInfo.isEmpty() )
     335           8 :                             m_aShapeProps.insert(std::pair<OString,OString>("pSegmentInfo", aSegmentInfo.makeStringAndClear()));
     336             :                     }
     337             :                     else
     338             :                         SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled shape path, missing either pVertices or pSegmentInfo");
     339             :                 }
     340           4 :                 break;
     341             :             case ESCHER_Prop_shapePath:
     342             :                 // noop, we use pSegmentInfo instead
     343           0 :                 break;
     344             :             case ESCHER_Prop_fFillOK:
     345          27 :                 if (!it->nPropValue)
     346           0 :                     m_aShapeProps.insert(std::pair<OString,OString>("fFillOK", "0"));
     347          27 :                 break;
     348             :             case ESCHER_Prop_dxTextLeft:
     349          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("dxTextLeft", OString::number(it->nPropValue)));
     350          17 :                 break;
     351             :             case ESCHER_Prop_dyTextTop:
     352          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("dyTextTop", OString::number(it->nPropValue)));
     353          17 :                 break;
     354             :             case ESCHER_Prop_dxTextRight:
     355          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("dxTextRight", OString::number(it->nPropValue)));
     356          17 :                 break;
     357             :             case ESCHER_Prop_dyTextBottom:
     358          17 :                 m_aShapeProps.insert(std::pair<OString,OString>("dyTextBottom", OString::number(it->nPropValue)));
     359          17 :                 break;
     360             :             case ESCHER_Prop_FitTextToShape:
     361             :                 // Size text to fit shape size: not supported by RTF
     362          17 :                 break;
     363             :             case ESCHER_Prop_adjustValue:
     364           1 :                 m_aShapeProps.insert(std::pair<OString,OString>("adjustValue", OString::number(it->nPropValue)));
     365           1 :                 break;
     366             :             case ESCHER_Prop_txflTextFlow:
     367           6 :                 m_aShapeProps.insert(std::pair<OString,OString>("txflTextFlow", OString::number(it->nPropValue)));
     368           6 :                 break;
     369             :             case ESCHER_Prop_fillType:
     370          22 :                 m_aShapeProps.insert(std::pair<OString,OString>("fillType", OString::number(it->nPropValue)));
     371          22 :                 break;
     372             :             case ESCHER_Prop_fillOpacity:
     373          16 :                 m_aShapeProps.insert(std::pair<OString,OString>("fillOpacity", OString::number(it->nPropValue)));
     374          16 :                 break;
     375             :             case ESCHER_Prop_fillBlip:
     376             :                 {
     377           4 :                     OStringBuffer aBuf;
     378           4 :                     aBuf.append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP).append(SAL_NEWLINE_STRING);
     379           4 :                     int nHeaderSize = 25; // The first bytes are WW8-specific, we're only interested in the PNG
     380           4 :                     aBuf.append(RtfAttributeOutput::WriteHex(it->pBuf + nHeaderSize, it->nPropSize - nHeaderSize));
     381           4 :                     aBuf.append('}');
     382           4 :                     m_aShapeProps.insert(std::pair<OString,OString>("fillBlip", aBuf.makeStringAndClear()));
     383             :                 }
     384           4 :                 break;
     385             :             default:
     386             :                 SAL_INFO("sw.rtf", OSL_THIS_FUNC << ": unhandled property: " << nId << " (value: " << it->nPropValue << ")");
     387         288 :                 break;
     388             :         }
     389          63 :     }
     390             : }
     391             : 
     392           0 : void RtfSdrExport::AddLineDimensions( const Rectangle& rRectangle )
     393             : {
     394             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     395             : 
     396             :     // We get the position relative to (the current?) character
     397           0 :     m_aShapeProps.insert(std::pair<OString,OString>("posrelh", "3"));
     398             : 
     399           0 :     switch ( m_nShapeFlags & 0xC0 )
     400             :     {
     401             :         case 0x40:
     402           0 :             m_aShapeProps.insert(std::pair<OString,OString>("fFlipV", "1"));
     403           0 :             break;
     404             :         case 0x80:
     405           0 :             m_aShapeProps.insert(std::pair<OString,OString>("fFlipH", "1"));
     406           0 :             break;
     407             :         case 0xC0:
     408           0 :             m_aShapeProps.insert(std::pair<OString,OString>("fFlipV", "1"));
     409           0 :             m_aShapeProps.insert(std::pair<OString,OString>("fFlipH", "1"));
     410           0 :             break;
     411             :     }
     412             : 
     413             :     // the actual dimensions
     414           0 :     m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
     415           0 :     m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
     416           0 :     m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
     417           0 :     m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
     418           0 : }
     419             : 
     420          63 : void RtfSdrExport::AddRectangleDimensions( OStringBuffer& rBuffer, const Rectangle& rRectangle )
     421             : {
     422             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     423             : 
     424             :     // We get the position relative to (the current?) character
     425          63 :     m_aShapeProps.insert(std::pair<OString,OString>("posrelh", "3"));
     426             : 
     427          63 :     rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
     428          63 :     rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
     429          63 :     rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
     430          63 :     rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
     431          63 : }
     432             : 
     433             : extern const char* pShapeTypes[];
     434             : 
     435         781 : static void lcl_AppendSP( OStringBuffer& rRunText, const char cName[], const OString& rValue)
     436             : {
     437         781 :     rRunText.append('{').append(OOO_STRING_SVTOOLS_RTF_SP)
     438         781 :         .append('{').append(OOO_STRING_SVTOOLS_RTF_SN " ").append(cName).append('}')
     439         781 :         .append('{').append(OOO_STRING_SVTOOLS_RTF_SV " ").append(rValue).append('}')
     440         781 :         .append('}');
     441         781 : }
     442             : 
     443           6 : void RtfSdrExport::impl_writeGraphic()
     444             : {
     445             :     // Get the Graphic object from the Sdr one.
     446           6 :     uno::Reference<drawing::XShape> xShape = GetXShapeForSdrObject(const_cast<SdrObject*>(m_pSdrObject));
     447           6 :     uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
     448           6 :     OUString sGraphicURL;
     449             :     try
     450             :     {
     451          12 :         xPropertySet->getPropertyValue("GraphicURL") >>= sGraphicURL;
     452             :     }
     453          12 :     catch (beans::UnknownPropertyException& rException)
     454             :     {
     455             :         // ATM groupshapes are not supported, just make sure we don't crash on them.
     456             :         SAL_WARN("sw.rtf", "failed. Message: " << rException.Message);
     457          12 :         return;
     458             :     }
     459           0 :     OString aURLBS(OUStringToOString(sGraphicURL, RTL_TEXTENCODING_UTF8));
     460           0 :     const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
     461           0 :     Graphic aGraphic = GraphicObject(aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin))).GetTransformedGraphic();
     462             : 
     463             :     // Export it to a stream.
     464           0 :     SvMemoryStream aStream;
     465           0 :     GraphicConverter::Export(aStream, aGraphic, CVT_PNG);
     466           0 :     aStream.Seek(STREAM_SEEK_TO_END);
     467           0 :     sal_uInt32 nSize = aStream.Tell();
     468           0 :     const sal_uInt8* pGraphicAry = (sal_uInt8*)aStream.GetData();
     469             : 
     470           0 :     Size aMapped(aGraphic.GetPrefSize());
     471             : 
     472             :     // Add it to the properties.
     473           0 :     RtfStringBuffer aBuf;
     474           0 :     aBuf->append('{').append(OOO_STRING_SVTOOLS_RTF_PICT).append(OOO_STRING_SVTOOLS_RTF_PNGBLIP);
     475           0 :     aBuf->append(OOO_STRING_SVTOOLS_RTF_PICW).append(sal_Int32(aMapped.Width()));
     476           0 :     aBuf->append(OOO_STRING_SVTOOLS_RTF_PICH).append(sal_Int32(aMapped.Height())).append(SAL_NEWLINE_STRING);
     477           0 :     aBuf->append(RtfAttributeOutput::WriteHex(pGraphicAry, nSize));
     478           0 :     aBuf->append('}');
     479           0 :     m_aShapeProps.insert(std::pair<OString,OString>("pib", aBuf.makeStringAndClear()));
     480             : }
     481             : 
     482          63 : sal_Int32 RtfSdrExport::StartShape()
     483             : {
     484             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     485             : 
     486          63 :     if ( m_nShapeType == ESCHER_ShpInst_Nil )
     487           0 :         return -1;
     488             : 
     489          63 :     m_aShapeProps.insert(std::pair<OString,OString>("shapeType", OString::number(m_nShapeType)));
     490          63 :     if (ESCHER_ShpInst_PictureFrame == m_nShapeType)
     491           6 :         impl_writeGraphic();
     492             : 
     493          63 :     m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHP);
     494          63 :     m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_IGNORE).append(OOO_STRING_SVTOOLS_RTF_SHPINST);
     495             : 
     496          63 :     m_rAttrOutput.RunText().append(m_pShapeStyle->makeStringAndClear());
     497             :     // Ignore \shpbxpage, \shpbxmargin, and \shpbxcolumn, in favor of the posrelh property.
     498          63 :     m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE);
     499             :     // Ignore \shpbypage, \shpbymargin, and \shpbycolumn, in favor of the posrelh property.
     500          63 :     m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE);
     501             : 
     502         718 :     for(std::map<OString,OString>::reverse_iterator i = m_aShapeProps.rbegin(); i != m_aShapeProps.rend(); ++i)
     503         655 :         lcl_AppendSP(m_rAttrOutput.RunText(), (*i).first.getStr(), (*i).second );
     504             : 
     505          63 :     lcl_AppendSP(m_rAttrOutput.RunText(), "wzDescription", msfilter::rtfutil::OutString( m_pSdrObject->GetDescription(), m_rExport.eCurrentEncoding));
     506          63 :     lcl_AppendSP(m_rAttrOutput.RunText(), "wzName", msfilter::rtfutil::OutString( m_pSdrObject->GetTitle(), m_rExport.eCurrentEncoding));
     507             : 
     508             :     // now check if we have some text
     509          63 :     const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
     510          63 :     if (pTxtObj)
     511             :     {
     512           3 :         const OutlinerParaObject* pParaObj = 0;
     513           3 :         bool bOwnParaObj = false;
     514             : 
     515             :         /*
     516             :         #i13885#
     517             :         When the object is actively being edited, that text is not set into
     518             :         the objects normal text object, but lives in a separate object.
     519             :         */
     520           3 :         if (pTxtObj->IsTextEditActive())
     521             :         {
     522           0 :             pParaObj = pTxtObj->GetEditOutlinerParaObject();
     523           0 :             bOwnParaObj = true;
     524             :         }
     525             :         else
     526             :         {
     527           3 :             pParaObj = pTxtObj->GetOutlinerParaObject();
     528             :         }
     529             : 
     530           3 :         if( pParaObj )
     531             :         {
     532             :             // this is reached only in case some text is attached to the shape
     533           2 :             WriteOutliner(*pParaObj);
     534           2 :             if( bOwnParaObj )
     535           0 :                 delete pParaObj;
     536             :         }
     537             :     }
     538             : 
     539          63 :     return m_nShapeType;
     540             : }
     541             : 
     542           2 : void RtfSdrExport::WriteOutliner(const OutlinerParaObject& rParaObj)
     543             : {
     544             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC << " start");
     545             : 
     546           2 :     const EditTextObject& rEditObj = rParaObj.GetTextObject();
     547           2 :     MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
     548             : 
     549           2 :     sal_Int32 nPara = rEditObj.GetParagraphCount();
     550             : 
     551           2 :     m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHPTXT).append(' ');
     552           4 :     for (sal_Int32 n = 0; n < nPara; ++n)
     553             :     {
     554           2 :         if( n )
     555           0 :             aAttrIter.NextPara( n );
     556             : 
     557           2 :         rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
     558             : 
     559           2 :         OUString aStr( rEditObj.GetText( n ));
     560           2 :         sal_Int32 nAktPos = 0;
     561           2 :         const sal_Int32 nEnd = aStr.getLength();
     562             : 
     563           2 :         aAttrIter.OutParaAttr(false);
     564           2 :         m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
     565             : 
     566           2 :         do {
     567           2 :             const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
     568           2 :             rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
     569             : 
     570           2 :             aAttrIter.OutAttr( nAktPos );
     571           2 :             m_rAttrOutput.RunText().append('{').append(m_rAttrOutput.Styles().makeStringAndClear()).append(SAL_NEWLINE_STRING);
     572           2 :             bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
     573           2 :             if( !bTxtAtr )
     574             :             {
     575           2 :                 OUString aOut( aStr.copy( nAktPos, nNextAttr - nAktPos ) );
     576           2 :                 m_rAttrOutput.RunText().append( msfilter::rtfutil::OutString( aOut, eChrSet ) );
     577             :             }
     578             : 
     579           2 :             m_rAttrOutput.RunText().append('}');
     580             : 
     581           2 :             nAktPos = nNextAttr;
     582           2 :             eChrSet = eNextChrSet;
     583           2 :             aAttrIter.NextPos();
     584             :         }
     585           2 :         while( nAktPos < nEnd );
     586           2 :     }
     587           2 :     m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_PAR).append('}');
     588             : 
     589           2 :     SAL_INFO("sw.rtf", OSL_THIS_FUNC << " end");
     590           2 : }
     591             : 
     592          63 : void RtfSdrExport::EndShape( sal_Int32 nShapeElement )
     593             : {
     594             :     SAL_INFO("sw.rtf", OSL_THIS_FUNC);
     595             : 
     596          63 :     if ( nShapeElement >= 0 )
     597             :     {
     598             :         // end of the shape
     599          63 :         m_rAttrOutput.RunText().append('}').append('}');
     600             :     }
     601          63 : }
     602             : 
     603           5 : sal_uInt32 RtfSdrExport::AddSdrObject( const SdrObject& rObj )
     604             : {
     605           5 :     m_pSdrObject = &rObj;
     606           5 :     return EscherEx::AddSdrObject(rObj);
     607             : }
     608             : 
     609             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10