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