Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/drawinglayer/source/tools/emfpregion.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <basegfx/point/b2dpoint.hxx>
21
#include <basegfx/range/b2drectangle.hxx>
22
#include <basegfx/polygon/b2dpolygon.hxx>
23
#include <basegfx/polygon/b2dpolygontools.hxx>
24
#include <basegfx/polygon/b2dpolypolygon.hxx>
25
#include <sal/log.hxx>
26
#include "emfpregion.hxx"
27
#include "emfppath.hxx"
28
29
namespace emfplushelper
30
{
31
    EMFPRegion::EMFPRegion()
32
0
    {
33
0
    }
34
35
    EMFPRegion::~EMFPRegion()
36
0
    {
37
0
    }
38
39
    ::basegfx::B2DPolyPolygon EMFPRegion::ReadRegionNode(SvStream& s, EmfPlusHelperData& rR, int nDepth)
40
0
    {
41
        // Regions are specified as a binary tree of region nodes, and each node must either be a terminal node
42
        // (RegionNodeDataTypeRect, RegionNodeDataTypePath, RegionNodeDataTypeEmpty, RegionNodeDataTypeInfinite)
43
        // or specify one or two child nodes
44
        // (RegionNodeDataTypeAnd, RegionNodeDataTypeOr, RegionNodeDataTypeXor,
45
        // RegionNodeDataTypeExclude, RegionNodeDataTypeComplement).
46
0
        constexpr int nMaxDepth = 2048;
47
0
        if (nDepth >= nMaxDepth)
48
0
        {
49
0
            SAL_WARN("drawinglayer.emf", "EMF+\t Region node too deeply nested (>" << nMaxDepth << ")");
50
0
            return {};
51
0
        }
52
53
0
        sal_uInt32 dataType(0);
54
0
        ::basegfx::B2DPolyPolygon polygon;
55
0
        s.ReadUInt32(dataType);
56
0
        SAL_INFO("drawinglayer.emf", "EMF+\t Region node data type 0x" << std::hex << dataType << std::dec);
57
58
0
        switch (dataType)
59
0
        {
60
0
        case RegionNodeDataTypeAnd: // CombineModeIntersect
61
0
        case RegionNodeDataTypeOr: // CombineModeUnion
62
0
        case RegionNodeDataTypeXor: // CombineModeXOR
63
0
        case RegionNodeDataTypeExclude: // CombineModeExclude
64
0
        case RegionNodeDataTypeComplement: // CombineModeComplement
65
0
        {
66
0
            ::basegfx::B2DPolyPolygon leftPolygon = ReadRegionNode(s, rR, nDepth + 1);
67
0
            ::basegfx::B2DPolyPolygon rightPolygon = ReadRegionNode(s, rR, nDepth + 1);
68
0
            polygon = EmfPlusHelperData::combineClip(leftPolygon, dataType, rightPolygon);
69
0
            break;
70
0
        }
71
0
        case RegionNodeDataTypeRect:
72
0
        {
73
0
            float dx(0), dy(0), dw(0), dh(0);
74
0
            s.ReadFloat(dx).ReadFloat(dy).ReadFloat(dw).ReadFloat(dh);
75
0
            SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeRect x:" << dx << ", y:" << dy <<
76
0
                     ", width:" << dw << ", height:" << dh);
77
78
0
            const ::basegfx::B2DPoint mappedStartPoint(rR.Map(dx, dy));
79
0
            const ::basegfx::B2DPoint mappedEndPoint(rR.Map(dx + dw, dy + dh));
80
0
            polygon = ::basegfx::B2DPolyPolygon(
81
0
                    ::basegfx::utils::createPolygonFromRect(
82
0
                        ::basegfx::B2DRectangle(
83
0
                            mappedStartPoint.getX(),
84
0
                            mappedStartPoint.getY(),
85
0
                            mappedEndPoint.getX(),
86
0
                            mappedEndPoint.getY())));
87
0
            break;
88
0
        }
89
0
        case RegionNodeDataTypePath:
90
0
        {
91
0
            sal_Int32 pathLength(0);
92
0
            s.ReadInt32(pathLength);
93
0
            SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypePath, Path Length: " << pathLength << " bytes");
94
95
0
            sal_uInt32 header(0), pathFlags(0);
96
0
            sal_Int32 points(0);
97
98
0
            s.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags);
99
0
            SAL_INFO("drawinglayer.emf", "EMF+\t\t header: 0x" << std::hex << header <<
100
0
                     " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec);
101
102
0
            EMFPPath path(points);
103
0
            path.Read(s, pathFlags);
104
0
            polygon = path.GetPolygon(rR);
105
0
            break;
106
0
        }
107
0
        case RegionNodeDataTypeEmpty:
108
0
        {
109
0
            SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeEmpty");
110
0
            SAL_WARN("drawinglayer.emf", "EMF+\t\t TODO we need to set empty polygon here");
111
0
            polygon = ::basegfx::B2DPolyPolygon();
112
113
0
            break;
114
0
        }
115
0
        case RegionNodeDataTypeInfinite:
116
0
        {
117
0
            SAL_INFO("drawinglayer.emf", "EMF+\t\t RegionNodeDataTypeInfinite");
118
0
            polygon = ::basegfx::B2DPolyPolygon();
119
0
            break;
120
0
        }
121
0
        default:
122
0
        {
123
0
            SAL_WARN("drawinglayer.emf", "EMF+\t\t Unhandled region type: 0x" << std::hex << dataType << std::dec);
124
0
            polygon = ::basegfx::B2DPolyPolygon();
125
0
        }
126
0
        }
127
0
        return polygon;
128
0
    }
129
130
    void EMFPRegion::ReadRegion(SvStream& s, EmfPlusHelperData& rR)
131
0
    {
132
0
        sal_uInt32 header(0), count(0);
133
0
        s.ReadUInt32(header).ReadUInt32(count);
134
        // An array should be RegionNodeCount+1 of EmfPlusRegionNode objects.
135
0
        SAL_INFO("drawinglayer.emf", "EMF+\t version: 0x" << std::hex << header << std::dec << ", region node count: " << count);
136
137
0
        regionPolyPolygon = ReadRegionNode(s, rR, 0);
138
0
    }
139
}
140
141
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */