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 meLineCap ( com::sun::star::drawing::LineCap_BUTT ) 52 { 53 } 54 55 // ----------------------------------------------------------------------- 56 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 73 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 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 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 110 LineInfo::~LineInfo() 111 { 112 DBG_DTOR( LineInfo, NULL ); 113 if( !( --mpImplLineInfo->mnRefCount ) ) 114 delete mpImplLineInfo; 115 } 116 117 // ----------------------------------------------------------------------- 118 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 135 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 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 159 void LineInfo::SetStyle( LineStyle eStyle ) 160 { 161 DBG_CHKTHIS( LineInfo, NULL ); 162 ImplMakeUnique(); 163 mpImplLineInfo->meStyle = eStyle; 164 } 165 166 // ----------------------------------------------------------------------- 167 168 void LineInfo::SetWidth( long nWidth ) 169 { 170 DBG_CHKTHIS( LineInfo, NULL ); 171 ImplMakeUnique(); 172 mpImplLineInfo->mnWidth = nWidth; 173 } 174 175 // ----------------------------------------------------------------------- 176 177 void LineInfo::SetDashCount( sal_uInt16 nDashCount ) 178 { 179 DBG_CHKTHIS( LineInfo, NULL ); 180 ImplMakeUnique(); 181 mpImplLineInfo->mnDashCount = nDashCount; 182 } 183 184 // ----------------------------------------------------------------------- 185 186 void LineInfo::SetDashLen( long nDashLen ) 187 { 188 DBG_CHKTHIS( LineInfo, NULL ); 189 ImplMakeUnique(); 190 mpImplLineInfo->mnDashLen = nDashLen; 191 } 192 193 // ----------------------------------------------------------------------- 194 195 void LineInfo::SetDotCount( sal_uInt16 nDotCount ) 196 { 197 DBG_CHKTHIS( LineInfo, NULL ); 198 ImplMakeUnique(); 199 mpImplLineInfo->mnDotCount = nDotCount; 200 } 201 202 // ----------------------------------------------------------------------- 203 204 void LineInfo::SetDotLen( long nDotLen ) 205 { 206 DBG_CHKTHIS( LineInfo, NULL ); 207 ImplMakeUnique(); 208 mpImplLineInfo->mnDotLen = nDotLen; 209 } 210 211 // ----------------------------------------------------------------------- 212 213 void LineInfo::SetDistance( long nDistance ) 214 { 215 DBG_CHKTHIS( LineInfo, NULL ); 216 ImplMakeUnique(); 217 mpImplLineInfo->mnDistance = nDistance; 218 } 219 220 // ----------------------------------------------------------------------- 221 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 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 248 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 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 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 313 SvStream& operator>>( SvStream& rIStm, LineInfo& rLineInfo ) 314 { 315 rLineInfo.ImplMakeUnique(); 316 return( rIStm >> *rLineInfo.mpImplLineInfo ); 317 } 318 319 // ----------------------------------------------------------------------- 320 321 SvStream& operator<<( SvStream& rOStm, const LineInfo& rLineInfo ) 322 { 323 return( rOStm << *rLineInfo.mpImplLineInfo ); 324 } 325 326 // ----------------------------------------------------------------------- 327 328 bool LineInfo::isDashDotOrFatLineUsed() const 329 { 330 return (LINE_DASH == GetStyle() || GetWidth() > 1); 331 } 332 333 // ----------------------------------------------------------------------- 334 335 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