[Libreoffice-commits] core.git: oox/source sd/qa

Regina Henschel (via logerrit) logerrit at kemper.freedesktop.org
Fri Aug 23 21:39:36 UTC 2019


 oox/source/export/shapes.cxx                |   74 ++++++++++++++++++++++++++--
 sd/qa/unit/data/odp/tdf99497_CircleKind.odp |binary
 sd/qa/unit/export-tests-ooxml2.cxx          |   42 +++++++++++++++
 3 files changed, 113 insertions(+), 3 deletions(-)

New commits:
commit 72b50be0197159c5afc5da4daf01ba303519b14a
Author:     Regina Henschel <rb.henschel at t-online.de>
AuthorDate: Tue Aug 20 10:43:46 2019 +0200
Commit:     Regina Henschel <rb.henschel at t-online.de>
CommitDate: Fri Aug 23 23:38:33 2019 +0200

    tdf#99497 CircleKind ARC, CUT, SECTION to OOXML arc, chord, pie
    
    Before this patch, a classical ellipse or circle was exported as
    OOXML preset type 'ellipse', regardless of the value of property
    CircleKind. Now the property is evaluated and the corresponding
    preset type is used.
    
    Change-Id: I49ff43cf7e2ce02654979e82f7d83d60ace39e23
    Reviewed-on: https://gerrit.libreoffice.org/77785
    Tested-by: Jenkins
    Reviewed-by: Regina Henschel <rb.henschel at t-online.de>

diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index a5928223ff1c..5e9d069c3290 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -47,6 +47,7 @@
 #include <com/sun/star/container/XEnumerationAccess.hpp>
 #include <com/sun/star/document/XExporter.hpp>
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/drawing/BitmapMode.hpp>
 #include <com/sun/star/drawing/ConnectorType.hpp>
@@ -102,6 +103,7 @@
 #include <oox/export/chartexport.hxx>
 #include <oox/mathml/export.hxx>
 #include <drawingml/presetgeometrynames.hxx>
+#include <basegfx/numeric/ftools.hxx>
 
 using namespace ::css;
 using namespace ::css::beans;
@@ -697,6 +699,21 @@ static sal_Int32 lcl_NormalizeAngle( sal_Int32 nAngle )
     return nAngle < 0 ? ( nAngle + 360 ) : nAngle ;
 }
 
+static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
+{
+    if (nWidth != 0 || nHeight != 0)
+    {
+        double fAngle = basegfx::deg2rad(nInternAngle / 100.0); // intern 1/100 deg to degree to rad
+        fAngle = atan2(nHeight * sin(fAngle), nWidth * cos(fAngle)); // circle to ellipse
+        fAngle = basegfx::rad2deg(fAngle) * 60000.0; // rad to degree to OOXML angle unit
+        sal_Int32 nAngle = basegfx::fround(fAngle); // normalize
+        nAngle = nAngle % 21600000;
+        return nAngle < 0 ? (nAngle + 21600000) : nAngle;
+    }
+    else // should be handled by caller, dummy value
+        return 0;
+}
+
 ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
 {
     // First check, if this is a Fontwork-shape. For DrawingML, such a shape is a
@@ -1055,7 +1072,7 @@ ShapeExport& ShapeExport::WriteEllipseShape( const Reference< XShape >& xShape )
 
     pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
 
-    // TODO: arc, section, cut, connector
+    // TODO: connector ?
 
     // non visual shape properties
     if (GetDocumentType() != DOCUMENT_DOCX)
@@ -1071,13 +1088,64 @@ ShapeExport& ShapeExport::WriteEllipseShape( const Reference< XShape >& xShape )
     else
         pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
 
+    Reference< XPropertySet > xProps( xShape, UNO_QUERY );
+    CircleKind  eCircleKind(CircleKind_FULL);
+    if (xProps.is())
+        xProps->getPropertyValue("CircleKind" ) >>= eCircleKind;
+
     // visual shape properties
     pFS->startElementNS( mnXmlNamespace, XML_spPr );
     WriteShapeTransformation( xShape, XML_a );
-    WritePresetShape( "ellipse" );
-    Reference< XPropertySet > xProps( xShape, UNO_QUERY );
+
+    if (CircleKind_FULL == eCircleKind)
+        WritePresetShape("ellipse");
+    else
+    {
+        sal_Int32 nStartAngleIntern(9000);
+        sal_Int32 nEndAngleIntern(0);
+        if (xProps.is())
+        {
+           xProps->getPropertyValue("CircleStartAngle" ) >>= nStartAngleIntern;
+           xProps->getPropertyValue("CircleEndAngle") >>= nEndAngleIntern;
+        }
+        std::vector< std::pair<sal_Int32,sal_Int32>> aAvList;
+        awt::Size aSize = xShape->getSize();
+        if (aSize.Width != 0 || aSize.Height != 0)
+        {
+            // Our arc has 90° up, OOXML has 90° down, so mirror it.
+            // API angles are 1/100 degree.
+            sal_Int32 nStartAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nEndAngleIntern, aSize.Width, aSize.Height));
+            sal_Int32 nEndAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nStartAngleIntern, aSize.Width, aSize.Height));
+            lcl_AppendAdjustmentValue( aAvList, 1, nStartAngleOOXML);
+            lcl_AppendAdjustmentValue( aAvList, 2, nEndAngleOOXML);
+        }
+        switch (eCircleKind)
+        {
+            case CircleKind_ARC :
+                WritePresetShape("arc", aAvList);
+            break;
+            case CircleKind_SECTION :
+                WritePresetShape("pie", aAvList);
+            break;
+            case CircleKind_CUT :
+                WritePresetShape("chord", aAvList);
+            break;
+        default :
+            WritePresetShape("ellipse");
+        }
+    }
     if( xProps.is() )
     {
+        if (CircleKind_ARC == eCircleKind)
+        {
+            // An arc in ODF is never filled, even if a fill style other than
+            // "none" is set. OOXML arc can be filled, so set fill explicit to
+            // NONE, otherwise some hidden or inherited filling is shown.
+            FillStyle eFillStyle(FillStyle_NONE);
+            uno::Any aNewValue;
+            aNewValue <<= eFillStyle;
+            xProps->setPropertyValue("FillStyle", aNewValue);
+        }
         WriteFill( xProps );
         WriteOutline( xProps );
     }
diff --git a/sd/qa/unit/data/odp/tdf99497_CircleKind.odp b/sd/qa/unit/data/odp/tdf99497_CircleKind.odp
new file mode 100644
index 000000000000..f3749dfdffb0
Binary files /dev/null and b/sd/qa/unit/data/odp/tdf99497_CircleKind.odp differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index dc1c4246ff35..0916ac95f3ff 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -193,6 +193,7 @@ public:
     void testTdf111789();
     void testTdf100348_convert_Fontwork2TextWarp();
     void testTdf1225573_FontWorkScaleX();
+    void testTdf99497_keepAppearanceOfCircleKind();
     /// SmartArt animated elements
     void testTdf104792();
     void testTdf90627();
@@ -288,6 +289,7 @@ public:
     CPPUNIT_TEST(testTdf111789);
     CPPUNIT_TEST(testTdf100348_convert_Fontwork2TextWarp);
     CPPUNIT_TEST(testTdf1225573_FontWorkScaleX);
+    CPPUNIT_TEST(testTdf99497_keepAppearanceOfCircleKind);
     CPPUNIT_TEST(testTdf104792);
     CPPUNIT_TEST(testTdf90627);
     CPPUNIT_TEST(testTdf104786);
@@ -2538,6 +2540,46 @@ void SdOOXMLExportTest2::testTdf126741()
     xDocShRef->DoClose();
 }
 
+void SdOOXMLExportTest2::testTdf99497_keepAppearanceOfCircleKind()
+{
+    // Error was, that all CircleKind were exported to 'ellipse'.
+    // Resulting pptx has to contain the customshapes of the corresponding kind
+    // slide 1 ARC -> arc, slide 2 CUT -> chord, slide 3 SECTION -> pie
+    // Adjustment values need to exist and their values need to correspond to the
+    // orignal angles. Shape 'arc' needs to be unfilled.
+    const OUString sPath("/sd/qa/unit/data/odp/tdf99497_CircleKind.odp");
+    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc(sPath), ODP);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+
+    // slide 1 45° -> adj1 = 20493903, 270° -> adj2 = 5400000, <a:noFill/> exists
+    xmlDocPtr pXmlDocContent1 = parseExport(tempFile, "ppt/slides/slide1.xml");
+    const OString sPathStart1("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
+    assertXPath(pXmlDocContent1, sPathStart1 + "[@prst='arc']");
+    const OString sPathAdj1(sPathStart1 + "/a:avLst/a:gd");
+    assertXPath(pXmlDocContent1, sPathAdj1 + "[@name='adj1' and  @fmla='val 20493903']");
+    assertXPath(pXmlDocContent1, sPathAdj1 + "[@name='adj2' and  @fmla='val 5400000']");
+    assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:noFill");
+
+    // slide 2 270° -> adj1 = 5400000, 180° -> adj2 = 10800000
+    xmlDocPtr pXmlDocContent2 = parseExport(tempFile, "ppt/slides/slide2.xml");
+    const OString sPathStart2("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
+    assertXPath(pXmlDocContent2, sPathStart2 + "[@prst='chord']");
+    const OString sPathAdj2(sPathStart2 + "/a:avLst/a:gd");
+    assertXPath(pXmlDocContent2, sPathAdj2 + "[@name='adj1' and  @fmla='val 5400000']");
+    assertXPath(pXmlDocContent2, sPathAdj2 + "[@name='adj2' and  @fmla='val 10800000']");
+
+    // slide 3 120° -> adj1 = 12600000, 30° -> adj2 = 20946396
+    xmlDocPtr pXmlDocContent3 = parseExport(tempFile, "ppt/slides/slide3.xml");
+    const OString sPathStart3("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
+    assertXPath(pXmlDocContent3, sPathStart3 + "[@prst='pie']");
+    const OString sPathAdj3(sPathStart3 + "/a:avLst/a:gd");
+    assertXPath(pXmlDocContent3, sPathAdj3 + "[@name='adj1' and  @fmla='val 12600000']");
+    assertXPath(pXmlDocContent3, sPathAdj3 + "[@name='adj2' and  @fmla='val 20946396']");
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();


More information about the Libreoffice-commits mailing list