include/oox/export/drawingml.hxx |    5 
 oox/source/export/drawingml.cxx  |  650 ++++++++++++++++++---------------------
 2 files changed, 309 insertions(+), 346 deletions(-)

New commits:
commit 365a3ed39083389f40612dec765d7b8e0dc2377b
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Tue Mar 29 16:23:46 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Mar 30 09:30:08 2022 +0200

    Extract 'switch' block out of WriteCustomGeometry
    
    This is a follow up to commit 2029b2f6dd0109c5892e5ac5640022b31fe42fd2.
    That commit has increased the line count of WriteCustomGeometry to more
    than 500. This patch splits it to a main part of about 230 lines and
    a new method for the previous 'switch' block of about 300 lines. That
    makes the loops in the main part better readable.
    
    Change-Id: Ied4378f54e7c8dc7965a5b1db15baf0b35f63f59
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132274
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index b507a0e41b60..fb125dd647ad 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -202,6 +202,11 @@ protected:
     void WriteSoftEdgeEffect(const 
css::uno::Reference<css::beans::XPropertySet>& rXPropSet);
     void WriteCustomGeometryPoint(const 
css::drawing::EnhancedCustomShapeParameterPair& rParamPair,
                                   const EnhancedCustomShape2d& rCustomShape2d);
+    bool WriteCustomGeometrySegment(
+        const sal_Int16 eCommand, const sal_Int32 nCount,
+        const 
css::uno::Sequence<css::drawing::EnhancedCustomShapeParameterPair>& rPairs,
+        sal_Int32& rnPairIndex, double& rfCurrentX, double& rfCurrentY, bool& 
rbCurrentValid,
+        const EnhancedCustomShape2d& rCustomShape2d);
 
 public:
     DrawingML( ::sax_fastparser::FSHelperPtr pFS, ::oox::core::XmlFilterBase* 
pFB, DocumentType eDocumentType = DOCUMENT_PPTX, DMLTextExport* pTextExport = 
nullptr )
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index ff092b44641c..a790a643abc0 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -4038,352 +4038,9 @@ bool DrawingML::WriteCustomGeometry(
             }
             for (sal_Int32 k = 0; k < rSegment.Count && bOK; ++k)
             {
-                switch (rSegment.Command)
-                {
-                    case MOVETO:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_moveTo);
-                            WriteCustomGeometryPoint(aPairs[nPairIndex], 
aCustomShape2d);
-                            mpFS->endElementNS(XML_a, XML_moveTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            bCurrentValid = true;
-                            nPairIndex++;
-                        }
-                        break;
-                    }
-                    case LINETO:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_lnTo);
-                            WriteCustomGeometryPoint(aPairs[nPairIndex], 
aCustomShape2d);
-                            mpFS->endElementNS(XML_a, XML_lnTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            bCurrentValid = true;
-                            nPairIndex++;
-                        }
-                        break;
-                    }
-                    case CURVETO:
-                    {
-                        if (nPairIndex + 2 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_cubicBezTo);
-                            for (sal_uInt8 l = 0; l <= 2; ++l)
-                            {
-                                WriteCustomGeometryPoint(aPairs[nPairIndex + 
l], aCustomShape2d);
-                            }
-                            mpFS->endElementNS(XML_a, XML_cubicBezTo);
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex + 2].First,
-                                                        false, false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex + 2].Second,
-                                                        false, false);
-                            bCurrentValid = true;
-                            nPairIndex += 3;
-                        }
-                        break;
-                    }
-                    case ANGLEELLIPSETO:
-                    case ANGLEELLIPSE:
-                    {
-                        if (nPairIndex + 2 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // Read parameters
-                            double fCx = 0.0;
-                            aCustomShape2d.GetParameter(fCx, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            double fCy = 0.0;
-                            aCustomShape2d.GetParameter(fCy, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            double fWR = 0.0;
-                            aCustomShape2d.GetParameter(fWR, aPairs[nPairIndex 
+ 1].First, false,
-                                                        false);
-                            double fHR = 0.0;
-                            aCustomShape2d.GetParameter(fHR, aPairs[nPairIndex 
+ 1].Second, false,
-                                                        false);
-                            double fStartAngle = 0.0;
-                            aCustomShape2d.GetParameter(fStartAngle, 
aPairs[nPairIndex + 2].First,
-                                                        false, false);
-                            double fEndAngle = 0.0;
-                            aCustomShape2d.GetParameter(fEndAngle, 
aPairs[nPairIndex + 2].Second,
-                                                        false, false);
-
-                            // Prepare start and swing angle
-                            sal_Int32 nStartAng(std::lround(fStartAngle * 
60000));
-                            sal_Int32 nSwingAng = 0;
-                            if (basegfx::fTools::equalZero(fStartAngle)
-                                && basegfx::fTools::equalZero(fEndAngle - 
360.0))
-                                nSwingAng = 360 * 60000; // special case full 
circle
-                            else
-                            {
-                                nSwingAng = std::lround((fEndAngle - 
fStartAngle) * 60000);
-                                if (nSwingAng < 0)
-                                    nSwingAng += 360 * 60000;
-                            }
-
-                            // calculate start point on ellipse
-                            double fSx = 0.0;
-                            double fSy = 0.0;
-                            getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, 
fCx, fCy, fStartAngle);
-
-                            // write markup for going to start point
-                            if (rSegment.Command == ANGLEELLIPSETO)
-                            {
-                                mpFS->startElementNS(XML_a, XML_lnTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fSx)), XML_y,
-                                                      
OString::number(std::lround(fSy)));
-                                mpFS->endElementNS(XML_a, XML_lnTo);
-                            }
-                            else
-                            {
-                                mpFS->startElementNS(XML_a, XML_moveTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fSx)), XML_y,
-                                                      
OString::number(std::lround(fSy)));
-                                mpFS->endElementNS(XML_a, XML_moveTo);
-                            }
-                            // write markup for arcTo
-                            if (!basegfx::fTools::equalZero(fWR)
-                                && !basegfx::fTools::equalZero(fHR))
-                                mpFS->singleElement(FSNS(XML_a, XML_arcTo), 
XML_wR,
-                                                    
OString::number(std::lround(fWR)), XML_hR,
-                                                    
OString::number(std::lround(fHR)), XML_stAng,
-                                                    
OString::number(nStartAng), XML_swAng,
-                                                    
OString::number(nSwingAng));
-
-                            getEllipsePointFromViewAngle(fCurrentX, fCurrentY, 
fWR, fHR, fCx, fCy,
-                                                         fEndAngle);
-                            bCurrentValid = true;
-                            nPairIndex += 3;
-                        }
-                        break;
-                    }
-                    case ARCTO:
-                    case ARC:
-                    case CLOCKWISEARCTO:
-                    case CLOCKWISEARC:
-                    {
-                        if (nPairIndex + 3 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // read parameters
-                            double fX1 = 0.0;
-                            aCustomShape2d.GetParameter(fX1, 
aPairs[nPairIndex].First, false,
-                                                        false);
-                            double fY1 = 0.0;
-                            aCustomShape2d.GetParameter(fY1, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-                            double fX2 = 0.0;
-                            aCustomShape2d.GetParameter(fX2, aPairs[nPairIndex 
+ 1].First, false,
-                                                        false);
-                            double fY2 = 0.0;
-                            aCustomShape2d.GetParameter(fY2, aPairs[nPairIndex 
+ 1].Second, false,
-                                                        false);
-                            double fX3 = 0.0;
-                            aCustomShape2d.GetParameter(fX3, aPairs[nPairIndex 
+ 2].First, false,
-                                                        false);
-                            double fY3 = 0.0;
-                            aCustomShape2d.GetParameter(fY3, aPairs[nPairIndex 
+ 2].Second, false,
-                                                        false);
-                            double fX4 = 0.0;
-                            aCustomShape2d.GetParameter(fX4, aPairs[nPairIndex 
+ 3].First, false,
-                                                        false);
-                            double fY4 = 0.0;
-                            aCustomShape2d.GetParameter(fY4, aPairs[nPairIndex 
+ 3].Second, false,
-                                                        false);
-                            // calculate ellipse parameter
-                            const double fWR = (fX2 - fX1) / 2.0;
-                            const double fHR = (fY2 - fY1) / 2.0;
-                            const double fCx = (fX1 + fX2) / 2.0;
-                            const double fCy = (fY1 + fY2) / 2.0;
-                            // calculate start angle
-                            double fStartAngle = 0.0;
-                            double fPx = 0.0;
-                            double fPy = 0.0;
-                            getEllipsePointAndAngleFromRayPoint(fStartAngle, 
fPx, fPy, fWR, fHR,
-                                                                fCx, fCy, fX3, 
fY3);
-                            // markup for going to start point
-                            if (rSegment.Command == ARCTO || rSegment.Command 
== CLOCKWISEARCTO)
-                            {
-                                mpFS->startElementNS(XML_a, XML_lnTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fPx)), XML_y,
-                                                      
OString::number(std::lround(fPy)));
-                                mpFS->endElementNS(XML_a, XML_lnTo);
-                            }
-                            else
-                            {
-                                mpFS->startElementNS(XML_a, XML_moveTo);
-                                mpFS->singleElementNS(XML_a, XML_pt, XML_x,
-                                                      
OString::number(std::lround(fPx)), XML_y,
-                                                      
OString::number(std::lround(fPy)));
-                                mpFS->endElementNS(XML_a, XML_moveTo);
-                            }
-                            // calculate swing angle
-                            double fEndAngle = 0.0;
-                            getEllipsePointAndAngleFromRayPoint(fEndAngle, 
fPx, fPy, fWR, fHR, fCx,
-                                                                fCy, fX4, fY4);
-                            double fSwingAngle(fEndAngle - fStartAngle);
-                            const bool bIsClockwise(rSegment.Command == 
CLOCKWISEARCTO
-                                                    || rSegment.Command == 
CLOCKWISEARC);
-                            if (bIsClockwise && fSwingAngle < 0)
-                                fSwingAngle += 360.0;
-                            else if (!bIsClockwise && fSwingAngle > 0)
-                                fSwingAngle -= 360.0;
-                            // markup for arcTo
-                            // ToDo: write markup for case zero width or 
height of ellipse
-                            const sal_Int32 nStartAng(std::lround(fStartAngle 
* 60000));
-                            const sal_Int32 nSwingAng(std::lround(fSwingAngle 
* 60000));
-                            mpFS->singleElement(
-                                FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(std::lround(fWR)),
-                                XML_hR, OString::number(std::lround(fHR)), 
XML_stAng,
-                                OString::number(nStartAng), XML_swAng, 
OString::number(nSwingAng));
-                            fCurrentX = fPx;
-                            fCurrentY = fPy;
-                            bCurrentValid = true;
-                            nPairIndex += 4;
-                        }
-                        break;
-                    }
-                    case ELLIPTICALQUADRANTX:
-                    case ELLIPTICALQUADRANTY:
-                    {
-                        if (nPairIndex >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            // read parameters
-                            double fX = 0.0;
-                            aCustomShape2d.GetParameter(fX, 
aPairs[nPairIndex].First, false, false);
-                            double fY = 0.0;
-                            aCustomShape2d.GetParameter(fY, 
aPairs[nPairIndex].Second, false,
-                                                        false);
-
-                            // Prepare parameters for arcTo
-                            if (bCurrentValid)
-                            {
-                                double fWR = std::abs(fCurrentX - fX);
-                                double fHR = std::abs(fCurrentY - fY);
-                                double fStartAngle(0.0);
-                                double fSwingAngle(0.0);
-                                // The starting direction of the arc toggles 
between X and Y
-                                if ((rSegment.Command == ELLIPTICALQUADRANTX 
&& !(k % 2))
-                                    || (rSegment.Command == 
ELLIPTICALQUADRANTY && (k % 2)))
-                                {
-                                    // arc starts horizontal
-                                    fStartAngle = fY < fCurrentY ? 90.0 : 
270.0;
-                                    const bool bClockwise = (fX < fCurrentX && 
fY < fCurrentY)
-                                                            || (fX > fCurrentX 
&& fY > fCurrentY);
-                                    fSwingAngle = bClockwise ? 90.0 : -90.0;
-                                }
-                                else
-                                {
-                                    // arc starts vertical
-                                    fStartAngle = fX < fCurrentX ? 0.0 : 180.0;
-                                    const bool bClockwise = (fX < fCurrentX && 
fY > fCurrentY)
-                                                            || (fX > fCurrentX 
&& fY < fCurrentY);
-                                    fSwingAngle = bClockwise ? 90.0 : -90.0;
-                                }
-                                sal_Int32 nStartAng(std::lround(fStartAngle * 
60000));
-                                sal_Int32 nSwingAng(std::lround(fSwingAngle * 
60000));
-                                mpFS->singleElement(FSNS(XML_a, XML_arcTo), 
XML_wR,
-                                                    
OString::number(std::lround(fWR)), XML_hR,
-                                                    
OString::number(std::lround(fHR)), XML_stAng,
-                                                    
OString::number(nStartAng), XML_swAng,
-                                                    
OString::number(nSwingAng));
-                            }
-                            else
-                            {
-                                // faulty path, but we continue with the 
target point
-                                mpFS->startElementNS(XML_a, XML_moveTo);
-                                WriteCustomGeometryPoint(aPairs[nPairIndex], 
aCustomShape2d);
-                                mpFS->endElementNS(XML_a, XML_moveTo);
-                            }
-                            fCurrentX = fX;
-                            fCurrentY = fY;
-                            bCurrentValid = true;
-                            nPairIndex++;
-                        }
-                        break;
-                    }
-                    case QUADRATICCURVETO:
-                    {
-                        if (nPairIndex + 1 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            mpFS->startElementNS(XML_a, XML_quadBezTo);
-                            for( sal_uInt8 l = 0; l < 2; ++l )
-                            {
-                                WriteCustomGeometryPoint(aPairs[nPairIndex + 
l], aCustomShape2d);
-                            }
-                            mpFS->endElementNS( XML_a, XML_quadBezTo );
-                            aCustomShape2d.GetParameter(fCurrentX, 
aPairs[nPairIndex + 1].First, false,
-                                                        false);
-                            aCustomShape2d.GetParameter(fCurrentY, 
aPairs[nPairIndex + 1].Second, false,
-                                                        false);
-                            bCurrentValid = true;
-                            nPairIndex += 2;
-                        }
-                        break;
-                    }
-                    case ARCANGLETO:
-                    {
-                        if (nPairIndex + 1 >= aPairs.getLength())
-                            bOK = false;
-                        else
-                        {
-                            double fWR = 0.0;
-                            aCustomShape2d.GetParameter(fWR, 
aPairs[nPairIndex].First, false, false);
-                            double fHR = 0.0;
-                            aCustomShape2d.GetParameter(fHR, 
aPairs[nPairIndex].Second, false, false);
-                            double fStartAngle = 0.0;
-                            aCustomShape2d.GetParameter(fStartAngle, 
aPairs[nPairIndex + 1].First,
-                                                        false, false);
-                            sal_Int32 nStartAng(std::lround(fStartAngle * 
60000));
-                            double fSwingAng = 0.0;
-                            aCustomShape2d.GetParameter(fSwingAng, 
aPairs[nPairIndex + 1].Second,
-                                                        false, false);
-                            sal_Int32 nSwingAng(std::lround(fSwingAng * 
60000));
-                            mpFS->singleElement(FSNS(XML_a, XML_arcTo), 
XML_wR, OString::number(fWR),
-                                                XML_hR, OString::number(fHR), 
XML_stAng,
-                                                OString::number(nStartAng), 
XML_swAng,
-                                                OString::number(nSwingAng));
-                            double fPx = 0.0;
-                            double fPy = 0.0;
-                            getEllipsePointFromViewAngle(fPx, fPy, fWR, fHR, 
0.0, 0.0, fStartAngle);
-                            double fCx = fCurrentX - fPx;
-                            double fCy = fCurrentY - fPy;
-                            getEllipsePointFromViewAngle(fCurrentX, fCurrentY, 
fWR, fHR, fCx, fCy,
-                                                         fStartAngle + 
fSwingAng);
-                            bCurrentValid = true;
-                            nPairIndex += 2;
-                        }
-                        break;
-                    }
-                    default:
-                        // do nothing
-                        break;
-                }
-            } // end loop for commands which are repeated
+                bOK = WriteCustomGeometrySegment(rSegment.Command, k, aPairs, 
nPairIndex, fCurrentX,
+                                                 fCurrentY, bCurrentValid, 
aCustomShape2d);
+            }
         } // end loop over all commands of subpath
         // finish this subpath in any case
         mpFS->endElementNS(XML_a, XML_path);
@@ -4401,6 +4058,307 @@ bool DrawingML::WriteCustomGeometry(
     return true; // We have written custGeom even if path is poorly structured.
 }
 
+bool DrawingML::WriteCustomGeometrySegment(
+    const sal_Int16 eCommand, const sal_Int32 nCount,
+    const uno::Sequence<css::drawing::EnhancedCustomShapeParameterPair>& 
rPairs,
+    sal_Int32& rnPairIndex, double& rfCurrentX, double& rfCurrentY, bool& 
rbCurrentValid,
+    const EnhancedCustomShape2d& rCustomShape2d)
+{
+    switch (eCommand)
+    {
+        case MOVETO:
+        {
+            if (rnPairIndex >= rPairs.getLength())
+                return false;
+
+            mpFS->startElementNS(XML_a, XML_moveTo);
+            WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+            mpFS->endElementNS(XML_a, XML_moveTo);
+            rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex].First, 
false, false);
+            rCustomShape2d.GetParameter(rfCurrentY, 
rPairs[rnPairIndex].Second, false, false);
+            rbCurrentValid = true;
+            rnPairIndex++;
+            break;
+        }
+        case LINETO:
+        {
+            if (rnPairIndex >= rPairs.getLength())
+                return false;
+
+            mpFS->startElementNS(XML_a, XML_lnTo);
+            WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+            mpFS->endElementNS(XML_a, XML_lnTo);
+            rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex].First, 
false, false);
+            rCustomShape2d.GetParameter(rfCurrentY, 
rPairs[rnPairIndex].Second, false, false);
+            rbCurrentValid = true;
+            rnPairIndex++;
+            break;
+        }
+        case CURVETO:
+        {
+            if (rnPairIndex + 2 >= rPairs.getLength())
+                return false;
+
+            mpFS->startElementNS(XML_a, XML_cubicBezTo);
+            for (sal_uInt8 i = 0; i <= 2; ++i)
+            {
+                WriteCustomGeometryPoint(rPairs[rnPairIndex + i], 
rCustomShape2d);
+            }
+            mpFS->endElementNS(XML_a, XML_cubicBezTo);
+            rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex + 
2].First, false, false);
+            rCustomShape2d.GetParameter(rfCurrentY, rPairs[rnPairIndex + 
2].Second, false, false);
+            rbCurrentValid = true;
+            rnPairIndex += 3;
+            break;
+        }
+        case ANGLEELLIPSETO:
+        case ANGLEELLIPSE:
+        {
+            if (rnPairIndex + 2 >= rPairs.getLength())
+                return false;
+
+            // Read parameters
+            double fCx = 0.0;
+            rCustomShape2d.GetParameter(fCx, rPairs[rnPairIndex].First, false, 
false);
+            double fCy = 0.0;
+            rCustomShape2d.GetParameter(fCy, rPairs[rnPairIndex].Second, 
false, false);
+            double fWR = 0.0;
+            rCustomShape2d.GetParameter(fWR, rPairs[rnPairIndex + 1].First, 
false, false);
+            double fHR = 0.0;
+            rCustomShape2d.GetParameter(fHR, rPairs[rnPairIndex + 1].Second, 
false, false);
+            double fStartAngle = 0.0;
+            rCustomShape2d.GetParameter(fStartAngle, rPairs[rnPairIndex + 
2].First, false, false);
+            double fEndAngle = 0.0;
+            rCustomShape2d.GetParameter(fEndAngle, rPairs[rnPairIndex + 
2].Second, false, false);
+
+            // Prepare start and swing angle
+            sal_Int32 nStartAng(std::lround(fStartAngle * 60000));
+            sal_Int32 nSwingAng = 0;
+            if (basegfx::fTools::equalZero(fStartAngle)
+                && basegfx::fTools::equalZero(fEndAngle - 360.0))
+                nSwingAng = 360 * 60000; // special case full circle
+            else
+            {
+                nSwingAng = std::lround((fEndAngle - fStartAngle) * 60000);
+                if (nSwingAng < 0)
+                    nSwingAng += 360 * 60000;
+            }
+
+            // calculate start point on ellipse
+            double fSx = 0.0;
+            double fSy = 0.0;
+            getEllipsePointFromViewAngle(fSx, fSy, fWR, fHR, fCx, fCy, 
fStartAngle);
+
+            // write markup for going to start point
+            if (eCommand == ANGLEELLIPSETO)
+            {
+                mpFS->startElementNS(XML_a, XML_lnTo);
+                mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fSx)),
+                                      XML_y, 
OString::number(std::lround(fSy)));
+                mpFS->endElementNS(XML_a, XML_lnTo);
+            }
+            else
+            {
+                mpFS->startElementNS(XML_a, XML_moveTo);
+                mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fSx)),
+                                      XML_y, 
OString::number(std::lround(fSy)));
+                mpFS->endElementNS(XML_a, XML_moveTo);
+            }
+            // write markup for arcTo
+            if (!basegfx::fTools::equalZero(fWR) && 
!basegfx::fTools::equalZero(fHR))
+                mpFS->singleElement(
+                    FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(std::lround(fWR)), XML_hR,
+                    OString::number(std::lround(fHR)), XML_stAng, 
OString::number(nStartAng),
+                    XML_swAng, OString::number(nSwingAng));
+
+            getEllipsePointFromViewAngle(rfCurrentX, rfCurrentY, fWR, fHR, 
fCx, fCy, fEndAngle);
+            rbCurrentValid = true;
+            rnPairIndex += 3;
+            break;
+        }
+        case ARCTO:
+        case ARC:
+        case CLOCKWISEARCTO:
+        case CLOCKWISEARC:
+        {
+            if (rnPairIndex + 3 >= rPairs.getLength())
+                return false;
+
+            // read parameters
+            double fX1 = 0.0;
+            rCustomShape2d.GetParameter(fX1, rPairs[rnPairIndex].First, false, 
false);
+            double fY1 = 0.0;
+            rCustomShape2d.GetParameter(fY1, rPairs[rnPairIndex].Second, 
false, false);
+            double fX2 = 0.0;
+            rCustomShape2d.GetParameter(fX2, rPairs[rnPairIndex + 1].First, 
false, false);
+            double fY2 = 0.0;
+            rCustomShape2d.GetParameter(fY2, rPairs[rnPairIndex + 1].Second, 
false, false);
+            double fX3 = 0.0;
+            rCustomShape2d.GetParameter(fX3, rPairs[rnPairIndex + 2].First, 
false, false);
+            double fY3 = 0.0;
+            rCustomShape2d.GetParameter(fY3, rPairs[rnPairIndex + 2].Second, 
false, false);
+            double fX4 = 0.0;
+            rCustomShape2d.GetParameter(fX4, rPairs[rnPairIndex + 3].First, 
false, false);
+            double fY4 = 0.0;
+            rCustomShape2d.GetParameter(fY4, rPairs[rnPairIndex + 3].Second, 
false, false);
+            // calculate ellipse parameter
+            const double fWR = (fX2 - fX1) / 2.0;
+            const double fHR = (fY2 - fY1) / 2.0;
+            const double fCx = (fX1 + fX2) / 2.0;
+            const double fCy = (fY1 + fY2) / 2.0;
+            // calculate start angle
+            double fStartAngle = 0.0;
+            double fPx = 0.0;
+            double fPy = 0.0;
+            getEllipsePointAndAngleFromRayPoint(fStartAngle, fPx, fPy, fWR, 
fHR, fCx, fCy, fX3,
+                                                fY3);
+            // markup for going to start point
+            if (eCommand == ARCTO || eCommand == CLOCKWISEARCTO)
+            {
+                mpFS->startElementNS(XML_a, XML_lnTo);
+                mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fPx)),
+                                      XML_y, 
OString::number(std::lround(fPy)));
+                mpFS->endElementNS(XML_a, XML_lnTo);
+            }
+            else
+            {
+                mpFS->startElementNS(XML_a, XML_moveTo);
+                mpFS->singleElementNS(XML_a, XML_pt, XML_x, 
OString::number(std::lround(fPx)),
+                                      XML_y, 
OString::number(std::lround(fPy)));
+                mpFS->endElementNS(XML_a, XML_moveTo);
+            }
+            // calculate swing angle
+            double fEndAngle = 0.0;
+            getEllipsePointAndAngleFromRayPoint(fEndAngle, fPx, fPy, fWR, fHR, 
fCx, fCy, fX4, fY4);
+            double fSwingAngle(fEndAngle - fStartAngle);
+            const bool bIsClockwise(eCommand == CLOCKWISEARCTO || eCommand == 
CLOCKWISEARC);
+            if (bIsClockwise && fSwingAngle < 0)
+                fSwingAngle += 360.0;
+            else if (!bIsClockwise && fSwingAngle > 0)
+                fSwingAngle -= 360.0;
+            // markup for arcTo
+            // ToDo: write markup for case zero width or height of ellipse
+            const sal_Int32 nStartAng(std::lround(fStartAngle * 60000));
+            const sal_Int32 nSwingAng(std::lround(fSwingAngle * 60000));
+            mpFS->singleElement(FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(std::lround(fWR)),
+                                XML_hR, OString::number(std::lround(fHR)), 
XML_stAng,
+                                OString::number(nStartAng), XML_swAng, 
OString::number(nSwingAng));
+            rfCurrentX = fPx;
+            rfCurrentY = fPy;
+            rbCurrentValid = true;
+            rnPairIndex += 4;
+            break;
+        }
+        case ELLIPTICALQUADRANTX:
+        case ELLIPTICALQUADRANTY:
+        {
+            if (rnPairIndex >= rPairs.getLength())
+                return false;
+
+            // read parameters
+            double fX = 0.0;
+            rCustomShape2d.GetParameter(fX, rPairs[rnPairIndex].First, false, 
false);
+            double fY = 0.0;
+            rCustomShape2d.GetParameter(fY, rPairs[rnPairIndex].Second, false, 
false);
+
+            // Prepare parameters for arcTo
+            if (rbCurrentValid)
+            {
+                double fWR = std::abs(rfCurrentX - fX);
+                double fHR = std::abs(rfCurrentY - fY);
+                double fStartAngle(0.0);
+                double fSwingAngle(0.0);
+                // The starting direction of the arc toggles between X and Y
+                if ((eCommand == ELLIPTICALQUADRANTX && !(nCount % 2))
+                    || (eCommand == ELLIPTICALQUADRANTY && (nCount % 2)))
+                {
+                    // arc starts horizontal
+                    fStartAngle = fY < rfCurrentY ? 90.0 : 270.0;
+                    const bool bClockwise = (fX < rfCurrentX && fY < 
rfCurrentY)
+                                            || (fX > rfCurrentX && fY > 
rfCurrentY);
+                    fSwingAngle = bClockwise ? 90.0 : -90.0;
+                }
+                else
+                {
+                    // arc starts vertical
+                    fStartAngle = fX < rfCurrentX ? 0.0 : 180.0;
+                    const bool bClockwise = (fX < rfCurrentX && fY > 
rfCurrentY)
+                                            || (fX > rfCurrentX && fY < 
rfCurrentY);
+                    fSwingAngle = bClockwise ? 90.0 : -90.0;
+                }
+                sal_Int32 nStartAng(std::lround(fStartAngle * 60000));
+                sal_Int32 nSwingAng(std::lround(fSwingAngle * 60000));
+                mpFS->singleElement(
+                    FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(std::lround(fWR)), XML_hR,
+                    OString::number(std::lround(fHR)), XML_stAng, 
OString::number(nStartAng),
+                    XML_swAng, OString::number(nSwingAng));
+            }
+            else
+            {
+                // faulty path, but we continue with the target point
+                mpFS->startElementNS(XML_a, XML_moveTo);
+                WriteCustomGeometryPoint(rPairs[rnPairIndex], rCustomShape2d);
+                mpFS->endElementNS(XML_a, XML_moveTo);
+            }
+            rfCurrentX = fX;
+            rfCurrentY = fY;
+            rbCurrentValid = true;
+            rnPairIndex++;
+            break;
+        }
+        case QUADRATICCURVETO:
+        {
+            if (rnPairIndex + 1 >= rPairs.getLength())
+                return false;
+
+            mpFS->startElementNS(XML_a, XML_quadBezTo);
+            for (sal_uInt8 i = 0; i < 2; ++i)
+            {
+                WriteCustomGeometryPoint(rPairs[rnPairIndex + i], 
rCustomShape2d);
+            }
+            mpFS->endElementNS(XML_a, XML_quadBezTo);
+            rCustomShape2d.GetParameter(rfCurrentX, rPairs[rnPairIndex + 
1].First, false, false);
+            rCustomShape2d.GetParameter(rfCurrentY, rPairs[rnPairIndex + 
1].Second, false, false);
+            rbCurrentValid = true;
+            rnPairIndex += 2;
+            break;
+        }
+        case ARCANGLETO:
+        {
+            if (rnPairIndex + 1 >= rPairs.getLength())
+                return false;
+
+            double fWR = 0.0;
+            rCustomShape2d.GetParameter(fWR, rPairs[rnPairIndex].First, false, 
false);
+            double fHR = 0.0;
+            rCustomShape2d.GetParameter(fHR, rPairs[rnPairIndex].Second, 
false, false);
+            double fStartAngle = 0.0;
+            rCustomShape2d.GetParameter(fStartAngle, rPairs[rnPairIndex + 
1].First, false, false);
+            sal_Int32 nStartAng(std::lround(fStartAngle * 60000));
+            double fSwingAng = 0.0;
+            rCustomShape2d.GetParameter(fSwingAng, rPairs[rnPairIndex + 
1].Second, false, false);
+            sal_Int32 nSwingAng(std::lround(fSwingAng * 60000));
+            mpFS->singleElement(FSNS(XML_a, XML_arcTo), XML_wR, 
OString::number(fWR), XML_hR,
+                                OString::number(fHR), XML_stAng, 
OString::number(nStartAng),
+                                XML_swAng, OString::number(nSwingAng));
+            double fPx = 0.0;
+            double fPy = 0.0;
+            getEllipsePointFromViewAngle(fPx, fPy, fWR, fHR, 0.0, 0.0, 
fStartAngle);
+            double fCx = rfCurrentX - fPx;
+            double fCy = rfCurrentY - fPy;
+            getEllipsePointFromViewAngle(rfCurrentX, rfCurrentY, fWR, fHR, 
fCx, fCy,
+                                         fStartAngle + fSwingAng);
+            rbCurrentValid = true;
+            rnPairIndex += 2;
+            break;
+        }
+        default:
+            // do nothing
+            break;
+    }
+    return true;
+}
+
 void DrawingML::WriteCustomGeometryPoint(
     const drawing::EnhancedCustomShapeParameterPair& rParamPair,
     const EnhancedCustomShape2d& rCustomShape2d)

Reply via email to