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 
43 inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
44 {
45  return(meStyle == rB.meStyle
46  && mnWidth == rB.mnWidth
47  && mnDashCount == rB.mnDashCount
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 
57 LineInfo::LineInfo( LineStyle eStyle, double nWidth )
58 {
59  mpImplLineInfo->meStyle = eStyle;
60  mpImplLineInfo->mnWidth = nWidth;
61 }
62 
63 LineInfo::LineInfo( const LineInfo& ) = default;
64 
65 LineInfo::LineInfo( LineInfo&& ) = default;
66 
67 LineInfo::~LineInfo() = default;
68 
69 LineInfo& LineInfo::operator=( const LineInfo& ) = default;
70 
71 LineInfo& LineInfo::operator=( LineInfo&& ) = default;
72 
73 bool LineInfo::operator==( const LineInfo& rLineInfo ) const
74 {
75  return mpImplLineInfo == rLineInfo.mpImplLineInfo;
76 }
77 
78 void LineInfo::SetStyle( LineStyle eStyle )
79 {
80  mpImplLineInfo->meStyle = eStyle;
81 }
82 
83 void LineInfo::SetWidth( double nWidth )
84 {
85  mpImplLineInfo->mnWidth = nWidth;
86 }
87 
88 void LineInfo::SetDashCount( sal_uInt16 nDashCount )
89 {
90  mpImplLineInfo->mnDashCount = nDashCount;
91 }
92 
93 void LineInfo::SetDashLen( double nDashLen )
94 {
95  mpImplLineInfo->mnDashLen = nDashLen;
96 }
97 
98 void LineInfo::SetDotCount( sal_uInt16 nDotCount )
99 {
100  mpImplLineInfo->mnDotCount = nDotCount;
101 }
102 
103 void LineInfo::SetDotLen( double nDotLen )
104 {
105  mpImplLineInfo->mnDotLen = nDotLen;
106 }
107 
108 void LineInfo::SetDistance( double nDistance )
109 {
110  mpImplLineInfo->mnDistance = nDistance;
111 }
112 
113 void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
114 {
115  mpImplLineInfo->meLineJoin = eLineJoin;
116 }
117 
118 void LineInfo::SetLineCap(css::drawing::LineCap eLineCap)
119 {
120  mpImplLineInfo->meLineCap = eLineCap;
121 }
122 
123 bool LineInfo::IsDefault() const
124 {
125  return( !mpImplLineInfo->mnWidth
126  && ( LineStyle::Solid == mpImplLineInfo->meStyle )
127  && ( css::drawing::LineCap_BUTT == mpImplLineInfo->meLineCap));
128 }
129 
130 static 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 
142 SvStream& ReadLineInfo( SvStream& rIStm, LineInfo& rLineInfo )
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 
190 SvStream& 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 
220 std::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 
244 void 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  {
260  basegfx::B2DPolyPolygon aResult;
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  {
283  o_rFillPolyPolygon.append(basegfx::utils::createAreaGeometry(
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 & WriteUInt16(sal_uInt16 nUInt16)
SvStream & WriteInt32(sal_Int32 nInt32)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
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)
LineStyle
Definition: vclenum.hxx:185
exports com.sun.star. drawing
B2IRange fround(const B2DRange &rRange)
double mnDotLen
Definition: lineinfo.hxx:39
void applyLineDashing(const B2DPolygon &rCandidate, const std::vector< double > &rDotDashArray, B2DPolyPolygon *pLineTarget, B2DPolyPolygon *pGapTarget, double fDotDashLength)
SvStream & ReadLineInfo(SvStream &rIStm, LineInfo &rLineInfo)
Definition: lineinfo.cxx:142
uno_Any a
double mnDashLen
Definition: lineinfo.hxx:38
B2DLineJoin
sal_uInt16 mnDotCount
Definition: lineinfo.hxx:47
SvStream & ReadDouble(double &rDouble)
SvStream & ReadInt32(sal_Int32 &rInt32)
bool operator==(const ImplLineInfo &) const
Definition: lineinfo.cxx:43
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
sal_uInt32 count() const
sal_uInt16 GetVersion() const
LineStyle meStyle
Definition: lineinfo.hxx:44
basegfx::B2DLineJoin meLineJoin
Definition: lineinfo.hxx:42
double mnWidth
Definition: lineinfo.hxx:37
double mnWidth
css::drawing::LineCap meLineCap
Definition: lineinfo.hxx:43
double mnDistance
Definition: lineinfo.hxx:40
static void ReadLimitedDouble(SvStream &rIStm, double &fDest)
Definition: lineinfo.cxx:130
#define SAL_WARN(area, stream)
SvStream & WriteDouble(const double &rDouble)
std::string Round
SvStream & WriteLineInfo(SvStream &rOStm, const LineInfo &rLineInfo)
Definition: lineinfo.cxx:190
sal_uInt16 mnDashCount
Definition: lineinfo.hxx:46