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

Generated by: LCOV version 1.10