tdf#122646 EMF+ Implement proper line width display

With this patch I have implemented proper line width display,
and improved performance (we are not multiply by matrix of doubles,
but only by one double.

Change-Id: Ica85b93ac7b7f37a9debb7bc232f2d9140c2a772
Reviewed-on: https://gerrit.libreoffice.org/66136
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx
index e72d3a1..82e8f94 100644
--- a/drawinglayer/source/tools/emfpcustomlinecap.cxx
+++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx
@@ -17,24 +17,6 @@
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <com/sun/star/rendering/PathCapType.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/TexturingMode.hpp>
#include <com/sun/star/rendering/XCanvas.hpp>
#include <basegfx/utils/canvastools.hxx>
#include <basegfx/utils/gradienttools.hxx>
#include <basegfx/utils/tools.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <vcl/canvastools.hxx>
#include <sal/log.hxx>
#include "emfpcustomlinecap.hxx"
#include "emfppath.hxx"
diff --git a/drawinglayer/source/tools/emfpcustomlinecap.hxx b/drawinglayer/source/tools/emfpcustomlinecap.hxx
index 4fb5b45..3fd2d2f 100644
--- a/drawinglayer/source/tools/emfpcustomlinecap.hxx
+++ b/drawinglayer/source/tools/emfpcustomlinecap.hxx
@@ -20,6 +20,7 @@
#ifndef INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPCUSTOMLINECAP_HXX
#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPCUSTOMLINECAP_HXX

#include <com/sun/star/rendering/StrokeAttributes.hpp>
#include "emfphelperdata.hxx"

namespace emfplushelper
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index fdbb3e4..5c86d69 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -412,28 +412,18 @@ namespace emfplushelper
                lineCap = static_cast<css::drawing::LineCap>(EMFPPen::lcl_convertStrokeCap(pen->startCap));
                SAL_WARN_IF(pen->startCap != pen->endCap, "drawinglayer", "emf+ pen uses different start and end cap");
            }
            // transform the pen width
            double adjustedPenWidth = pen->penWidth;

            // If a zero width is specified, a minimum value must be used, which is determined by the units
            if (pen->penWidth == 0.0)
            {
                adjustedPenWidth = pen->penUnit == 0 ? 0.18f   // 0.18f is determined by comparison with MSO  (case of Unit == World)
                    : 0.05f;  // 0.05f is taken from old EMF+ implementation (case of Unit == Pixel etc.)
            }
            // transform and compare to 5 (the value 5 is determined by comparison to MSO)
            const double transformedPenWidth = std::max( MapSize(adjustedPenWidth, 0).getX(), 5.);

            const double transformedPenWidth = maMapTransform.get(0, 0) * pen->penWidth;
            drawinglayer::attribute::LineAttribute lineAttribute(pen->GetColor().getBColor(),
                                                                transformedPenWidth,
                                                                lineJoin,
                                                                lineCap);
                                                                 transformedPenWidth,
                                                                 lineJoin,
                                                                 lineCap);

            drawinglayer::attribute::StrokeAttribute aStrokeAttribute;
            if (pen->penDataFlags & 0x00000020 && pen->dashStyle != EmfPlusLineStyleCustom) // pen has a predefined line style
            {
                // short writing
                const double pw = transformedPenWidth;
                const double pw = maMapTransform.get(1, 1) * pen->penWidth;
                // taken from the old cppcanvas implementation and multiplied with pen width
                const std::vector<double> dash = { 3*pw, 3*pw };
                const std::vector<double> dot = { pw, 3*pw };
@@ -465,7 +455,7 @@ namespace emfplushelper
                for (size_t i=0; i<aPattern.size(); i++)
                {
                    // convert from float to double and multiply with the adjusted pen width
                    aPattern[i] = transformedPenWidth * pen->dashPattern[i];
                    aPattern[i] = maMapTransform.get(1, 1) * pen->penWidth * pen->dashPattern[i];
                }
                aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(aPattern);
            }
@@ -1230,9 +1220,9 @@ namespace emfplushelper
                                {
                                    float x1, y1, x2, y2, x3, y3;

                                    ReadPoint(rMS, x1, y1, flags);
                                    ReadPoint(rMS, x2, y2, flags);
                                    ReadPoint(rMS, x3, y3, flags);
                                    ReadPoint(rMS, x1, y1, flags); // upper-left point
                                    ReadPoint(rMS, x2, y2, flags); // upper-right
                                    ReadPoint(rMS, x3, y3, flags); // lower-left

                                    SAL_INFO("drawinglayer", "EMF+\t destination points: " << x1 << "," << y1 << " " << x2 << "," << y2 << " " << x3 << "," << y3);
                                    SAL_INFO("drawinglayer", "EMF+\t destination rectangle: " << x1 << "," << y1 << " " << x2 - x1 << "x" << y3 - y1);
diff --git a/drawinglayer/source/tools/emfppen.cxx b/drawinglayer/source/tools/emfppen.cxx
index eb0f593..039a5c0 100644
--- a/drawinglayer/source/tools/emfppen.cxx
+++ b/drawinglayer/source/tools/emfppen.cxx
@@ -19,23 +19,7 @@

#include <com/sun/star/rendering/PathCapType.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/TexturingMode.hpp>
#include <com/sun/star/rendering/XCanvas.hpp>
#include <basegfx/utils/canvastools.hxx>
#include <basegfx/utils/gradienttools.hxx>
#include <basegfx/utils/tools.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <sal/log.hxx>
#include <vcl/canvastools.hxx>
#include "emfppen.hxx"
#include "emfpcustomlinecap.hxx"

@@ -83,20 +67,6 @@ namespace emfplushelper
    {
    }

    void EMFPPen::SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, EmfPlusHelperData const & rR, const ::basegfx::B2DHomMatrix& mapModeTransform)
    {
        // If a zero width is specified, a minimum value is used, which is determined by the units.
        //TODO Add support for other units than Pixel
        rStrokeAttributes.StrokeWidth = fabs((mapModeTransform * rR.MapSize(penWidth == 0.0 ? 0.05 : penWidth, 0)).getLength());

        // tdf#31814 Based on observation of different EMF+ files (eg. exported by ChemDraw),
        // there is minimal value of line width
        if (rStrokeAttributes.StrokeWidth < 1.0)
        {
            rStrokeAttributes.StrokeWidth = 1.0;
        }
    }

    /// Convert stroke caps between EMF+ and rendering API
    sal_Int8 EMFPPen::lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
    {
@@ -125,40 +95,6 @@ namespace emfplushelper
        return 0;
    }


    void EMFPPen::SetStrokeAttributes(rendering::StrokeAttributes& rStrokeAttributes)
    {
        rStrokeAttributes.JoinType = lcl_convertLineJoinType(lineJoin);

        if (dashStyle != EmfPlusLineStyleSolid)
        {
            const float dash[] = { 3, 3 };
            const float dot[] = { 1, 3 };
            const float dashdot[] = { 3, 3, 1, 3 };
            const float dashdotdot[] = { 3, 3, 1, 3, 1, 3 };

            sal_Int32 nLen = 0;
            const float *pPattern = nullptr;
            switch (dashStyle)
            {
                case EmfPlusLineStyleDash:       nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
                case EmfPlusLineStyleDot:        nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
                case EmfPlusLineStyleDashDot:    nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
                case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
                case EmfPlusLineStyleCustom:     nLen = dashPattern.size(); pPattern = dashPattern.data(); break;
            }

            if (nLen > 0)
            {
                uno::Sequence<double> aDashArray(nLen);
                for (int i = 0; i < nLen; ++i)
                    aDashArray[i] = pPattern[i];

                rStrokeAttributes.DashArray = aDashArray;
            }
        }
    }

    void EMFPPen::Read(SvStream& s, EmfPlusHelperData const & rR)
    {
        sal_uInt32 graphicsVersion, penType;
@@ -170,6 +106,13 @@ namespace emfplushelper

        penWidth = penWidth * EmfPlusHelperData::getUnitToPixelMultiplier(static_cast<UnitType>(penUnit));

        // If a zero width is specified, a minimum value must be used, which is determined by the units
        if (penWidth == 0.0)
        { //TODO Check if these values is correct
            penWidth = penUnit == 0 ? 0.18f
                : 0.05f;  // 0.05f is taken from old EMF+ implementation (case of Unit == Pixel etc.)
        }

        if (penDataFlags & PenDataTransform)
        {
            EmfPlusHelperData::readXForm(s, pen_transformation);
diff --git a/drawinglayer/source/tools/emfppen.hxx b/drawinglayer/source/tools/emfppen.hxx
index 5c0818b..a0b8dc4 100644
--- a/drawinglayer/source/tools/emfppen.hxx
+++ b/drawinglayer/source/tools/emfppen.hxx
@@ -21,7 +21,6 @@
#define INCLUDED_DRAWINGLAYER_SOURCE_TOOLS_EMFPPEN_HXX

#include "emfpbrush.hxx"
#include <com/sun/star/rendering/StrokeAttributes.hpp>
#include <vector>

namespace emfplushelper
@@ -68,10 +67,6 @@ namespace emfplushelper

        virtual ~EMFPPen() override;

        void SetStrokeWidth(com::sun::star::rendering::StrokeAttributes& rStrokeAttributes, EmfPlusHelperData const & rR, const ::basegfx::B2DHomMatrix& mapModeTransform);

        void SetStrokeAttributes(com::sun::star::rendering::StrokeAttributes& rStrokeAttributes);

        void Read(SvStream& s, EmfPlusHelperData const & rR);

        static sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke);