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