1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <drawinglayer/primitive2d/sceneprimitive2d.hxx> 32*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 33*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 34*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 35*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 36*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 37*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 38*cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 39*cdf0e10cSrcweir #include <drawinglayer/processor3d/zbufferprocessor3d.hxx> 40*cdf0e10cSrcweir #include <drawinglayer/processor3d/shadow3dextractor.hxx> 41*cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation2d.hxx> 42*cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 43*cdf0e10cSrcweir #include <svtools/optionsdrawinglayer.hxx> 44*cdf0e10cSrcweir #include <drawinglayer/processor3d/geometry2dextractor.hxx> 45*cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir using namespace com::sun::star; 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir namespace drawinglayer 54*cdf0e10cSrcweir { 55*cdf0e10cSrcweir namespace primitive2d 56*cdf0e10cSrcweir { 57*cdf0e10cSrcweir bool ScenePrimitive2D::impGetShadow3D(const geometry::ViewInformation2D& /*rViewInformation*/) const 58*cdf0e10cSrcweir { 59*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir // create on demand 62*cdf0e10cSrcweir if(!mbShadow3DChecked && getChildren3D().hasElements()) 63*cdf0e10cSrcweir { 64*cdf0e10cSrcweir basegfx::B3DVector aLightNormal; 65*cdf0e10cSrcweir const double fShadowSlant(getSdrSceneAttribute().getShadowSlant()); 66*cdf0e10cSrcweir const basegfx::B3DRange aScene3DRange(primitive3d::getB3DRangeFromPrimitive3DSequence(getChildren3D(), getViewInformation3D())); 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir if(maSdrLightingAttribute.getLightVector().size()) 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir // get light normal from first light and normalize 71*cdf0e10cSrcweir aLightNormal = maSdrLightingAttribute.getLightVector()[0].getDirection(); 72*cdf0e10cSrcweir aLightNormal.normalize(); 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir // create shadow extraction processor 76*cdf0e10cSrcweir processor3d::Shadow3DExtractingProcessor aShadowProcessor( 77*cdf0e10cSrcweir getViewInformation3D(), 78*cdf0e10cSrcweir getObjectTransformation(), 79*cdf0e10cSrcweir aLightNormal, 80*cdf0e10cSrcweir fShadowSlant, 81*cdf0e10cSrcweir aScene3DRange); 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir // process local primitives 84*cdf0e10cSrcweir aShadowProcessor.process(getChildren3D()); 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir // fetch result and set checked flag 87*cdf0e10cSrcweir const_cast< ScenePrimitive2D* >(this)->maShadowPrimitives = aShadowProcessor.getPrimitive2DSequence(); 88*cdf0e10cSrcweir const_cast< ScenePrimitive2D* >(this)->mbShadow3DChecked = true; 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir // return if there are shadow primitives 92*cdf0e10cSrcweir return maShadowPrimitives.hasElements(); 93*cdf0e10cSrcweir } 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir void ScenePrimitive2D::calculateDiscreteSizes( 96*cdf0e10cSrcweir const geometry::ViewInformation2D& rViewInformation, 97*cdf0e10cSrcweir basegfx::B2DRange& rDiscreteRange, 98*cdf0e10cSrcweir basegfx::B2DRange& rVisibleDiscreteRange, 99*cdf0e10cSrcweir basegfx::B2DRange& rUnitVisibleRange) const 100*cdf0e10cSrcweir { 101*cdf0e10cSrcweir // use unit range and transform to discrete coordinates 102*cdf0e10cSrcweir rDiscreteRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); 103*cdf0e10cSrcweir rDiscreteRange.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir // clip it against discrete Viewport (if set) 106*cdf0e10cSrcweir rVisibleDiscreteRange = rDiscreteRange; 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir if(!rViewInformation.getViewport().isEmpty()) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir rVisibleDiscreteRange.intersect(rViewInformation.getDiscreteViewport()); 111*cdf0e10cSrcweir } 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir if(rVisibleDiscreteRange.isEmpty()) 114*cdf0e10cSrcweir { 115*cdf0e10cSrcweir rUnitVisibleRange = rVisibleDiscreteRange; 116*cdf0e10cSrcweir } 117*cdf0e10cSrcweir else 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir // create UnitVisibleRange containing unit range values [0.0 .. 1.0] describing 120*cdf0e10cSrcweir // the relative position of rVisibleDiscreteRange inside rDiscreteRange 121*cdf0e10cSrcweir const double fDiscreteScaleFactorX(basegfx::fTools::equalZero(rDiscreteRange.getWidth()) ? 1.0 : 1.0 / rDiscreteRange.getWidth()); 122*cdf0e10cSrcweir const double fDiscreteScaleFactorY(basegfx::fTools::equalZero(rDiscreteRange.getHeight()) ? 1.0 : 1.0 / rDiscreteRange.getHeight()); 123*cdf0e10cSrcweir 124*cdf0e10cSrcweir const double fMinX(basegfx::fTools::equal(rVisibleDiscreteRange.getMinX(), rDiscreteRange.getMinX()) 125*cdf0e10cSrcweir ? 0.0 126*cdf0e10cSrcweir : (rVisibleDiscreteRange.getMinX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX); 127*cdf0e10cSrcweir const double fMinY(basegfx::fTools::equal(rVisibleDiscreteRange.getMinY(), rDiscreteRange.getMinY()) 128*cdf0e10cSrcweir ? 0.0 129*cdf0e10cSrcweir : (rVisibleDiscreteRange.getMinY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY); 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir const double fMaxX(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxX(), rDiscreteRange.getMaxX()) 132*cdf0e10cSrcweir ? 1.0 133*cdf0e10cSrcweir : (rVisibleDiscreteRange.getMaxX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX); 134*cdf0e10cSrcweir const double fMaxY(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxY(), rDiscreteRange.getMaxY()) 135*cdf0e10cSrcweir ? 1.0 136*cdf0e10cSrcweir : (rVisibleDiscreteRange.getMaxY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY); 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir rUnitVisibleRange = basegfx::B2DRange(fMinX, fMinY, fMaxX, fMaxY); 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir Primitive2DSequence ScenePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir Primitive2DSequence aRetval; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir // create 2D shadows from contained 3D primitives. This creates the shadow primitives on demand and tells if 147*cdf0e10cSrcweir // there are some or not. Do this at start, the shadow might still be visible even when the scene is not 148*cdf0e10cSrcweir if(impGetShadow3D(rViewInformation)) 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir // test visibility 151*cdf0e10cSrcweir const basegfx::B2DRange aShadow2DRange( 152*cdf0e10cSrcweir getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation)); 153*cdf0e10cSrcweir const basegfx::B2DRange aViewRange( 154*cdf0e10cSrcweir rViewInformation.getViewport()); 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir if(aViewRange.isEmpty() || aShadow2DRange.overlaps(aViewRange)) 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir // add extracted 2d shadows (before 3d scene creations itself) 159*cdf0e10cSrcweir aRetval = maShadowPrimitives; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir // get the involved ranges (see helper method calculateDiscreteSizes for details) 164*cdf0e10cSrcweir basegfx::B2DRange aDiscreteRange; 165*cdf0e10cSrcweir basegfx::B2DRange aVisibleDiscreteRange; 166*cdf0e10cSrcweir basegfx::B2DRange aUnitVisibleRange; 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir if(!aVisibleDiscreteRange.isEmpty()) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir // test if discrete view size (pixel) maybe too big and limit it 173*cdf0e10cSrcweir double fViewSizeX(aVisibleDiscreteRange.getWidth()); 174*cdf0e10cSrcweir double fViewSizeY(aVisibleDiscreteRange.getHeight()); 175*cdf0e10cSrcweir const double fViewVisibleArea(fViewSizeX * fViewSizeY); 176*cdf0e10cSrcweir const SvtOptionsDrawinglayer aDrawinglayerOpt; 177*cdf0e10cSrcweir const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit()); 178*cdf0e10cSrcweir double fReduceFactor(1.0); 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir if(fViewVisibleArea > fMaximumVisibleArea) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir fReduceFactor = sqrt(fMaximumVisibleArea / fViewVisibleArea); 183*cdf0e10cSrcweir fViewSizeX *= fReduceFactor; 184*cdf0e10cSrcweir fViewSizeY *= fReduceFactor; 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir if(rViewInformation.getReducedDisplayQuality()) 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir // when reducing the visualisation is allowed (e.g. an OverlayObject 190*cdf0e10cSrcweir // only needed for dragging), reduce resolution extra 191*cdf0e10cSrcweir // to speed up dragging interactions 192*cdf0e10cSrcweir const double fArea(fViewSizeX * fViewSizeY); 193*cdf0e10cSrcweir double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0))); 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir if(fReducedVisualisationFactor > 1.0) 196*cdf0e10cSrcweir { 197*cdf0e10cSrcweir fReducedVisualisationFactor = 1.0; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir else if(fReducedVisualisationFactor < 0.20) 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir fReducedVisualisationFactor = 0.20; 202*cdf0e10cSrcweir } 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir if(fReducedVisualisationFactor != 1.0) 205*cdf0e10cSrcweir { 206*cdf0e10cSrcweir fReduceFactor *= fReducedVisualisationFactor; 207*cdf0e10cSrcweir fViewSizeX *= fReducedVisualisationFactor; 208*cdf0e10cSrcweir fViewSizeY *= fReducedVisualisationFactor; 209*cdf0e10cSrcweir } 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir // calculate logic render size in world coordinates for usage in renderer 213*cdf0e10cSrcweir basegfx::B2DVector aLogicRenderSize( 214*cdf0e10cSrcweir aDiscreteRange.getWidth() * fReduceFactor, 215*cdf0e10cSrcweir aDiscreteRange.getHeight() * fReduceFactor); 216*cdf0e10cSrcweir aLogicRenderSize *= rViewInformation.getInverseObjectToViewTransformation(); 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir // determine the oversample value 219*cdf0e10cSrcweir static sal_uInt16 nDefaultOversampleValue(3); 220*cdf0e10cSrcweir const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process 223*cdf0e10cSrcweir processor3d::ZBufferProcessor3D aZBufferProcessor3D( 224*cdf0e10cSrcweir getViewInformation3D(), 225*cdf0e10cSrcweir rViewInformation, 226*cdf0e10cSrcweir getSdrSceneAttribute(), 227*cdf0e10cSrcweir getSdrLightingAttribute(), 228*cdf0e10cSrcweir aLogicRenderSize.getX(), 229*cdf0e10cSrcweir aLogicRenderSize.getY(), 230*cdf0e10cSrcweir aUnitVisibleRange, 231*cdf0e10cSrcweir nOversampleValue); 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir aZBufferProcessor3D.process(getChildren3D()); 234*cdf0e10cSrcweir aZBufferProcessor3D.finish(); 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx(); 237*cdf0e10cSrcweir const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir // create transform for the created bitmap in discrete coordinates first. 242*cdf0e10cSrcweir basegfx::B2DHomMatrix aNew2DTransform; 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); 245*cdf0e10cSrcweir aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); 246*cdf0e10cSrcweir aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); 247*cdf0e10cSrcweir aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir // transform back to world coordinates for usage in primitive creation 250*cdf0e10cSrcweir aNew2DTransform *= rViewInformation.getInverseObjectToViewTransformation(); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir // create bitmap primitive and add 253*cdf0e10cSrcweir const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); 254*cdf0e10cSrcweir appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef); 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir // test: Allow to add an outline in the debugger when tests are needed 257*cdf0e10cSrcweir static bool bAddOutlineToCreated3DSceneRepresentation(false); 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir if(bAddOutlineToCreated3DSceneRepresentation) 260*cdf0e10cSrcweir { 261*cdf0e10cSrcweir basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon()); 262*cdf0e10cSrcweir aOutline.transform(aNew2DTransform); 263*cdf0e10cSrcweir const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); 264*cdf0e10cSrcweir appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef2); 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir } 268*cdf0e10cSrcweir 269*cdf0e10cSrcweir return aRetval; 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir Primitive2DSequence ScenePrimitive2D::getGeometry2D() const 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir Primitive2DSequence aRetval; 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir // create 2D projected geometry from 3D geometry 277*cdf0e10cSrcweir if(getChildren3D().hasElements()) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir // create 2D geometry extraction processor 280*cdf0e10cSrcweir processor3d::Geometry2DExtractingProcessor aGeometryProcessor( 281*cdf0e10cSrcweir getViewInformation3D(), 282*cdf0e10cSrcweir getObjectTransformation()); 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir // process local primitives 285*cdf0e10cSrcweir aGeometryProcessor.process(getChildren3D()); 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir // fetch result 288*cdf0e10cSrcweir aRetval = aGeometryProcessor.getPrimitive2DSequence(); 289*cdf0e10cSrcweir } 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir return aRetval; 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir Primitive2DSequence ScenePrimitive2D::getShadow2D(const geometry::ViewInformation2D& rViewInformation) const 295*cdf0e10cSrcweir { 296*cdf0e10cSrcweir Primitive2DSequence aRetval; 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir // create 2D shadows from contained 3D primitives 299*cdf0e10cSrcweir if(impGetShadow3D(rViewInformation)) 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir // add extracted 2d shadows (before 3d scene creations itself) 302*cdf0e10cSrcweir aRetval = maShadowPrimitives; 303*cdf0e10cSrcweir } 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir return aRetval; 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir bool ScenePrimitive2D::tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const 309*cdf0e10cSrcweir { 310*cdf0e10cSrcweir if(!maOldRenderedBitmap.IsEmpty() && !maOldUnitVisiblePart.isEmpty()) 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation()); 313*cdf0e10cSrcweir aInverseSceneTransform.invert(); 314*cdf0e10cSrcweir const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint); 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir if(maOldUnitVisiblePart.isInside(aRelativePoint)) 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir // calculate coordinates relative to visualized part 319*cdf0e10cSrcweir double fDivisorX(maOldUnitVisiblePart.getWidth()); 320*cdf0e10cSrcweir double fDivisorY(maOldUnitVisiblePart.getHeight()); 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir if(basegfx::fTools::equalZero(fDivisorX)) 323*cdf0e10cSrcweir { 324*cdf0e10cSrcweir fDivisorX = 1.0; 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir if(basegfx::fTools::equalZero(fDivisorY)) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir fDivisorY = 1.0; 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX); 333*cdf0e10cSrcweir const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY); 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir // combine with real BitmapSizePixel to get bitmap coordinates 336*cdf0e10cSrcweir const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); 337*cdf0e10cSrcweir const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width())); 338*cdf0e10cSrcweir const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height())); 339*cdf0e10cSrcweir 340*cdf0e10cSrcweir // try to get a statement about transparency in that pixel 341*cdf0e10cSrcweir o_rResult = (0xff != maOldRenderedBitmap.GetTransparency(nX, nY)); 342*cdf0e10cSrcweir return true; 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir } 345*cdf0e10cSrcweir 346*cdf0e10cSrcweir return false; 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir ScenePrimitive2D::ScenePrimitive2D( 350*cdf0e10cSrcweir const primitive3d::Primitive3DSequence& rxChildren3D, 351*cdf0e10cSrcweir const attribute::SdrSceneAttribute& rSdrSceneAttribute, 352*cdf0e10cSrcweir const attribute::SdrLightingAttribute& rSdrLightingAttribute, 353*cdf0e10cSrcweir const basegfx::B2DHomMatrix& rObjectTransformation, 354*cdf0e10cSrcweir const geometry::ViewInformation3D& rViewInformation3D) 355*cdf0e10cSrcweir : BufferedDecompositionPrimitive2D(), 356*cdf0e10cSrcweir mxChildren3D(rxChildren3D), 357*cdf0e10cSrcweir maSdrSceneAttribute(rSdrSceneAttribute), 358*cdf0e10cSrcweir maSdrLightingAttribute(rSdrLightingAttribute), 359*cdf0e10cSrcweir maObjectTransformation(rObjectTransformation), 360*cdf0e10cSrcweir maViewInformation3D(rViewInformation3D), 361*cdf0e10cSrcweir maShadowPrimitives(), 362*cdf0e10cSrcweir mbShadow3DChecked(false), 363*cdf0e10cSrcweir mfOldDiscreteSizeX(0.0), 364*cdf0e10cSrcweir mfOldDiscreteSizeY(0.0), 365*cdf0e10cSrcweir maOldUnitVisiblePart(), 366*cdf0e10cSrcweir maOldRenderedBitmap() 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir } 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir bool ScenePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir const ScenePrimitive2D& rCompare = (ScenePrimitive2D&)rPrimitive; 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir return (primitive3d::arePrimitive3DSequencesEqual(getChildren3D(), rCompare.getChildren3D()) 377*cdf0e10cSrcweir && getSdrSceneAttribute() == rCompare.getSdrSceneAttribute() 378*cdf0e10cSrcweir && getSdrLightingAttribute() == rCompare.getSdrLightingAttribute() 379*cdf0e10cSrcweir && getObjectTransformation() == rCompare.getObjectTransformation() 380*cdf0e10cSrcweir && getViewInformation3D() == rCompare.getViewInformation3D()); 381*cdf0e10cSrcweir } 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir return false; 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir basegfx::B2DRange ScenePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const 387*cdf0e10cSrcweir { 388*cdf0e10cSrcweir // transform unit range to discrete coordinate range 389*cdf0e10cSrcweir basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); 390*cdf0e10cSrcweir aRetval.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir // force to discrete expanded bounds (it grows, so expanding works perfectly well) 393*cdf0e10cSrcweir aRetval.expand(basegfx::B2DTuple(floor(aRetval.getMinX()), floor(aRetval.getMinY()))); 394*cdf0e10cSrcweir aRetval.expand(basegfx::B2DTuple(ceil(aRetval.getMaxX()), ceil(aRetval.getMaxY()))); 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir // transform back from discrete (view) to world coordinates 397*cdf0e10cSrcweir aRetval.transform(rViewInformation.getInverseObjectToViewTransformation()); 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir // expand by evtl. existing shadow primitives 400*cdf0e10cSrcweir if(impGetShadow3D(rViewInformation)) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir const basegfx::B2DRange aShadow2DRange(getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation)); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir if(!aShadow2DRange.isEmpty()) 405*cdf0e10cSrcweir { 406*cdf0e10cSrcweir aRetval.expand(aShadow2DRange); 407*cdf0e10cSrcweir } 408*cdf0e10cSrcweir } 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir return aRetval; 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir Primitive2DSequence ScenePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 414*cdf0e10cSrcweir { 415*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir // get the involved ranges (see helper method calculateDiscreteSizes for details) 418*cdf0e10cSrcweir basegfx::B2DRange aDiscreteRange; 419*cdf0e10cSrcweir basegfx::B2DRange aUnitVisibleRange; 420*cdf0e10cSrcweir bool bNeedNewDecomposition(false); 421*cdf0e10cSrcweir bool bDiscreteSizesAreCalculated(false); 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir if(getBuffered2DDecomposition().hasElements()) 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir basegfx::B2DRange aVisibleDiscreteRange; 426*cdf0e10cSrcweir calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); 427*cdf0e10cSrcweir bDiscreteSizesAreCalculated = true; 428*cdf0e10cSrcweir 429*cdf0e10cSrcweir // needs to be painted when the new part is not part of the last 430*cdf0e10cSrcweir // decomposition 431*cdf0e10cSrcweir if(!maOldUnitVisiblePart.isInside(aUnitVisibleRange)) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir bNeedNewDecomposition = true; 434*cdf0e10cSrcweir } 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir // display has changed and cannot be reused when resolution got bigger. It 437*cdf0e10cSrcweir // can be reused when resolution got smaller, though. 438*cdf0e10cSrcweir if(!bNeedNewDecomposition) 439*cdf0e10cSrcweir { 440*cdf0e10cSrcweir if(basegfx::fTools::more(aDiscreteRange.getWidth(), mfOldDiscreteSizeX) || 441*cdf0e10cSrcweir basegfx::fTools::more(aDiscreteRange.getHeight(), mfOldDiscreteSizeY)) 442*cdf0e10cSrcweir { 443*cdf0e10cSrcweir bNeedNewDecomposition = true; 444*cdf0e10cSrcweir } 445*cdf0e10cSrcweir } 446*cdf0e10cSrcweir } 447*cdf0e10cSrcweir 448*cdf0e10cSrcweir if(bNeedNewDecomposition) 449*cdf0e10cSrcweir { 450*cdf0e10cSrcweir // conditions of last local decomposition have changed, delete 451*cdf0e10cSrcweir const_cast< ScenePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence()); 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir if(!getBuffered2DDecomposition().hasElements()) 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir if(!bDiscreteSizesAreCalculated) 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir basegfx::B2DRange aVisibleDiscreteRange; 459*cdf0e10cSrcweir calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); 460*cdf0e10cSrcweir } 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir // remember last used NewDiscreteSize and NewUnitVisiblePart 463*cdf0e10cSrcweir ScenePrimitive2D* pThat = const_cast< ScenePrimitive2D* >(this); 464*cdf0e10cSrcweir pThat->mfOldDiscreteSizeX = aDiscreteRange.getWidth(); 465*cdf0e10cSrcweir pThat->mfOldDiscreteSizeY = aDiscreteRange.getHeight(); 466*cdf0e10cSrcweir pThat->maOldUnitVisiblePart = aUnitVisibleRange; 467*cdf0e10cSrcweir } 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir // use parent implementation 470*cdf0e10cSrcweir return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation); 471*cdf0e10cSrcweir } 472*cdf0e10cSrcweir 473*cdf0e10cSrcweir // provide unique ID 474*cdf0e10cSrcweir ImplPrimitrive2DIDBlock(ScenePrimitive2D, PRIMITIVE2D_ID_SCENEPRIMITIVE2D) 475*cdf0e10cSrcweir 476*cdf0e10cSrcweir } // end of namespace primitive2d 477*cdf0e10cSrcweir } // end of namespace drawinglayer 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 480*cdf0e10cSrcweir // eof 481