xref: /trunk/main/vcl/source/gdi/lineinfo.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 #include <tools/stream.hxx>
31 #include <tools/vcompat.hxx>
32 #include <tools/debug.hxx>
33 #include <vcl/lineinfo.hxx>
34 #include <basegfx/polygon/b2dpolypolygon.hxx>
35 #include <basegfx/polygon/b2dpolygontools.hxx>
36 #include <basegfx/polygon/b2dlinegeometry.hxx>
37 #include <numeric>
38 
39 DBG_NAME( LineInfo )
40 
41 // ----------------
42 // - ImplLineInfo -
43 // ----------------
44 
45 ImplLineInfo::ImplLineInfo() :
46     mnRefCount	( 1 ),
47     meStyle		( LINE_SOLID ),
48 	mnWidth		( 0 ),
49 	mnDashCount	( 0 ),
50 	mnDashLen	( 0 ),
51 	mnDotCount	( 0 ),
52 	mnDotLen	( 0 ),
53 	mnDistance	( 0 ),
54     meLineJoin  ( basegfx::B2DLINEJOIN_ROUND )
55 {
56 }
57 
58 // -----------------------------------------------------------------------
59 
60 ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
61 	mnRefCount	( 1 ),
62     meStyle		( rImplLineInfo.meStyle ),
63 	mnWidth		( rImplLineInfo.mnWidth ),
64 	mnDashCount	( rImplLineInfo.mnDashCount	),
65 	mnDashLen	( rImplLineInfo.mnDashLen ),
66 	mnDotCount	( rImplLineInfo.mnDotCount ),
67 	mnDotLen	( rImplLineInfo.mnDotLen ),
68 	mnDistance	( rImplLineInfo.mnDistance ),
69     meLineJoin  ( rImplLineInfo.meLineJoin )
70 {
71 }
72 
73 // -----------------------------------------------------------------------
74 
75 inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
76 {
77 	return(meStyle == rB.meStyle
78 		&& mnWidth == rB.mnWidth
79 		&& mnDashCount == rB.mnDashCount
80 		&& mnDashLen == rB.mnDashLen
81 		&& mnDotCount == rB.mnDotCount
82 		&& mnDotLen == rB.mnDotLen
83 		&& mnDistance == rB.mnDistance
84 		&& meLineJoin == rB.meLineJoin);
85 }
86 
87 // ------------
88 // - LineInfo -
89 // ------------
90 
91 LineInfo::LineInfo( LineStyle eStyle, long nWidth )
92 {
93     DBG_CTOR( LineInfo, NULL );
94     mpImplLineInfo = new ImplLineInfo;
95     mpImplLineInfo->meStyle = eStyle;
96     mpImplLineInfo->mnWidth = nWidth;
97 }
98 
99 // -----------------------------------------------------------------------
100 
101 LineInfo::LineInfo( const LineInfo& rLineInfo )
102 {
103     DBG_CTOR( LineInfo, NULL );
104     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
105     mpImplLineInfo = rLineInfo.mpImplLineInfo;
106     mpImplLineInfo->mnRefCount++;
107 }
108 
109 // -----------------------------------------------------------------------
110 
111 LineInfo::~LineInfo()
112 {
113     DBG_DTOR( LineInfo, NULL );
114     if( !( --mpImplLineInfo->mnRefCount ) )
115         delete mpImplLineInfo;
116 }
117 
118 // -----------------------------------------------------------------------
119 
120 LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
121 {
122     DBG_CHKTHIS( LineInfo, NULL );
123     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
124 
125     rLineInfo.mpImplLineInfo->mnRefCount++;
126 
127     if( !( --mpImplLineInfo->mnRefCount ) )
128         delete mpImplLineInfo;
129 
130 	mpImplLineInfo = rLineInfo.mpImplLineInfo;
131     return *this;
132 }
133 
134 // -----------------------------------------------------------------------
135 
136 sal_Bool LineInfo::operator==( const LineInfo& rLineInfo ) const
137 {
138     DBG_CHKTHIS( LineInfo, NULL );
139     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
140 
141     return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
142            *mpImplLineInfo == *rLineInfo.mpImplLineInfo );
143 }
144 
145 // -----------------------------------------------------------------------
146 
147 void LineInfo::ImplMakeUnique()
148 {
149     if( mpImplLineInfo->mnRefCount != 1 )
150 	{
151 		if( mpImplLineInfo->mnRefCount )
152 			mpImplLineInfo->mnRefCount--;
153 
154         mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
155 	}
156 }
157 
158 // -----------------------------------------------------------------------
159 
160 void LineInfo::SetStyle( LineStyle eStyle )
161 {
162     DBG_CHKTHIS( LineInfo, NULL );
163     ImplMakeUnique();
164     mpImplLineInfo->meStyle = eStyle;
165 }
166 
167 // -----------------------------------------------------------------------
168 
169 void LineInfo::SetWidth( long nWidth )
170 {
171     DBG_CHKTHIS( LineInfo, NULL );
172     ImplMakeUnique();
173     mpImplLineInfo->mnWidth = nWidth;
174 }
175 
176 // -----------------------------------------------------------------------
177 
178 void LineInfo::SetDashCount( sal_uInt16 nDashCount )
179 {
180 	DBG_CHKTHIS( LineInfo, NULL );
181 	ImplMakeUnique();
182 	mpImplLineInfo->mnDashCount = nDashCount;
183 }
184 
185 // -----------------------------------------------------------------------
186 
187 void LineInfo::SetDashLen( long nDashLen )
188 {
189 	DBG_CHKTHIS( LineInfo, NULL );
190 	ImplMakeUnique();
191 	mpImplLineInfo->mnDashLen = nDashLen;
192 }
193 
194 // -----------------------------------------------------------------------
195 
196 void LineInfo::SetDotCount( sal_uInt16 nDotCount )
197 {
198 	DBG_CHKTHIS( LineInfo, NULL );
199 	ImplMakeUnique();
200 	mpImplLineInfo->mnDotCount = nDotCount;
201 }
202 
203 // -----------------------------------------------------------------------
204 
205 void LineInfo::SetDotLen( long nDotLen )
206 {
207 	DBG_CHKTHIS( LineInfo, NULL );
208 	ImplMakeUnique();
209 	mpImplLineInfo->mnDotLen = nDotLen;
210 }
211 
212 // -----------------------------------------------------------------------
213 
214 void LineInfo::SetDistance( long nDistance )
215 {
216 	DBG_CHKTHIS( LineInfo, NULL );
217 	ImplMakeUnique();
218 	mpImplLineInfo->mnDistance = nDistance;
219 }
220 
221 // -----------------------------------------------------------------------
222 
223 void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
224 {
225 	DBG_CHKTHIS( LineInfo, NULL );
226 
227     if(eLineJoin != mpImplLineInfo->meLineJoin)
228     {
229     	ImplMakeUnique();
230         mpImplLineInfo->meLineJoin = eLineJoin;
231     }
232 }
233 
234 // -----------------------------------------------------------------------
235 
236 SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
237 {
238     VersionCompat	aCompat( rIStm, STREAM_READ );
239     sal_uInt16			nTmp16;
240 
241     rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
242     rIStm >> rImplLineInfo.mnWidth;
243 
244 	if( aCompat.GetVersion() >= 2 )
245 	{
246 		// version 2
247 		rIStm >> rImplLineInfo.mnDashCount >> rImplLineInfo.mnDashLen;
248 		rIStm >> rImplLineInfo.mnDotCount >> rImplLineInfo.mnDotLen;
249 		rIStm >> rImplLineInfo.mnDistance;
250 	}
251 
252 	if( aCompat.GetVersion() >= 3 )
253 	{
254 		// version 3
255         rIStm >> nTmp16; rImplLineInfo.meLineJoin = (basegfx::B2DLineJoin) nTmp16;
256     }
257 
258     return rIStm;
259 }
260 
261 // -----------------------------------------------------------------------
262 
263 SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
264 {
265     VersionCompat aCompat( rOStm, STREAM_WRITE, 3 );
266 
267     // version 1
268 	rOStm << (sal_uInt16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
269 
270 	// since version2
271 	rOStm << rImplLineInfo.mnDashCount << rImplLineInfo.mnDashLen;
272 	rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
273 	rOStm << rImplLineInfo.mnDistance;
274 
275 	// since version3
276 	rOStm << (sal_uInt16) rImplLineInfo.meLineJoin;
277 
278     return rOStm;
279 }
280 
281 // -----------------------------------------------------------------------
282 
283 SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
284 {
285     rLineInfo.ImplMakeUnique();
286     return( rIStm >> *rLineInfo.mpImplLineInfo );
287 }
288 
289 // -----------------------------------------------------------------------
290 
291 SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
292 {
293     return( rOStm << *rLineInfo.mpImplLineInfo );
294 }
295 
296 // -----------------------------------------------------------------------
297 
298 bool LineInfo::isDashDotOrFatLineUsed() const
299 {
300 	return (LINE_DASH == GetStyle() || GetWidth() > 1);
301 }
302 
303 // -----------------------------------------------------------------------
304 
305 void LineInfo::applyToB2DPolyPolygon(
306 	basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
307 	basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
308 {
309 	o_rFillPolyPolygon.clear();
310 
311 	if(io_rLinePolyPolygon.count())
312 	{
313 		if(LINE_DASH == GetStyle())
314 		{
315 			::std::vector< double > fDotDashArray;
316 			const double fDashLen(GetDashLen());
317 			const double fDotLen(GetDotLen());
318 			const double fDistance(GetDistance());
319 
320 			for(sal_uInt16 a(0); a < GetDashCount(); a++)
321 			{
322 				fDotDashArray.push_back(fDashLen);
323 				fDotDashArray.push_back(fDistance);
324 			}
325 
326 			for(sal_uInt16 b(0); b < GetDotCount(); b++)
327 			{
328 				fDotDashArray.push_back(fDotLen);
329 				fDotDashArray.push_back(fDistance);
330 			}
331 
332 			const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
333 
334 			if(fAccumulated > 0.0)
335 			{
336 				basegfx::B2DPolyPolygon aResult;
337 
338 				for(sal_uInt32 c(0); c < io_rLinePolyPolygon.count(); c++)
339 				{
340 					basegfx::B2DPolyPolygon aLineTraget;
341 					basegfx::tools::applyLineDashing(
342 						io_rLinePolyPolygon.getB2DPolygon(c),
343 						fDotDashArray,
344 						&aLineTraget);
345 					aResult.append(aLineTraget);
346 				}
347 
348 				io_rLinePolyPolygon = aResult;
349 			}
350 		}
351 
352 		if(GetWidth() > 1 && io_rLinePolyPolygon.count())
353 		{
354 			const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
355 
356 			for(sal_uInt32 a(0); a < io_rLinePolyPolygon.count(); a++)
357 			{
358 				o_rFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
359 					io_rLinePolyPolygon.getB2DPolygon(a),
360 					fHalfLineWidth,
361 					GetLineJoin()));
362 			}
363 
364 			io_rLinePolyPolygon.clear();
365 		}
366 	}
367 }
368 
369 // -----------------------------------------------------------------------
370