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