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

Generated by: LCOV version 1.11