xref: /aoo41x/main/vcl/source/gdi/lineinfo.cxx (revision 9f62ea84)
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 
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 {
52 }
53 
54 // -----------------------------------------------------------------------
55 
56 ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
57 	mnRefCount	( 1 ),
58     meStyle		( rImplLineInfo.meStyle ),
59 	mnWidth		( rImplLineInfo.mnWidth ),
60 	mnDashCount	( rImplLineInfo.mnDashCount	),
61 	mnDashLen	( rImplLineInfo.mnDashLen ),
62 	mnDotCount	( rImplLineInfo.mnDotCount ),
63 	mnDotLen	( rImplLineInfo.mnDotLen ),
64 	mnDistance	( rImplLineInfo.mnDistance ),
65     meLineJoin  ( rImplLineInfo.meLineJoin )
66 {
67 }
68 
69 // -----------------------------------------------------------------------
70 
71 inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
72 {
73 	return(meStyle == rB.meStyle
74 		&& mnWidth == rB.mnWidth
75 		&& mnDashCount == rB.mnDashCount
76 		&& mnDashLen == rB.mnDashLen
77 		&& mnDotCount == rB.mnDotCount
78 		&& mnDotLen == rB.mnDotLen
79 		&& mnDistance == rB.mnDistance
80 		&& meLineJoin == rB.meLineJoin);
81 }
82 
83 // ------------
84 // - LineInfo -
85 // ------------
86 
87 LineInfo::LineInfo( LineStyle eStyle, long nWidth )
88 {
89     DBG_CTOR( LineInfo, NULL );
90     mpImplLineInfo = new ImplLineInfo;
91     mpImplLineInfo->meStyle = eStyle;
92     mpImplLineInfo->mnWidth = nWidth;
93 }
94 
95 // -----------------------------------------------------------------------
96 
97 LineInfo::LineInfo( const LineInfo& rLineInfo )
98 {
99     DBG_CTOR( LineInfo, NULL );
100     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
101     mpImplLineInfo = rLineInfo.mpImplLineInfo;
102     mpImplLineInfo->mnRefCount++;
103 }
104 
105 // -----------------------------------------------------------------------
106 
107 LineInfo::~LineInfo()
108 {
109     DBG_DTOR( LineInfo, NULL );
110     if( !( --mpImplLineInfo->mnRefCount ) )
111         delete mpImplLineInfo;
112 }
113 
114 // -----------------------------------------------------------------------
115 
116 LineInfo& LineInfo::operator=( const LineInfo& rLineInfo )
117 {
118     DBG_CHKTHIS( LineInfo, NULL );
119     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
120 
121     rLineInfo.mpImplLineInfo->mnRefCount++;
122 
123     if( !( --mpImplLineInfo->mnRefCount ) )
124         delete mpImplLineInfo;
125 
126 	mpImplLineInfo = rLineInfo.mpImplLineInfo;
127     return *this;
128 }
129 
130 // -----------------------------------------------------------------------
131 
132 sal_Bool LineInfo::operator==( const LineInfo& rLineInfo ) const
133 {
134     DBG_CHKTHIS( LineInfo, NULL );
135     DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
136 
137     return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
138            *mpImplLineInfo == *rLineInfo.mpImplLineInfo );
139 }
140 
141 // -----------------------------------------------------------------------
142 
143 void LineInfo::ImplMakeUnique()
144 {
145     if( mpImplLineInfo->mnRefCount != 1 )
146 	{
147 		if( mpImplLineInfo->mnRefCount )
148 			mpImplLineInfo->mnRefCount--;
149 
150         mpImplLineInfo = new ImplLineInfo( *mpImplLineInfo );
151 	}
152 }
153 
154 // -----------------------------------------------------------------------
155 
156 void LineInfo::SetStyle( LineStyle eStyle )
157 {
158     DBG_CHKTHIS( LineInfo, NULL );
159     ImplMakeUnique();
160     mpImplLineInfo->meStyle = eStyle;
161 }
162 
163 // -----------------------------------------------------------------------
164 
165 void LineInfo::SetWidth( long nWidth )
166 {
167     DBG_CHKTHIS( LineInfo, NULL );
168     ImplMakeUnique();
169     mpImplLineInfo->mnWidth = nWidth;
170 }
171 
172 // -----------------------------------------------------------------------
173 
174 void LineInfo::SetDashCount( sal_uInt16 nDashCount )
175 {
176 	DBG_CHKTHIS( LineInfo, NULL );
177 	ImplMakeUnique();
178 	mpImplLineInfo->mnDashCount = nDashCount;
179 }
180 
181 // -----------------------------------------------------------------------
182 
183 void LineInfo::SetDashLen( long nDashLen )
184 {
185 	DBG_CHKTHIS( LineInfo, NULL );
186 	ImplMakeUnique();
187 	mpImplLineInfo->mnDashLen = nDashLen;
188 }
189 
190 // -----------------------------------------------------------------------
191 
192 void LineInfo::SetDotCount( sal_uInt16 nDotCount )
193 {
194 	DBG_CHKTHIS( LineInfo, NULL );
195 	ImplMakeUnique();
196 	mpImplLineInfo->mnDotCount = nDotCount;
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 void LineInfo::SetDotLen( long nDotLen )
202 {
203 	DBG_CHKTHIS( LineInfo, NULL );
204 	ImplMakeUnique();
205 	mpImplLineInfo->mnDotLen = nDotLen;
206 }
207 
208 // -----------------------------------------------------------------------
209 
210 void LineInfo::SetDistance( long nDistance )
211 {
212 	DBG_CHKTHIS( LineInfo, NULL );
213 	ImplMakeUnique();
214 	mpImplLineInfo->mnDistance = nDistance;
215 }
216 
217 // -----------------------------------------------------------------------
218 
219 void LineInfo::SetLineJoin(basegfx::B2DLineJoin eLineJoin)
220 {
221 	DBG_CHKTHIS( LineInfo, NULL );
222 
223     if(eLineJoin != mpImplLineInfo->meLineJoin)
224     {
225     	ImplMakeUnique();
226         mpImplLineInfo->meLineJoin = eLineJoin;
227     }
228 }
229 
230 // -----------------------------------------------------------------------
231 
232 SvStream& operator>>( SvStream& rIStm, ImplLineInfo& rImplLineInfo )
233 {
234     VersionCompat	aCompat( rIStm, STREAM_READ );
235     sal_uInt16			nTmp16;
236 
237     rIStm >> nTmp16; rImplLineInfo.meStyle = (LineStyle) nTmp16;
238     rIStm >> rImplLineInfo.mnWidth;
239 
240 	if( aCompat.GetVersion() >= 2 )
241 	{
242 		// version 2
243 		rIStm >> rImplLineInfo.mnDashCount >> rImplLineInfo.mnDashLen;
244 		rIStm >> rImplLineInfo.mnDotCount >> rImplLineInfo.mnDotLen;
245 		rIStm >> rImplLineInfo.mnDistance;
246 	}
247 
248 	if( aCompat.GetVersion() >= 3 )
249 	{
250 		// version 3
251         rIStm >> nTmp16; rImplLineInfo.meLineJoin = (basegfx::B2DLineJoin) nTmp16;
252     }
253 
254     return rIStm;
255 }
256 
257 // -----------------------------------------------------------------------
258 
259 SvStream& operator<<( SvStream& rOStm, const ImplLineInfo& rImplLineInfo )
260 {
261     VersionCompat aCompat( rOStm, STREAM_WRITE, 3 );
262 
263     // version 1
264 	rOStm << (sal_uInt16) rImplLineInfo.meStyle << rImplLineInfo.mnWidth;
265 
266 	// since version2
267 	rOStm << rImplLineInfo.mnDashCount << rImplLineInfo.mnDashLen;
268 	rOStm << rImplLineInfo.mnDotCount << rImplLineInfo.mnDotLen;
269 	rOStm << rImplLineInfo.mnDistance;
270 
271 	// since version3
272 	rOStm << (sal_uInt16) rImplLineInfo.meLineJoin;
273 
274     return rOStm;
275 }
276 
277 // -----------------------------------------------------------------------
278 
279 SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo )
280 {
281     rLineInfo.ImplMakeUnique();
282     return( rIStm >> *rLineInfo.mpImplLineInfo );
283 }
284 
285 // -----------------------------------------------------------------------
286 
287 SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo )
288 {
289     return( rOStm << *rLineInfo.mpImplLineInfo );
290 }
291 
292 // -----------------------------------------------------------------------
293 
294 bool LineInfo::isDashDotOrFatLineUsed() const
295 {
296 	return (LINE_DASH == GetStyle() || GetWidth() > 1);
297 }
298 
299 // -----------------------------------------------------------------------
300 
301 void LineInfo::applyToB2DPolyPolygon(
302 	basegfx::B2DPolyPolygon& io_rLinePolyPolygon,
303 	basegfx::B2DPolyPolygon& o_rFillPolyPolygon) const
304 {
305 	o_rFillPolyPolygon.clear();
306 
307 	if(io_rLinePolyPolygon.count())
308 	{
309 		if(LINE_DASH == GetStyle())
310 		{
311 			::std::vector< double > fDotDashArray;
312 			const double fDashLen(GetDashLen());
313 			const double fDotLen(GetDotLen());
314 			const double fDistance(GetDistance());
315 
316 			for(sal_uInt16 a(0); a < GetDashCount(); a++)
317 			{
318 				fDotDashArray.push_back(fDashLen);
319 				fDotDashArray.push_back(fDistance);
320 			}
321 
322 			for(sal_uInt16 b(0); b < GetDotCount(); b++)
323 			{
324 				fDotDashArray.push_back(fDotLen);
325 				fDotDashArray.push_back(fDistance);
326 			}
327 
328 			const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0));
329 
330 			if(fAccumulated > 0.0)
331 			{
332 				basegfx::B2DPolyPolygon aResult;
333 
334 				for(sal_uInt32 c(0); c < io_rLinePolyPolygon.count(); c++)
335 				{
336 					basegfx::B2DPolyPolygon aLineTraget;
337 					basegfx::tools::applyLineDashing(
338 						io_rLinePolyPolygon.getB2DPolygon(c),
339 						fDotDashArray,
340 						&aLineTraget);
341 					aResult.append(aLineTraget);
342 				}
343 
344 				io_rLinePolyPolygon = aResult;
345 			}
346 		}
347 
348 		if(GetWidth() > 1 && io_rLinePolyPolygon.count())
349 		{
350 			const double fHalfLineWidth((GetWidth() * 0.5) + 0.5);
351 
352 			for(sal_uInt32 a(0); a < io_rLinePolyPolygon.count(); a++)
353 			{
354 				o_rFillPolyPolygon.append(basegfx::tools::createAreaGeometry(
355 					io_rLinePolyPolygon.getB2DPolygon(a),
356 					fHalfLineWidth,
357 					GetLineJoin()));
358 			}
359 
360 			io_rLinePolyPolygon.clear();
361 		}
362 	}
363 }
364 
365 // -----------------------------------------------------------------------
366