LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - sceneprimitive2d.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 131 210 62.4 %
Date: 2015-06-13 12:38:46 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
      21             : #include <basegfx/tools/canvastools.hxx>
      22             : #include <basegfx/polygon/b2dpolygontools.hxx>
      23             : #include <basegfx/polygon/b2dpolygon.hxx>
      24             : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      25             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      26             : #include <basegfx/matrix/b2dhommatrix.hxx>
      27             : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
      28             : #include <drawinglayer/processor3d/zbufferprocessor3d.hxx>
      29             : #include <drawinglayer/processor3d/shadow3dextractor.hxx>
      30             : #include <drawinglayer/geometry/viewinformation2d.hxx>
      31             : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      32             : #include <svtools/optionsdrawinglayer.hxx>
      33             : #include <drawinglayer/processor3d/geometry2dextractor.hxx>
      34             : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
      35             : 
      36             : 
      37             : 
      38             : using namespace com::sun::star;
      39             : 
      40             : 
      41             : 
      42             : namespace drawinglayer
      43             : {
      44             :     namespace primitive2d
      45             :     {
      46         110 :         bool ScenePrimitive2D::impGetShadow3D(const geometry::ViewInformation2D& /*rViewInformation*/) const
      47             :         {
      48         110 :             ::osl::MutexGuard aGuard( m_aMutex );
      49             : 
      50             :             // create on demand
      51         110 :             if(!mbShadow3DChecked && getChildren3D().hasElements())
      52             :             {
      53          15 :                 basegfx::B3DVector aLightNormal;
      54          15 :                 const double fShadowSlant(getSdrSceneAttribute().getShadowSlant());
      55          15 :                 const basegfx::B3DRange aScene3DRange(primitive3d::getB3DRangeFromPrimitive3DSequence(getChildren3D(), getViewInformation3D()));
      56             : 
      57          15 :                 if(maSdrLightingAttribute.getLightVector().size())
      58             :                 {
      59             :                     // get light normal from first light and normalize
      60          15 :                     aLightNormal = maSdrLightingAttribute.getLightVector()[0].getDirection();
      61          15 :                     aLightNormal.normalize();
      62             :                 }
      63             : 
      64             :                 // create shadow extraction processor
      65             :                 processor3d::Shadow3DExtractingProcessor aShadowProcessor(
      66          15 :                     getViewInformation3D(),
      67          15 :                     getObjectTransformation(),
      68             :                     aLightNormal,
      69             :                     fShadowSlant,
      70          30 :                     aScene3DRange);
      71             : 
      72             :                 // process local primitives
      73          15 :                 aShadowProcessor.process(getChildren3D());
      74             : 
      75             :                 // fetch result and set checked flag
      76          15 :                 const_cast< ScenePrimitive2D* >(this)->maShadowPrimitives = aShadowProcessor.getPrimitive2DSequence();
      77          30 :                 const_cast< ScenePrimitive2D* >(this)->mbShadow3DChecked = true;
      78             :             }
      79             : 
      80             :             // return if there are shadow primitives
      81         110 :             return maShadowPrimitives.hasElements();
      82             :         }
      83             : 
      84          35 :         void ScenePrimitive2D::calculateDiscreteSizes(
      85             :             const geometry::ViewInformation2D& rViewInformation,
      86             :             basegfx::B2DRange& rDiscreteRange,
      87             :             basegfx::B2DRange& rVisibleDiscreteRange,
      88             :             basegfx::B2DRange& rUnitVisibleRange) const
      89             :         {
      90             :             // use unit range and transform to discrete coordinates
      91          35 :             rDiscreteRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0);
      92          35 :             rDiscreteRange.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation());
      93             : 
      94             :             // clip it against discrete Viewport (if set)
      95          35 :             rVisibleDiscreteRange = rDiscreteRange;
      96             : 
      97          35 :             if(!rViewInformation.getViewport().isEmpty())
      98             :             {
      99          35 :                 rVisibleDiscreteRange.intersect(rViewInformation.getDiscreteViewport());
     100             :             }
     101             : 
     102          35 :             if(rVisibleDiscreteRange.isEmpty())
     103             :             {
     104           0 :                 rUnitVisibleRange = rVisibleDiscreteRange;
     105             :             }
     106             :             else
     107             :             {
     108             :                 // create UnitVisibleRange containing unit range values [0.0 .. 1.0] describing
     109             :                 // the relative position of rVisibleDiscreteRange inside rDiscreteRange
     110          35 :                 const double fDiscreteScaleFactorX(basegfx::fTools::equalZero(rDiscreteRange.getWidth()) ? 1.0 : 1.0 / rDiscreteRange.getWidth());
     111          35 :                 const double fDiscreteScaleFactorY(basegfx::fTools::equalZero(rDiscreteRange.getHeight()) ? 1.0 : 1.0 / rDiscreteRange.getHeight());
     112             : 
     113          70 :                 const double fMinX(basegfx::fTools::equal(rVisibleDiscreteRange.getMinX(), rDiscreteRange.getMinX())
     114             :                     ? 0.0
     115          35 :                     : (rVisibleDiscreteRange.getMinX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX);
     116          70 :                 const double fMinY(basegfx::fTools::equal(rVisibleDiscreteRange.getMinY(), rDiscreteRange.getMinY())
     117             :                     ? 0.0
     118          35 :                     : (rVisibleDiscreteRange.getMinY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY);
     119             : 
     120          70 :                 const double fMaxX(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxX(), rDiscreteRange.getMaxX())
     121             :                     ? 1.0
     122          35 :                     : (rVisibleDiscreteRange.getMaxX() - rDiscreteRange.getMinX()) * fDiscreteScaleFactorX);
     123          70 :                 const double fMaxY(basegfx::fTools::equal(rVisibleDiscreteRange.getMaxY(), rDiscreteRange.getMaxY())
     124             :                     ? 1.0
     125          35 :                     : (rVisibleDiscreteRange.getMaxY() - rDiscreteRange.getMinY()) * fDiscreteScaleFactorY);
     126             : 
     127          35 :                 rUnitVisibleRange = basegfx::B2DRange(fMinX, fMinY, fMaxX, fMaxY);
     128             :             }
     129          35 :         }
     130             : 
     131          13 :         Primitive2DSequence ScenePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
     132             :         {
     133          13 :             Primitive2DSequence aRetval;
     134             : 
     135             :             // create 2D shadows from contained 3D primitives. This creates the shadow primitives on demand and tells if
     136             :             // there are some or not. Do this at start, the shadow might still be visible even when the scene is not
     137          13 :             if(impGetShadow3D(rViewInformation))
     138             :             {
     139             :                 // test visibility
     140             :                 const basegfx::B2DRange aShadow2DRange(
     141           0 :                     getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation));
     142             :                 const basegfx::B2DRange aViewRange(
     143           0 :                     rViewInformation.getViewport());
     144             : 
     145           0 :                 if(aViewRange.isEmpty() || aShadow2DRange.overlaps(aViewRange))
     146             :                 {
     147             :                     // add extracted 2d shadows (before 3d scene creations itself)
     148           0 :                     aRetval = maShadowPrimitives;
     149             :                 }
     150             :             }
     151             : 
     152             :             // get the involved ranges (see helper method calculateDiscreteSizes for details)
     153          13 :             basegfx::B2DRange aDiscreteRange;
     154          13 :             basegfx::B2DRange aVisibleDiscreteRange;
     155          13 :             basegfx::B2DRange aUnitVisibleRange;
     156             : 
     157          13 :             calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange);
     158             : 
     159          13 :             if(!aVisibleDiscreteRange.isEmpty())
     160             :             {
     161             :                 // test if discrete view size (pixel) maybe too big and limit it
     162          13 :                 double fViewSizeX(aVisibleDiscreteRange.getWidth());
     163          13 :                 double fViewSizeY(aVisibleDiscreteRange.getHeight());
     164          13 :                 const double fViewVisibleArea(fViewSizeX * fViewSizeY);
     165          13 :                 const SvtOptionsDrawinglayer aDrawinglayerOpt;
     166          13 :                 const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit());
     167          13 :                 double fReduceFactor(1.0);
     168             : 
     169          13 :                 if(fViewVisibleArea > fMaximumVisibleArea)
     170             :                 {
     171           0 :                     fReduceFactor = sqrt(fMaximumVisibleArea / fViewVisibleArea);
     172           0 :                     fViewSizeX *= fReduceFactor;
     173           0 :                     fViewSizeY *= fReduceFactor;
     174             :                 }
     175             : 
     176          13 :                 if(rViewInformation.getReducedDisplayQuality())
     177             :                 {
     178             :                     // when reducing the visualisation is allowed (e.g. an OverlayObject
     179             :                     // only needed for dragging), reduce resolution extra
     180             :                     // to speed up dragging interactions
     181           0 :                     const double fArea(fViewSizeX * fViewSizeY);
     182           0 :                     double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0)));
     183             : 
     184           0 :                     if(fReducedVisualisationFactor > 1.0)
     185             :                     {
     186           0 :                         fReducedVisualisationFactor = 1.0;
     187             :                     }
     188           0 :                     else if(fReducedVisualisationFactor < 0.20)
     189             :                     {
     190           0 :                         fReducedVisualisationFactor = 0.20;
     191             :                     }
     192             : 
     193           0 :                     if(fReducedVisualisationFactor != 1.0)
     194             :                     {
     195           0 :                         fReduceFactor *= fReducedVisualisationFactor;
     196             :                     }
     197             :                 }
     198             : 
     199             :                 // determine the oversample value
     200             :                 static sal_uInt16 nDefaultOversampleValue(3);
     201          13 :                 const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0);
     202             : 
     203          26 :                 geometry::ViewInformation3D aViewInformation3D(getViewInformation3D());
     204             :                 {
     205             :                     // calculate a transformation from DiscreteRange to evtl. rotated/sheared content.
     206             :                     // Start with full transformation from object to discrete units
     207          13 :                     basegfx::B2DHomMatrix aObjToUnit(rViewInformation.getObjectToViewTransformation() * getObjectTransformation());
     208             : 
     209             :                     // bring to unit coordinates by applying inverse DiscreteRange
     210          13 :                     aObjToUnit.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY());
     211          13 :                     aObjToUnit.scale(1.0 / aDiscreteRange.getWidth(), 1.0 / aDiscreteRange.getHeight());
     212             : 
     213             :                     // calculate transformed user coordinate system
     214          26 :                     const basegfx::B2DPoint aStandardNull(0.0, 0.0);
     215          26 :                     const basegfx::B2DPoint aUnitRangeTopLeft(aObjToUnit * aStandardNull);
     216          26 :                     const basegfx::B2DVector aStandardXAxis(1.0, 0.0);
     217          26 :                     const basegfx::B2DVector aUnitRangeXAxis(aObjToUnit * aStandardXAxis);
     218          26 :                     const basegfx::B2DVector aStandardYAxis(0.0, 1.0);
     219          26 :                     const basegfx::B2DVector aUnitRangeYAxis(aObjToUnit * aStandardYAxis);
     220             : 
     221          13 :                     if(!aUnitRangeTopLeft.equal(aStandardNull) || !aUnitRangeXAxis.equal(aStandardXAxis) || !aUnitRangeYAxis.equal(aStandardYAxis))
     222             :                     {
     223             :                         // build transformation from unit range to user coordinate system; the unit range
     224             :                         // X and Y axes are the column vectors, the null point is the offset
     225           0 :                         basegfx::B2DHomMatrix aUnitRangeToUser;
     226             : 
     227             :                         aUnitRangeToUser.set3x2(
     228             :                             aUnitRangeXAxis.getX(), aUnitRangeYAxis.getX(), aUnitRangeTopLeft.getX(),
     229           0 :                             aUnitRangeXAxis.getY(), aUnitRangeYAxis.getY(), aUnitRangeTopLeft.getY());
     230             : 
     231             :                         // decompose to allow to apply this to the 3D transformation
     232           0 :                         basegfx::B2DVector aScale, aTranslate;
     233             :                         double fRotate, fShearX;
     234           0 :                         aUnitRangeToUser.decompose(aScale, aTranslate, fRotate, fShearX);
     235             : 
     236             :                         // apply before DeviceToView and after Projection, 3D is in range [-1.0 .. 1.0] in X,Y and Z
     237             :                         // and not yet flipped in Y
     238           0 :                         basegfx::B3DHomMatrix aExtendedProjection(aViewInformation3D.getProjection());
     239             : 
     240             :                         // bring to unit coordiantes, flip Y, leave Z unchanged
     241           0 :                         aExtendedProjection.scale(0.5, -0.5, 1.0);
     242           0 :                         aExtendedProjection.translate(0.5, 0.5, 0.0);
     243             : 
     244             :                         // apply extra; Y is flipped now, go with positive shear and rotate values
     245           0 :                         aExtendedProjection.scale(aScale.getX(), aScale.getY(), 1.0);
     246           0 :                         aExtendedProjection.shearXZ(fShearX, 0.0);
     247           0 :                         aExtendedProjection.rotate(0.0, 0.0, fRotate);
     248           0 :                         aExtendedProjection.translate(aTranslate.getX(), aTranslate.getY(), 0.0);
     249             : 
     250             :                         // back to state after projection
     251           0 :                         aExtendedProjection.translate(-0.5, -0.5, 0.0);
     252           0 :                         aExtendedProjection.scale(2.0, -2.0, 1.0);
     253             : 
     254           0 :                         aViewInformation3D = geometry::ViewInformation3D(
     255           0 :                             aViewInformation3D.getObjectTransformation(),
     256           0 :                             aViewInformation3D.getOrientation(),
     257             :                             aExtendedProjection,
     258           0 :                             aViewInformation3D.getDeviceToView(),
     259             :                             aViewInformation3D.getViewTime(),
     260           0 :                             aViewInformation3D.getExtendedInformationSequence());
     261          13 :                     }
     262             :                 }
     263             : 
     264             :                 // calculate logic render size in world coordinates for usage in renderer
     265          26 :                 const basegfx::B2DHomMatrix aInverseOToV(rViewInformation.getInverseObjectToViewTransformation());
     266          13 :                 const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength());
     267          13 :                 const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength());
     268             : 
     269             :                 // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process
     270             :                 processor3d::ZBufferProcessor3D aZBufferProcessor3D(
     271             :                     aViewInformation3D,
     272             :                     rViewInformation,
     273          13 :                     getSdrSceneAttribute(),
     274          13 :                     getSdrLightingAttribute(),
     275             :                     fLogicX,
     276             :                     fLogicY,
     277             :                     aUnitVisibleRange,
     278          39 :                     nOversampleValue);
     279             : 
     280          13 :                 aZBufferProcessor3D.process(getChildren3D());
     281          13 :                 aZBufferProcessor3D.finish();
     282             : 
     283          13 :                 const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx();
     284          13 :                 const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
     285             : 
     286          13 :                 if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight())
     287             :                 {
     288             :                     // create transform for the created bitmap in discrete coordinates first.
     289          13 :                     basegfx::B2DHomMatrix aNew2DTransform;
     290             : 
     291          13 :                     aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth());
     292          13 :                     aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight());
     293          13 :                     aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX());
     294          13 :                     aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY());
     295             : 
     296             :                     // transform back to world coordinates for usage in primitive creation
     297          13 :                     aNew2DTransform *= aInverseOToV;
     298             : 
     299             :                     // create bitmap primitive and add
     300          26 :                     const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform));
     301          13 :                     appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef);
     302             : 
     303             :                     // test: Allow to add an outline in the debugger when tests are needed
     304             :                     static bool bAddOutlineToCreated3DSceneRepresentation(false);
     305             : 
     306          13 :                     if(bAddOutlineToCreated3DSceneRepresentation)
     307             :                     {
     308           0 :                         basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon());
     309           0 :                         aOutline.transform(aNew2DTransform);
     310           0 :                         const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0)));
     311           0 :                         appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef2);
     312          13 :                     }
     313          13 :                 }
     314             :             }
     315             : 
     316          13 :             return aRetval;
     317             :         }
     318             : 
     319           0 :         Primitive2DSequence ScenePrimitive2D::getGeometry2D() const
     320             :         {
     321           0 :             Primitive2DSequence aRetval;
     322             : 
     323             :             // create 2D projected geometry from 3D geometry
     324           0 :             if(getChildren3D().hasElements())
     325             :             {
     326             :                 // create 2D geometry extraction processor
     327             :                 processor3d::Geometry2DExtractingProcessor aGeometryProcessor(
     328           0 :                     getViewInformation3D(),
     329           0 :                     getObjectTransformation());
     330             : 
     331             :                 // process local primitives
     332           0 :                 aGeometryProcessor.process(getChildren3D());
     333             : 
     334             :                 // fetch result
     335           0 :                 aRetval = aGeometryProcessor.getPrimitive2DSequence();
     336             :             }
     337             : 
     338           0 :             return aRetval;
     339             :         }
     340             : 
     341           0 :         Primitive2DSequence ScenePrimitive2D::getShadow2D(const geometry::ViewInformation2D& rViewInformation) const
     342             :         {
     343           0 :             Primitive2DSequence aRetval;
     344             : 
     345             :             // create 2D shadows from contained 3D primitives
     346           0 :             if(impGetShadow3D(rViewInformation))
     347             :             {
     348             :                 // add extracted 2d shadows (before 3d scene creations itself)
     349           0 :                 aRetval = maShadowPrimitives;
     350             :             }
     351             : 
     352           0 :             return aRetval;
     353             :         }
     354             : 
     355           0 :         bool ScenePrimitive2D::tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const
     356             :         {
     357           0 :             if(!maOldRenderedBitmap.IsEmpty() && !maOldUnitVisiblePart.isEmpty())
     358             :             {
     359           0 :                 basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation());
     360           0 :                 aInverseSceneTransform.invert();
     361           0 :                 const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint);
     362             : 
     363           0 :                 if(maOldUnitVisiblePart.isInside(aRelativePoint))
     364             :                 {
     365             :                     // calculate coordinates relative to visualized part
     366           0 :                     double fDivisorX(maOldUnitVisiblePart.getWidth());
     367           0 :                     double fDivisorY(maOldUnitVisiblePart.getHeight());
     368             : 
     369           0 :                     if(basegfx::fTools::equalZero(fDivisorX))
     370             :                     {
     371           0 :                         fDivisorX = 1.0;
     372             :                     }
     373             : 
     374           0 :                     if(basegfx::fTools::equalZero(fDivisorY))
     375             :                     {
     376           0 :                         fDivisorY = 1.0;
     377             :                     }
     378             : 
     379           0 :                     const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX);
     380           0 :                     const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY);
     381             : 
     382             :                     // combine with real BitmapSizePixel to get bitmap coordinates
     383           0 :                     const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel());
     384           0 :                     const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width()));
     385           0 :                     const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height()));
     386             : 
     387             :                     // try to get a statement about transparency in that pixel
     388           0 :                     o_rResult = (0xff != maOldRenderedBitmap.GetTransparency(nX, nY));
     389           0 :                     return true;
     390           0 :                 }
     391             :             }
     392             : 
     393           0 :             return false;
     394             :         }
     395             : 
     396          24 :         ScenePrimitive2D::ScenePrimitive2D(
     397             :             const primitive3d::Primitive3DSequence& rxChildren3D,
     398             :             const attribute::SdrSceneAttribute& rSdrSceneAttribute,
     399             :             const attribute::SdrLightingAttribute& rSdrLightingAttribute,
     400             :             const basegfx::B2DHomMatrix& rObjectTransformation,
     401             :             const geometry::ViewInformation3D& rViewInformation3D)
     402             :         :   BufferedDecompositionPrimitive2D(),
     403             :             mxChildren3D(rxChildren3D),
     404             :             maSdrSceneAttribute(rSdrSceneAttribute),
     405             :             maSdrLightingAttribute(rSdrLightingAttribute),
     406             :             maObjectTransformation(rObjectTransformation),
     407             :             maViewInformation3D(rViewInformation3D),
     408             :             maShadowPrimitives(),
     409             :             mbShadow3DChecked(false),
     410             :             mfOldDiscreteSizeX(0.0),
     411             :             mfOldDiscreteSizeY(0.0),
     412             :             maOldUnitVisiblePart(),
     413          24 :             maOldRenderedBitmap()
     414             :         {
     415          24 :         }
     416             : 
     417          29 :         bool ScenePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     418             :         {
     419          29 :             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
     420             :             {
     421          29 :                 const ScenePrimitive2D& rCompare = static_cast<const ScenePrimitive2D&>(rPrimitive);
     422             : 
     423          29 :                 return (primitive3d::arePrimitive3DSequencesEqual(getChildren3D(), rCompare.getChildren3D())
     424          29 :                     && getSdrSceneAttribute() == rCompare.getSdrSceneAttribute()
     425          29 :                     && getSdrLightingAttribute() == rCompare.getSdrLightingAttribute()
     426          29 :                     && getObjectTransformation() == rCompare.getObjectTransformation()
     427          58 :                     && getViewInformation3D() == rCompare.getViewInformation3D());
     428             :             }
     429             : 
     430           0 :             return false;
     431             :         }
     432             : 
     433          97 :         basegfx::B2DRange ScenePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
     434             :         {
     435             :             // transform unit range to discrete coordinate range
     436          97 :             basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
     437          97 :             aRetval.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation());
     438             : 
     439             :             // force to discrete expanded bounds (it grows, so expanding works perfectly well)
     440          97 :             aRetval.expand(basegfx::B2DTuple(floor(aRetval.getMinX()), floor(aRetval.getMinY())));
     441          97 :             aRetval.expand(basegfx::B2DTuple(ceil(aRetval.getMaxX()), ceil(aRetval.getMaxY())));
     442             : 
     443             :             // transform back from discrete (view) to world coordinates
     444          97 :             aRetval.transform(rViewInformation.getInverseObjectToViewTransformation());
     445             : 
     446             :             // expand by evtl. existing shadow primitives
     447          97 :             if(impGetShadow3D(rViewInformation))
     448             :             {
     449           0 :                 const basegfx::B2DRange aShadow2DRange(getB2DRangeFromPrimitive2DSequence(maShadowPrimitives, rViewInformation));
     450             : 
     451           0 :                 if(!aShadow2DRange.isEmpty())
     452             :                 {
     453           0 :                     aRetval.expand(aShadow2DRange);
     454             :                 }
     455             :             }
     456             : 
     457          97 :             return aRetval;
     458             :         }
     459             : 
     460          22 :         Primitive2DSequence ScenePrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
     461             :         {
     462          22 :             ::osl::MutexGuard aGuard( m_aMutex );
     463             : 
     464             :             // get the involved ranges (see helper method calculateDiscreteSizes for details)
     465          22 :             basegfx::B2DRange aDiscreteRange;
     466          22 :             basegfx::B2DRange aUnitVisibleRange;
     467          22 :             bool bNeedNewDecomposition(false);
     468          22 :             bool bDiscreteSizesAreCalculated(false);
     469             : 
     470          22 :             if(getBuffered2DDecomposition().hasElements())
     471             :             {
     472           9 :                 basegfx::B2DRange aVisibleDiscreteRange;
     473           9 :                 calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange);
     474           9 :                 bDiscreteSizesAreCalculated = true;
     475             : 
     476             :                 // needs to be painted when the new part is not part of the last
     477             :                 // decomposition
     478           9 :                 if(!maOldUnitVisiblePart.isInside(aUnitVisibleRange))
     479             :                 {
     480           0 :                     bNeedNewDecomposition = true;
     481             :                 }
     482             : 
     483             :                 // display has changed and cannot be reused when resolution got bigger. It
     484             :                 // can be reused when resolution got smaller, though.
     485           9 :                 if(!bNeedNewDecomposition)
     486             :                 {
     487          36 :                     if(basegfx::fTools::more(aDiscreteRange.getWidth(), mfOldDiscreteSizeX) ||
     488          27 :                         basegfx::fTools::more(aDiscreteRange.getHeight(), mfOldDiscreteSizeY))
     489             :                     {
     490           0 :                         bNeedNewDecomposition = true;
     491             :                     }
     492             :                 }
     493             :             }
     494             : 
     495          22 :             if(bNeedNewDecomposition)
     496             :             {
     497             :                 // conditions of last local decomposition have changed, delete
     498           0 :                 const_cast< ScenePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
     499             :             }
     500             : 
     501          22 :             if(!getBuffered2DDecomposition().hasElements())
     502             :             {
     503          13 :                 if(!bDiscreteSizesAreCalculated)
     504             :                 {
     505          13 :                     basegfx::B2DRange aVisibleDiscreteRange;
     506          13 :                     calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange);
     507             :                 }
     508             : 
     509             :                 // remember last used NewDiscreteSize and NewUnitVisiblePart
     510          13 :                 ScenePrimitive2D* pThat = const_cast< ScenePrimitive2D* >(this);
     511          13 :                 pThat->mfOldDiscreteSizeX = aDiscreteRange.getWidth();
     512          13 :                 pThat->mfOldDiscreteSizeY = aDiscreteRange.getHeight();
     513          13 :                 pThat->maOldUnitVisiblePart = aUnitVisibleRange;
     514             :             }
     515             : 
     516             :             // use parent implementation
     517          22 :             return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
     518             :         }
     519             : 
     520             :         // provide unique ID
     521          80 :         ImplPrimitive2DIDBlock(ScenePrimitive2D, PRIMITIVE2D_ID_SCENEPRIMITIVE2D)
     522             : 
     523             :     } // end of namespace primitive2d
     524             : } // end of namespace drawinglayer
     525             : 
     526             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11