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