Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/gdi/lineinfo.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 <sal/log.hxx>
21
#include <tools/stream.hxx>
22
#include <tools/vcompat.hxx>
23
#include <vcl/lineinfo.hxx>
24
#include <basegfx/polygon/b2dpolypolygon.hxx>
25
#include <basegfx/polygon/b2dpolygontools.hxx>
26
#include <basegfx/polygon/b2dlinegeometry.hxx>
27
#include <numeric>
28
29
30
ImplLineInfo::ImplLineInfo()
31
430k
    : mnWidth(0)
32
430k
    , mnDashLen(0)
33
430k
    , mnDotLen(0)
34
430k
    , mnDistance(0)
35
430k
    , meLineJoin(basegfx::B2DLineJoin::Round)
36
430k
    , meLineCap(css::drawing::LineCap_BUTT)
37
430k
    , meStyle(LineStyle::Solid)
38
430k
    , mnDashCount(0)
39
430k
    , mnDotCount(0)
40
430k
{
41
430k
}
42
43
inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
44
52.0k
{
45
52.0k
    return(meStyle == rB.meStyle
46
51.7k
        && mnWidth == rB.mnWidth
47
51.1k
        && mnDashCount == rB.mnDashCount
48
50.7k
        && mnDashLen == rB.mnDashLen
49
50.6k
        && mnDotCount == rB.mnDotCount
50
50.5k
        && mnDotLen == rB.mnDotLen
51
50.5k
        && mnDistance == rB.mnDistance
52
50.5k
        && meLineJoin == rB.meLineJoin
53
50.3k
        && meLineCap == rB.meLineCap);
54
52.0k
}
55
56
57
LineInfo::LineInfo( LineStyle eStyle, double nWidth )
58
430k
{
59
430k
    mpImplLineInfo->meStyle = eStyle;
60
430k
    mpImplLineInfo->mnWidth = nWidth;
61
430k
}
62
63
1.37M
LineInfo::LineInfo( const LineInfo& ) = default;
64
65
1.37M
LineInfo::LineInfo( LineInfo&& ) = default;
66
67
3.18M
LineInfo::~LineInfo() = default;
68
69
214k
LineInfo& LineInfo::operator=( const LineInfo& ) = default;
70
71
7.24k
LineInfo& LineInfo::operator=( LineInfo&& ) = default;
72
73
bool LineInfo::operator==( const LineInfo& rLineInfo ) const
74
92.5k
{
75
92.5k
    return mpImplLineInfo == rLineInfo.mpImplLineInfo;
76
92.5k
}
77
78
void LineInfo::SetStyle( LineStyle eStyle )
79
212k
{
80
212k
    mpImplLineInfo->meStyle = eStyle;
81
212k
}
82
83
void LineInfo::SetWidth( double nWidth )
84
223k
{
85
223k
    mpImplLineInfo->mnWidth = nWidth;
86
223k
}
87
88
void LineInfo::SetDashCount( sal_uInt16 nDashCount )
89
28.0k
{
90
28.0k
    mpImplLineInfo->mnDashCount = nDashCount;
91
28.0k
}
92
93
void LineInfo::SetDashLen( double nDashLen )
94
27.0k
{
95
27.0k
    mpImplLineInfo->mnDashLen = nDashLen;
96
27.0k
}
97
98
void LineInfo::SetDotCount( sal_uInt16 nDotCount )
99
28.1k
{
100
28.1k
    mpImplLineInfo->mnDotCount = nDotCount;
101
28.1k
}
102
103
void LineInfo::SetDotLen( double nDotLen )
104
27.1k
{
105
27.1k
    mpImplLineInfo->mnDotLen = nDotLen;
106
27.1k
}
107
108
void LineInfo::SetDistance( double nDistance )
109
27.2k
{
110
27.2k
    mpImplLineInfo->mnDistance = nDistance;
111
27.2k
}
112
113
void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
114
14.5k
{
115
14.5k
    mpImplLineInfo->meLineJoin = eLineJoin;
116
14.5k
}
117
118
void LineInfo::SetLineCap(css::drawing::LineCap eLineCap)
119
14.5k
{
120
14.5k
    mpImplLineInfo->meLineCap = eLineCap;
121
14.5k
}
122
123
bool LineInfo::IsDefault() const
124
2.33M
{
125
2.33M
    return( !mpImplLineInfo->mnWidth
126
140k
        && ( LineStyle::Solid == mpImplLineInfo->meStyle )
127
63.6k
        && ( css::drawing::LineCap_BUTT == mpImplLineInfo->meLineCap));
128
2.33M
}
129
130
static void ReadLimitedDouble(SvStream& rIStm, double &fDest)
131
8.54k
{
132
8.54k
    double fTmp(0.0);
133
8.54k
    rIStm.ReadDouble(fTmp);
134
8.54k
    if (!std::isfinite(fTmp) || fTmp < std::numeric_limits<sal_Int32>::min() || fTmp > std::numeric_limits<sal_Int32>::max())
135
3.18k
    {
136
3.18k
        SAL_WARN("vcl", "Parsing error: out of range double: " << fTmp);
137
3.18k
        return;
138
3.18k
    }
139
5.35k
    fDest = fTmp;
140
5.35k
}
141
142
SvStream& ReadLineInfo( SvStream& rIStm, LineInfo& rLineInfo )
143
5.37k
{
144
5.37k
    VersionCompatRead aCompat( rIStm );
145
5.37k
    sal_uInt16          nTmp16(0);
146
5.37k
    sal_Int32       nTmp32(0);
147
148
5.37k
    rIStm.ReadUInt16( nTmp16 );
149
5.37k
    rLineInfo.mpImplLineInfo->meStyle = static_cast<LineStyle>(nTmp16);
150
5.37k
    rIStm.ReadInt32( nTmp32 );
151
5.37k
    rLineInfo.mpImplLineInfo->mnWidth = nTmp32;
152
153
5.37k
    if( aCompat.GetVersion() >= 2 )
154
4.80k
    {
155
        // version 2
156
4.80k
        rIStm.ReadUInt16( rLineInfo.mpImplLineInfo->mnDashCount ).ReadInt32( nTmp32 );
157
4.80k
        rLineInfo.mpImplLineInfo->mnDashLen = nTmp32;
158
4.80k
        rIStm.ReadUInt16( rLineInfo.mpImplLineInfo->mnDotCount ).ReadInt32( nTmp32 );
159
4.80k
        rLineInfo.mpImplLineInfo->mnDotLen = nTmp32;
160
4.80k
        rIStm.ReadInt32( nTmp32 );
161
4.80k
        rLineInfo.mpImplLineInfo->mnDistance = nTmp32;
162
4.80k
    }
163
164
5.37k
    if( aCompat.GetVersion() >= 3 )
165
4.80k
    {
166
        // version 3
167
4.80k
        rIStm.ReadUInt16( nTmp16 );
168
4.80k
        rLineInfo.mpImplLineInfo->meLineJoin = static_cast<basegfx::B2DLineJoin>(nTmp16);
169
4.80k
    }
170
171
5.37k
    if( aCompat.GetVersion() >= 4 )
172
2.14k
    {
173
        // version 4
174
2.14k
        rIStm.ReadUInt16( nTmp16 );
175
2.14k
        rLineInfo.mpImplLineInfo->meLineCap = static_cast<css::drawing::LineCap>(nTmp16);
176
2.14k
    }
177
178
5.37k
    if( aCompat.GetVersion() >= 5 )
179
2.13k
    {
180
        // version 5
181
2.13k
        ReadLimitedDouble(rIStm, rLineInfo.mpImplLineInfo->mnWidth);
182
2.13k
        ReadLimitedDouble(rIStm, rLineInfo.mpImplLineInfo->mnDashLen);
183
2.13k
        ReadLimitedDouble(rIStm, rLineInfo.mpImplLineInfo->mnDotLen);
184
2.13k
        ReadLimitedDouble(rIStm, rLineInfo.mpImplLineInfo->mnDistance);
185
2.13k
    }
186
187
5.37k
    return rIStm;
188
5.37k
}
189
190
SvStream& WriteLineInfo( SvStream& rOStm, const LineInfo& rLineInfo )
191
56
{
192
56
    VersionCompatWrite aCompat( rOStm, 5 );
193
194
    // version 1
195
56
    rOStm.WriteUInt16( static_cast<sal_uInt16>(rLineInfo.mpImplLineInfo->meStyle) )
196
56
         .WriteInt32( basegfx::fround( rLineInfo.mpImplLineInfo->mnWidth ));
197
198
    // since version2
199
56
    rOStm.WriteUInt16( rLineInfo.mpImplLineInfo->mnDashCount )
200
56
         .WriteInt32( basegfx::fround( rLineInfo.mpImplLineInfo->mnDashLen ));
201
56
    rOStm.WriteUInt16( rLineInfo.mpImplLineInfo->mnDotCount )
202
56
         .WriteInt32( basegfx::fround( rLineInfo.mpImplLineInfo->mnDotLen ));
203
56
    rOStm.WriteInt32( basegfx::fround( rLineInfo.mpImplLineInfo->mnDistance ));
204
205
    // since version3
206
56
    rOStm.WriteUInt16( static_cast<sal_uInt16>(rLineInfo.mpImplLineInfo->meLineJoin) );
207
208
    // since version4
209
56
    rOStm.WriteUInt16( static_cast<sal_uInt16>(rLineInfo.mpImplLineInfo->meLineCap) );
210
211
    // since version5
212
56
    rOStm.WriteDouble( rLineInfo.mpImplLineInfo->mnWidth );
213
56
    rOStm.WriteDouble( rLineInfo.mpImplLineInfo->mnDashLen );
214
56
    rOStm.WriteDouble( rLineInfo.mpImplLineInfo->mnDotLen );
215
56
    rOStm.WriteDouble( rLineInfo.mpImplLineInfo->mnDistance );
216
217
56
    return rOStm;
218
56
}
219
220
std::vector< double > LineInfo::GetDotDashArray() const
221
0
{
222
0
    ::std::vector< double > fDotDashArray;
223
0
    if ( GetStyle() != LineStyle::Dash )
224
0
        return fDotDashArray;
225
226
0
    const double fDashLen(GetDashLen());
227
0
    const double fDotLen(GetDotLen());
228
0
    const double fDistance(GetDistance());
229
230
0
    for(sal_uInt16 a(0); a < GetDashCount(); a++)
231
0
    {
232
0
        fDotDashArray.push_back(fDashLen);
233
0
        fDotDashArray.push_back(fDistance);
234
0
    }
235
236
0
    for(sal_uInt16 b(0); b < GetDotCount(); b++)
237
0
    {
238
0
        fDotDashArray.push_back(fDotLen);
239
0
        fDotDashArray.push_back(fDistance);
240
0
    }
241
0
    return fDotDashArray;
242
0
}
243
244
void LineInfo::applyToB2DPolyPolygon(
245
    basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
246
    basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
247
0
{
248
0
    o_rFillPolyPolygon.clear();
249
250
0
    if(!io_rLinePolyPolygon.count())
251
0
        return;
252
253
0
    if(LineStyle::Dash == GetStyle())
254
0
    {
255
0
        ::std::vector< double > fDotDashArray = GetDotDashArray();
256
0
        const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
257
258
0
        if(fAccumulated > 0.0)
259
0
        {
260
0
            basegfx::B2DPolyPolygon aResult;
261
262
0
            for(auto const& rPolygon : std::as_const(io_rLinePolyPolygon))
263
0
            {
264
0
                basegfx::B2DPolyPolygon aLineTarget;
265
0
                basegfx::utils::applyLineDashing(
266
0
                    rPolygon,
267
0
                    fDotDashArray,
268
0
                    &aLineTarget);
269
0
                aResult.append(aLineTarget);
270
0
            }
271
272
0
            io_rLinePolyPolygon = std::move(aResult);
273
0
        }
274
0
    }
275
276
0
    if(!(GetWidth() > 1 && io_rLinePolyPolygon.count()))
277
0
        return;
278
279
0
    const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
280
281
0
    for(auto const& rPolygon : std::as_const(io_rLinePolyPolygon))
282
0
    {
283
0
        o_rFillPolyPolygon.append(basegfx::utils::createAreaGeometry(
284
0
            rPolygon,
285
0
            fHalfLineWidth,
286
0
            GetLineJoin(),
287
0
            GetLineCap()));
288
0
    }
289
290
0
    io_rLinePolyPolygon.clear();
291
0
}
292
293
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */