LCOV - code coverage report
Current view: top level - writerfilter/source/rtftok - rtfsdrimport.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 524 558 93.9 %
Date: 2015-06-13 12:38:46 Functions: 19 19 100.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             : 
      10             : #include <rtfsdrimport.hxx>
      11             : #include <com/sun/star/container/XNamed.hpp>
      12             : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
      13             : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
      14             : #include <com/sun/star/drawing/LineStyle.hpp>
      15             : #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
      16             : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
      17             : #include <com/sun/star/lang/XServiceInfo.hpp>
      18             : #include <com/sun/star/table/BorderLine2.hpp>
      19             : #include <com/sun/star/text/HoriOrientation.hpp>
      20             : #include <com/sun/star/text/RelOrientation.hpp>
      21             : #include <com/sun/star/text/SizeType.hpp>
      22             : #include <com/sun/star/text/VertOrientation.hpp>
      23             : #include <com/sun/star/text/WrapTextMode.hpp>
      24             : #include <com/sun/star/text/WritingMode.hpp>
      25             : #include <com/sun/star/text/TextContentAnchorType.hpp>
      26             : #include <ooxml/resourceids.hxx>
      27             : #include <filter/msfilter/util.hxx>
      28             : #include <svx/svdtrans.hxx>
      29             : #include <comphelper/sequence.hxx>
      30             : #include <rtfreferenceproperties.hxx>
      31             : #include <oox/vml/vmlformatting.hxx>
      32             : #include <oox/helper/modelobjecthelper.hxx>
      33             : #include <oox/drawingml/shapepropertymap.hxx>
      34             : #include <oox/helper/propertyset.hxx>
      35             : #include <boost/logic/tribool.hpp>
      36             : 
      37             : using namespace com::sun::star;
      38             : 
      39             : namespace writerfilter
      40             : {
      41             : namespace rtftok
      42             : {
      43             : 
      44         504 : RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument,
      45             :                            uno::Reference<lang::XComponent> const& xDstDoc)
      46             :     : m_rImport(rDocument)
      47             :     , m_bTextFrame(false)
      48             :     , m_bTextGraphicObject(false)
      49         504 :     , m_bFakePict(false)
      50             : {
      51         504 :     uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY);
      52         504 :     if (xDrawings.is())
      53         478 :         m_aParents.push(xDrawings->getDrawPage());
      54         504 : }
      55             : 
      56        1512 : RTFSdrImport::~RTFSdrImport()
      57             : {
      58         504 :     if (m_aParents.size())
      59         478 :         m_aParents.pop();
      60        1008 : }
      61             : 
      62         109 : void RTFSdrImport::createShape(const OUString& aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet)
      63             : {
      64         109 :     if (m_rImport.getModelFactory().is())
      65         100 :         xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY);
      66         109 :     xPropertySet.set(xShape, uno::UNO_QUERY);
      67         109 : }
      68             : 
      69          48 : std::vector<beans::PropertyValue> RTFSdrImport::getTextFrameDefaults(bool bNew)
      70             : {
      71          48 :     std::vector<beans::PropertyValue> aRet;
      72          96 :     beans::PropertyValue aPropertyValue;
      73             : 
      74          48 :     aPropertyValue.Name = "HoriOrient";
      75          48 :     aPropertyValue.Value <<= text::HoriOrientation::NONE;
      76          48 :     aRet.push_back(aPropertyValue);
      77          48 :     aPropertyValue.Name = "HoriOrientRelation";
      78          48 :     aPropertyValue.Value <<= text::RelOrientation::FRAME;
      79          48 :     aRet.push_back(aPropertyValue);
      80          48 :     aPropertyValue.Name = "VertOrient";
      81          48 :     aPropertyValue.Value <<= text::VertOrientation::NONE;
      82          48 :     aRet.push_back(aPropertyValue);
      83          48 :     aPropertyValue.Name = "VertOrientRelation";
      84          48 :     aPropertyValue.Value <<= text::RelOrientation::FRAME;
      85          48 :     aRet.push_back(aPropertyValue);
      86          48 :     if (!bNew)
      87             :     {
      88          13 :         aPropertyValue.Name = "BackColorTransparency";
      89          13 :         aPropertyValue.Value <<= sal_Int32(100);
      90          13 :         aRet.push_back(aPropertyValue);
      91             :     }
      92             :     // See the spec, new-style frame default margins are specified in EMUs.
      93          48 :     aPropertyValue.Name = "LeftBorderDistance";
      94          48 :     aPropertyValue.Value <<= sal_Int32(bNew ? (91440 / 360) : 0);
      95          48 :     aRet.push_back(aPropertyValue);
      96          48 :     aPropertyValue.Name = "RightBorderDistance";
      97          48 :     aPropertyValue.Value <<= sal_Int32(bNew ? (91440 / 360) : 0);
      98          48 :     aRet.push_back(aPropertyValue);
      99          48 :     aPropertyValue.Name = "TopBorderDistance";
     100          48 :     aPropertyValue.Value <<= sal_Int32(bNew ? (45720 / 360) : 0);
     101          48 :     aRet.push_back(aPropertyValue);
     102          48 :     aPropertyValue.Name = "BottomBorderDistance";
     103          48 :     aPropertyValue.Value <<= sal_Int32(bNew ? (45720 / 360) : 0);
     104          48 :     aRet.push_back(aPropertyValue);
     105          48 :     aPropertyValue.Name = "SizeType";
     106          48 :     aPropertyValue.Value <<= text::SizeType::FIX;
     107          48 :     aRet.push_back(aPropertyValue);
     108          96 :     return aRet;
     109             : }
     110             : 
     111           6 : void RTFSdrImport::pushParent(uno::Reference<drawing::XShapes> const& xParent)
     112             : {
     113           6 :     m_aParents.push(xParent);
     114           6 : }
     115             : 
     116           6 : void RTFSdrImport::popParent()
     117             : {
     118           6 :     m_aParents.pop();
     119           6 : }
     120             : 
     121          85 : void RTFSdrImport::resolveDhgt(uno::Reference<beans::XPropertySet> const& xPropertySet,
     122             :                                sal_Int32 const nZOrder, bool const bOldStyle)
     123             : {
     124          85 :     xPropertySet->setPropertyValue("ZOrder", uno::makeAny(m_aGraphicZOrderHelper.findZOrder(nZOrder, bOldStyle)));
     125          85 :     m_aGraphicZOrderHelper.addItem(xPropertySet, nZOrder);
     126          85 : }
     127             : 
     128         110 : void RTFSdrImport::resolveLineColorAndWidth(bool bTextFrame, const uno::Reference<beans::XPropertySet>& xPropertySet, uno::Any& rLineColor, uno::Any& rLineWidth)
     129             : {
     130         110 :     if (!bTextFrame)
     131             :     {
     132          74 :         xPropertySet->setPropertyValue("LineColor", rLineColor);
     133          74 :         xPropertySet->setPropertyValue("LineWidth", rLineWidth);
     134             :     }
     135             :     else
     136             :     {
     137             :         static const char* aBorders[] =
     138             :         {
     139             :             "TopBorder", "LeftBorder", "BottomBorder", "RightBorder"
     140             :         };
     141         180 :         for (unsigned int i = 0; i < SAL_N_ELEMENTS(aBorders); ++i)
     142             :         {
     143         144 :             table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(OUString::createFromAscii(aBorders[i])).get<table::BorderLine2>();
     144         144 :             if (rLineColor.hasValue())
     145         144 :                 aBorderLine.Color = rLineColor.get<sal_Int32>();
     146         144 :             if (rLineWidth.hasValue())
     147         140 :                 aBorderLine.LineWidth = rLineWidth.get<sal_Int32>();
     148         144 :             xPropertySet->setPropertyValue(OUString::createFromAscii(aBorders[i]), uno::makeAny(aBorderLine));
     149             :         }
     150             :     }
     151         110 : }
     152             : 
     153          43 : void RTFSdrImport::resolveFLine(uno::Reference<beans::XPropertySet> const& xPropertySet,
     154             :                                 sal_Int32 const nFLine)
     155             : {
     156          43 :     if (nFLine == 0)
     157          26 :         xPropertySet->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_NONE));
     158             :     else
     159          17 :         xPropertySet->setPropertyValue("LineStyle", uno::makeAny(drawing::LineStyle_SOLID));
     160          43 : }
     161             : 
     162          58 : void RTFSdrImport::applyProperty(uno::Reference<drawing::XShape> const& xShape, const OUString& aKey, const OUString& aValue)
     163             : {
     164          58 :     uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
     165          58 :     sal_Int16 nHoriOrient = 0;
     166          58 :     sal_Int16 nVertOrient = 0;
     167          58 :     boost::logic::tribool obFitShapeToText(boost::logic::indeterminate);
     168          58 :     bool bFilled = true;
     169             : 
     170          58 :     if (aKey == "posh")
     171             :     {
     172          11 :         switch (aValue.toInt32())
     173             :         {
     174             :         case 1:
     175           0 :             nHoriOrient = text::HoriOrientation::LEFT;
     176           0 :             break;
     177             :         case 2:
     178          10 :             nHoriOrient = text::HoriOrientation::CENTER;
     179          10 :             break;
     180             :         case 3:
     181           0 :             nHoriOrient = text::HoriOrientation::RIGHT;
     182           0 :             break;
     183             :         case 4:
     184           0 :             nHoriOrient = text::HoriOrientation::INSIDE;
     185           0 :             break;
     186             :         case 5:
     187           0 :             nHoriOrient = text::HoriOrientation::OUTSIDE;
     188           0 :             break;
     189             :         default:
     190           1 :             break;
     191             :         }
     192             :     }
     193          47 :     else if (aKey == "posv")
     194             :     {
     195           5 :         switch (aValue.toInt32())
     196             :         {
     197             :         case 1:
     198           2 :             nVertOrient = text::VertOrientation::TOP;
     199           2 :             break;
     200             :         case 2:
     201           2 :             nVertOrient = text::VertOrientation::CENTER;
     202           2 :             break;
     203             :         case 3:
     204           0 :             nVertOrient = text::VertOrientation::BOTTOM;
     205           0 :             break;
     206             :         default:
     207           1 :             break;
     208             :         }
     209             :     }
     210          42 :     else if (aKey == "fFitShapeToText")
     211          11 :         obFitShapeToText = aValue.toInt32() == 1;
     212          31 :     else if (aKey == "fFilled")
     213          28 :         bFilled = aValue.toInt32() == 1;
     214           3 :     else if (aKey == "rotation")
     215             :     {
     216             :         // See DffPropertyReader::Fix16ToAngle(): in RTF, positive rotation angles are clockwise, we have them as counter-clockwise.
     217             :         // Additionally, RTF type is 0..360*2^16, our is 0..360*100.
     218           3 :         sal_Int32 nRotation = aValue.toInt32()*100/65536;
     219           3 :         uno::Reference<lang::XServiceInfo> xServiceInfo(xShape, uno::UNO_QUERY);
     220           3 :         if (!xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
     221           2 :             xPropertySet->setPropertyValue("RotateAngle", uno::makeAny(sal_Int32(NormAngle360(nRotation * -1))));
     222             :     }
     223             : 
     224          58 :     if (nHoriOrient != 0 && xPropertySet.is())
     225           9 :         xPropertySet->setPropertyValue("HoriOrient", uno::makeAny(nHoriOrient));
     226          58 :     if (nVertOrient != 0 && xPropertySet.is())
     227           3 :         xPropertySet->setPropertyValue("VertOrient", uno::makeAny(nVertOrient));
     228          58 :     if (!boost::logic::indeterminate(obFitShapeToText) && xPropertySet.is())
     229             :     {
     230           7 :         xPropertySet->setPropertyValue("SizeType", uno::makeAny(obFitShapeToText ? text::SizeType::MIN : text::SizeType::FIX));
     231           7 :         xPropertySet->setPropertyValue("FrameIsAutomaticHeight", uno::makeAny(static_cast<bool>(obFitShapeToText)));
     232             :     }
     233          58 :     if (!bFilled && xPropertySet.is())
     234             :     {
     235          14 :         if (m_bTextFrame)
     236           5 :             xPropertySet->setPropertyValue("BackColorTransparency", uno::makeAny(sal_Int32(100)));
     237             :         else
     238           9 :             xPropertySet->setPropertyValue("FillStyle", uno::makeAny(drawing::FillStyle_NONE));
     239          58 :     }
     240          58 : }
     241             : 
     242         109 : int RTFSdrImport::initShape(uno::Reference<drawing::XShape>& o_xShape,
     243             :                             uno::Reference<beans::XPropertySet>& o_xPropSet,
     244             :                             bool& o_rIsCustomShape,
     245             :                             RTFShape const& rShape, bool const bClose, ShapeOrPict const shapeOrPict)
     246             : {
     247             :     assert(!o_xShape.is());
     248             :     assert(!o_xPropSet.is());
     249         109 :     o_rIsCustomShape = false;
     250         109 :     m_bFakePict = false;
     251             : 
     252             :     // first, find the shape type
     253         109 :     int nType = -1;
     254         270 :     auto iter = std::find_if(rShape.aProperties.begin(), rShape.aProperties.end(), [](std::pair<OUString, OUString> aProperty)
     255             :     {
     256         270 :         return aProperty.first == "shapeType";
     257         379 :     });
     258             : 
     259         109 :     if (iter == rShape.aProperties.end())
     260             :     {
     261           7 :         if (SHAPE == shapeOrPict)
     262             :         {
     263             :             // The spec doesn't state what is the default for shapeType,
     264             :             // Word seems to implement it as a rectangle.
     265           5 :             nType = ESCHER_ShpInst_Rectangle;
     266             :         }
     267             :         else
     268             :         {
     269             :             // pict is picture by default but can be a rectangle too fdo#79319
     270           2 :             nType = ESCHER_ShpInst_PictureFrame;
     271             :         }
     272             :     }
     273             :     else
     274             :     {
     275         102 :         nType = iter->second.toInt32();
     276         102 :         if (PICT == shapeOrPict && ESCHER_ShpInst_PictureFrame != nType)
     277             :         {
     278           2 :             m_bFakePict = true;
     279             :         }
     280             :     }
     281             : 
     282         109 :     switch (nType)
     283             :     {
     284             :     case ESCHER_ShpInst_PictureFrame:
     285          27 :         createShape("com.sun.star.drawing.GraphicObjectShape", o_xShape, o_xPropSet);
     286          27 :         m_bTextGraphicObject = true;
     287          27 :         break;
     288             :     case ESCHER_ShpInst_Line:
     289           6 :         createShape("com.sun.star.drawing.LineShape", o_xShape, o_xPropSet);
     290           6 :         break;
     291             :     case ESCHER_ShpInst_Rectangle:
     292             :     case ESCHER_ShpInst_TextBox:
     293             :         // If we're inside a groupshape, can't use text frames.
     294          64 :         if (!bClose && m_aParents.size() == 1)
     295             :         {
     296          35 :             createShape("com.sun.star.text.TextFrame", o_xShape, o_xPropSet);
     297          35 :             m_bTextFrame = true;
     298          35 :             std::vector<beans::PropertyValue> aDefaults = getTextFrameDefaults(true);
     299         350 :             for (size_t j = 0; j < aDefaults.size(); ++j)
     300         315 :                 o_xPropSet->setPropertyValue(aDefaults[j].Name, aDefaults[j].Value);
     301          35 :             break;
     302             :         }
     303             :     // fall-through intended
     304             :     default:
     305          41 :         createShape("com.sun.star.drawing.CustomShape", o_xShape, o_xPropSet);
     306          41 :         o_rIsCustomShape = true;
     307          41 :         break;
     308             :     }
     309             : 
     310             :     // Defaults
     311         109 :     if (o_xPropSet.is() && !m_bTextFrame)
     312             :     {
     313          65 :         o_xPropSet->setPropertyValue("FillColor", uno::makeAny(sal_uInt32(0xffffff))); // White in Word, kind of blue in Writer.
     314             :     }
     315             : 
     316         109 :     return nType;
     317             : }
     318             : 
     319         109 : void RTFSdrImport::resolve(RTFShape& rShape, bool bClose, ShapeOrPict const shapeOrPict)
     320             : {
     321         109 :     bool bPib = false;
     322         109 :     m_bTextFrame = false;
     323         109 :     m_bTextGraphicObject = false;
     324             : 
     325         109 :     uno::Reference<drawing::XShape> xShape;
     326         190 :     uno::Reference<beans::XPropertySet> xPropertySet;
     327         190 :     uno::Any aAny;
     328         190 :     beans::PropertyValue aPropertyValue;
     329         109 :     awt::Rectangle aViewBox;
     330         190 :     std::vector<beans::PropertyValue> aPath;
     331             :     // Default line color is black in Word, blue in Writer.
     332         190 :     uno::Any aLineColor = uno::makeAny(COL_BLACK);
     333             :     // Default line width is 0.75 pt (26 mm100) in Word, 0 in Writer.
     334         190 :     uno::Any aLineWidth = uno::makeAny(sal_Int32(26));
     335         109 :     text::WritingMode eWritingMode = text::WritingMode_LR_TB;
     336             :     // Groupshape support
     337         190 :     boost::optional<sal_Int32> oGroupLeft, oGroupTop, oGroupRight, oGroupBottom;
     338         190 :     boost::optional<sal_Int32> oRelLeft, oRelTop, oRelRight, oRelBottom;
     339             : 
     340             :     // Importing these are not trivial, let the VML import do the hard work.
     341         190 :     oox::vml::FillModel aFillModel; // Gradient.
     342         190 :     oox::vml::ShadowModel aShadowModel; // Shadow.
     343             : 
     344         109 :     bool bOpaque = true;
     345             : 
     346         190 :     boost::optional<sal_Int16> oRelativeWidth, oRelativeHeight;
     347         109 :     sal_Int16 nRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
     348         109 :     sal_Int16 nRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
     349             : 
     350         109 :     bool bCustom(false);
     351         109 :     int const nType = initShape(xShape, xPropertySet, bCustom, rShape, bClose, shapeOrPict);
     352             : 
     353        3204 :     for (std::vector< std::pair<OUString, OUString> >::iterator i = rShape.aProperties.begin();
     354        2136 :             i != rShape.aProperties.end(); ++i)
     355             :     {
     356         959 :         if (i->first == "shapeType")
     357             :         {
     358         103 :             continue; // ignore: already handled by initShape
     359             :         }
     360         856 :         else if (i->first == "wzName")
     361             :         {
     362          14 :             if (m_bTextFrame)
     363             :             {
     364           0 :                 uno::Reference<container::XNamed> xNamed(xShape, uno::UNO_QUERY);
     365           0 :                 xNamed->setName(i->second);
     366             :             }
     367             :             else
     368          14 :                 xPropertySet->setPropertyValue("Name", uno::makeAny(i->second));
     369             :         }
     370         842 :         else if (i->first == "wzDescription")
     371          19 :             xPropertySet->setPropertyValue("Description", uno::makeAny(i->second));
     372         823 :         else if (i->first == "pib")
     373             :         {
     374          22 :             m_rImport.setDestinationText(i->second);
     375          22 :             bPib = true;
     376             :         }
     377         801 :         else if (i->first == "fillColor" && xPropertySet.is())
     378             :         {
     379          26 :             aAny <<= msfilter::util::BGRToRGB(i->second.toUInt32());
     380          26 :             if (m_bTextFrame)
     381          10 :                 xPropertySet->setPropertyValue("BackColor", aAny);
     382             :             else
     383          16 :                 xPropertySet->setPropertyValue("FillColor", aAny);
     384             : 
     385             :             // fillType will decide, possible it'll be the start color of a gradient.
     386          26 :             aFillModel.moColor.set("#" + OUString::fromUtf8(msfilter::util::ConvertColor(aAny.get<sal_Int32>())));
     387             :         }
     388         775 :         else if (i->first == "fillBackColor")
     389             :             // fillType will decide, possible it'll be the end color of a gradient.
     390          10 :             aFillModel.moColor2.set("#" + OUString::fromUtf8(msfilter::util::ConvertColor(msfilter::util::BGRToRGB(i->second.toInt32()))));
     391         765 :         else if (i->first == "lineColor")
     392          26 :             aLineColor <<= msfilter::util::BGRToRGB(i->second.toInt32());
     393         739 :         else if (i->first == "lineBackColor")
     394             :             ; // Ignore: complementer of lineColor
     395         735 :         else if (i->first == "txflTextFlow" && xPropertySet.is())
     396             :         {
     397           3 :             if (i->second.toInt32() == 1)
     398           0 :                 eWritingMode = text::WritingMode_TB_RL;
     399             :         }
     400         732 :         else if (i->first == "fLine" && xPropertySet.is())
     401          17 :             resolveFLine(xPropertySet, i->second.toInt32());
     402         715 :         else if (i->first == "fillOpacity" && xPropertySet.is())
     403             :         {
     404           0 :             int opacity = 100 - (i->second.toInt32())*100/65536;
     405           0 :             aAny <<= uno::makeAny(sal_uInt32(opacity));
     406           0 :             xPropertySet->setPropertyValue("FillTransparence", aAny);
     407             :         }
     408         715 :         else if (i->first == "lineWidth")
     409          25 :             aLineWidth <<= i->second.toInt32()/360;
     410         690 :         else if (i->first == "pVerticies")
     411             :         {
     412           5 :             std::vector<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
     413           5 :             sal_Int32 nSize = 0; // Size of a token (its value is hardwired in the exporter)
     414           5 :             sal_Int32 nCount = 0; // Number of tokens
     415           5 :             sal_Int32 nCharIndex = 0; // Character index
     416         140 :             do
     417             :             {
     418         140 :                 OUString aToken = i->second.getToken(0, ';', nCharIndex);
     419         140 :                 if (!nSize)
     420           5 :                     nSize = aToken.toInt32();
     421         135 :                 else if (!nCount)
     422           5 :                     nCount = aToken.toInt32();
     423         130 :                 else if (aToken.getLength())
     424             :                 {
     425             :                     // The coordinates are in an (x,y) form.
     426         130 :                     aToken = aToken.copy(1, aToken.getLength() - 2);
     427         130 :                     sal_Int32 nI = 0;
     428         130 :                     boost::optional<sal_Int32> oX;
     429         260 :                     boost::optional<sal_Int32> oY;
     430         260 :                     do
     431             :                     {
     432         260 :                         OUString aPoint = aToken.getToken(0, ',', nI);
     433         260 :                         if (!oX)
     434         130 :                             oX.reset(aPoint.toInt32());
     435             :                         else
     436         130 :                             oY.reset(aPoint.toInt32());
     437             :                     }
     438         260 :                     while (nI >= 0);
     439         260 :                     drawing::EnhancedCustomShapeParameterPair aPair;
     440         130 :                     aPair.First.Value <<= *oX;
     441         130 :                     aPair.Second.Value <<= *oY;
     442         260 :                     aCoordinates.push_back(aPair);
     443         140 :                 }
     444             :             }
     445         140 :             while (nCharIndex >= 0);
     446           5 :             aPropertyValue.Name = "Coordinates";
     447           5 :             aPropertyValue.Value <<= comphelper::containerToSequence(aCoordinates);
     448           5 :             aPath.push_back(aPropertyValue);
     449             :         }
     450         685 :         else if (i->first == "pSegmentInfo")
     451             :         {
     452           5 :             std::vector<drawing::EnhancedCustomShapeSegment> aSegments;
     453           5 :             sal_Int32 nSize = 0;
     454           5 :             sal_Int32 nCount = 0;
     455           5 :             sal_Int32 nCharIndex = 0;
     456          41 :             do
     457             :             {
     458          41 :                 sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32();
     459          41 :                 if (!nSize)
     460           5 :                     nSize = nSeg;
     461          36 :                 else if (!nCount)
     462           5 :                     nCount = nSeg;
     463             :                 else
     464             :                 {
     465          31 :                     sal_Int32 nPoints = 1;
     466          31 :                     if (nSeg >= 0x2000 && nSeg < 0x20FF)
     467             :                     {
     468           6 :                         nPoints = nSeg & 0x0FFF;
     469           6 :                         nSeg &= 0xFF00;
     470             :                     }
     471             : 
     472          31 :                     drawing::EnhancedCustomShapeSegment aSegment;
     473          31 :                     switch (nSeg)
     474             :                     {
     475             :                     case 0x0001: // lineto
     476           3 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
     477           3 :                         aSegment.Count = sal_Int32(1);
     478           3 :                         aSegments.push_back(aSegment);
     479           3 :                         break;
     480             :                     case 0x4000: // moveto
     481           7 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
     482           7 :                         aSegment.Count = sal_Int32(1);
     483           7 :                         aSegments.push_back(aSegment);
     484           7 :                         break;
     485             :                     case 0x2000: // curveto
     486           6 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
     487           6 :                         aSegment.Count = sal_Int32(nPoints);
     488           6 :                         aSegments.push_back(aSegment);
     489           6 :                         break;
     490             :                     case 0xb300: // arcto
     491           0 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
     492           0 :                         aSegment.Count = sal_Int32(0);
     493           0 :                         aSegments.push_back(aSegment);
     494           0 :                         break;
     495             :                     case 0xac00:
     496             :                     case 0xaa00: // nofill
     497             :                     case 0xab00: // nostroke
     498             :                     case 0x6001: // close
     499           3 :                         break;
     500             :                     case 0x8000: // end
     501           7 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
     502           7 :                         aSegment.Count = sal_Int32(0);
     503           7 :                         aSegments.push_back(aSegment);
     504           7 :                         break;
     505             :                     default: // given number of lineto elements
     506           5 :                         aSegment.Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
     507           5 :                         aSegment.Count = nSeg;
     508           5 :                         aSegments.push_back(aSegment);
     509           5 :                         break;
     510             :                     }
     511             :                 }
     512             :             }
     513          41 :             while (nCharIndex >= 0);
     514           5 :             aPropertyValue.Name = "Segments";
     515           5 :             aPropertyValue.Value <<= comphelper::containerToSequence(aSegments);
     516           5 :             aPath.push_back(aPropertyValue);
     517             :         }
     518         680 :         else if (i->first == "geoLeft")
     519           2 :             aViewBox.X = i->second.toInt32();
     520         678 :         else if (i->first == "geoTop")
     521           2 :             aViewBox.Y = i->second.toInt32();
     522         676 :         else if (i->first == "geoRight")
     523           4 :             aViewBox.Width = i->second.toInt32();
     524         672 :         else if (i->first == "geoBottom")
     525           4 :             aViewBox.Height = i->second.toInt32();
     526         668 :         else if (i->first == "dhgt")
     527             :         {
     528             :             // dhgt is Word 2007, \shpz is Word 97-2003, the later has priority.
     529          13 :             if (!rShape.oZ)
     530           0 :                 resolveDhgt(xPropertySet, i->second.toInt32(), /*bOldStyle=*/false);
     531             :         }
     532             :         // These are in EMU, convert to mm100.
     533         655 :         else if (i->first == "dxTextLeft")
     534             :         {
     535          19 :             if (xPropertySet.is())
     536          15 :                 xPropertySet->setPropertyValue("LeftBorderDistance", uno::makeAny(i->second.toInt32() / 360));
     537             :         }
     538         636 :         else if (i->first == "dyTextTop")
     539             :         {
     540          18 :             if (xPropertySet.is())
     541          14 :                 xPropertySet->setPropertyValue("TopBorderDistance", uno::makeAny(i->second.toInt32() / 360));
     542             :         }
     543         618 :         else if (i->first == "dxTextRight")
     544             :         {
     545          19 :             if (xPropertySet.is())
     546          15 :                 xPropertySet->setPropertyValue("RightBorderDistance", uno::makeAny(i->second.toInt32() / 360));
     547             :         }
     548         599 :         else if (i->first == "dyTextBottom")
     549             :         {
     550          18 :             if (xPropertySet.is())
     551          14 :                 xPropertySet->setPropertyValue("BottomBorderDistance", uno::makeAny(i->second.toInt32() / 360));
     552             :         }
     553         581 :         else if (i->first == "dxWrapDistLeft")
     554             :         {
     555          13 :             if (m_bTextGraphicObject)
     556           1 :                 rShape.aAnchorAttributes.set(NS_ooxml::LN_CT_Anchor_distL, std::make_shared<RTFValue>(i->second.toInt32()));
     557          12 :             else if (xPropertySet.is())
     558          12 :                 xPropertySet->setPropertyValue("LeftMargin", uno::makeAny(i->second.toInt32() / 360));
     559             :         }
     560         568 :         else if (i->first == "dyWrapDistTop")
     561             :         {
     562          12 :             if (m_bTextGraphicObject)
     563           1 :                 rShape.aAnchorAttributes.set(NS_ooxml::LN_CT_Anchor_distT, std::make_shared<RTFValue>(i->second.toInt32()));
     564          11 :             else if (xPropertySet.is())
     565          11 :                 xPropertySet->setPropertyValue("TopMargin", uno::makeAny(i->second.toInt32() / 360));
     566             :         }
     567         556 :         else if (i->first == "dxWrapDistRight")
     568             :         {
     569          13 :             if (m_bTextGraphicObject)
     570           1 :                 rShape.aAnchorAttributes.set(NS_ooxml::LN_CT_Anchor_distR, std::make_shared<RTFValue>(i->second.toInt32()));
     571          12 :             else if (xPropertySet.is())
     572          12 :                 xPropertySet->setPropertyValue("RightMargin", uno::makeAny(i->second.toInt32() / 360));
     573             :         }
     574         543 :         else if (i->first == "dyWrapDistBottom")
     575             :         {
     576          12 :             if (m_bTextGraphicObject)
     577           1 :                 rShape.aAnchorAttributes.set(NS_ooxml::LN_CT_Anchor_distB, std::make_shared<RTFValue>(i->second.toInt32()));
     578          11 :             else if (xPropertySet.is())
     579          11 :                 xPropertySet->setPropertyValue("BottomMargin", uno::makeAny(i->second.toInt32() / 360));
     580             :         }
     581         531 :         else if (i->first == "fillType")
     582             :         {
     583          10 :             switch (i->second.toInt32())
     584             :             {
     585             :             case 7: // Shade using the fillAngle
     586           6 :                 aFillModel.moType.set(oox::XML_gradient);
     587           6 :                 break;
     588             :             default:
     589             :                 SAL_INFO("writerfilter", "TODO handle fillType value '" << i->second << "'");
     590           4 :                 break;
     591             :             }
     592             :         }
     593         521 :         else if (i->first == "fillFocus")
     594           6 :             aFillModel.moFocus.set(i->second.toDouble() / 100); // percent
     595         515 :         else if (i->first == "fShadow" && xPropertySet.is())
     596             :         {
     597          15 :             if (i->second.toInt32() == 1)
     598          12 :                 aShadowModel.mbHasShadow = true;
     599             :         }
     600         500 :         else if (i->first == "shadowColor")
     601          12 :             aShadowModel.moColor.set("#" + OUString::fromUtf8(msfilter::util::ConvertColor(msfilter::util::BGRToRGB(i->second.toInt32()))));
     602         488 :         else if (i->first == "shadowOffsetX")
     603             :             // EMUs to points
     604          12 :             aShadowModel.moOffset.set(OUString::number(i->second.toDouble() / 12700) + "pt");
     605         476 :         else if (i->first == "posh" || i->first == "posv" || i->first == "fFitShapeToText" || i->first == "fFilled" || i->first == "rotation")
     606          47 :             applyProperty(xShape, i->first, i->second);
     607         429 :         else if (i->first == "posrelh")
     608             :         {
     609          26 :             switch (i->second.toInt32())
     610             :             {
     611             :             case 1:
     612           7 :                 rShape.nHoriOrientRelation = text::RelOrientation::PAGE_FRAME;
     613           7 :                 break;
     614             :             default:
     615          19 :                 break;
     616             :             }
     617             :         }
     618         403 :         else if (i->first == "posrelv")
     619             :         {
     620          22 :             switch (i->second.toInt32())
     621             :             {
     622             :             case 1:
     623           7 :                 rShape.nVertOrientRelation = text::RelOrientation::PAGE_FRAME;
     624           7 :                 break;
     625             :             default:
     626          15 :                 break;
     627             :             }
     628             :         }
     629         381 :         else if (i->first == "groupLeft")
     630          13 :             oGroupLeft.reset(convertTwipToMm100(i->second.toInt32()));
     631         368 :         else if (i->first == "groupTop")
     632          13 :             oGroupTop.reset(convertTwipToMm100(i->second.toInt32()));
     633         355 :         else if (i->first == "groupRight")
     634          13 :             oGroupRight.reset(convertTwipToMm100(i->second.toInt32()));
     635         342 :         else if (i->first == "groupBottom")
     636          13 :             oGroupBottom.reset(convertTwipToMm100(i->second.toInt32()));
     637         329 :         else if (i->first == "relLeft")
     638          13 :             oRelLeft.reset(convertTwipToMm100(i->second.toInt32()));
     639         316 :         else if (i->first == "relTop")
     640          13 :             oRelTop.reset(convertTwipToMm100(i->second.toInt32()));
     641         303 :         else if (i->first == "relRight")
     642          13 :             oRelRight.reset(convertTwipToMm100(i->second.toInt32()));
     643         290 :         else if (i->first == "relBottom")
     644          13 :             oRelBottom.reset(convertTwipToMm100(i->second.toInt32()));
     645         277 :         else if (i->first == "fBehindDocument")
     646          15 :             bOpaque = !i->second.toInt32();
     647         262 :         else if (i->first == "pctHoriz" || i->first == "pctVert")
     648             :         {
     649           6 :             sal_Int16 nPercentage = rtl::math::round(i->second.toDouble() / 10);
     650           6 :             boost::optional<sal_Int16>& rPercentage = i->first == "pctHoriz" ? oRelativeWidth : oRelativeHeight;
     651           6 :             if (nPercentage)
     652           6 :                 rPercentage = nPercentage;
     653             :         }
     654         256 :         else if (i->first == "sizerelh")
     655             :         {
     656           1 :             if (xPropertySet.is())
     657             :             {
     658           1 :                 switch (i->second.toInt32())
     659             :                 {
     660             :                 case 0: // margin
     661           0 :                     nRelativeWidthRelation = text::RelOrientation::FRAME;
     662           0 :                     break;
     663             :                 case 1: // page
     664           1 :                     nRelativeWidthRelation = text::RelOrientation::PAGE_FRAME;
     665           1 :                     break;
     666             :                 default:
     667             :                     SAL_WARN("writerfilter", "RTFSdrImport::resolve: unhandled sizerelh value: " << i->second);
     668           0 :                     break;
     669             :                 }
     670             :             }
     671             :         }
     672         255 :         else if (i->first == "sizerelv")
     673             :         {
     674           3 :             if (xPropertySet.is())
     675             :             {
     676           3 :                 switch (i->second.toInt32())
     677             :                 {
     678             :                 case 0: // margin
     679           3 :                     nRelativeHeightRelation = text::RelOrientation::FRAME;
     680           3 :                     break;
     681             :                 case 1: // page
     682           0 :                     nRelativeHeightRelation = text::RelOrientation::PAGE_FRAME;
     683           0 :                     break;
     684             :                 default:
     685             :                     SAL_WARN("writerfilter", "RTFSdrImport::resolve: unhandled sizerelv value: " << i->second);
     686           0 :                     break;
     687             :                 }
     688             :             }
     689             :         }
     690         252 :         else if (i->first == "fHorizRule") // TODO: what does "fStandardHR" do?
     691             :         {
     692             :             // horizontal rule: relative width defaults to 100% of paragraph
     693             :             // TODO: does it have a default height?
     694           1 :             if (!oRelativeWidth)
     695             :             {
     696           1 :                 oRelativeWidth = 100;
     697             :             }
     698           1 :             nRelativeWidthRelation = text::RelOrientation::FRAME;
     699           1 :             sal_Int16 const nVertOrient = text::VertOrientation::CENTER;
     700           1 :             if (xPropertySet.is())
     701             :             {
     702           1 :                 xPropertySet->setPropertyValue("VertOrient", uno::makeAny(nVertOrient));
     703             :             }
     704             :         }
     705         251 :         else if (i->first == "pctHR")
     706             :         {
     707             :             // horizontal rule relative width in permille
     708           0 :             oRelativeWidth = i->second.toInt32() / 10;
     709             :         }
     710         251 :         else if (i->first == "dxHeightHR")
     711             :         {
     712             :             // horizontal rule height
     713           1 :             sal_uInt32 const nHeight(convertTwipToMm100(i->second.toInt32()));
     714           1 :             rShape.nBottom = rShape.nTop + nHeight;
     715             :         }
     716         250 :         else if (i->first == "dxWidthHR")
     717             :         {
     718             :             // horizontal rule width
     719           0 :             sal_uInt32 const nWidth(convertTwipToMm100(i->second.toInt32()));
     720           0 :             rShape.nRight = rShape.nLeft + nWidth;
     721             :         }
     722         250 :         else if (i->first == "alignHR")
     723             :         {
     724             :             // horizontal orientation *for horizontal rule*
     725           1 :             sal_Int16 nHoriOrient = text::HoriOrientation::NONE;
     726           1 :             switch (i->second.toInt32())
     727             :             {
     728             :             case 0:
     729           0 :                 nHoriOrient = text::HoriOrientation::LEFT;
     730           0 :                 break;
     731             :             case 1:
     732           1 :                 nHoriOrient = text::HoriOrientation::CENTER;
     733           1 :                 break;
     734             :             case 2:
     735           0 :                 nHoriOrient = text::HoriOrientation::RIGHT;
     736           0 :                 break;
     737             :             }
     738           1 :             if (xPropertySet.is() && text::HoriOrientation::NONE != nHoriOrient)
     739             :             {
     740           1 :                 xPropertySet->setPropertyValue("HoriOrient", uno::makeAny(nHoriOrient));
     741             :             }
     742             :         }
     743         249 :         else if (i->first == "pWrapPolygonVertices")
     744             :         {
     745           3 :             RTFSprms aPolygonSprms;
     746           3 :             sal_Int32 nSize = 0; // Size of a token
     747           3 :             sal_Int32 nCount = 0; // Number of tokens
     748           3 :             sal_Int32 nCharIndex = 0; // Character index
     749          39 :             do
     750             :             {
     751          39 :                 OUString aToken = i->second.getToken(0, ';', nCharIndex);
     752          39 :                 if (!nSize)
     753           3 :                     nSize = aToken.toInt32();
     754          36 :                 else if (!nCount)
     755           3 :                     nCount = aToken.toInt32();
     756          33 :                 else if (aToken.getLength())
     757             :                 {
     758             :                     // The coordinates are in an (x,y) form.
     759          33 :                     aToken = aToken.copy(1, aToken.getLength() - 2);
     760          33 :                     sal_Int32 nI = 0;
     761          33 :                     boost::optional<sal_Int32> oX;
     762          66 :                     boost::optional<sal_Int32> oY;
     763          66 :                     do
     764             :                     {
     765          66 :                         OUString aPoint = aToken.getToken(0, ',', nI);
     766          66 :                         if (!oX)
     767          33 :                             oX.reset(aPoint.toInt32());
     768             :                         else
     769          33 :                             oY.reset(aPoint.toInt32());
     770             :                     }
     771          66 :                     while (nI >= 0);
     772          66 :                     RTFSprms aPathAttributes;
     773          33 :                     aPathAttributes.set(NS_ooxml::LN_CT_Point2D_x, std::make_shared<RTFValue>(*oX));
     774          33 :                     aPathAttributes.set(NS_ooxml::LN_CT_Point2D_y, std::make_shared<RTFValue>(*oY));
     775          66 :                     aPolygonSprms.set(NS_ooxml::LN_CT_WrapPath_lineTo, std::make_shared<RTFValue>(aPathAttributes), RTFOverwrite::NO_APPEND);
     776          39 :                 }
     777             :             }
     778          39 :             while (nCharIndex >= 0);
     779           3 :             rShape.aWrapPolygonSprms = aPolygonSprms;
     780             :         }
     781             :         else
     782             :             SAL_INFO("writerfilter", "TODO handle shape property '" << i->first << "':'" << i->second << "'");
     783             :     }
     784             : 
     785         109 :     if (xPropertySet.is())
     786             :     {
     787         100 :         resolveLineColorAndWidth(m_bTextFrame, xPropertySet, aLineColor, aLineWidth);
     788         100 :         if (rShape.oZ)
     789          59 :             resolveDhgt(xPropertySet, *rShape.oZ, /*bOldStyle=*/false);
     790         100 :         if (m_bTextFrame)
     791             :             // Writer textframes implement text::WritingMode2, which is a different data type.
     792          35 :             xPropertySet->setPropertyValue("WritingMode", uno::makeAny(sal_Int16(eWritingMode)));
     793             :         else
     794          65 :             xPropertySet->setPropertyValue("TextWritingMode", uno::makeAny(eWritingMode));
     795             :     }
     796             : 
     797         109 :     if (m_aParents.size() && m_aParents.top().is() && !m_bTextFrame)
     798          65 :         m_aParents.top()->add(xShape);
     799             : 
     800         109 :     if (bPib)
     801             :     {
     802          22 :         m_rImport.resolvePict(false, xShape);
     803             :     }
     804             : 
     805         109 :     if (nType == ESCHER_ShpInst_PictureFrame) // picture frame
     806             :     {
     807             :         assert(!m_bTextFrame);
     808          27 :         if (!bPib) // ??? not sure if the early return should be removed on else?
     809             :         {
     810           6 :             m_xShape = xShape; // store it for later resolvePict call
     811             :         }
     812          27 :         return;
     813             :     }
     814             : 
     815          82 :     if (bCustom && xShape.is() && !bPib)
     816             :     {
     817          33 :         uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
     818          33 :         xDefaulter->createCustomShapeDefaults(OUString::number(nType));
     819             :     }
     820             : 
     821             :     // Creating CustomShapeGeometry property
     822          82 :     std::vector<beans::PropertyValue> aGeometry;
     823          82 :     if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height)
     824             :     {
     825           4 :         aViewBox.Width -= aViewBox.X;
     826           4 :         aViewBox.Height -= aViewBox.Y;
     827           4 :         aPropertyValue.Name = "ViewBox";
     828           4 :         aPropertyValue.Value <<= aViewBox;
     829           4 :         aGeometry.push_back(aPropertyValue);
     830             :     }
     831          82 :     if (!aPath.empty())
     832             :     {
     833           5 :         aPropertyValue.Name = "Path";
     834           5 :         aPropertyValue.Value <<= comphelper::containerToSequence(aPath);
     835           5 :         aGeometry.push_back(aPropertyValue);
     836             :     }
     837          82 :     if (!aGeometry.empty() && xPropertySet.is() && !m_bTextFrame)
     838           4 :         xPropertySet->setPropertyValue("CustomShapeGeometry", uno::Any(comphelper::containerToSequence(aGeometry)));
     839             : 
     840             :     // Set position and size
     841          82 :     if (xShape.is())
     842             :     {
     843          75 :         sal_Int32 nLeft = rShape.nLeft;
     844          75 :         sal_Int32 nTop = rShape.nTop;
     845             : 
     846          87 :         bool bInShapeGroup = oGroupLeft && oGroupTop && oGroupRight && oGroupBottom
     847          87 :                              && oRelLeft && oRelTop && oRelRight && oRelBottom;
     848          75 :         if (bInShapeGroup)
     849             :         {
     850             :             // See lclGetAbsPoint() in the VML import: rShape is the group shape, oGroup is its coordinate system, oRel is the relative child shape.
     851          12 :             sal_Int32 nShapeWidth = rShape.nRight - rShape.nLeft;
     852          12 :             sal_Int32 nShapeHeight = rShape.nBottom - rShape.nTop;
     853          12 :             sal_Int32 nCoordSysWidth = *oGroupRight - *oGroupLeft;
     854          12 :             sal_Int32 nCoordSysHeight = *oGroupBottom - *oGroupTop;
     855          12 :             double fWidthRatio = static_cast< double >(nShapeWidth) / nCoordSysWidth;
     856          12 :             double fHeightRatio = static_cast< double >(nShapeHeight) / nCoordSysHeight;
     857          12 :             nLeft = static_cast< sal_Int32 >(rShape.nLeft + fWidthRatio * (*oRelLeft - *oGroupLeft));
     858          12 :             nTop = static_cast< sal_Int32 >(rShape.nTop + fHeightRatio * (*oRelTop - *oGroupTop));
     859             :         }
     860             : 
     861          75 :         if (m_bTextFrame)
     862             :         {
     863          35 :             xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny(nLeft));
     864          35 :             xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny(nTop));
     865             :         }
     866             :         else
     867          40 :             xShape->setPosition(awt::Point(nLeft, nTop));
     868             : 
     869          75 :         if (bInShapeGroup)
     870          12 :             xShape->setSize(awt::Size(*oRelRight - *oRelLeft, *oRelBottom - *oRelTop));
     871             :         else
     872          63 :             xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
     873             : 
     874          75 :         if (rShape.nHoriOrientRelation != 0)
     875          20 :             xPropertySet->setPropertyValue("HoriOrientRelation", uno::makeAny(rShape.nHoriOrientRelation));
     876          75 :         if (rShape.nVertOrientRelation != 0)
     877          19 :             xPropertySet->setPropertyValue("VertOrientRelation", uno::makeAny(rShape.nVertOrientRelation));
     878          75 :         if (rShape.nWrap != -1)
     879          65 :             xPropertySet->setPropertyValue("Surround", uno::makeAny(text::WrapTextMode(rShape.nWrap)));
     880          75 :         oox::ModelObjectHelper aModelObjectHelper(m_rImport.getModelFactory());
     881          75 :         if (aFillModel.moType.has())
     882             :         {
     883           6 :             oox::drawingml::ShapePropertyMap aPropMap(aModelObjectHelper);
     884           6 :             aFillModel.pushToPropMap(aPropMap, m_rImport.getGraphicHelper());
     885             :             // Sets the FillStyle and FillGradient UNO properties.
     886           6 :             oox::PropertySet(xShape).setProperties(aPropMap);
     887             :         }
     888             : 
     889          75 :         if (aShadowModel.mbHasShadow)
     890             :         {
     891          12 :             oox::drawingml::ShapePropertyMap aPropMap(aModelObjectHelper);
     892          12 :             aShadowModel.pushToPropMap(aPropMap, m_rImport.getGraphicHelper());
     893             :             // Sets the ShadowFormat UNO property.
     894          12 :             oox::PropertySet(xShape).setProperties(aPropMap);
     895             :         }
     896          75 :         xPropertySet->setPropertyValue("AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
     897          75 :         xPropertySet->setPropertyValue("Opaque", uno::makeAny(bOpaque));
     898          75 :         if (oRelativeWidth)
     899             :         {
     900           4 :             xPropertySet->setPropertyValue("RelativeWidth", uno::makeAny(*oRelativeWidth));
     901           4 :             xPropertySet->setPropertyValue("RelativeWidthRelation", uno::makeAny(nRelativeWidthRelation));
     902             :         }
     903          75 :         if (oRelativeHeight)
     904             :         {
     905           3 :             xPropertySet->setPropertyValue("RelativeHeight", uno::makeAny(*oRelativeHeight));
     906           3 :             xPropertySet->setPropertyValue("RelativeHeightRelation", uno::makeAny(nRelativeHeightRelation));
     907          75 :         }
     908             :     }
     909             : 
     910          82 :     if (m_rImport.isInBackground())
     911             :     {
     912           1 :         RTFSprms aAttributes;
     913           1 :         aAttributes.set(NS_ooxml::LN_CT_Background_color, std::make_shared<RTFValue>(xPropertySet->getPropertyValue("FillColor").get<sal_Int32>()));
     914           1 :         m_rImport.Mapper().props(std::make_shared<RTFReferenceProperties>(aAttributes));
     915             : 
     916           2 :         uno::Reference<lang::XComponent> xComponent(xShape, uno::UNO_QUERY);
     917           1 :         xComponent->dispose();
     918           2 :         return;
     919             :     }
     920             : 
     921             :     // Send it to dmapper
     922          81 :     m_rImport.Mapper().startShape(xShape);
     923          81 :     if (bClose)
     924             :     {
     925          37 :         m_rImport.Mapper().endShape();
     926             :     }
     927         162 :     m_xShape = xShape;
     928             : }
     929             : 
     930          44 : void RTFSdrImport::close()
     931             : {
     932          44 :     m_rImport.Mapper().endShape();
     933          44 : }
     934             : 
     935          10 : void RTFSdrImport::append(const OUString& aKey, const OUString& aValue)
     936             : {
     937          10 :     applyProperty(m_xShape, aKey, aValue);
     938          10 : }
     939             : 
     940           2 : void RTFSdrImport::appendGroupProperty(const OUString& aKey, const OUString& aValue)
     941             : {
     942           2 :     uno::Reference<drawing::XShape> xShape(m_aParents.top(), uno::UNO_QUERY);
     943           2 :     if (xShape.is())
     944           1 :         applyProperty(xShape, aKey, aValue);
     945           2 : }
     946             : 
     947             : } // namespace rtftok
     948          72 : } // namespace writerfilter
     949             : 
     950             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11