[Libreoffice-commits] core.git: sw/qa writerfilter/source

Miklos Vajna vmiklos at suse.cz
Tue Jun 25 06:35:23 PDT 2013


 sw/qa/extras/rtfimport/data/fdo66040.rtf       |   85 +++++++++++++++++++++++++
 sw/qa/extras/rtfimport/rtfimport.cxx           |   23 ++++++
 writerfilter/source/rtftok/rtfdocumentimpl.cxx |    9 ++
 writerfilter/source/rtftok/rtfdocumentimpl.hxx |    2 
 writerfilter/source/rtftok/rtfsdrimport.cxx    |   52 ++++++++++++++-
 5 files changed, 165 insertions(+), 6 deletions(-)

New commits:
commit a8ee2ee7529900628b1c533d77c039618917bc97
Author: Miklos Vajna <vmiklos at suse.cz>
Date:   Tue Jun 25 14:47:48 2013 +0200

    fdo#66040 RTF import: initial groupshape support
    
    There are two cases here: if the shapes contain tables (or other
    Writer-specific features), we should use text frames and we should not
    create the actual group shape, as Writer textframes can't be part of
    such group shapes.  The other case is when the shapes contain simple
    text, OTOH there are groupshape-level transformations defined, in that
    case we should choose drawinglayer rectangles and actually create a
    group shape.
    
    This commit implements support for the first case only.
    
    Change-Id: I9dc99b0711ce5c7a29ea0b14539df0121f9de3d0

diff --git a/sw/qa/extras/rtfimport/data/fdo66040.rtf b/sw/qa/extras/rtfimport/data/fdo66040.rtf
new file mode 100644
index 0000000..e067f23
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/fdo66040.rtf
@@ -0,0 +1,85 @@
+{\rtf1
+\paperw16840\paperh11907\margl567\margr567\margt567\margb567
+{\shpgrp
+{\*\shpinst\shpleft-201\shptop-585\shpright16112\shpbottom11321
+{\sp
+{\sn groupLeft}
+{\sv 288}
+}
+{\sp
+{\sn groupTop}
+{\sv -18}
+}
+{\sp
+{\sn groupRight}
+{\sv 16601}
+}
+{\sp
+{\sn groupBottom}
+{\sv 11888}
+}
+{\shp
+{\*\shpinst
+{\sp
+{\sn relLeft}
+{\sv 288}
+}
+{\sp
+{\sn relTop}
+{\sv -18}
+}
+{\sp
+{\sn relRight}
+{\sv 8225}
+}
+{\sp
+{\sn relBottom}
+{\sv 11888}
+}
+{\sp
+{\sn shapeType}
+{\sv 202}
+}
+{\shptxt foo\par
+\pard\plain \intbl A\cell B\cell
+{
+\trowd \irow0\irowband0\lastrow \ltrrow\ts32\trgaph108\trleft-108\trbrdrt\brdrs\brdrw10\brdrcf17 \trbrdrl\brdrs\brdrw10\brdrcf17 \trbrdrb\brdrs\brdrw10\brdrcf17 \trbrdrr\brdrs\brdrw10\brdrcf17 \trbrdrh
+\brdrs\brdrw10\brdrcf17 \trbrdrv\brdrs\brdrw10\brdrcf17 \trftsWidth1\trftsWidthB3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid14568770\tbllkhdrrows\tbllkhdrcols\tbllknocolband\tblind0\tblindtype3 \clvertalt\clbrdrt
+\brdrs\brdrw10\brdrcf17 \clbrdrl\brdrs\brdrw10\brdrcf17 \clbrdrb\brdrs\brdrw10\brdrcf17 \clbrdrr\brdrs\brdrw10\brdrcf17 \cltxlrtb\clftsWidth3\clwWidth1783\clshdrawnil \cellx1675\clvertalt\clbrdrt\brdrs\brdrw10\brdrcf17 \clbrdrl\brdrs\brdrw10\brdrcf17
+\clbrdrb\brdrs\brdrw10\brdrcf17 \clbrdrr\brdrs\brdrw10\brdrcf17 \cltxlrtb\clftsWidth3\clwWidth1784\clshdrawnil \cellx3459\row }
+\pard
+bar
+\par
+}
+}
+}
+{\shp
+{\*\shpinst
+{\sp
+{\sn relLeft}
+{\sv 8664}
+}
+{\sp
+{\sn relTop}
+{\sv -18}
+}
+{\sp
+{\sn relRight}
+{\sv 16601}
+}
+{\sp
+{\sn relBottom}
+{\sv 11888}
+}
+{\sp
+{\sn shapeType}
+{\sv 202}
+}
+{\shptxt baz
+}
+}
+}
+}
+}
+\par
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 53be3b2..a9c74b1 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -146,6 +146,7 @@ public:
     void testN825305();
     void testParaBottomMargin();
     void testN823655();
+    void testFdo66040();
 
     CPPUNIT_TEST_SUITE(Test);
 #if !defined(MACOSX) && !defined(WNT)
@@ -278,6 +279,7 @@ void Test::run()
         {"n825305.rtf", &Test::testN825305},
         {"para-bottom-margin.rtf", &Test::testParaBottomMargin},
         {"n823655.rtf", &Test::testN823655},
+        {"fdo66040.rtf", &Test::testFdo66040},
     };
     header();
     for (unsigned int i = 0; i < SAL_N_ELEMENTS(aMethods); ++i)
@@ -1332,6 +1334,27 @@ void Test::testN823655()
     CPPUNIT_ASSERT_EQUAL(sal_Int32(286), aCoordinates[0].Second.Value.get<sal_Int32>());
 }
 
+void Test::testFdo66040()
+{
+    uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
+    // This was 0 (no shapes were imported), we want two textframes.
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xDraws->getCount());
+
+    // The second paragraph of the first shape should be actually a table, with "A" in its A1 cell.
+    uno::Reference<text::XTextRange> xTextRange(xDraws->getByIndex(0), uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextRange->getText();
+    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(2, xText), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("A"), uno::Reference<text::XTextRange>(xTable->getCellByName("A1"), uno::UNO_QUERY)->getString());
+
+    // Make sure the second shape has the correct position and size.
+    uno::Reference<drawing::XShape> xShape(xDraws->getByIndex(1), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(14420), getProperty<sal_Int32>(xShape, "HoriOrientPosition"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(-1032), getProperty<sal_Int32>(xShape, "VertOrientPosition"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(14000), xShape->getSize().Width);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(21001), xShape->getSize().Height);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 7c4f545..76ab7ea 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -1667,6 +1667,10 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
             m_aStates.top().nDestinationState = DESTINATION_BACKGROUND;
             m_aStates.top().bInBackground = true;
             break;
+        case RTF_SHPGRP:
+            m_aStates.top().nDestinationState = DESTINATION_SHAPEGROUP;
+            m_aStates.top().bInShapeGroup = true;
+            break;
         default:
             SAL_INFO("writerfilter", "TODO handle destination '" << lcl_RtfToString(nKeyword) << "'");
             // Make sure we skip destinations (even without \*) till we don't handle them
@@ -3876,7 +3880,7 @@ int RTFDocumentImpl::popState()
             break;
         case DESTINATION_PICPROP:
         case DESTINATION_SHAPEINSTRUCTION:
-            if (!m_bObject && !aState.bInListpicture && !m_aStates.top().bHadShapeText)
+            if (!m_bObject && !aState.bInListpicture && !m_aStates.top().bHadShapeText && !m_aStates.top().bInShapeGroup)
                 m_pSdrImport->resolve(m_aStates.top().aShape, true);
             break;
         case DESTINATION_BOOKMARKSTART:
@@ -4711,7 +4715,8 @@ RTFParserState::RTFParserState(RTFDocumentImpl *pDocumentImpl)
     bHasTableStyle(false),
     bInListpicture(false),
     bInBackground(false),
-    bHadShapeText(false)
+    bHadShapeText(false),
+    bInShapeGroup(false)
 {
 }
 
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 7ca1c24..b878309 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -164,6 +164,7 @@ namespace writerfilter {
             DESTINATION_UPR,
             DESTINATION_LFOLEVEL,
             DESTINATION_BACKGROUND,
+            DESTINATION_SHAPEGROUP,
         };
 
         enum RTFBorderState
@@ -406,6 +407,7 @@ namespace writerfilter {
                 bool bInBackground;
 
                 bool bHadShapeText;
+                bool bInShapeGroup; ///< If we're inside a \shpgrp group.
         };
 
         class RTFTokenizer;
diff --git a/writerfilter/source/rtftok/rtfsdrimport.cxx b/writerfilter/source/rtftok/rtfsdrimport.cxx
index 6cac9c1..c47a29b 100644
--- a/writerfilter/source/rtftok/rtfsdrimport.cxx
+++ b/writerfilter/source/rtftok/rtfsdrimport.cxx
@@ -36,6 +36,8 @@
 #include <oox/drawingml/shapepropertymap.hxx>
 #include <oox/helper/propertyset.hxx>
 
+#define TWIP_TO_MM100(TWIP)     ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L))
+
 namespace writerfilter {
 namespace rtftok {
 
@@ -201,6 +203,9 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose)
     // Default line width is 0.75 pt (26 mm100) in Word, 0 in Writer.
     uno::Any aLineWidth = uno::makeAny(sal_Int32(26));
     text::WritingMode eWritingMode = text::WritingMode_LR_TB;
+    // Groupshape support
+    boost::optional<sal_Int32> oGroupLeft, oGroupTop, oGroupRight, oGroupBottom;
+    boost::optional<sal_Int32> oRelLeft, oRelTop, oRelRight, oRelBottom;
 
     // Importing these are not trivial, let the VML import do the hard work.
     oox::vml::FillModel aFillModel; // Gradient.
@@ -483,6 +488,22 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose)
                     break;
             }
         }
+        else if (i->first == "groupLeft")
+            oGroupLeft.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "groupTop")
+            oGroupTop.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "groupRight")
+            oGroupRight.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "groupBottom")
+            oGroupBottom.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "relLeft")
+            oRelLeft.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "relTop")
+            oRelTop.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "relRight")
+            oRelRight.reset(TWIP_TO_MM100(i->second.toInt32()));
+        else if (i->first == "relBottom")
+            oRelBottom.reset(TWIP_TO_MM100(i->second.toInt32()));
         else
             SAL_INFO("writerfilter", "TODO handle shape property '" << i->first << "':'" << i->second << "'");
     }
@@ -563,14 +584,37 @@ void RTFSdrImport::resolve(RTFShape& rShape, bool bClose)
     // Set position and size
     if (xShape.is())
     {
+        sal_Int32 nLeft = rShape.nLeft;
+        sal_Int32 nTop = rShape.nTop;
+
+        bool bInShapeGroup = oGroupLeft && oGroupTop && oGroupRight && oGroupBottom
+            && oRelLeft && oRelTop && oRelRight && oRelBottom;
+        if (bInShapeGroup)
+        {
+            // See lclGetAbsPoint() in the VML import: rShape is the group shape, oGroup is its coordinate system, oRel is the relative child shape.
+            sal_Int32 nShapeWidth = rShape.nRight - rShape.nLeft;
+            sal_Int32 nShapeHeight = rShape.nBottom - rShape.nTop;
+            sal_Int32 nCoordSysWidth = *oGroupRight - *oGroupLeft;
+            sal_Int32 nCoordSysHeight = *oGroupBottom - *oGroupTop;
+            double fWidthRatio = static_cast< double >( nShapeWidth ) / nCoordSysWidth;
+            double fHeightRatio = static_cast< double >( nShapeHeight ) / nCoordSysHeight;
+            nLeft = static_cast< sal_Int32 >( rShape.nLeft + fWidthRatio * (*oRelLeft - *oGroupLeft) );
+            nTop = static_cast< sal_Int32 >( rShape.nTop + fHeightRatio * (*oRelTop - *oGroupTop) );
+        }
+
         if (bTextFrame)
         {
-            xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny(rShape.nLeft));
-            xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny(rShape.nTop));
+            xPropertySet->setPropertyValue("HoriOrientPosition", uno::makeAny(nLeft));
+            xPropertySet->setPropertyValue("VertOrientPosition", uno::makeAny(nTop));
         }
         else
-            xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop));
-        xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
+            xShape->setPosition(awt::Point(nLeft, nTop));
+
+        if (bInShapeGroup)
+            xShape->setSize(awt::Size(*oRelRight - *oRelLeft, *oRelBottom - *oRelTop));
+        else
+            xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
+
         if (rShape.nHoriOrientRelation != 0)
             xPropertySet->setPropertyValue("HoriOrientRelation", uno::makeAny(rShape.nHoriOrientRelation));
         if (rShape.nVertOrientRelation != 0)


More information about the Libreoffice-commits mailing list