xref: /trunk/main/vcl/source/gdi/lineinfo.cxx (revision 5aaf853b)
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