[Libreoffice-commits] core.git: Branch 'distro/vector/vector-5.4' - cppcanvas/source

Bartosz Kosiorek (via logerrit) logerrit at kemper.freedesktop.org
Thu Mar 12 08:22:58 UTC 2020


 cppcanvas/source/mtfrenderer/emfplus.cxx    |   12 -
 cppcanvas/source/mtfrenderer/emfpregion.cxx |  170 +++++++++++++++++++++++-----
 cppcanvas/source/mtfrenderer/emfpregion.hxx |   21 ++-
 3 files changed, 165 insertions(+), 38 deletions(-)

New commits:
commit ff248538cbe5a74dbe31049097a0d569b829efa9
Author:     Bartosz Kosiorek <gang65 at poczta.onet.pl>
AuthorDate: Sun Nov 5 00:02:49 2017 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Mar 12 09:22:08 2020 +0100

    tdf#113704 Implement proper reading of the EmfPlusRegionNode
    
    Regions are specified as a binary tree of region nodes, and each node must
    either be a terminal node or specify one or two child nodes.
    
    Nodes contains two child nodes:
      RegionNodeDataTypeAnd = 0x00000001,
      RegionNodeDataTypeOr = 0x00000002,
      RegionNodeDataTypeXor = 0x00000003,
      RegionNodeDataTypeExclude = 0x00000004,
      RegionNodeDataTypeComplement = 0x00000005,
    
    Terminal nodes:
      RegionNodeDataTypeRect = 0x10000000,
      RegionNodeDataTypePath = 0x10000001,
      RegionNodeDataTypeEmpty = 0x10000002,
      RegionNodeDataTypeInfinite = 0x10000003
    
    RegionNode must contain at least one element.
    
    (cherry picked from commit d0c4cee7e5ad00363d264aec0011a4b07983b19d)
    
    Conflicts:
            drawinglayer/source/tools/emfpbrush.cxx
            drawinglayer/source/tools/emfpcustomlinecap.cxx
            drawinglayer/source/tools/emfphelperdata.cxx
            drawinglayer/source/tools/emfphelperdata.hxx
            drawinglayer/source/tools/emfppath.cxx
            drawinglayer/source/tools/emfpregion.cxx
            sw/source/ui/config/optload.src
            vcl/source/src/units.src
    
    Change-Id: I668e5892701b979f09bcf5bbce44a43226676192

diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 8cfd1127540e..736e181dcbfe 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -129,8 +129,6 @@ namespace
 #define EmfPlusObjectTypeImageAttributes 0x800
 #define EmfPlusObjectTypeCustomLineCap 0x900
 
-#define EmfPlusRegionInitialStateInfinite 0x10000003
-
 enum EmfPlusCombineMode
 {
     EmfPlusCombineModeReplace = 0x00000000,
@@ -748,7 +746,7 @@ namespace cppcanvas
                 EMFPRegion *region;
 
                 aObjects [index] = region = new EMFPRegion ();
-                region->Read (rObjectStream);
+                region->ReadRegion (rObjectStream, *this);
 
                 break;
             }
@@ -1572,11 +1570,9 @@ namespace cppcanvas
                         SAL_INFO("cppcanvas.emf", "EMF+\tregion in slot: " << (flags & 0xff) << " combine mode: " << combineMode);
                         EMFPRegion *region = static_cast<EMFPRegion*>(aObjects [flags & 0xff]);
 
-                        // reset clip
-                        if (region && region->parts == 0 && region->initialState == EmfPlusRegionInitialStateInfinite) {
-                            updateClipping (::basegfx::B2DPolyPolygon (), rFactoryParms, combineMode == 1);
-                        } else {
-                            SAL_INFO("cppcanvas.emf", "EMF+\tTODO");
+                        if (region)
+                        {
+                            updateClipping(region->regionPolyPolygon, rFactoryParms, combineMode == 1);
                         }
                         break;
                     }
diff --git a/cppcanvas/source/mtfrenderer/emfpregion.cxx b/cppcanvas/source/mtfrenderer/emfpregion.cxx
index 99db436fb5aa..08a7b5afe906 100755
--- a/cppcanvas/source/mtfrenderer/emfpregion.cxx
+++ b/cppcanvas/source/mtfrenderer/emfpregion.cxx
@@ -37,56 +37,176 @@
 #include <vcl/canvastools.hxx>
 #include <implrenderer.hxx>
 #include <emfpregion.hxx>
+#include <emfppath.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::basegfx;
 
+enum EmfPlusCombineMode
+{
+    EmfPlusCombineModeReplace = 0x00000000,
+    EmfPlusCombineModeIntersect = 0x00000001,
+    EmfPlusCombineModeUnion = 0x00000002,
+    EmfPlusCombineModeXOR = 0x00000003,
+    EmfPlusCombineModeExclude = 0x00000004,
+    EmfPlusCombineModeComplement = 0x00000005
+};
+
 namespace cppcanvas
 {
     namespace internal
     {
         EMFPRegion::EMFPRegion()
-            : parts(0)
-            , combineMode(nullptr)
-            , initialState(0)
-            , ix(0.0)
-            , iy(0.0)
-            , iw(0.0)
-            , ih(0.0)
         {
         }
 
         EMFPRegion::~EMFPRegion()
         {
-            if (combineMode) {
-                delete[] combineMode;
-                combineMode = nullptr;
+        }
+
+        ::basegfx::B2DPolyPolygon combineClip(::basegfx::B2DPolyPolygon const & leftPolygon, int combineMode, ::basegfx::B2DPolyPolygon const & rightPolygon)
+        {
+            basegfx::B2DPolyPolygon aClippedPolyPolygon;
+            switch (combineMode)
+            {
+            case EmfPlusCombineModeReplace:
+            {
+                aClippedPolyPolygon = rightPolygon;
+                break;
+            }
+            case EmfPlusCombineModeIntersect:
+            {
+                if (leftPolygon.count())
+                {
+                    aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                                leftPolygon,
+                                rightPolygon,
+                                true,
+                                false);
+                }
+                break;
+            }
+            case EmfPlusCombineModeUnion:
+            {
+                aClippedPolyPolygon = ::basegfx::tools::solvePolygonOperationOr(leftPolygon, rightPolygon);
+                break;
+            }
+            case EmfPlusCombineModeXOR:
+            {
+                aClippedPolyPolygon = ::basegfx::tools::solvePolygonOperationXor(leftPolygon, rightPolygon);
+                break;
+            }
+            case EmfPlusCombineModeExclude:
+            {
+                // Replaces the existing region with the part of itself that is not in the new region.
+                aClippedPolyPolygon = ::basegfx::tools::solvePolygonOperationDiff(leftPolygon, rightPolygon);
+                break;
+            }
+            case EmfPlusCombineModeComplement:
+            {
+                // Replaces the existing region with the part of the new region that is not in the existing region.
+                aClippedPolyPolygon = ::basegfx::tools::solvePolygonOperationDiff(rightPolygon, leftPolygon);
+                break;
+            }
             }
+            return aClippedPolyPolygon;
         }
 
-        void EMFPRegion::Read(SvStream& s)
+        ::basegfx::B2DPolyPolygon EMFPRegion::ReadRegionNode(SvStream& s, ImplRenderer& rR)
         {
-            sal_uInt32 header;
+            // Regions are specified as a binary tree of region nodes, and each node must either be a terminal node
+            // (RegionNodeDataTypeRect, RegionNodeDataTypePath, RegionNodeDataTypeEmpty, RegionNodeDataTypeInfinite)
+            // or specify one or two child nodes
+            // (RegionNodeDataTypeAnd, RegionNodeDataTypeOr, RegionNodeDataTypeXor,
+            // RegionNodeDataTypeExclude, RegionNodeDataTypeComplement).
+            sal_uInt32 dataType;
+            ::basegfx::B2DPolyPolygon polygon;
+            s.ReadUInt32(dataType);
+            SAL_INFO("cppcanvas.emf", "EMF+\t Region node data type 0x" << std::hex << dataType << std::dec);
 
-            s.ReadUInt32(header).ReadInt32(parts);
+            switch (dataType)
+            {
+            case RegionNodeDataTypeAnd: // CombineModeIntersect
+            case RegionNodeDataTypeOr: // CombineModeUnion
+            case RegionNodeDataTypeXor: // CombineModeXOR
+            case RegionNodeDataTypeExclude: // CombineModeExclude
+            case RegionNodeDataTypeComplement: // CombineModeComplement
+            {
+                ::basegfx::B2DPolyPolygon leftPolygon = ReadRegionNode(s, rR);
+                ::basegfx::B2DPolyPolygon rightPolygon = ReadRegionNode(s, rR);
+                polygon = combineClip(leftPolygon, dataType, rightPolygon);
+                break;
+            }
+            case RegionNodeDataTypeRect:
+            {
+                float dx, dy, dw, dh;
+                s.ReadFloat(dx).ReadFloat(dy).ReadFloat(dw).ReadFloat(dh);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\t RegionNodeDataTypeRect x:" << dx << ", y:" << dy <<
+                         ", width:" << dw << ", height:" << dh);
 
-            SAL_INFO("cppcanvas.emf", "EMF+\tregion");
-            SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " parts: " << parts << std::dec);
+                const ::basegfx::B2DPoint mappedStartPoint(rR.Map(dx, dy));
+                const ::basegfx::B2DPoint mappedEndPoint(rR.Map(dx + dw, dy + dh));
+                const ::basegfx::B2DPolyPolygon polyPolygon(
+                        ::basegfx::tools::createPolygonFromRect(
+                            ::basegfx::B2DRectangle(
+                                mappedStartPoint.getX(),
+                                mappedStartPoint.getY(),
+                                mappedEndPoint.getX(),
+                                mappedEndPoint.getY())));
+                polygon = polyPolygon;
+                break;
+            }
+            case RegionNodeDataTypePath:
+            {
+                sal_Int32 pathLength;
+                s.ReadInt32(pathLength);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\t RegionNodeDataTypePath, Path Length: " << pathLength << " bytes");
 
-            if (parts) {
-                if (parts<0 || sal_uInt32(parts)>SAL_MAX_INT32 / sizeof(sal_Int32))
-                    parts = SAL_MAX_INT32 / sizeof(sal_Int32);
+                sal_uInt32 header, pathFlags;
+                sal_Int32 points;
 
-                combineMode = new sal_Int32[parts];
+                s.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags);
+                SAL_INFO("cppcanvas.emf", "EMF+\t\t header: 0x" << std::hex << header <<
+                         " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec);
 
-                for (int i = 0; i < parts; i++) {
-                    s.ReadInt32(combineMode[i]);
-                    SAL_INFO("cppcanvas.emf", "EMF+\tcombine mode [" << i << "]: 0x" << std::hex << combineMode[i] << std::dec);
-                }
+                EMFPPath path(points);
+                path.Read(s, pathFlags, rR);
+                polygon = path.GetPolygon(rR);
+                break;
+            }
+            case RegionNodeDataTypeEmpty:
+            {
+                SAL_INFO("cppcanvas.emf", "EMF+\t\t RegionNodeDataTypeEmpty");
+                SAL_WARN("cppcanvas.emf", "EMF+\t\t TODO we need to set empty polygon here");
+                polygon = ::basegfx::B2DPolyPolygon();
+
+                break;
+            }
+            case RegionNodeDataTypeInfinite:
+            {
+                SAL_INFO("cppcanvas.emf", "EMF+\t\t RegionNodeDataTypeInfinite");
+                polygon = ::basegfx::B2DPolyPolygon();
+                break;
             }
+            default:
+            {
+                SAL_WARN("cppcanvas.emf", "EMF+\t\t Unhandled region type: 0x" << std::hex << dataType << std::dec);
+                polygon = ::basegfx::B2DPolyPolygon();
+            }
+            }
+            return polygon;
+        }
+
+        void EMFPRegion::ReadRegion(SvStream& s, ImplRenderer& rR)
+        {
+            sal_uInt32 header, count;
+            s.ReadUInt32(header).ReadUInt32(count);
+            // An array should be RegionNodeCount+1 of EmfPlusRegionNode objects.
+            SAL_INFO("cppcanvas.emf", "EMF+\t version: 0x" << std::hex << header << std::dec << ", region node count: " << count);
 
-            s.ReadInt32(initialState);
-            SAL_INFO("cppcanvas.emf", "EMF+\tinitial state: 0x" << std::hex << initialState << std::dec);
+            regionPolyPolygon = ReadRegionNode(s, rR);
         }
     }
 }
diff --git a/cppcanvas/source/mtfrenderer/emfpregion.hxx b/cppcanvas/source/mtfrenderer/emfpregion.hxx
index 876aebcdbd67..a1e1ca0c22ab 100755
--- a/cppcanvas/source/mtfrenderer/emfpregion.hxx
+++ b/cppcanvas/source/mtfrenderer/emfpregion.hxx
@@ -24,16 +24,27 @@ namespace cppcanvas
 {
     namespace internal
     {
+        typedef enum
+        {
+            RegionNodeDataTypeAnd = 0x00000001,
+            RegionNodeDataTypeOr = 0x00000002,
+            RegionNodeDataTypeXor = 0x00000003,
+            RegionNodeDataTypeExclude = 0x00000004,
+            RegionNodeDataTypeComplement = 0x00000005,
+            RegionNodeDataTypeRect = 0x10000000,
+            RegionNodeDataTypePath = 0x10000001,
+            RegionNodeDataTypeEmpty = 0x10000002,
+            RegionNodeDataTypeInfinite = 0x10000003
+        } RegionNodeDataType;
+
         struct EMFPRegion : public EMFPObject
         {
-            sal_Int32 parts;
-            sal_Int32 *combineMode;
-            sal_Int32 initialState;
-            float ix, iy, iw, ih;
+            ::basegfx::B2DPolyPolygon regionPolyPolygon;
 
             EMFPRegion();
             virtual ~EMFPRegion() override;
-            void Read(SvStream& s);
+            void ReadRegion(SvStream& s, ImplRenderer& rR);
+            ::basegfx::B2DPolyPolygon ReadRegionNode(SvStream& s, ImplRenderer& rR);
         };
     }
 }


More information about the Libreoffice-commits mailing list