1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <tools/stream.hxx>
27 #include <tools/vcompat.hxx>
28 #include <tools/debug.hxx>
29 #include <vcl/lineinfo.hxx>
30 #include <basegfx/polygon/b2dpolypolygon.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <basegfx/polygon/b2dlinegeometry.hxx>
33 #include <numeric>
34
DBG_NAME(LineInfo)35 DBG_NAME( LineInfo )
36
37 // ----------------
38 // - ImplLineInfo -
39 // ----------------
40
41 ImplLineInfo::ImplLineInfo() :
42 mnRefCount ( 1 ),
43 meStyle ( LINE_SOLID ),
44 mnWidth ( 0 ),
45 mnDashCount ( 0 ),
46 mnDashLen ( 0 ),
47 mnDotCount ( 0 ),
48 mnDotLen ( 0 ),
49 mnDistance ( 0 ),
50 meLineJoin ( basegfx::B2DLINEJOIN_ROUND ),
51 meLineCap ( com::sun::star::drawing::LineCap_BUTT )
52 {
53 }
54
55 // -----------------------------------------------------------------------
56
ImplLineInfo(const ImplLineInfo & rImplLineInfo)57 ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
58 mnRefCount ( 1 ),
59 meStyle ( rImplLineInfo.meStyle ),
60 mnWidth ( rImplLineInfo.mnWidth ),
61 mnDashCount ( rImplLineInfo.mnDashCount ),
62 mnDashLen ( rImplLineInfo.mnDashLen ),
63 mnDotCount ( rImplLineInfo.mnDotCount ),
64 mnDotLen ( rImplLineInfo.mnDotLen ),
65 mnDistance ( rImplLineInfo.mnDistance ),
66 meLineJoin ( rImplLineInfo.meLineJoin ),
67 meLineCap ( rImplLineInfo.meLineCap )
68 {
69 }
70
71 // -----------------------------------------------------------------------
72
operator ==(const ImplLineInfo & rB) const73 inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
74 {
75 return(meStyle == rB.meStyle
76 && mnWidth == rB.mnWidth
77 && mnDashCount == rB.mnDashCount
78 && mnDashLen == rB.mnDashLen
79 && mnDotCount == rB.mnDotCount
80 && mnDotLen == rB.mnDotLen
81 && mnDistance == rB.mnDistance
82 && meLineJoin == rB.meLineJoin
83 && meLineCap == rB.meLineCap);
84 }
85
86 // ------------
87 // - LineInfo -
88 // ------------
89
LineInfo(LineStyle eStyle,long nWidth)90 LineInfo::LineInfo( LineStyle eStyle, long nWidth )
91 {
92 DBG_CTOR( LineInfo, NULL );
93 mpImplLineInfo = new ImplLineInfo;
94 mpImplLineInfo->meStyle = eStyle;
95 mpImplLineInfo->mnWidth = nWidth;
96 }
97
98 // -----------------------------------------------------------------------
99
LineInfo(const LineInfo & rLineInfo)100 LineInfo::LineInfo( const LineInfo& rLineInfo )
101 {
102 DBG_CTOR( LineInfo, NULL );
103 DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
104 mpImplLineInfo = rLineInfo.mpImplLineInfo;
105 mpImplLineInfo->mnRefCount++;
106 }
107
108 // -----------------------------------------------------------------------
109
~LineInfo()110 LineInfo::~LineInfo()
111 {
112 DBG_DTOR( LineInfo, NULL );
113 if( !( --mpImplLineInfo->mnRefCount ) )
114 delete mpImplLineInfo;
115 }
116
117 // -----------------------------------------------------------------------
118
operator =(const LineInfo & rLineInfo)119 LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
120 {
121 DBG_CHKTHIS( LineInfo, NULL );
122 DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
123
124 rLineInfo.mpImplLineInfo->mnRefCount++;
125
126 if( !( --mpImplLineInfo->mnRefCount ) )
127 delete mpImplLineInfo;
128
129 mpImplLineInfo = rLineInfo.mpImplLineInfo;
130 return *this;
131 }
132
133 // -----------------------------------------------------------------------
134
operator ==(const LineInfo & rLineInfo) const135 sal_Bool LineInfo::operator==( const LineInfo& rLineInfo ) const
136 {
137 DBG_CHKTHIS( LineInfo, NULL );
138 DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
139
140 return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
141 *mpImplLineInfo == *rLineInfo.mpImplLineInfo );
142 }
143
144 // -----------------------------------------------------------------------
145
ImplMakeUnique()146 void LineInfo::ImplMakeUnique()
147 {
148 if( mpImplLineInfo->mnRefCount != 1 )
149 {
150 if( mpImplLineInfo->mnRefCount )
151 mpImplLineInfo->mnRefCount--;
152
153 mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
154 }
155 }
156
157 // -----------------------------------------------------------------------
158
SetStyle(LineStyle eStyle)159 void LineInfo::SetStyle( LineStyle eStyle )
160 {
161 DBG_CHKTHIS( LineInfo, NULL );
162 ImplMakeUnique();
163 mpImplLineInfo->meStyle = eStyle;
164 }
165
166 // -----------------------------------------------------------------------
167
SetWidth(long nWidth)168 void LineInfo::SetWidth( long nWidth )
169 {
170 DBG_CHKTHIS( LineInfo, NULL );
171 ImplMakeUnique();
172 mpImplLineInfo->mnWidth = nWidth;
173 }
174
175 // -----------------------------------------------------------------------
176
SetDashCount(sal_uInt16 nDashCount)177 void LineInfo::SetDashCount( sal_uInt16 nDashCount )
178 {
179 DBG_CHKTHIS( LineInfo, NULL );
180 ImplMakeUnique();
181 mpImplLineInfo->mnDashCount = nDashCount;
182 }
183
184 // -----------------------------------------------------------------------
185
SetDashLen(long nDashLen)186 void LineInfo::SetDashLen( long nDashLen )
187 {
188 DBG_CHKTHIS( LineInfo, NULL );
189 ImplMakeUnique();
190 mpImplLineInfo->mnDashLen = nDashLen;
191 }
192
193 // -----------------------------------------------------------------------
194
SetDotCount(sal_uInt16 nDotCount)195 void LineInfo::SetDotCount( sal_uInt16 nDotCount )
196 {
197 DBG_CHKTHIS( LineInfo, NULL );
198 ImplMakeUnique();
199 mpImplLineInfo->mnDotCount = nDotCount;
200 }
201
202 // -----------------------------------------------------------------------
203
SetDotLen(long nDotLen)204 void LineInfo::SetDotLen( long nDotLen )
205 {
206 DBG_CHKTHIS( LineInfo, NULL );
207 ImplMakeUnique();
208 mpImplLineInfo->mnDotLen = nDotLen;
209 }
210
211 // -----------------------------------------------------------------------
212
SetDistance(long nDistance)213 void LineInfo::SetDistance( long nDistance )
214 {
215 DBG_CHKTHIS( LineInfo, NULL );
216 ImplMakeUnique();
217 mpImplLineInfo->mnDistance = nDistance;
218 }
219
220 // -----------------------------------------------------------------------
221
SetLineJoin(basegfx::B2DLineJoin eLineJoin)222 void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
223 {
224 DBG_CHKTHIS( LineInfo, NULL );
225
226 if(eLineJoin != mpImplLineInfo->meLineJoin)
227 {
228 ImplMakeUnique();
229 mpImplLineInfo->meLineJoin = eLineJoin;
230 }
231 }
232
233 // -----------------------------------------------------------------------
234
SetLineCap(com::sun::star::drawing::LineCap eLineCap)235 void LineInfo::SetLineCap(com::sun::star::drawing::LineCap eLineCap)
236 {
237 DBG_CHKTHIS( LineInfo, NULL );
238
239 if(eLineCap != mpImplLineInfo->meLineCap)
240 {
241 ImplMakeUnique();
242 mpImplLineInfo->meLineCap = eLineCap;
243 }
244 }
245
246 // -----------------------------------------------------------------------
247
IsDefault() const248 sal_Bool LineInfo::IsDefault() const
249 {
250 return( !mpImplLineInfo->mnWidth
251 && ( LINE_SOLID == mpImplLineInfo->meStyle )
252 && ( com::sun::star::drawing::LineCap_BUTT == mpImplLineInfo->meLineCap));
253 }
254
255 // -----------------------------------------------------------------------
256
operator >>(SvStream & rIStm,ImplLineInfo & rImplLineInfo)257 SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
258 {
259 VersionCompat aCompat( rIStm, STREAM_READ );
260 sal_uInt16 nTmp16;
261
262 rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
263 rIStm >> rImplLineInfo.mnWidth;
264
265 if( aCompat.GetVersion() >= 2 )
266 {
267 // version 2
268 rIStm >> rImplLineInfo.mnDashCount >> rImplLineInfo.mnDashLen;
269 rIStm >> rImplLineInfo.mnDotCount >> rImplLineInfo.mnDotLen;
270 rIStm >> rImplLineInfo.mnDistance;
271 }
272
273 if( aCompat.GetVersion() >= 3 )
274 {
275 // version 3
276 rIStm >> nTmp16; rImplLineInfo.meLineJoin = (basegfx::B2DLineJoin) nTmp16;
277 }
278
279 if( aCompat.GetVersion() >= 4 )
280 {
281 // version 4
282 rIStm >> nTmp16; rImplLineInfo.meLineCap = (com::sun::star::drawing::LineCap) nTmp16;
283 }
284
285 return rIStm;
286 }
287
288 // -----------------------------------------------------------------------
289
operator <<(SvStream & rOStm,const ImplLineInfo & rImplLineInfo)290 SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
291 {
292 VersionCompat aCompat( rOStm, STREAM_WRITE, 4 );
293
294 // version 1
295 rOStm << (sal_uInt16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
296
297 // since version2
298 rOStm << rImplLineInfo.mnDashCount << rImplLineInfo.mnDashLen;
299 rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
300 rOStm << rImplLineInfo.mnDistance;
301
302 // since version3
303 rOStm << (sal_uInt16) rImplLineInfo.meLineJoin;
304
305 // since version4
306 rOStm << (sal_uInt16) rImplLineInfo.meLineCap;
307
308 return rOStm;
309 }
310
311 // -----------------------------------------------------------------------
312
operator >>(SvStream & rIStm,LineInfo & rLineInfo)313 SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
314 {
315 rLineInfo.ImplMakeUnique();
316 return( rIStm >> *rLineInfo.mpImplLineInfo );
317 }
318
319 // -----------------------------------------------------------------------
320
operator <<(SvStream & rOStm,const LineInfo & rLineInfo)321 SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
322 {
323 return( rOStm << *rLineInfo.mpImplLineInfo );
324 }
325
326 // -----------------------------------------------------------------------
327
isDashDotOrFatLineUsed() const328 bool LineInfo::isDashDotOrFatLineUsed() const
329 {
330 return (LINE_DASH == GetStyle() || GetWidth() > 1);
331 }
332
333 // -----------------------------------------------------------------------
334
applyToB2DPolyPolygon(basegfx::B2DPolyPolygon & io_rLinePolyPolygon,basegfx::B2DPolyPolygon & o_rFillPolyPolygon) const335 void LineInfo::applyToB2DPolyPolygon(
336 basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
337 basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
338 {
339 o_rFillPolyPolygon.clear();
340
341 if(io_rLinePolyPolygon.count())
342 {
343 if(LINE_DASH == GetStyle())
344 {
345 ::std::vector< double > fDotDashArray;
346 const double fDashLen(GetDashLen());
347 const double fDotLen(GetDotLen());
348 const double fDistance(GetDistance());
349
350 for(sal_uInt16 a(0); a < GetDashCount(); a++)
351 {
352 fDotDashArray.push_back(fDashLen);
353 fDotDashArray.push_back(fDistance);
354 }
355
356 for(sal_uInt16 b(0); b < GetDotCount(); b++)
357 {
358 fDotDashArray.push_back(fDotLen);
359 fDotDashArray.push_back(fDistance);
360 }
361
362 const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
363
364 if(fAccumulated > 0.0)
365 {
366 basegfx::B2DPolyPolygon aResult;
367
368 for(sal_uInt32 c(0); c < io_rLinePolyPolygon.count(); c++)
369 {
370 basegfx::B2DPolyPolygon aLineTraget;
371 basegfx::tools::applyLineDashing(
372 io_rLinePolyPolygon.getB2DPolygon(c),
373 fDotDashArray,
374 &aLineTraget);
375 aResult.append(aLineTraget);
376 }
377
378 io_rLinePolyPolygon = aResult;
379 }
380 }
381
382 if(GetWidth() > 1 && io_rLinePolyPolygon.count())
383 {
384 const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
385
386 for(sal_uInt32 a(0); a < io_rLinePolyPolygon.count(); a++)
387 {
388 o_rFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
389 io_rLinePolyPolygon.getB2DPolygon(a),
390 fHalfLineWidth,
391 GetLineJoin(),
392 GetLineCap()));
393 }
394
395 io_rLinePolyPolygon.clear();
396 }
397 }
398 }
399
400 // -----------------------------------------------------------------------
401