1ddde725dSArmin Le Grand /************************************************************** 2ddde725dSArmin Le Grand * 3ddde725dSArmin Le Grand * Licensed to the Apache Software Foundation (ASF) under one 4ddde725dSArmin Le Grand * or more contributor license agreements. See the NOTICE file 5ddde725dSArmin Le Grand * distributed with this work for additional information 6ddde725dSArmin Le Grand * regarding copyright ownership. The ASF licenses this file 7ddde725dSArmin Le Grand * to you under the Apache License, Version 2.0 (the 8ddde725dSArmin Le Grand * "License"); you may not use this file except in compliance 9ddde725dSArmin Le Grand * with the License. You may obtain a copy of the License at 10ddde725dSArmin Le Grand * 11ddde725dSArmin Le Grand * http:\\www.apache.org\licenses\LICENSE-2.0 12ddde725dSArmin Le Grand * 13ddde725dSArmin Le Grand * Unless required by applicable law or agreed to in writing, 14ddde725dSArmin Le Grand * software distributed under the License is distributed on an 15ddde725dSArmin Le Grand * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16ddde725dSArmin Le Grand * KIND, either express or implied. See the License for the 17ddde725dSArmin Le Grand * specific language governing permissions and limitations 18ddde725dSArmin Le Grand * under the License. 19ddde725dSArmin Le Grand * 20ddde725dSArmin Le Grand *************************************************************/ 21ddde725dSArmin Le Grand 22ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove 23ddde725dSArmin Le Grand #include "precompiled_drawinglayer.hxx" 24ddde725dSArmin Le Grand 25ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> 26ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 27ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 29ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 30ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx> 31ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx> 32ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygon.hxx> 33ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> 34ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 35ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 36ddde725dSArmin Le Grand #include <drawinglayer/geometry/viewinformation2d.hxx> 37ddde725dSArmin Le Grand 38ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 39ddde725dSArmin Le Grand 40ddde725dSArmin Le Grand using namespace com::sun::star; 41ddde725dSArmin Le Grand 42ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 43ddde725dSArmin Le Grand 44ddde725dSArmin Le Grand namespace drawinglayer 45ddde725dSArmin Le Grand { 46ddde725dSArmin Le Grand namespace primitive2d 47ddde725dSArmin Le Grand { 48ddde725dSArmin Le Grand Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const 49ddde725dSArmin Le Grand { 50ddde725dSArmin Le Grand const SvgGradientEntryVector& rEntries = getGradientEntries(); 51ddde725dSArmin Le Grand const sal_uInt32 nCount(rEntries.size()); 52ddde725dSArmin Le Grand Primitive2DSequence xRetval; 53ddde725dSArmin Le Grand 54ddde725dSArmin Le Grand if(nCount) 55ddde725dSArmin Le Grand { 56ddde725dSArmin Le Grand const SvgGradientEntry& rSingleEntry = rEntries[nCount - 1]; 57ddde725dSArmin Le Grand const double fOpacity(rSingleEntry.getOpacity()); 58ddde725dSArmin Le Grand 59ddde725dSArmin Le Grand if(fOpacity > 0.0) 60ddde725dSArmin Le Grand { 61ddde725dSArmin Le Grand Primitive2DReference xRef( 62ddde725dSArmin Le Grand new PolyPolygonColorPrimitive2D( 63ddde725dSArmin Le Grand getPolyPolygon(), 64ddde725dSArmin Le Grand rSingleEntry.getColor())); 65ddde725dSArmin Le Grand 66ddde725dSArmin Le Grand if(fOpacity < 1.0) 67ddde725dSArmin Le Grand { 68ddde725dSArmin Le Grand const Primitive2DSequence aContent(&xRef, 1); 69ddde725dSArmin Le Grand 70ddde725dSArmin Le Grand xRef = Primitive2DReference( 71ddde725dSArmin Le Grand new UnifiedTransparencePrimitive2D( 72ddde725dSArmin Le Grand aContent, 73ddde725dSArmin Le Grand 1.0 - fOpacity)); 74ddde725dSArmin Le Grand } 75ddde725dSArmin Le Grand 76ddde725dSArmin Le Grand xRetval = Primitive2DSequence(&xRef, 1); 77ddde725dSArmin Le Grand } 78ddde725dSArmin Le Grand } 79ddde725dSArmin Le Grand else 80ddde725dSArmin Le Grand { 81ddde725dSArmin Le Grand OSL_ENSURE(false, "Single gradient entry construction without entry (!)"); 82ddde725dSArmin Le Grand } 83ddde725dSArmin Le Grand 84ddde725dSArmin Le Grand return xRetval; 85ddde725dSArmin Le Grand } 86ddde725dSArmin Le Grand 87ddde725dSArmin Le Grand void SvgGradientHelper::checkPreconditions() 88ddde725dSArmin Le Grand { 89ddde725dSArmin Le Grand mbPreconditionsChecked = true; 90ddde725dSArmin Le Grand const SvgGradientEntryVector& rEntries = getGradientEntries(); 91ddde725dSArmin Le Grand 92ddde725dSArmin Le Grand if(rEntries.empty()) 93ddde725dSArmin Le Grand { 94ddde725dSArmin Le Grand // no fill at all 95ddde725dSArmin Le Grand } 96ddde725dSArmin Le Grand else 97ddde725dSArmin Le Grand { 98ddde725dSArmin Le Grand const sal_uInt32 nCount(rEntries.size()); 99ddde725dSArmin Le Grand 100ddde725dSArmin Le Grand if(1 == nCount) 101ddde725dSArmin Le Grand { 102ddde725dSArmin Le Grand // fill with single existing color 103ddde725dSArmin Le Grand setSingleEntry(); 104ddde725dSArmin Le Grand } 105ddde725dSArmin Le Grand else 106ddde725dSArmin Le Grand { 107ddde725dSArmin Le Grand // sort maGradientEntries when more than one 108ddde725dSArmin Le Grand std::sort(maGradientEntries.begin(), maGradientEntries.end()); 109ddde725dSArmin Le Grand 110ddde725dSArmin Le Grand // gradient with at least two colors 111ddde725dSArmin Le Grand bool bAllInvisible(true); 112ddde725dSArmin Le Grand 113ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nCount; a++) 114ddde725dSArmin Le Grand { 115ddde725dSArmin Le Grand const SvgGradientEntry& rCandidate = rEntries[a]; 116ddde725dSArmin Le Grand 117ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(rCandidate.getOpacity())) 118ddde725dSArmin Le Grand { 119ddde725dSArmin Le Grand // invisible 120ddde725dSArmin Le Grand mbFullyOpaque = false; 121ddde725dSArmin Le Grand } 122ddde725dSArmin Le Grand else if(basegfx::fTools::equal(rCandidate.getOpacity(), 1.0)) 123ddde725dSArmin Le Grand { 124ddde725dSArmin Le Grand // completely opaque 125ddde725dSArmin Le Grand bAllInvisible = false; 126ddde725dSArmin Le Grand } 127ddde725dSArmin Le Grand else 128ddde725dSArmin Le Grand { 129ddde725dSArmin Le Grand // opacity 130ddde725dSArmin Le Grand bAllInvisible = false; 131ddde725dSArmin Le Grand mbFullyOpaque = false; 132ddde725dSArmin Le Grand } 133ddde725dSArmin Le Grand } 134ddde725dSArmin Le Grand 135ddde725dSArmin Le Grand if(bAllInvisible) 136ddde725dSArmin Le Grand { 137ddde725dSArmin Le Grand // all invisible, nothing to do 138ddde725dSArmin Le Grand } 139ddde725dSArmin Le Grand else 140ddde725dSArmin Le Grand { 141ddde725dSArmin Le Grand const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); 142ddde725dSArmin Le Grand 143ddde725dSArmin Le Grand if(aPolyRange.isEmpty()) 144ddde725dSArmin Le Grand { 145ddde725dSArmin Le Grand // no range to fill, nothing to do 146ddde725dSArmin Le Grand } 147ddde725dSArmin Le Grand else 148ddde725dSArmin Le Grand { 149ddde725dSArmin Le Grand const double fPolyWidth(aPolyRange.getWidth()); 150ddde725dSArmin Le Grand const double fPolyHeight(aPolyRange.getHeight()); 151ddde725dSArmin Le Grand 152ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(fPolyWidth) || basegfx::fTools::equalZero(fPolyHeight)) 153ddde725dSArmin Le Grand { 154ddde725dSArmin Le Grand // no width/height to fill, nothing to do 155ddde725dSArmin Le Grand } 156ddde725dSArmin Le Grand else 157ddde725dSArmin Le Grand { 158ddde725dSArmin Le Grand mbCreatesContent = true; 159ddde725dSArmin Le Grand } 160ddde725dSArmin Le Grand } 161ddde725dSArmin Le Grand } 162ddde725dSArmin Le Grand } 163ddde725dSArmin Le Grand } 164ddde725dSArmin Le Grand } 165ddde725dSArmin Le Grand 166ddde725dSArmin Le Grand double SvgGradientHelper::createRun( 167ddde725dSArmin Le Grand Primitive2DVector& rTargetColor, 168ddde725dSArmin Le Grand Primitive2DVector& rTargetOpacity, 169ddde725dSArmin Le Grand double fPos, 170ddde725dSArmin Le Grand double fMax, 171ddde725dSArmin Le Grand const SvgGradientEntryVector& rEntries, 172ddde725dSArmin Le Grand sal_Int32 nOffset) const 173ddde725dSArmin Le Grand { 174ddde725dSArmin Le Grand const sal_uInt32 nCount(rEntries.size()); 175ddde725dSArmin Le Grand 176ddde725dSArmin Le Grand if(nCount) 177ddde725dSArmin Le Grand { 178ddde725dSArmin Le Grand const SvgGradientEntry& rStart = rEntries[0]; 179ddde725dSArmin Le Grand const bool bCreateStartPad(fPos < 0.0 && Spread_pad == getSpreadMethod()); 180ddde725dSArmin Le Grand const bool bCreateStartFill(rStart.getOffset() > 0.0); 181ddde725dSArmin Le Grand sal_uInt32 nIndex(0); 182ddde725dSArmin Le Grand 183ddde725dSArmin Le Grand if(bCreateStartPad || bCreateStartFill) 184ddde725dSArmin Le Grand { 185ddde725dSArmin Le Grand const SvgGradientEntry aTemp(bCreateStartPad ? fPos : 0.0, rStart.getColor(), rStart.getOpacity()); 186ddde725dSArmin Le Grand 187ddde725dSArmin Le Grand createAtom(rTargetColor, rTargetOpacity, aTemp, rStart, nOffset); 188ddde725dSArmin Le Grand fPos = rStart.getOffset(); 189ddde725dSArmin Le Grand } 190ddde725dSArmin Le Grand 191ddde725dSArmin Le Grand while(fPos < 1.0 && nIndex + 1 < nCount) 192ddde725dSArmin Le Grand { 193ddde725dSArmin Le Grand const SvgGradientEntry& rCandidateA = rEntries[nIndex++]; 194ddde725dSArmin Le Grand const SvgGradientEntry& rCandidateB = rEntries[nIndex]; 195ddde725dSArmin Le Grand 196ddde725dSArmin Le Grand createAtom(rTargetColor, rTargetOpacity, rCandidateA, rCandidateB, nOffset); 197ddde725dSArmin Le Grand fPos = rCandidateB.getOffset(); 198ddde725dSArmin Le Grand } 199ddde725dSArmin Le Grand 200ddde725dSArmin Le Grand const SvgGradientEntry& rEnd = rEntries[nCount - 1]; 201ddde725dSArmin Le Grand const bool bCreateEndPad(fPos < fMax && Spread_pad == getSpreadMethod()); 202ddde725dSArmin Le Grand const bool bCreateEndFill(rEnd.getOffset() < 1.0); 203ddde725dSArmin Le Grand 204ddde725dSArmin Le Grand if(bCreateEndPad || bCreateEndFill) 205ddde725dSArmin Le Grand { 206ddde725dSArmin Le Grand fPos = bCreateEndPad ? fMax : 1.0; 207ddde725dSArmin Le Grand const SvgGradientEntry aTemp(fPos, rEnd.getColor(), rEnd.getOpacity()); 208ddde725dSArmin Le Grand 209ddde725dSArmin Le Grand createAtom(rTargetColor, rTargetOpacity, rEnd, aTemp, nOffset); 210ddde725dSArmin Le Grand } 211ddde725dSArmin Le Grand } 212ddde725dSArmin Le Grand else 213ddde725dSArmin Le Grand { 214ddde725dSArmin Le Grand OSL_ENSURE(false, "GradientAtom creation without ColorStops (!)"); 215ddde725dSArmin Le Grand fPos = fMax; 216ddde725dSArmin Le Grand } 217ddde725dSArmin Le Grand 218ddde725dSArmin Le Grand return fPos; 219ddde725dSArmin Le Grand } 220ddde725dSArmin Le Grand 221ddde725dSArmin Le Grand Primitive2DSequence SvgGradientHelper::createResult( 222ddde725dSArmin Le Grand const Primitive2DVector& rTargetColor, 223ddde725dSArmin Le Grand const Primitive2DVector& rTargetOpacity, 224ddde725dSArmin Le Grand const basegfx::B2DHomMatrix& rUnitGradientToObject, 225ddde725dSArmin Le Grand bool bInvert) const 226ddde725dSArmin Le Grand { 227ddde725dSArmin Le Grand Primitive2DSequence xRetval; 228ddde725dSArmin Le Grand const Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(rTargetColor, bInvert)); 229ddde725dSArmin Le Grand const Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(rTargetOpacity, bInvert)); 230ddde725dSArmin Le Grand 231ddde725dSArmin Le Grand if(aTargetColorEntries.hasElements()) 232ddde725dSArmin Le Grand { 233ddde725dSArmin Le Grand Primitive2DReference xRefContent; 234ddde725dSArmin Le Grand 235ddde725dSArmin Le Grand if(aTargetOpacityEntries.hasElements()) 236ddde725dSArmin Le Grand { 237ddde725dSArmin Le Grand const Primitive2DReference xRefOpacity = new TransparencePrimitive2D( 238ddde725dSArmin Le Grand aTargetColorEntries, 239ddde725dSArmin Le Grand aTargetOpacityEntries); 240ddde725dSArmin Le Grand 241ddde725dSArmin Le Grand xRefContent = new TransformPrimitive2D( 242ddde725dSArmin Le Grand rUnitGradientToObject, 243ddde725dSArmin Le Grand Primitive2DSequence(&xRefOpacity, 1)); 244ddde725dSArmin Le Grand } 245ddde725dSArmin Le Grand else 246ddde725dSArmin Le Grand { 247ddde725dSArmin Le Grand xRefContent = new TransformPrimitive2D( 248ddde725dSArmin Le Grand rUnitGradientToObject, 249ddde725dSArmin Le Grand aTargetColorEntries); 250ddde725dSArmin Le Grand } 251ddde725dSArmin Le Grand 252ddde725dSArmin Le Grand xRefContent = new MaskPrimitive2D( 253ddde725dSArmin Le Grand getPolyPolygon(), 254ddde725dSArmin Le Grand Primitive2DSequence(&xRefContent, 1)); 255ddde725dSArmin Le Grand 256ddde725dSArmin Le Grand xRetval = Primitive2DSequence(&xRefContent, 1); 257ddde725dSArmin Le Grand } 258ddde725dSArmin Le Grand 259ddde725dSArmin Le Grand return xRetval; 260ddde725dSArmin Le Grand } 261ddde725dSArmin Le Grand 262ddde725dSArmin Le Grand SvgGradientHelper::SvgGradientHelper( 263ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPolyPolygon, 264ddde725dSArmin Le Grand const SvgGradientEntryVector& rGradientEntries, 265ddde725dSArmin Le Grand const basegfx::B2DPoint& rStart, 266ddde725dSArmin Le Grand SpreadMethod aSpreadMethod, 267ddde725dSArmin Le Grand double fOverlapping) 268ddde725dSArmin Le Grand : maPolyPolygon(rPolyPolygon), 269ddde725dSArmin Le Grand maGradientEntries(rGradientEntries), 270ddde725dSArmin Le Grand maStart(rStart), 271ddde725dSArmin Le Grand maSpreadMethod(aSpreadMethod), 272ddde725dSArmin Le Grand mfOverlapping(fOverlapping), 273ddde725dSArmin Le Grand mbPreconditionsChecked(false), 274ddde725dSArmin Le Grand mbCreatesContent(false), 275ddde725dSArmin Le Grand mbSingleEntry(false), 276ddde725dSArmin Le Grand mbFullyOpaque(true) 277ddde725dSArmin Le Grand { 278ddde725dSArmin Le Grand } 279ddde725dSArmin Le Grand 280ddde725dSArmin Le Grand bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const 281ddde725dSArmin Le Grand { 282ddde725dSArmin Le Grand const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper); 283ddde725dSArmin Le Grand 284ddde725dSArmin Le Grand return (getPolyPolygon() == rCompare.getPolyPolygon() 285ddde725dSArmin Le Grand && getGradientEntries() == rCompare.getGradientEntries() 286ddde725dSArmin Le Grand && getStart() == rCompare.getStart() 287ddde725dSArmin Le Grand && getSpreadMethod() == rCompare.getSpreadMethod() 288ddde725dSArmin Le Grand && getOverlapping() == rCompare.getOverlapping()); 289ddde725dSArmin Le Grand } 290ddde725dSArmin Le Grand 291ddde725dSArmin Le Grand } // end of namespace primitive2d 292ddde725dSArmin Le Grand } // end of namespace drawinglayer 293ddde725dSArmin Le Grand 294ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 295ddde725dSArmin Le Grand 296ddde725dSArmin Le Grand namespace drawinglayer 297ddde725dSArmin Le Grand { 298ddde725dSArmin Le Grand namespace primitive2d 299ddde725dSArmin Le Grand { 300ddde725dSArmin Le Grand void SvgLinearGradientPrimitive2D::checkPreconditions() 301ddde725dSArmin Le Grand { 302ddde725dSArmin Le Grand // call parent 303ddde725dSArmin Le Grand SvgGradientHelper::checkPreconditions(); 304ddde725dSArmin Le Grand 305ddde725dSArmin Le Grand if(getCreatesContent()) 306ddde725dSArmin Le Grand { 307ddde725dSArmin Le Grand // Check Vector 308ddde725dSArmin Le Grand const basegfx::B2DVector aVector(getEnd() - getStart()); 309ddde725dSArmin Le Grand 310ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(aVector.getX()) && basegfx::fTools::equalZero(aVector.getY())) 311ddde725dSArmin Le Grand { 312ddde725dSArmin Le Grand // fill with single color using last stop color 313ddde725dSArmin Le Grand setSingleEntry(); 314ddde725dSArmin Le Grand } 315ddde725dSArmin Le Grand } 316ddde725dSArmin Le Grand } 317ddde725dSArmin Le Grand 318ddde725dSArmin Le Grand void SvgLinearGradientPrimitive2D::ensureGeometry( 319ddde725dSArmin Le Grand basegfx::B2DPolyPolygon& rPolyPolygon, 320ddde725dSArmin Le Grand const SvgGradientEntry& rFrom, 321ddde725dSArmin Le Grand const SvgGradientEntry& rTo, 322ddde725dSArmin Le Grand sal_Int32 nOffset) const 323ddde725dSArmin Le Grand { 324ddde725dSArmin Le Grand if(!rPolyPolygon.count()) 325ddde725dSArmin Le Grand { 326ddde725dSArmin Le Grand rPolyPolygon.append( 327ddde725dSArmin Le Grand basegfx::tools::createPolygonFromRect( 328ddde725dSArmin Le Grand basegfx::B2DRange( 329ddde725dSArmin Le Grand rFrom.getOffset() - getOverlapping() + nOffset, 330ddde725dSArmin Le Grand 0.0, 331ddde725dSArmin Le Grand rTo.getOffset() + getOverlapping() + nOffset, 332ddde725dSArmin Le Grand 1.0))); 333ddde725dSArmin Le Grand } 334ddde725dSArmin Le Grand } 335ddde725dSArmin Le Grand 336ddde725dSArmin Le Grand void SvgLinearGradientPrimitive2D::createAtom( 337ddde725dSArmin Le Grand Primitive2DVector& rTargetColor, 338ddde725dSArmin Le Grand Primitive2DVector& rTargetOpacity, 339ddde725dSArmin Le Grand const SvgGradientEntry& rFrom, 340ddde725dSArmin Le Grand const SvgGradientEntry& rTo, 341ddde725dSArmin Le Grand sal_Int32 nOffset) const 342ddde725dSArmin Le Grand { 343ddde725dSArmin Le Grand // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset()) 344ddde725dSArmin Le Grand if(rFrom.getOffset() == rTo.getOffset()) 345ddde725dSArmin Le Grand { 346ddde725dSArmin Le Grand OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)"); 347ddde725dSArmin Le Grand } 348ddde725dSArmin Le Grand else 349ddde725dSArmin Le Grand { 350ddde725dSArmin Le Grand const bool bColorChange(rFrom.getColor() != rTo.getColor()); 351ddde725dSArmin Le Grand const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity()); 352ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPolyPolygon; 353ddde725dSArmin Le Grand 354ddde725dSArmin Le Grand if(bColorChange) 355ddde725dSArmin Le Grand { 356ddde725dSArmin Le Grand rTargetColor.push_back( 357ddde725dSArmin Le Grand new SvgLinearAtomPrimitive2D( 358ddde725dSArmin Le Grand rFrom.getColor(), rFrom.getOffset() + nOffset, 359ddde725dSArmin Le Grand rTo.getColor(), rTo.getOffset() + nOffset, 360ddde725dSArmin Le Grand getOverlapping())); 361ddde725dSArmin Le Grand } 362ddde725dSArmin Le Grand else 363ddde725dSArmin Le Grand { 364ddde725dSArmin Le Grand ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); 365ddde725dSArmin Le Grand rTargetColor.push_back( 366ddde725dSArmin Le Grand new PolyPolygonColorPrimitive2D( 367ddde725dSArmin Le Grand aPolyPolygon, 368ddde725dSArmin Le Grand rFrom.getColor())); 369ddde725dSArmin Le Grand } 370ddde725dSArmin Le Grand 371ddde725dSArmin Le Grand if(bOpacityChange) 372ddde725dSArmin Le Grand { 373ddde725dSArmin Le Grand const double fTransFrom(1.0 - rFrom.getOpacity()); 374ddde725dSArmin Le Grand const double fTransTo(1.0 - rTo.getOpacity()); 375ddde725dSArmin Le Grand 376ddde725dSArmin Le Grand rTargetOpacity.push_back( 377ddde725dSArmin Le Grand new SvgLinearAtomPrimitive2D( 378ddde725dSArmin Le Grand basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset, 379ddde725dSArmin Le Grand basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset, 380ddde725dSArmin Le Grand getOverlapping())); 381ddde725dSArmin Le Grand } 382ddde725dSArmin Le Grand else if(!getFullyOpaque()) 383ddde725dSArmin Le Grand { 384ddde725dSArmin Le Grand const double fTransparence(1.0 - rFrom.getOpacity()); 385ddde725dSArmin Le Grand 386ddde725dSArmin Le Grand ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); 387ddde725dSArmin Le Grand rTargetOpacity.push_back( 388ddde725dSArmin Le Grand new PolyPolygonColorPrimitive2D( 389ddde725dSArmin Le Grand aPolyPolygon, 390ddde725dSArmin Le Grand basegfx::BColor(fTransparence, fTransparence, fTransparence))); 391ddde725dSArmin Le Grand } 392ddde725dSArmin Le Grand } 393ddde725dSArmin Le Grand } 394ddde725dSArmin Le Grand 395ddde725dSArmin Le Grand Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 396ddde725dSArmin Le Grand { 397ddde725dSArmin Le Grand Primitive2DSequence xRetval; 398ddde725dSArmin Le Grand 399ddde725dSArmin Le Grand if(!getPreconditionsChecked()) 400ddde725dSArmin Le Grand { 401ddde725dSArmin Le Grand const_cast< SvgLinearGradientPrimitive2D* >(this)->checkPreconditions(); 402ddde725dSArmin Le Grand } 403ddde725dSArmin Le Grand 404ddde725dSArmin Le Grand if(getSingleEntry()) 405ddde725dSArmin Le Grand { 406ddde725dSArmin Le Grand // fill with last existing color 407ddde725dSArmin Le Grand xRetval = createSingleGradientEntryFill(); 408ddde725dSArmin Le Grand } 409ddde725dSArmin Le Grand else if(getCreatesContent()) 410ddde725dSArmin Le Grand { 411ddde725dSArmin Le Grand // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely 412ddde725dSArmin Le Grand // invisible, width and height to fill are not empty 413ddde725dSArmin Le Grand const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); 414ddde725dSArmin Le Grand const double fPolyWidth(aPolyRange.getWidth()); 415ddde725dSArmin Le Grand const double fPolyHeight(aPolyRange.getHeight()); 416ddde725dSArmin Le Grand 417ddde725dSArmin Le Grand // create ObjectTransform based on polygon range 418ddde725dSArmin Le Grand const basegfx::B2DHomMatrix aObjectTransform( 419ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 420ddde725dSArmin Le Grand fPolyWidth, fPolyHeight, 421ddde725dSArmin Le Grand aPolyRange.getMinX(), aPolyRange.getMinY())); 422ddde725dSArmin Le Grand 423ddde725dSArmin Le Grand // create unit transform from unit vector [0.0 .. 1.0] along the X-Axis to given 424ddde725dSArmin Le Grand // gradient vector defined by Start,End 425ddde725dSArmin Le Grand const basegfx::B2DVector aVector(getEnd() - getStart()); 426ddde725dSArmin Le Grand const double fVectorLength(aVector.getLength()); 427ddde725dSArmin Le Grand basegfx::B2DHomMatrix aUnitGradientToGradient; 428ddde725dSArmin Le Grand 429ddde725dSArmin Le Grand aUnitGradientToGradient.scale(fVectorLength, 1.0); 430ddde725dSArmin Le Grand aUnitGradientToGradient.rotate(atan2(aVector.getY(), aVector.getX())); 431ddde725dSArmin Le Grand aUnitGradientToGradient.translate(getStart().getX(), getStart().getY()); 432ddde725dSArmin Le Grand 433ddde725dSArmin Le Grand // create full transform from unit gradient coordinates to object coordinates 434ddde725dSArmin Le Grand // including the SvgGradient transformation 435ddde725dSArmin Le Grand basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient); 436ddde725dSArmin Le Grand 437ddde725dSArmin Le Grand // create inverse from it 438ddde725dSArmin Le Grand basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject); 439ddde725dSArmin Le Grand aObjectToUnitGradient.invert(); 440ddde725dSArmin Le Grand 441ddde725dSArmin Le Grand // back-transform polygon to unit gradient coordinates and get 442ddde725dSArmin Le Grand // UnitRage. This is the range the gradient has to cover 443ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon()); 444ddde725dSArmin Le Grand aUnitPoly.transform(aObjectToUnitGradient); 445ddde725dSArmin Le Grand const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange()); 446ddde725dSArmin Le Grand 447ddde725dSArmin Le Grand // prepare result vectors 448ddde725dSArmin Le Grand Primitive2DVector aTargetColor; 449ddde725dSArmin Le Grand Primitive2DVector aTargetOpacity; 450ddde725dSArmin Le Grand 451ddde725dSArmin Le Grand if(basegfx::fTools::more(aUnitRange.getWidth(), 0.0)) 452ddde725dSArmin Le Grand { 453ddde725dSArmin Le Grand // add a pre-multiply to aUnitGradientToObject to allow 454ddde725dSArmin Le Grand // multiplication of the polygon(xl, 0.0, xr, 1.0) 455ddde725dSArmin Le Grand const basegfx::B2DHomMatrix aPreMultiply( 456ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 457ddde725dSArmin Le Grand 1.0, aUnitRange.getHeight(), 0.0, aUnitRange.getMinY())); 458ddde725dSArmin Le Grand aUnitGradientToObject = aUnitGradientToObject * aPreMultiply; 459ddde725dSArmin Le Grand 460ddde725dSArmin Le Grand // create central run, may also already do all necessary when 461ddde725dSArmin Le Grand // Spread_pad is set as SpreadMethod and/or the range is smaller 462ddde725dSArmin Le Grand double fPos(createRun(aTargetColor, aTargetOpacity, aUnitRange.getMinX(), aUnitRange.getMaxX(), getGradientEntries(), 0)); 463ddde725dSArmin Le Grand 464ddde725dSArmin Le Grand if(fPos < aUnitRange.getMaxX()) 465ddde725dSArmin Le Grand { 466ddde725dSArmin Le Grand // can only happen when SpreadMethod is Spread_reflect or Spread_repeat, 467ddde725dSArmin Le Grand // else the start and end pads are already created and fPos == aUnitRange.getMaxX(). 468ddde725dSArmin Le Grand // Its possible to express the repeated linear gradient by adding the 469ddde725dSArmin Le Grand // transformed central run. Crete it this way 470ddde725dSArmin Le Grand Primitive2DSequence aTargetColorEntries(Primitive2DVectorToPrimitive2DSequence(aTargetColor)); 471ddde725dSArmin Le Grand Primitive2DSequence aTargetOpacityEntries(Primitive2DVectorToPrimitive2DSequence(aTargetOpacity)); 472ddde725dSArmin Le Grand aTargetColor.clear(); 473ddde725dSArmin Le Grand aTargetOpacity.clear(); 474ddde725dSArmin Le Grand 475ddde725dSArmin Le Grand if(aTargetColorEntries.hasElements()) 476ddde725dSArmin Le Grand { 477ddde725dSArmin Le Grand // add original central run as group primitive 478ddde725dSArmin Le Grand aTargetColor.push_back(new GroupPrimitive2D(aTargetColorEntries)); 479ddde725dSArmin Le Grand 480ddde725dSArmin Le Grand if(aTargetOpacityEntries.hasElements()) 481ddde725dSArmin Le Grand { 482ddde725dSArmin Le Grand aTargetOpacity.push_back(new GroupPrimitive2D(aTargetOpacityEntries)); 483ddde725dSArmin Le Grand } 484ddde725dSArmin Le Grand 485ddde725dSArmin Le Grand // add negative runs 486ddde725dSArmin Le Grand fPos = 0.0; 487ddde725dSArmin Le Grand sal_Int32 nOffset(0); 488ddde725dSArmin Le Grand 489ddde725dSArmin Le Grand while(fPos > aUnitRange.getMinX()) 490ddde725dSArmin Le Grand { 491ddde725dSArmin Le Grand fPos -= 1.0; 492ddde725dSArmin Le Grand nOffset++; 493ddde725dSArmin Le Grand 494ddde725dSArmin Le Grand basegfx::B2DHomMatrix aTransform; 495ddde725dSArmin Le Grand const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); 496ddde725dSArmin Le Grand 497ddde725dSArmin Le Grand if(bMirror) 498ddde725dSArmin Le Grand { 499ddde725dSArmin Le Grand aTransform.scale(-1.0, 1.0); 500ddde725dSArmin Le Grand aTransform.translate(fPos + 1.0, 0.0); 501ddde725dSArmin Le Grand } 502ddde725dSArmin Le Grand else 503ddde725dSArmin Le Grand { 504ddde725dSArmin Le Grand aTransform.translate(fPos, 0.0); 505ddde725dSArmin Le Grand } 506ddde725dSArmin Le Grand 507ddde725dSArmin Le Grand aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries)); 508ddde725dSArmin Le Grand 509ddde725dSArmin Le Grand if(aTargetOpacityEntries.hasElements()) 510ddde725dSArmin Le Grand { 511ddde725dSArmin Le Grand aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries)); 512ddde725dSArmin Le Grand } 513ddde725dSArmin Le Grand } 514ddde725dSArmin Le Grand 515ddde725dSArmin Le Grand // add positive runs 516ddde725dSArmin Le Grand fPos = 1.0; 517ddde725dSArmin Le Grand nOffset = 1; 518ddde725dSArmin Le Grand 519ddde725dSArmin Le Grand while(fPos < aUnitRange.getMaxX()) 520ddde725dSArmin Le Grand { 521ddde725dSArmin Le Grand basegfx::B2DHomMatrix aTransform; 522ddde725dSArmin Le Grand const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); 523ddde725dSArmin Le Grand 524ddde725dSArmin Le Grand if(bMirror) 525ddde725dSArmin Le Grand { 526ddde725dSArmin Le Grand aTransform.scale(-1.0, 1.0); 527ddde725dSArmin Le Grand aTransform.translate(fPos + 1.0, 0.0); 528ddde725dSArmin Le Grand } 529ddde725dSArmin Le Grand else 530ddde725dSArmin Le Grand { 531ddde725dSArmin Le Grand aTransform.translate(fPos, 0.0); 532ddde725dSArmin Le Grand } 533ddde725dSArmin Le Grand 534ddde725dSArmin Le Grand aTargetColor.push_back(new TransformPrimitive2D(aTransform, aTargetColorEntries)); 535ddde725dSArmin Le Grand 536ddde725dSArmin Le Grand if(aTargetOpacityEntries.hasElements()) 537ddde725dSArmin Le Grand { 538ddde725dSArmin Le Grand aTargetOpacity.push_back(new TransformPrimitive2D(aTransform, aTargetOpacityEntries)); 539ddde725dSArmin Le Grand } 540ddde725dSArmin Le Grand 541ddde725dSArmin Le Grand fPos += 1.0; 542ddde725dSArmin Le Grand nOffset++; 543ddde725dSArmin Le Grand } 544ddde725dSArmin Le Grand } 545ddde725dSArmin Le Grand } 546ddde725dSArmin Le Grand } 547ddde725dSArmin Le Grand 548ddde725dSArmin Le Grand xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject); 549ddde725dSArmin Le Grand } 550ddde725dSArmin Le Grand 551ddde725dSArmin Le Grand return xRetval; 552ddde725dSArmin Le Grand } 553ddde725dSArmin Le Grand 554ddde725dSArmin Le Grand SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D( 555ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPolyPolygon, 556ddde725dSArmin Le Grand const SvgGradientEntryVector& rGradientEntries, 557ddde725dSArmin Le Grand const basegfx::B2DPoint& rStart, 558ddde725dSArmin Le Grand const basegfx::B2DPoint& rEnd, 559ddde725dSArmin Le Grand SpreadMethod aSpreadMethod, 560ddde725dSArmin Le Grand double fOverlapping) 561ddde725dSArmin Le Grand : BufferedDecompositionPrimitive2D(), 562ddde725dSArmin Le Grand SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping), 563ddde725dSArmin Le Grand maEnd(rEnd) 564ddde725dSArmin Le Grand { 565ddde725dSArmin Le Grand } 566ddde725dSArmin Le Grand 567ddde725dSArmin Le Grand bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 568ddde725dSArmin Le Grand { 569ddde725dSArmin Le Grand const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive); 570ddde725dSArmin Le Grand 571ddde725dSArmin Le Grand if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper)) 572ddde725dSArmin Le Grand { 573ddde725dSArmin Le Grand const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive); 574ddde725dSArmin Le Grand 575ddde725dSArmin Le Grand return (getEnd() == rCompare.getEnd()); 576ddde725dSArmin Le Grand } 577ddde725dSArmin Le Grand 578ddde725dSArmin Le Grand return false; 579ddde725dSArmin Le Grand } 580ddde725dSArmin Le Grand 581ddde725dSArmin Le Grand basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const 582ddde725dSArmin Le Grand { 583ddde725dSArmin Le Grand // return ObjectRange 584ddde725dSArmin Le Grand return getPolyPolygon().getB2DRange(); 585ddde725dSArmin Le Grand } 586ddde725dSArmin Le Grand 587ddde725dSArmin Le Grand // provide unique ID 588ddde725dSArmin Le Grand ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D) 589ddde725dSArmin Le Grand 590ddde725dSArmin Le Grand } // end of namespace primitive2d 591ddde725dSArmin Le Grand } // end of namespace drawinglayer 592ddde725dSArmin Le Grand 593ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 594ddde725dSArmin Le Grand 595ddde725dSArmin Le Grand namespace drawinglayer 596ddde725dSArmin Le Grand { 597ddde725dSArmin Le Grand namespace primitive2d 598ddde725dSArmin Le Grand { 599ddde725dSArmin Le Grand void SvgRadialGradientPrimitive2D::checkPreconditions() 600ddde725dSArmin Le Grand { 601ddde725dSArmin Le Grand // call parent 602ddde725dSArmin Le Grand SvgGradientHelper::checkPreconditions(); 603ddde725dSArmin Le Grand 604ddde725dSArmin Le Grand if(getCreatesContent()) 605ddde725dSArmin Le Grand { 606ddde725dSArmin Le Grand // Check Radius 607ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(getRadius())) 608ddde725dSArmin Le Grand { 609ddde725dSArmin Le Grand // fill with single color using last stop color 610ddde725dSArmin Le Grand setSingleEntry(); 611ddde725dSArmin Le Grand } 612ddde725dSArmin Le Grand } 613ddde725dSArmin Le Grand } 614ddde725dSArmin Le Grand 615ddde725dSArmin Le Grand void SvgRadialGradientPrimitive2D::ensureGeometry( 616ddde725dSArmin Le Grand basegfx::B2DPolyPolygon& rPolyPolygon, 617ddde725dSArmin Le Grand const SvgGradientEntry& rFrom, 618ddde725dSArmin Le Grand const SvgGradientEntry& rTo, 619ddde725dSArmin Le Grand sal_Int32 nOffset) const 620ddde725dSArmin Le Grand { 621ddde725dSArmin Le Grand if(!rPolyPolygon.count()) 622ddde725dSArmin Le Grand { 623ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); 624ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); 625ddde725dSArmin Le Grand double fScaleFrom(rFrom.getOffset() + nOffset); 626ddde725dSArmin Le Grand const double fScaleTo(rTo.getOffset() + nOffset); 627ddde725dSArmin Le Grand 628ddde725dSArmin Le Grand if(fScaleFrom > getOverlapping()) 629ddde725dSArmin Le Grand { 630ddde725dSArmin Le Grand fScaleFrom -= getOverlapping(); 631ddde725dSArmin Le Grand } 632ddde725dSArmin Le Grand 633ddde725dSArmin Le Grand if(isFocalSet()) 634ddde725dSArmin Le Grand { 635ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); 636ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); 637ddde725dSArmin Le Grand 638ddde725dSArmin Le Grand aPolygonA.transform( 639ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 640ddde725dSArmin Le Grand fScaleFrom, 641ddde725dSArmin Le Grand fScaleFrom, 642ddde725dSArmin Le Grand aTranslateFrom.getX(), 643ddde725dSArmin Le Grand aTranslateFrom.getY())); 644ddde725dSArmin Le Grand aPolygonB.transform( 645ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 646ddde725dSArmin Le Grand fScaleTo, 647ddde725dSArmin Le Grand fScaleTo, 648ddde725dSArmin Le Grand aTranslateTo.getX(), 649ddde725dSArmin Le Grand aTranslateTo.getY())); 650ddde725dSArmin Le Grand } 651ddde725dSArmin Le Grand else 652ddde725dSArmin Le Grand { 653ddde725dSArmin Le Grand aPolygonA.transform( 654ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 655ddde725dSArmin Le Grand fScaleFrom, 656ddde725dSArmin Le Grand fScaleFrom)); 657ddde725dSArmin Le Grand aPolygonB.transform( 658ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 659ddde725dSArmin Le Grand fScaleTo, 660ddde725dSArmin Le Grand fScaleTo)); 661ddde725dSArmin Le Grand } 662ddde725dSArmin Le Grand 663ddde725dSArmin Le Grand // add the outer polygon first 664ddde725dSArmin Le Grand rPolyPolygon.append(aPolygonB); 665ddde725dSArmin Le Grand rPolyPolygon.append(aPolygonA); 666ddde725dSArmin Le Grand } 667ddde725dSArmin Le Grand } 668ddde725dSArmin Le Grand 669ddde725dSArmin Le Grand void SvgRadialGradientPrimitive2D::createAtom( 670ddde725dSArmin Le Grand Primitive2DVector& rTargetColor, 671ddde725dSArmin Le Grand Primitive2DVector& rTargetOpacity, 672ddde725dSArmin Le Grand const SvgGradientEntry& rFrom, 673ddde725dSArmin Le Grand const SvgGradientEntry& rTo, 674ddde725dSArmin Le Grand sal_Int32 nOffset) const 675ddde725dSArmin Le Grand { 676ddde725dSArmin Le Grand // create gradient atom [rFrom.getOffset() .. rTo.getOffset()] with (rFrom.getOffset() > rTo.getOffset()) 677ddde725dSArmin Le Grand if(rFrom.getOffset() == rTo.getOffset()) 678ddde725dSArmin Le Grand { 679ddde725dSArmin Le Grand OSL_ENSURE(false, "SvgGradient Atom creation with no step width (!)"); 680ddde725dSArmin Le Grand } 681ddde725dSArmin Le Grand else 682ddde725dSArmin Le Grand { 683ddde725dSArmin Le Grand const bool bColorChange(rFrom.getColor() != rTo.getColor()); 684ddde725dSArmin Le Grand const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity()); 685ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPolyPolygon; 686ddde725dSArmin Le Grand 687ddde725dSArmin Le Grand if(bColorChange) 688ddde725dSArmin Le Grand { 689ddde725dSArmin Le Grand const double fScaleFrom(rFrom.getOffset() + nOffset); 690ddde725dSArmin Le Grand const double fScaleTo(rTo.getOffset() + nOffset); 691ddde725dSArmin Le Grand 692ddde725dSArmin Le Grand if(isFocalSet()) 693ddde725dSArmin Le Grand { 694ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); 695ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); 696ddde725dSArmin Le Grand 697ddde725dSArmin Le Grand rTargetColor.push_back( 698ddde725dSArmin Le Grand new SvgRadialAtomPrimitive2D( 699ddde725dSArmin Le Grand rFrom.getColor(), fScaleFrom, aTranslateFrom, 700ddde725dSArmin Le Grand rTo.getColor(), fScaleTo, aTranslateTo, 701ddde725dSArmin Le Grand getOverlapping())); 702ddde725dSArmin Le Grand } 703ddde725dSArmin Le Grand else 704ddde725dSArmin Le Grand { 705ddde725dSArmin Le Grand rTargetColor.push_back( 706ddde725dSArmin Le Grand new SvgRadialAtomPrimitive2D( 707ddde725dSArmin Le Grand rFrom.getColor(), fScaleFrom, 708ddde725dSArmin Le Grand rTo.getColor(), fScaleTo, 709ddde725dSArmin Le Grand getOverlapping())); 710ddde725dSArmin Le Grand } 711ddde725dSArmin Le Grand } 712ddde725dSArmin Le Grand else 713ddde725dSArmin Le Grand { 714ddde725dSArmin Le Grand ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); 715ddde725dSArmin Le Grand rTargetColor.push_back( 716ddde725dSArmin Le Grand new PolyPolygonColorPrimitive2D( 717ddde725dSArmin Le Grand aPolyPolygon, 718ddde725dSArmin Le Grand rFrom.getColor())); 719ddde725dSArmin Le Grand } 720ddde725dSArmin Le Grand 721ddde725dSArmin Le Grand if(bOpacityChange) 722ddde725dSArmin Le Grand { 723ddde725dSArmin Le Grand const double fTransFrom(1.0 - rFrom.getOpacity()); 724ddde725dSArmin Le Grand const double fTransTo(1.0 - rTo.getOpacity()); 725ddde725dSArmin Le Grand const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom); 726ddde725dSArmin Le Grand const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo); 727ddde725dSArmin Le Grand const double fScaleFrom(rFrom.getOffset() + nOffset); 728ddde725dSArmin Le Grand const double fScaleTo(rTo.getOffset() + nOffset); 729ddde725dSArmin Le Grand 730ddde725dSArmin Le Grand if(isFocalSet()) 731ddde725dSArmin Le Grand { 732ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom)); 733ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo)); 734ddde725dSArmin Le Grand 735ddde725dSArmin Le Grand rTargetOpacity.push_back( 736ddde725dSArmin Le Grand new SvgRadialAtomPrimitive2D( 737ddde725dSArmin Le Grand aColorFrom, fScaleFrom, aTranslateFrom, 738ddde725dSArmin Le Grand aColorTo, fScaleTo, aTranslateTo, 739ddde725dSArmin Le Grand getOverlapping())); 740ddde725dSArmin Le Grand } 741ddde725dSArmin Le Grand else 742ddde725dSArmin Le Grand { 743ddde725dSArmin Le Grand rTargetOpacity.push_back( 744ddde725dSArmin Le Grand new SvgRadialAtomPrimitive2D( 745ddde725dSArmin Le Grand aColorFrom, fScaleFrom, 746ddde725dSArmin Le Grand aColorTo, fScaleTo, 747ddde725dSArmin Le Grand getOverlapping())); 748ddde725dSArmin Le Grand } 749ddde725dSArmin Le Grand } 750ddde725dSArmin Le Grand else if(!getFullyOpaque()) 751ddde725dSArmin Le Grand { 752ddde725dSArmin Le Grand const double fTransparence(1.0 - rFrom.getOpacity()); 753ddde725dSArmin Le Grand 754ddde725dSArmin Le Grand ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset); 755ddde725dSArmin Le Grand rTargetOpacity.push_back( 756ddde725dSArmin Le Grand new PolyPolygonColorPrimitive2D( 757ddde725dSArmin Le Grand aPolyPolygon, 758ddde725dSArmin Le Grand basegfx::BColor(fTransparence, fTransparence, fTransparence))); 759ddde725dSArmin Le Grand } 760ddde725dSArmin Le Grand } 761ddde725dSArmin Le Grand } 762ddde725dSArmin Le Grand 763ddde725dSArmin Le Grand const SvgGradientEntryVector& SvgRadialGradientPrimitive2D::getMirroredGradientEntries() const 764ddde725dSArmin Le Grand { 765ddde725dSArmin Le Grand if(maMirroredGradientEntries.empty() && !getGradientEntries().empty()) 766ddde725dSArmin Le Grand { 767ddde725dSArmin Le Grand const_cast< SvgRadialGradientPrimitive2D* >(this)->createMirroredGradientEntries(); 768ddde725dSArmin Le Grand } 769ddde725dSArmin Le Grand 770ddde725dSArmin Le Grand return maMirroredGradientEntries; 771ddde725dSArmin Le Grand } 772ddde725dSArmin Le Grand 773ddde725dSArmin Le Grand void SvgRadialGradientPrimitive2D::createMirroredGradientEntries() 774ddde725dSArmin Le Grand { 775ddde725dSArmin Le Grand if(maMirroredGradientEntries.empty() && !getGradientEntries().empty()) 776ddde725dSArmin Le Grand { 777ddde725dSArmin Le Grand const sal_uInt32 nCount(getGradientEntries().size()); 778ddde725dSArmin Le Grand maMirroredGradientEntries.clear(); 779ddde725dSArmin Le Grand maMirroredGradientEntries.reserve(nCount); 780ddde725dSArmin Le Grand 781ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nCount; a++) 782ddde725dSArmin Le Grand { 783ddde725dSArmin Le Grand const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a]; 784ddde725dSArmin Le Grand 785ddde725dSArmin Le Grand maMirroredGradientEntries.push_back( 786ddde725dSArmin Le Grand SvgGradientEntry( 787ddde725dSArmin Le Grand 1.0 - rCandidate.getOffset(), 788ddde725dSArmin Le Grand rCandidate.getColor(), 789ddde725dSArmin Le Grand rCandidate.getOpacity())); 790ddde725dSArmin Le Grand } 791ddde725dSArmin Le Grand } 792ddde725dSArmin Le Grand } 793ddde725dSArmin Le Grand 794ddde725dSArmin Le Grand Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 795ddde725dSArmin Le Grand { 796ddde725dSArmin Le Grand Primitive2DSequence xRetval; 797ddde725dSArmin Le Grand 798ddde725dSArmin Le Grand if(!getPreconditionsChecked()) 799ddde725dSArmin Le Grand { 800ddde725dSArmin Le Grand const_cast< SvgRadialGradientPrimitive2D* >(this)->checkPreconditions(); 801ddde725dSArmin Le Grand } 802ddde725dSArmin Le Grand 803ddde725dSArmin Le Grand if(getSingleEntry()) 804ddde725dSArmin Le Grand { 805ddde725dSArmin Le Grand // fill with last existing color 806ddde725dSArmin Le Grand xRetval = createSingleGradientEntryFill(); 807ddde725dSArmin Le Grand } 808ddde725dSArmin Le Grand else if(getCreatesContent()) 809ddde725dSArmin Le Grand { 810ddde725dSArmin Le Grand // at least two color stops in range [0.0 .. 1.0], sorted, non-null vector, not completely 811ddde725dSArmin Le Grand // invisible, width and height to fill are not empty 812ddde725dSArmin Le Grand const basegfx::B2DRange aPolyRange(getPolyPolygon().getB2DRange()); 813ddde725dSArmin Le Grand const double fPolyWidth(aPolyRange.getWidth()); 814ddde725dSArmin Le Grand const double fPolyHeight(aPolyRange.getHeight()); 815ddde725dSArmin Le Grand 816ddde725dSArmin Le Grand // create ObjectTransform based on polygon range 817ddde725dSArmin Le Grand const basegfx::B2DHomMatrix aObjectTransform( 818ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 819ddde725dSArmin Le Grand fPolyWidth, fPolyHeight, 820ddde725dSArmin Le Grand aPolyRange.getMinX(), aPolyRange.getMinY())); 821ddde725dSArmin Le Grand 822ddde725dSArmin Le Grand // create unit transform from unit vector to given linear gradient vector 823ddde725dSArmin Le Grand basegfx::B2DHomMatrix aUnitGradientToGradient; 824ddde725dSArmin Le Grand 825ddde725dSArmin Le Grand aUnitGradientToGradient.scale(getRadius(), getRadius()); 826ddde725dSArmin Le Grand aUnitGradientToGradient.translate(getStart().getX(), getStart().getY()); 827ddde725dSArmin Le Grand 828ddde725dSArmin Le Grand // create full transform from unit gradient coordinates to object coordinates 829ddde725dSArmin Le Grand // including the SvgGradient transformation 830ddde725dSArmin Le Grand basegfx::B2DHomMatrix aUnitGradientToObject(aObjectTransform * aUnitGradientToGradient); 831ddde725dSArmin Le Grand 832ddde725dSArmin Le Grand // create inverse from it 833ddde725dSArmin Le Grand basegfx::B2DHomMatrix aObjectToUnitGradient(aUnitGradientToObject); 834ddde725dSArmin Le Grand aObjectToUnitGradient.invert(); 835ddde725dSArmin Le Grand 836ddde725dSArmin Le Grand // back-transform polygon to unit gradient coordinates and get 837ddde725dSArmin Le Grand // UnitRage. This is the range the gradient has to cover 838ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aUnitPoly(getPolyPolygon()); 839ddde725dSArmin Le Grand aUnitPoly.transform(aObjectToUnitGradient); 840ddde725dSArmin Le Grand const basegfx::B2DRange aUnitRange(aUnitPoly.getB2DRange()); 841ddde725dSArmin Le Grand 842ddde725dSArmin Le Grand // create range which the gradient has to cover to cover the whole given geometry. 843ddde725dSArmin Le Grand // For circle, go from 0.0 to max radius in all directions (the corners) 844ddde725dSArmin Le Grand double fMax(basegfx::B2DVector(aUnitRange.getMinimum()).getLength()); 845ddde725dSArmin Le Grand fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaximum()).getLength()); 846ddde725dSArmin Le Grand fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMinX(), aUnitRange.getMaxY()).getLength()); 847ddde725dSArmin Le Grand fMax = std::max(fMax, basegfx::B2DVector(aUnitRange.getMaxX(), aUnitRange.getMinY()).getLength()); 848ddde725dSArmin Le Grand 849ddde725dSArmin Le Grand // prepare result vectors 850ddde725dSArmin Le Grand Primitive2DVector aTargetColor; 851ddde725dSArmin Le Grand Primitive2DVector aTargetOpacity; 852ddde725dSArmin Le Grand 853ddde725dSArmin Le Grand if(0.0 < fMax) 854ddde725dSArmin Le Grand { 855ddde725dSArmin Le Grand // prepare maFocalVector 856ddde725dSArmin Le Grand if(isFocalSet()) 857ddde725dSArmin Le Grand { 858ddde725dSArmin Le Grand const_cast< SvgRadialGradientPrimitive2D* >(this)->maFocalLength = fMax; 859ddde725dSArmin Le Grand } 860ddde725dSArmin Le Grand 861ddde725dSArmin Le Grand // create central run, may also already do all necessary when 862ddde725dSArmin Le Grand // Spread_pad is set as SpreadMethod and/or the range is smaller 863ddde725dSArmin Le Grand double fPos(createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), 0)); 864ddde725dSArmin Le Grand 865ddde725dSArmin Le Grand if(fPos < fMax) 866ddde725dSArmin Le Grand { 867ddde725dSArmin Le Grand // can only happen when SpreadMethod is Spread_reflect or Spread_repeat, 868ddde725dSArmin Le Grand // else the start and end pads are already created and fPos == fMax. 869ddde725dSArmin Le Grand // For radial there is no way to transform the already created 870ddde725dSArmin Le Grand // central run, it needs to be created from 1.0 to fMax 871ddde725dSArmin Le Grand sal_Int32 nOffset(1); 872ddde725dSArmin Le Grand 873ddde725dSArmin Le Grand while(fPos < fMax) 874ddde725dSArmin Le Grand { 875ddde725dSArmin Le Grand const bool bMirror(Spread_reflect == getSpreadMethod() && (nOffset % 2)); 876ddde725dSArmin Le Grand 877ddde725dSArmin Le Grand if(bMirror) 878ddde725dSArmin Le Grand { 879ddde725dSArmin Le Grand createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getMirroredGradientEntries(), nOffset); 880ddde725dSArmin Le Grand } 881ddde725dSArmin Le Grand else 882ddde725dSArmin Le Grand { 883ddde725dSArmin Le Grand createRun(aTargetColor, aTargetOpacity, 0.0, fMax, getGradientEntries(), nOffset); 884ddde725dSArmin Le Grand } 885ddde725dSArmin Le Grand 886ddde725dSArmin Le Grand nOffset++; 887ddde725dSArmin Le Grand fPos += 1.0; 888ddde725dSArmin Le Grand } 889ddde725dSArmin Le Grand } 890ddde725dSArmin Le Grand } 891ddde725dSArmin Le Grand 892ddde725dSArmin Le Grand xRetval = createResult(aTargetColor, aTargetOpacity, aUnitGradientToObject, true); 893ddde725dSArmin Le Grand } 894ddde725dSArmin Le Grand 895ddde725dSArmin Le Grand return xRetval; 896ddde725dSArmin Le Grand } 897ddde725dSArmin Le Grand 898ddde725dSArmin Le Grand SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D( 899ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPolyPolygon, 900ddde725dSArmin Le Grand const SvgGradientEntryVector& rGradientEntries, 901ddde725dSArmin Le Grand const basegfx::B2DPoint& rStart, 902ddde725dSArmin Le Grand double fRadius, 903ddde725dSArmin Le Grand SpreadMethod aSpreadMethod, 904ddde725dSArmin Le Grand const basegfx::B2DPoint* pFocal, 905ddde725dSArmin Le Grand double fOverlapping) 906ddde725dSArmin Le Grand : BufferedDecompositionPrimitive2D(), 907ddde725dSArmin Le Grand SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping), 908ddde725dSArmin Le Grand mfRadius(fRadius), 909ddde725dSArmin Le Grand maFocal(rStart), 910ddde725dSArmin Le Grand maFocalVector(0.0, 0.0), 911ddde725dSArmin Le Grand maFocalLength(0.0), 912ddde725dSArmin Le Grand maMirroredGradientEntries(), 913ddde725dSArmin Le Grand mbFocalSet(false) 914ddde725dSArmin Le Grand { 915ddde725dSArmin Le Grand if(pFocal) 916ddde725dSArmin Le Grand { 917ddde725dSArmin Le Grand maFocal = *pFocal; 918ddde725dSArmin Le Grand maFocalVector = maFocal - getStart(); 919ddde725dSArmin Le Grand mbFocalSet = true; 920ddde725dSArmin Le Grand } 921ddde725dSArmin Le Grand } 922ddde725dSArmin Le Grand 923ddde725dSArmin Le Grand bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 924ddde725dSArmin Le Grand { 925ddde725dSArmin Le Grand const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive); 926ddde725dSArmin Le Grand 927ddde725dSArmin Le Grand if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper)) 928ddde725dSArmin Le Grand { 929ddde725dSArmin Le Grand const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive); 930ddde725dSArmin Le Grand 931ddde725dSArmin Le Grand if(getRadius() == rCompare.getRadius()) 932ddde725dSArmin Le Grand { 933ddde725dSArmin Le Grand if(isFocalSet() == rCompare.isFocalSet()) 934ddde725dSArmin Le Grand { 935ddde725dSArmin Le Grand if(isFocalSet()) 936ddde725dSArmin Le Grand { 937ddde725dSArmin Le Grand return getFocal() == rCompare.getFocal(); 938ddde725dSArmin Le Grand } 939ddde725dSArmin Le Grand else 940ddde725dSArmin Le Grand { 941ddde725dSArmin Le Grand return true; 942ddde725dSArmin Le Grand } 943ddde725dSArmin Le Grand } 944ddde725dSArmin Le Grand } 945ddde725dSArmin Le Grand } 946ddde725dSArmin Le Grand 947ddde725dSArmin Le Grand return false; 948ddde725dSArmin Le Grand } 949ddde725dSArmin Le Grand 950ddde725dSArmin Le Grand basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const 951ddde725dSArmin Le Grand { 952ddde725dSArmin Le Grand // return ObjectRange 953ddde725dSArmin Le Grand return getPolyPolygon().getB2DRange(); 954ddde725dSArmin Le Grand } 955ddde725dSArmin Le Grand 956ddde725dSArmin Le Grand // provide unique ID 957ddde725dSArmin Le Grand ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D) 958ddde725dSArmin Le Grand 959ddde725dSArmin Le Grand } // end of namespace primitive2d 960ddde725dSArmin Le Grand } // end of namespace drawinglayer 961ddde725dSArmin Le Grand 962ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 963ddde725dSArmin Le Grand // SvgLinearAtomPrimitive2D class 964ddde725dSArmin Le Grand 965ddde725dSArmin Le Grand namespace drawinglayer 966ddde725dSArmin Le Grand { 967ddde725dSArmin Le Grand namespace primitive2d 968ddde725dSArmin Le Grand { 969*e2bf1e9dSArmin Le Grand Primitive2DSequence SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 970ddde725dSArmin Le Grand { 971ddde725dSArmin Le Grand Primitive2DSequence xRetval; 972ddde725dSArmin Le Grand const double fDelta(getOffsetB() - getOffsetA()); 973ddde725dSArmin Le Grand 974ddde725dSArmin Le Grand if(!basegfx::fTools::equalZero(fDelta)) 975ddde725dSArmin Le Grand { 976ddde725dSArmin Le Grand if(getColorA() == getColorB()) 977ddde725dSArmin Le Grand { 978ddde725dSArmin Le Grand const basegfx::B2DPolygon aPolygon( 979ddde725dSArmin Le Grand basegfx::tools::createPolygonFromRect( 980ddde725dSArmin Le Grand basegfx::B2DRange( 981ddde725dSArmin Le Grand getOffsetA() - getOverlapping(), 982ddde725dSArmin Le Grand 0.0, 983ddde725dSArmin Le Grand getOffsetB() + getOverlapping(), 984ddde725dSArmin Le Grand 1.0))); 985ddde725dSArmin Le Grand 986ddde725dSArmin Le Grand xRetval.realloc(1); 987ddde725dSArmin Le Grand xRetval[0] = new PolyPolygonColorPrimitive2D( 988ddde725dSArmin Le Grand basegfx::B2DPolyPolygon(aPolygon), 989ddde725dSArmin Le Grand getColorA()); 990ddde725dSArmin Le Grand } 991ddde725dSArmin Le Grand else 992ddde725dSArmin Le Grand { 993ddde725dSArmin Le Grand // calc discrete length to change color all 2.5 pixels 994ddde725dSArmin Le Grand sal_uInt32 nSteps(basegfx::fround(fDelta / (getDiscreteUnit() * 2.5))); 995ddde725dSArmin Le Grand 996ddde725dSArmin Le Grand // use color distance, assume to do every 3rd 997ddde725dSArmin Le Grand const double fColorDistance(getColorA().getDistance(getColorB())); 998ddde725dSArmin Le Grand const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3))); 999ddde725dSArmin Le Grand nSteps = std::min(nSteps, nColorSteps); 1000ddde725dSArmin Le Grand 1001ddde725dSArmin Le Grand // roughly cut when too big 1002ddde725dSArmin Le Grand nSteps = std::min(nSteps, sal_uInt32(100)); 1003ddde725dSArmin Le Grand nSteps = std::max(nSteps, sal_uInt32(1)); 1004ddde725dSArmin Le Grand 1005ddde725dSArmin Le Grand // preapare iteration 1006ddde725dSArmin Le Grand double fStart(0.0); 1007ddde725dSArmin Le Grand double fStep(fDelta / nSteps); 1008ddde725dSArmin Le Grand 1009ddde725dSArmin Le Grand xRetval.realloc(nSteps); 1010ddde725dSArmin Le Grand 1011ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep) 1012ddde725dSArmin Le Grand { 1013ddde725dSArmin Le Grand const double fLeft(getOffsetA() + fStart); 1014ddde725dSArmin Le Grand const double fRight(fLeft + fStep); 1015ddde725dSArmin Le Grand const basegfx::B2DPolygon aPolygon( 1016ddde725dSArmin Le Grand basegfx::tools::createPolygonFromRect( 1017ddde725dSArmin Le Grand basegfx::B2DRange( 1018ddde725dSArmin Le Grand fLeft - getOverlapping(), 1019ddde725dSArmin Le Grand 0.0, 1020ddde725dSArmin Le Grand fRight + getOverlapping(), 1021ddde725dSArmin Le Grand 1.0))); 1022ddde725dSArmin Le Grand 1023ddde725dSArmin Le Grand xRetval[a] = new PolyPolygonColorPrimitive2D( 1024ddde725dSArmin Le Grand basegfx::B2DPolyPolygon(aPolygon), 1025ddde725dSArmin Le Grand basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta)); 1026ddde725dSArmin Le Grand } 1027ddde725dSArmin Le Grand } 1028ddde725dSArmin Le Grand } 1029ddde725dSArmin Le Grand 1030ddde725dSArmin Le Grand return xRetval; 1031ddde725dSArmin Le Grand } 1032ddde725dSArmin Le Grand 1033ddde725dSArmin Le Grand bool SvgLinearAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 1034ddde725dSArmin Le Grand { 1035ddde725dSArmin Le Grand if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 1036ddde725dSArmin Le Grand { 1037ddde725dSArmin Le Grand const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive); 1038ddde725dSArmin Le Grand 1039ddde725dSArmin Le Grand return (getColorA() == rCompare.getColorA() 1040ddde725dSArmin Le Grand && getColorB() == rCompare.getColorB() 1041ddde725dSArmin Le Grand && getOffsetA() == rCompare.getOffsetA() 1042ddde725dSArmin Le Grand && getOffsetB() == rCompare.getOffsetB() 1043ddde725dSArmin Le Grand && getOverlapping() == rCompare.getOverlapping()); 1044ddde725dSArmin Le Grand } 1045ddde725dSArmin Le Grand 1046ddde725dSArmin Le Grand return false; 1047ddde725dSArmin Le Grand } 1048ddde725dSArmin Le Grand 1049ddde725dSArmin Le Grand // provide unique ID 1050ddde725dSArmin Le Grand ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D) 1051ddde725dSArmin Le Grand 1052ddde725dSArmin Le Grand } // end of namespace primitive2d 1053ddde725dSArmin Le Grand } // end of namespace drawinglayer 1054ddde725dSArmin Le Grand 1055ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 1056ddde725dSArmin Le Grand // SvgRadialAtomPrimitive2D class 1057ddde725dSArmin Le Grand 1058ddde725dSArmin Le Grand namespace drawinglayer 1059ddde725dSArmin Le Grand { 1060ddde725dSArmin Le Grand namespace primitive2d 1061ddde725dSArmin Le Grand { 1062ddde725dSArmin Le Grand Primitive2DSequence SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 1063ddde725dSArmin Le Grand { 1064ddde725dSArmin Le Grand Primitive2DSequence xRetval; 1065ddde725dSArmin Le Grand const double fDeltaScale(getScaleB() - getScaleA()); 1066ddde725dSArmin Le Grand 1067ddde725dSArmin Le Grand if(!basegfx::fTools::equalZero(fDeltaScale)) 1068ddde725dSArmin Le Grand { 1069ddde725dSArmin Le Grand if(getColorA() == getColorB()) 1070ddde725dSArmin Le Grand { 1071ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); 1072ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); 1073ddde725dSArmin Le Grand double fScaleA(getScaleA()); 1074ddde725dSArmin Le Grand const double fScaleB(getScaleB()); 1075ddde725dSArmin Le Grand 1076ddde725dSArmin Le Grand if(fScaleA > getOverlapping()) 1077ddde725dSArmin Le Grand { 1078ddde725dSArmin Le Grand fScaleA -= getOverlapping(); 1079ddde725dSArmin Le Grand } 1080ddde725dSArmin Le Grand 1081ddde725dSArmin Le Grand const bool bUseA(basegfx::fTools::equalZero(fScaleA)); 1082ddde725dSArmin Le Grand 1083ddde725dSArmin Le Grand if(getTranslateSet()) 1084ddde725dSArmin Le Grand { 1085ddde725dSArmin Le Grand if(bUseA) 1086ddde725dSArmin Le Grand { 1087ddde725dSArmin Le Grand aPolygonA.transform( 1088ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 1089ddde725dSArmin Le Grand fScaleA, 1090ddde725dSArmin Le Grand fScaleA, 1091ddde725dSArmin Le Grand getTranslateA().getX(), 1092ddde725dSArmin Le Grand getTranslateA().getY())); 1093ddde725dSArmin Le Grand } 1094ddde725dSArmin Le Grand 1095ddde725dSArmin Le Grand aPolygonB.transform( 1096ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 1097ddde725dSArmin Le Grand fScaleB, 1098ddde725dSArmin Le Grand fScaleB, 1099ddde725dSArmin Le Grand getTranslateB().getX(), 1100ddde725dSArmin Le Grand getTranslateB().getY())); 1101ddde725dSArmin Le Grand } 1102ddde725dSArmin Le Grand else 1103ddde725dSArmin Le Grand { 1104ddde725dSArmin Le Grand if(bUseA) 1105ddde725dSArmin Le Grand { 1106ddde725dSArmin Le Grand aPolygonA.transform( 1107ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 1108ddde725dSArmin Le Grand fScaleA, 1109ddde725dSArmin Le Grand fScaleA)); 1110ddde725dSArmin Le Grand } 1111ddde725dSArmin Le Grand 1112ddde725dSArmin Le Grand aPolygonB.transform( 1113ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 1114ddde725dSArmin Le Grand fScaleB, 1115ddde725dSArmin Le Grand fScaleB)); 1116ddde725dSArmin Le Grand } 1117ddde725dSArmin Le Grand 1118ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB); 1119ddde725dSArmin Le Grand 1120ddde725dSArmin Le Grand if(bUseA) 1121ddde725dSArmin Le Grand { 1122ddde725dSArmin Le Grand aPolyPolygon.append(aPolygonA); 1123ddde725dSArmin Le Grand } 1124ddde725dSArmin Le Grand 1125ddde725dSArmin Le Grand xRetval.realloc(1); 1126ddde725dSArmin Le Grand 1127ddde725dSArmin Le Grand xRetval[0] = new PolyPolygonColorPrimitive2D( 1128ddde725dSArmin Le Grand aPolyPolygon, 1129ddde725dSArmin Le Grand getColorA()); 1130ddde725dSArmin Le Grand } 1131ddde725dSArmin Le Grand else 1132ddde725dSArmin Le Grand { 1133ddde725dSArmin Le Grand // calc discrete length to change color all 2.5 pixels 1134ddde725dSArmin Le Grand sal_uInt32 nSteps(basegfx::fround(fDeltaScale / (getDiscreteUnit() * 2.5))); 1135ddde725dSArmin Le Grand 1136ddde725dSArmin Le Grand // use color distance, assume to do every 3rd 1137ddde725dSArmin Le Grand const double fColorDistance(getColorA().getDistance(getColorB())); 1138ddde725dSArmin Le Grand const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3))); 1139ddde725dSArmin Le Grand nSteps = std::min(nSteps, nColorSteps); 1140ddde725dSArmin Le Grand 1141ddde725dSArmin Le Grand // roughly cut when too big 1142ddde725dSArmin Le Grand nSteps = std::min(nSteps, sal_uInt32(100)); 1143ddde725dSArmin Le Grand nSteps = std::max(nSteps, sal_uInt32(1)); 1144ddde725dSArmin Le Grand 1145ddde725dSArmin Le Grand // preapare iteration 1146ddde725dSArmin Le Grand double fStartScale(0.0); 1147ddde725dSArmin Le Grand double fStepScale(fDeltaScale / nSteps); 1148ddde725dSArmin Le Grand 1149ddde725dSArmin Le Grand xRetval.realloc(nSteps); 1150ddde725dSArmin Le Grand 1151ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nSteps; a++, fStartScale += fStepScale) 1152ddde725dSArmin Le Grand { 1153ddde725dSArmin Le Grand double fScaleA(getScaleA() + fStartScale); 1154ddde725dSArmin Le Grand const double fScaleB(fScaleA + fStepScale); 1155ddde725dSArmin Le Grand const double fUnitScale(fStartScale/fDeltaScale); 1156ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle()); 1157ddde725dSArmin Le Grand basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle()); 1158ddde725dSArmin Le Grand 1159ddde725dSArmin Le Grand if(fScaleA > getOverlapping()) 1160ddde725dSArmin Le Grand { 1161ddde725dSArmin Le Grand fScaleA -= getOverlapping(); 1162ddde725dSArmin Le Grand } 1163ddde725dSArmin Le Grand 1164ddde725dSArmin Le Grand const bool bUseA(basegfx::fTools::equalZero(fScaleA)); 1165ddde725dSArmin Le Grand 1166ddde725dSArmin Le Grand if(getTranslateSet()) 1167ddde725dSArmin Le Grand { 1168ddde725dSArmin Le Grand const double fUnitScaleEnd((fStartScale + fStepScale)/fDeltaScale); 1169ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateB(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScaleEnd)); 1170ddde725dSArmin Le Grand 1171ddde725dSArmin Le Grand if(bUseA) 1172ddde725dSArmin Le Grand { 1173ddde725dSArmin Le Grand const basegfx::B2DVector aTranslateA(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScale)); 1174ddde725dSArmin Le Grand 1175ddde725dSArmin Le Grand aPolygonA.transform( 1176ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 1177ddde725dSArmin Le Grand fScaleA, 1178ddde725dSArmin Le Grand fScaleA, 1179ddde725dSArmin Le Grand aTranslateA.getX(), 1180ddde725dSArmin Le Grand aTranslateA.getY())); 1181ddde725dSArmin Le Grand } 1182ddde725dSArmin Le Grand 1183ddde725dSArmin Le Grand aPolygonB.transform( 1184ddde725dSArmin Le Grand basegfx::tools::createScaleTranslateB2DHomMatrix( 1185ddde725dSArmin Le Grand fScaleB, 1186ddde725dSArmin Le Grand fScaleB, 1187ddde725dSArmin Le Grand aTranslateB.getX(), 1188ddde725dSArmin Le Grand aTranslateB.getY())); 1189ddde725dSArmin Le Grand } 1190ddde725dSArmin Le Grand else 1191ddde725dSArmin Le Grand { 1192ddde725dSArmin Le Grand if(bUseA) 1193ddde725dSArmin Le Grand { 1194ddde725dSArmin Le Grand aPolygonA.transform( 1195ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 1196ddde725dSArmin Le Grand fScaleA, 1197ddde725dSArmin Le Grand fScaleA)); 1198ddde725dSArmin Le Grand } 1199ddde725dSArmin Le Grand 1200ddde725dSArmin Le Grand aPolygonB.transform( 1201ddde725dSArmin Le Grand basegfx::tools::createScaleB2DHomMatrix( 1202ddde725dSArmin Le Grand fScaleB, 1203ddde725dSArmin Le Grand fScaleB)); 1204ddde725dSArmin Le Grand } 1205ddde725dSArmin Le Grand 1206ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB); 1207ddde725dSArmin Le Grand 1208ddde725dSArmin Le Grand if(bUseA) 1209ddde725dSArmin Le Grand { 1210ddde725dSArmin Le Grand aPolyPolygon.append(aPolygonA); 1211ddde725dSArmin Le Grand } 1212ddde725dSArmin Le Grand 1213ddde725dSArmin Le Grand xRetval[nSteps - 1 - a] = new PolyPolygonColorPrimitive2D( 1214ddde725dSArmin Le Grand aPolyPolygon, 1215ddde725dSArmin Le Grand basegfx::interpolate(getColorA(), getColorB(), fUnitScale)); 1216ddde725dSArmin Le Grand } 1217ddde725dSArmin Le Grand } 1218ddde725dSArmin Le Grand } 1219ddde725dSArmin Le Grand 1220ddde725dSArmin Le Grand return xRetval; 1221ddde725dSArmin Le Grand } 1222ddde725dSArmin Le Grand 1223ddde725dSArmin Le Grand bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 1224ddde725dSArmin Le Grand { 1225ddde725dSArmin Le Grand if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 1226ddde725dSArmin Le Grand { 1227ddde725dSArmin Le Grand const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive); 1228ddde725dSArmin Le Grand 1229ddde725dSArmin Le Grand return (getColorA() == rCompare.getColorA() 1230ddde725dSArmin Le Grand && getColorB() == rCompare.getColorB() 1231ddde725dSArmin Le Grand && getScaleA() == rCompare.getScaleA() 1232ddde725dSArmin Le Grand && getScaleB() == rCompare.getScaleB() 1233ddde725dSArmin Le Grand && getTranslateA() == rCompare.getTranslateA() 1234ddde725dSArmin Le Grand && getTranslateB() == rCompare.getTranslateB() 1235ddde725dSArmin Le Grand && getOverlapping() == rCompare.getOverlapping()); 1236ddde725dSArmin Le Grand } 1237ddde725dSArmin Le Grand 1238ddde725dSArmin Le Grand return false; 1239ddde725dSArmin Le Grand } 1240ddde725dSArmin Le Grand 1241ddde725dSArmin Le Grand // provide unique ID 1242ddde725dSArmin Le Grand ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D) 1243ddde725dSArmin Le Grand 1244ddde725dSArmin Le Grand } // end of namespace primitive2d 1245ddde725dSArmin Le Grand } // end of namespace drawinglayer 1246ddde725dSArmin Le Grand 1247ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 1248ddde725dSArmin Le Grand // eof 1249