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