Line data Source code
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 <tools/stream.hxx>
21 : #include <tools/vcompat.hxx>
22 : #include <tools/debug.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 : DBG_NAME( LineInfo )
30 :
31 : // ----------------
32 : // - ImplLineInfo -
33 : // ----------------
34 :
35 4429 : ImplLineInfo::ImplLineInfo() :
36 : mnRefCount ( 1 ),
37 : meStyle ( LINE_SOLID ),
38 : mnWidth ( 0 ),
39 : mnDashCount ( 0 ),
40 : mnDashLen ( 0 ),
41 : mnDotCount ( 0 ),
42 : mnDotLen ( 0 ),
43 : mnDistance ( 0 ),
44 : meLineJoin ( basegfx::B2DLINEJOIN_ROUND ),
45 4429 : meLineCap ( com::sun::star::drawing::LineCap_BUTT )
46 : {
47 4429 : }
48 :
49 : // -----------------------------------------------------------------------
50 :
51 3090 : ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
52 : mnRefCount ( 1 ),
53 : meStyle ( rImplLineInfo.meStyle ),
54 : mnWidth ( rImplLineInfo.mnWidth ),
55 : mnDashCount ( rImplLineInfo.mnDashCount ),
56 : mnDashLen ( rImplLineInfo.mnDashLen ),
57 : mnDotCount ( rImplLineInfo.mnDotCount ),
58 : mnDotLen ( rImplLineInfo.mnDotLen ),
59 : mnDistance ( rImplLineInfo.mnDistance ),
60 : meLineJoin ( rImplLineInfo.meLineJoin ),
61 3090 : meLineCap ( rImplLineInfo.meLineCap )
62 : {
63 3090 : }
64 :
65 : // -----------------------------------------------------------------------
66 :
67 871 : inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
68 : {
69 : return(meStyle == rB.meStyle
70 : && mnWidth == rB.mnWidth
71 : && mnDashCount == rB.mnDashCount
72 : && mnDashLen == rB.mnDashLen
73 : && mnDotCount == rB.mnDotCount
74 : && mnDotLen == rB.mnDotLen
75 : && mnDistance == rB.mnDistance
76 : && meLineJoin == rB.meLineJoin
77 871 : && meLineCap == rB.meLineCap);
78 : }
79 :
80 : // ------------
81 : // - LineInfo -
82 : // ------------
83 :
84 4429 : LineInfo::LineInfo( LineStyle eStyle, long nWidth )
85 : {
86 : DBG_CTOR( LineInfo, NULL );
87 4429 : mpImplLineInfo = new ImplLineInfo;
88 4429 : mpImplLineInfo->meStyle = eStyle;
89 4429 : mpImplLineInfo->mnWidth = nWidth;
90 4429 : }
91 :
92 : // -----------------------------------------------------------------------
93 :
94 3255 : LineInfo::LineInfo( const LineInfo& rLineInfo )
95 : {
96 : DBG_CTOR( LineInfo, NULL );
97 : DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
98 3255 : mpImplLineInfo = rLineInfo.mpImplLineInfo;
99 3255 : mpImplLineInfo->mnRefCount++;
100 3255 : }
101 :
102 : // -----------------------------------------------------------------------
103 :
104 7684 : LineInfo::~LineInfo()
105 : {
106 : DBG_DTOR( LineInfo, NULL );
107 7684 : if( !( --mpImplLineInfo->mnRefCount ) )
108 6285 : delete mpImplLineInfo;
109 7684 : }
110 :
111 : // -----------------------------------------------------------------------
112 :
113 2089 : LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
114 : {
115 : DBG_CHKTHIS( LineInfo, NULL );
116 : DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
117 :
118 2089 : rLineInfo.mpImplLineInfo->mnRefCount++;
119 :
120 2089 : if( !( --mpImplLineInfo->mnRefCount ) )
121 1234 : delete mpImplLineInfo;
122 :
123 2089 : mpImplLineInfo = rLineInfo.mpImplLineInfo;
124 2089 : return *this;
125 : }
126 :
127 : // -----------------------------------------------------------------------
128 :
129 884 : sal_Bool LineInfo::operator==( const LineInfo& rLineInfo ) const
130 : {
131 : DBG_CHKTHIS( LineInfo, NULL );
132 : DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
133 :
134 : return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
135 884 : *mpImplLineInfo == *rLineInfo.mpImplLineInfo );
136 : }
137 :
138 : // -----------------------------------------------------------------------
139 :
140 3317 : void LineInfo::ImplMakeUnique()
141 : {
142 3317 : if( mpImplLineInfo->mnRefCount != 1 )
143 : {
144 3090 : if( mpImplLineInfo->mnRefCount )
145 3090 : mpImplLineInfo->mnRefCount--;
146 :
147 3090 : mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
148 : }
149 3317 : }
150 :
151 : // -----------------------------------------------------------------------
152 :
153 206 : void LineInfo::SetStyle( LineStyle eStyle )
154 : {
155 : DBG_CHKTHIS( LineInfo, NULL );
156 206 : ImplMakeUnique();
157 206 : mpImplLineInfo->meStyle = eStyle;
158 206 : }
159 :
160 : // -----------------------------------------------------------------------
161 :
162 3111 : void LineInfo::SetWidth( long nWidth )
163 : {
164 : DBG_CHKTHIS( LineInfo, NULL );
165 3111 : ImplMakeUnique();
166 3111 : mpImplLineInfo->mnWidth = nWidth;
167 3111 : }
168 :
169 : // -----------------------------------------------------------------------
170 :
171 0 : void LineInfo::SetDashCount( sal_uInt16 nDashCount )
172 : {
173 : DBG_CHKTHIS( LineInfo, NULL );
174 0 : ImplMakeUnique();
175 0 : mpImplLineInfo->mnDashCount = nDashCount;
176 0 : }
177 :
178 : // -----------------------------------------------------------------------
179 :
180 0 : void LineInfo::SetDashLen( long nDashLen )
181 : {
182 : DBG_CHKTHIS( LineInfo, NULL );
183 0 : ImplMakeUnique();
184 0 : mpImplLineInfo->mnDashLen = nDashLen;
185 0 : }
186 :
187 : // -----------------------------------------------------------------------
188 :
189 0 : void LineInfo::SetDotCount( sal_uInt16 nDotCount )
190 : {
191 : DBG_CHKTHIS( LineInfo, NULL );
192 0 : ImplMakeUnique();
193 0 : mpImplLineInfo->mnDotCount = nDotCount;
194 0 : }
195 :
196 : // -----------------------------------------------------------------------
197 :
198 0 : void LineInfo::SetDotLen( long nDotLen )
199 : {
200 : DBG_CHKTHIS( LineInfo, NULL );
201 0 : ImplMakeUnique();
202 0 : mpImplLineInfo->mnDotLen = nDotLen;
203 0 : }
204 :
205 : // -----------------------------------------------------------------------
206 :
207 0 : void LineInfo::SetDistance( long nDistance )
208 : {
209 : DBG_CHKTHIS( LineInfo, NULL );
210 0 : ImplMakeUnique();
211 0 : mpImplLineInfo->mnDistance = nDistance;
212 0 : }
213 :
214 : // -----------------------------------------------------------------------
215 :
216 5 : void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
217 : {
218 : DBG_CHKTHIS( LineInfo, NULL );
219 :
220 5 : if(eLineJoin != mpImplLineInfo->meLineJoin)
221 : {
222 0 : ImplMakeUnique();
223 0 : mpImplLineInfo->meLineJoin = eLineJoin;
224 : }
225 5 : }
226 :
227 : // -----------------------------------------------------------------------
228 :
229 5 : void LineInfo::SetLineCap(com::sun::star::drawing::LineCap eLineCap)
230 : {
231 : DBG_CHKTHIS( LineInfo, NULL );
232 5 : if(eLineCap != mpImplLineInfo->meLineCap)
233 : {
234 0 : ImplMakeUnique();
235 0 : mpImplLineInfo->meLineCap = eLineCap;
236 : }
237 5 : }
238 :
239 : // -----------------------------------------------------------------------
240 :
241 0 : sal_Bool LineInfo::IsDefault() const
242 : {
243 0 : return( !mpImplLineInfo->mnWidth
244 : && ( LINE_SOLID == mpImplLineInfo->meStyle )
245 0 : && ( com::sun::star::drawing::LineCap_BUTT == mpImplLineInfo->meLineCap));
246 : }
247 :
248 : // -----------------------------------------------------------------------
249 :
250 0 : SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
251 : {
252 0 : VersionCompat aCompat( rIStm, STREAM_READ );
253 0 : sal_uInt16 nTmp16(0);
254 0 : sal_Int32 nTmp32(0);
255 :
256 : //#fdo39428 SvStream no longer supports operator>>(long&)
257 0 : rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
258 0 : rIStm >> nTmp32;
259 0 : rImplLineInfo.mnWidth = nTmp32;
260 :
261 0 : if( aCompat.GetVersion() >= 2 )
262 : {
263 : // version 2
264 0 : rIStm >> rImplLineInfo.mnDashCount >> nTmp32;
265 0 : rImplLineInfo.mnDashLen = nTmp32;
266 0 : rIStm >> rImplLineInfo.mnDotCount >> nTmp32;
267 0 : rImplLineInfo.mnDotLen = nTmp32;
268 0 : rIStm >> nTmp32;
269 0 : rImplLineInfo.mnDistance = nTmp32;
270 : }
271 :
272 0 : if( aCompat.GetVersion() >= 3 )
273 : {
274 : // version 3
275 0 : rIStm >> nTmp16; rImplLineInfo.meLineJoin = (basegfx::B2DLineJoin) nTmp16;
276 : }
277 :
278 0 : if( aCompat.GetVersion() >= 4 )
279 : {
280 : // version 4
281 0 : rIStm >> nTmp16; rImplLineInfo.meLineCap = (com::sun::star::drawing::LineCap) nTmp16;
282 : }
283 :
284 0 : return rIStm;
285 : }
286 :
287 : // -----------------------------------------------------------------------
288 :
289 276 : SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
290 : {
291 276 : VersionCompat aCompat( rOStm, STREAM_WRITE, 4 );
292 :
293 : //#fdo39428 SvStream no longer supports operator<<(long)
294 : // version 1
295 276 : rOStm << (sal_uInt16) rImplLineInfo.meStyle << sal::static_int_cast<sal_Int32>(rImplLineInfo.mnWidth);
296 :
297 : // since version2
298 276 : rOStm << rImplLineInfo.mnDashCount << sal::static_int_cast<sal_Int32>(rImplLineInfo.mnDashLen);
299 276 : rOStm << rImplLineInfo.mnDotCount << sal::static_int_cast<sal_Int32>(rImplLineInfo.mnDotLen);
300 276 : rOStm << sal::static_int_cast<sal_Int32>(rImplLineInfo.mnDistance);
301 :
302 : // since version3
303 276 : rOStm << (sal_uInt16) rImplLineInfo.meLineJoin;
304 :
305 : // since version4
306 276 : rOStm << (sal_uInt16) rImplLineInfo.meLineCap;
307 :
308 276 : return rOStm;
309 : }
310 :
311 : // -----------------------------------------------------------------------
312 :
313 0 : SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
314 : {
315 0 : rLineInfo.ImplMakeUnique();
316 0 : return( rIStm >> *rLineInfo.mpImplLineInfo );
317 : }
318 :
319 : // -----------------------------------------------------------------------
320 :
321 276 : SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
322 : {
323 276 : return( rOStm << *rLineInfo.mpImplLineInfo );
324 : }
325 :
326 : // -----------------------------------------------------------------------
327 :
328 0 : void LineInfo::applyToB2DPolyPolygon(
329 : basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
330 : basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
331 : {
332 0 : o_rFillPolyPolygon.clear();
333 :
334 0 : if(io_rLinePolyPolygon.count())
335 : {
336 0 : if(LINE_DASH == GetStyle())
337 : {
338 0 : ::std::vector< double > fDotDashArray;
339 0 : const double fDashLen(GetDashLen());
340 0 : const double fDotLen(GetDotLen());
341 0 : const double fDistance(GetDistance());
342 :
343 0 : for(sal_uInt16 a(0); a < GetDashCount(); a++)
344 : {
345 0 : fDotDashArray.push_back(fDashLen);
346 0 : fDotDashArray.push_back(fDistance);
347 : }
348 :
349 0 : for(sal_uInt16 b(0); b < GetDotCount(); b++)
350 : {
351 0 : fDotDashArray.push_back(fDotLen);
352 0 : fDotDashArray.push_back(fDistance);
353 : }
354 :
355 0 : const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
356 :
357 0 : if(fAccumulated > 0.0)
358 : {
359 0 : basegfx::B2DPolyPolygon aResult;
360 :
361 0 : for(sal_uInt32 c(0); c < io_rLinePolyPolygon.count(); c++)
362 : {
363 0 : basegfx::B2DPolyPolygon aLineTraget;
364 : basegfx::tools::applyLineDashing(
365 : io_rLinePolyPolygon.getB2DPolygon(c),
366 : fDotDashArray,
367 0 : &aLineTraget);
368 0 : aResult.append(aLineTraget);
369 0 : }
370 :
371 0 : io_rLinePolyPolygon = aResult;
372 0 : }
373 : }
374 :
375 0 : if(GetWidth() > 1 && io_rLinePolyPolygon.count())
376 : {
377 0 : const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
378 :
379 0 : for(sal_uInt32 a(0); a < io_rLinePolyPolygon.count(); a++)
380 : {
381 : o_rFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
382 : io_rLinePolyPolygon.getB2DPolygon(a),
383 : fHalfLineWidth,
384 : GetLineJoin(),
385 0 : GetLineCap()));
386 : }
387 :
388 0 : io_rLinePolyPolygon.clear();
389 : }
390 : }
391 0 : }
392 :
393 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|