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