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