diff options
-rw-r--r-- | drawinglayer/source/attribute/fillgraphicattribute.cxx | 6 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/sceneprimitive2d.cxx | 251 | ||||
-rw-r--r-- | drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx | 4 | ||||
-rw-r--r-- | drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx | 4 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/zbufferprocessor3d.cxx | 394 | ||||
-rw-r--r-- | include/basegfx/matrix/b3dhommatrix.hxx | 2 | ||||
-rw-r--r-- | include/basegfx/polygon/b3dpolygon.hxx | 2 | ||||
-rw-r--r-- | include/basegfx/polygon/b3dpolypolygon.hxx | 2 | ||||
-rw-r--r-- | include/drawinglayer/processor3d/zbufferprocessor3d.hxx | 18 |
9 files changed, 376 insertions, 307 deletions
diff --git a/drawinglayer/source/attribute/fillgraphicattribute.cxx b/drawinglayer/source/attribute/fillgraphicattribute.cxx index 6d70e46de699..9465af23b054 100644 --- a/drawinglayer/source/attribute/fillgraphicattribute.cxx +++ b/drawinglayer/source/attribute/fillgraphicattribute.cxx @@ -51,6 +51,12 @@ namespace drawinglayer mfOffsetX(fOffsetX), mfOffsetY(fOffsetY) { + // access once to ensure that the buffered bitmap exists, else + // the SolarMutex may be needed to create it. This may not be + // available when a renderer works with multi-treading. + // When changing this, please check if it is still possible to + // use a metafile as texture for a 3D object + maGraphic.GetBitmapEx(); } ImpFillGraphicAttribute() diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx index 27a4e0dc3943..68acb57ff5d6 100644 --- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -32,10 +32,105 @@ #include <svtools/optionsdrawinglayer.hxx> #include <drawinglayer/processor3d/geometry2dextractor.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> - +#include <basegfx/raster/bzpixelraster.hxx> +#include <vcl/bitmapaccess.hxx> +#include <comphelper/threadpool.hxx> using namespace com::sun::star; +namespace +{ + BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize) + { + BitmapEx aRetval; + const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth()); + const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight()); + + if(nWidth && nHeight) + { + const Size aDestSize(nWidth, nHeight); + sal_uInt8 nInitAlpha(255); + Bitmap aContent(aDestSize, 24); + AlphaMask aAlpha(aDestSize, &nInitAlpha); + BitmapWriteAccess* pContent = aContent.AcquireWriteAccess(); + BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess(); + + if (pContent && pAlpha) + { + if(mnAntiAlialize) + { + const sal_uInt16 nDivisor(mnAntiAlialize * mnAntiAlialize); + + for(sal_uInt32 y(0L); y < nHeight; y++) + { + for(sal_uInt32 x(0L); x < nWidth; x++) + { + sal_uInt16 nRed(0); + sal_uInt16 nGreen(0); + sal_uInt16 nBlue(0); + sal_uInt16 nOpacity(0); + sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize)); + + for(sal_uInt32 c(0); c < mnAntiAlialize; c++) + { + for(sal_uInt32 d(0); d < mnAntiAlialize; d++) + { + const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++)); + nRed = nRed + rPixel.getRed(); + nGreen = nGreen + rPixel.getGreen(); + nBlue = nBlue + rPixel.getBlue(); + nOpacity = nOpacity + rPixel.getOpacity(); + } + + nIndex += rRaster.getWidth() - mnAntiAlialize; + } + + nOpacity = nOpacity / nDivisor; + + if(nOpacity) + { + pContent->SetPixel(y, x, BitmapColor( + (sal_uInt8)(nRed / nDivisor), + (sal_uInt8)(nGreen / nDivisor), + (sal_uInt8)(nBlue / nDivisor))); + pAlpha->SetPixel(y, x, BitmapColor(255 - (sal_uInt8)nOpacity)); + } + } + } + } + else + { + sal_uInt32 nIndex(0L); + + for(sal_uInt32 y(0L); y < nHeight; y++) + { + for(sal_uInt32 x(0L); x < nWidth; x++) + { + const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++)); + + if(rPixel.getOpacity()) + { + pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue())); + pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity())); + } + } + } + } + } + + aAlpha.ReleaseAccess(pAlpha); + Bitmap::ReleaseAccess(pContent); + + aRetval = BitmapEx(aContent, aAlpha); + + // #i101811# set PrefMapMode and PrefSize at newly created Bitmap + aRetval.SetPrefMapMode(MAP_PIXEL); + aRetval.SetPrefSize(Size(nWidth, nHeight)); + } + + return aRetval; + } +} // end of anonymous namespace namespace drawinglayer { @@ -263,49 +358,135 @@ namespace drawinglayer const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength()); const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength()); - // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process - processor3d::ZBufferProcessor3D aZBufferProcessor3D( - aViewInformation3D, - rViewInformation, - getSdrSceneAttribute(), - getSdrLightingAttribute(), - fLogicX, - fLogicY, - aUnitVisibleRange, - nOversampleValue); - - aZBufferProcessor3D.process(getChildren3D()); - aZBufferProcessor3D.finish(); + // generate ViewSizes + const double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength()); + const double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength()); - const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx(); - const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); + // generate RasterWidth and RasterHeight for visible part + const sal_Int32 nRasterWidth((sal_Int32)basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1); + const sal_Int32 nRasterHeight((sal_Int32)basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1); - if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) + if(nRasterWidth && nRasterHeight) { - // create transform for the created bitmap in discrete coordinates first. - basegfx::B2DHomMatrix aNew2DTransform; + // create view unit buffer + basegfx::BZPixelRaster aBZPixelRaster( + nOversampleValue ? nRasterWidth * nOversampleValue : nRasterWidth, + nOversampleValue ? nRasterHeight * nOversampleValue : nRasterHeight); - aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); - aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); - aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); - aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); + // check for parallel execution possibilities + static bool bMultithreadAllowed = true; + sal_Int32 nThreadCount(0); + comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool()); - // transform back to world coordinates for usage in primitive creation - aNew2DTransform *= aInverseOToV; + if(bMultithreadAllowed) + { + nThreadCount = rThreadPool.getWorkerCount(); + + if(nThreadCount > 1) + { + // at least use 10px per processor, so limit number of processors to + // target pixel size divided by 10 (which might be zero what is okay) + nThreadCount = std::min(nThreadCount, nRasterHeight / 10); + } + } - // create bitmap primitive and add - const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); - aRetval.push_back(xRef); + if(nThreadCount > 1) + { + class Executor : public comphelper::ThreadTask + { + private: + processor3d::ZBufferProcessor3D* mpZBufferProcessor3D; + const primitive3d::Primitive3DContainer& mrChildren3D; + + public: + explicit Executor( + processor3d::ZBufferProcessor3D* pZBufferProcessor3D, + const primitive3d::Primitive3DContainer& rChildren3D) + : mpZBufferProcessor3D(pZBufferProcessor3D), + mrChildren3D(rChildren3D) + { + } + + virtual void doWork() override + { + mpZBufferProcessor3D->process(mrChildren3D); + mpZBufferProcessor3D->finish(); + delete mpZBufferProcessor3D; + } + }; + + std::vector< processor3d::ZBufferProcessor3D* > aProcessors; + const sal_uInt32 nLinesPerThread(aBZPixelRaster.getHeight() / nThreadCount); + + for(sal_Int32 a(0); a < nThreadCount; a++) + { + processor3d::ZBufferProcessor3D* pNewZBufferProcessor3D = new processor3d::ZBufferProcessor3D( + aViewInformation3D, + getSdrSceneAttribute(), + getSdrLightingAttribute(), + aUnitVisibleRange, + nOversampleValue, + fFullViewSizeX, + fFullViewSizeY, + aBZPixelRaster, + nLinesPerThread * a, + a + 1 == nThreadCount ? aBZPixelRaster.getHeight() : nLinesPerThread * (a + 1)); + aProcessors.push_back(pNewZBufferProcessor3D); + Executor* pExecutor = new Executor(pNewZBufferProcessor3D, getChildren3D()); + rThreadPool.pushTask(pExecutor); + } + + rThreadPool.waitUntilEmpty(); + } + else + { + // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process + processor3d::ZBufferProcessor3D aZBufferProcessor3D( + aViewInformation3D, + getSdrSceneAttribute(), + getSdrLightingAttribute(), + aUnitVisibleRange, + nOversampleValue, + fFullViewSizeX, + fFullViewSizeY, + aBZPixelRaster, + 0, + aBZPixelRaster.getHeight()); + + aZBufferProcessor3D.process(getChildren3D()); + aZBufferProcessor3D.finish(); + } - // test: Allow to add an outline in the debugger when tests are needed - static bool bAddOutlineToCreated3DSceneRepresentation(false); + const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmapEx(aBZPixelRaster, nOversampleValue); + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); - if(bAddOutlineToCreated3DSceneRepresentation) + if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) { - basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon()); - aOutline.transform(aNew2DTransform); - const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); - aRetval.push_back(xRef2); + // create transform for the created bitmap in discrete coordinates first. + basegfx::B2DHomMatrix aNew2DTransform; + + aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); + aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); + aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); + aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); + + // transform back to world coordinates for usage in primitive creation + aNew2DTransform *= aInverseOToV; + + // create bitmap primitive and add + const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); + aRetval.push_back(xRef); + + // test: Allow to add an outline in the debugger when tests are needed + static bool bAddOutlineToCreated3DSceneRepresentation(false); + + if(bAddOutlineToCreated3DSceneRepresentation) + { + basegfx::B2DPolygon aOutline(basegfx::tools::createUnitPolygon()); + aOutline.transform(aNew2DTransform); + const Primitive2DReference xRef2(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); + aRetval.push_back(xRef2); + } } } } diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx index a5fe0ddb0348..be15838fd8b7 100644 --- a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx @@ -375,6 +375,8 @@ namespace drawinglayer // again when no longer geometry is needed for non-visible 3D objects as it is now for chart if(getPolyPolygon().count() && !maSlices.size()) { + ::osl::MutexGuard aGuard( m_aMutex ); + const_cast< SdrExtrudePrimitive3D& >(*this).impCreateSlices(); } @@ -488,6 +490,8 @@ namespace drawinglayer (!getBuffered3DDecomposition().empty() && *mpLastRLGViewInformation != rViewInformation)) { + ::osl::MutexGuard aGuard( m_aMutex ); + // conditions of last local decomposition with reduced lines have changed. Remember // new one and clear current decompositiopn SdrExtrudePrimitive3D* pThat = const_cast< SdrExtrudePrimitive3D* >(this); diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx index be66c16d7a8b..f831aba427bd 100644 --- a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx @@ -231,6 +231,8 @@ namespace drawinglayer // again when no longer geometry is needed for non-visible 3D objects as it is now for chart if(getPolyPolygon().count() && !maSlices.size()) { + ::osl::MutexGuard aGuard( m_aMutex ); + const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices(); } @@ -350,6 +352,8 @@ namespace drawinglayer (!getBuffered3DDecomposition().empty() && *mpLastRLGViewInformation != rViewInformation)) { + ::osl::MutexGuard aGuard( m_aMutex ); + // conditions of last local decomposition with reduced lines have changed. Remember // new one and clear current decompositiopn SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this); diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx index 0334c911ba76..3944f83705e0 100644 --- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx +++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx @@ -19,7 +19,6 @@ #include <drawinglayer/processor3d/zbufferprocessor3d.hxx> #include <basegfx/raster/bpixelraster.hxx> -#include <vcl/bitmapaccess.hxx> #include <basegfx/raster/rasterconvert3d.hxx> #include <basegfx/raster/bzpixelraster.hxx> #include <drawinglayer/attribute/materialattribute3d.hxx> @@ -35,100 +34,6 @@ using namespace com::sun::star; -namespace -{ - BitmapEx BPixelRasterToBitmapEx(const basegfx::BPixelRaster& rRaster, sal_uInt16 mnAntiAlialize) - { - BitmapEx aRetval; - const sal_uInt32 nWidth(mnAntiAlialize ? rRaster.getWidth()/mnAntiAlialize : rRaster.getWidth()); - const sal_uInt32 nHeight(mnAntiAlialize ? rRaster.getHeight()/mnAntiAlialize : rRaster.getHeight()); - - if(nWidth && nHeight) - { - const Size aDestSize(nWidth, nHeight); - sal_uInt8 nInitAlpha(255); - Bitmap aContent(aDestSize, 24); - AlphaMask aAlpha(aDestSize, &nInitAlpha); - BitmapWriteAccess* pContent = aContent.AcquireWriteAccess(); - BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess(); - - if (pContent && pAlpha) - { - if(mnAntiAlialize) - { - const sal_uInt16 nDivisor(mnAntiAlialize * mnAntiAlialize); - - for(sal_uInt32 y(0L); y < nHeight; y++) - { - for(sal_uInt32 x(0L); x < nWidth; x++) - { - sal_uInt16 nRed(0); - sal_uInt16 nGreen(0); - sal_uInt16 nBlue(0); - sal_uInt16 nOpacity(0); - sal_uInt32 nIndex(rRaster.getIndexFromXY(x * mnAntiAlialize, y * mnAntiAlialize)); - - for(sal_uInt32 c(0); c < mnAntiAlialize; c++) - { - for(sal_uInt32 d(0); d < mnAntiAlialize; d++) - { - const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++)); - nRed = nRed + rPixel.getRed(); - nGreen = nGreen + rPixel.getGreen(); - nBlue = nBlue + rPixel.getBlue(); - nOpacity = nOpacity + rPixel.getOpacity(); - } - - nIndex += rRaster.getWidth() - mnAntiAlialize; - } - - nOpacity = nOpacity / nDivisor; - - if(nOpacity) - { - pContent->SetPixel(y, x, BitmapColor( - (sal_uInt8)(nRed / nDivisor), - (sal_uInt8)(nGreen / nDivisor), - (sal_uInt8)(nBlue / nDivisor))); - pAlpha->SetPixel(y, x, BitmapColor(255 - (sal_uInt8)nOpacity)); - } - } - } - } - else - { - sal_uInt32 nIndex(0L); - - for(sal_uInt32 y(0L); y < nHeight; y++) - { - for(sal_uInt32 x(0L); x < nWidth; x++) - { - const basegfx::BPixel& rPixel(rRaster.getBPixel(nIndex++)); - - if(rPixel.getOpacity()) - { - pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue())); - pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity())); - } - } - } - } - } - - aAlpha.ReleaseAccess(pAlpha); - Bitmap::ReleaseAccess(pContent); - - aRetval = BitmapEx(aContent, aAlpha); - - // #i101811# set PrefMapMode and PrefSize at newly created Bitmap - aRetval.SetPrefMapMode(MAP_PIXEL); - aRetval.SetPrefSize(Size(nWidth, nHeight)); - } - - return aRetval; - } -} // end of anonymous namespace - class ZBufferRasterConverter3D : public basegfx::RasterConverter3D { private: @@ -536,211 +441,188 @@ namespace drawinglayer { void ZBufferProcessor3D::rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const { - if(mpBZPixelRaster) + if(getTransparenceCounter()) { - if(getTransparenceCounter()) + // transparent output; record for later sorting and painting from + // back to front + if(!mpRasterPrimitive3Ds) { - // transparent output; record for later sorting and painting from - // back to front - if(!mpRasterPrimitive3Ds) - { - const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >; - } - - mpRasterPrimitive3Ds->push_back(RasterPrimitive3D( - getGeoTexSvx(), - getTransparenceGeoTexSvx(), - rMaterial, - basegfx::B3DPolyPolygon(rHairline), - getModulate(), - getFilter(), - getSimpleTextureActive(), - true)); + const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >; } - else + + mpRasterPrimitive3Ds->push_back(RasterPrimitive3D( + getGeoTexSvx(), + getTransparenceGeoTexSvx(), + rMaterial, + basegfx::B3DPolyPolygon(rHairline), + getModulate(), + getFilter(), + getSimpleTextureActive(), + true)); + } + else + { + // do rasterconversion + mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial); + + if(mnAntiAlialize > 1) { - // do rasterconversion - mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial); + const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete()); - if(mnAntiAlialize > 1) + if(bForceLineSnap) { - const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete()); + basegfx::B3DHomMatrix aTransform; + basegfx::B3DPolygon aSnappedHairline(rHairline); + const double fScaleDown(1.0 / mnAntiAlialize); + const double fScaleUp(mnAntiAlialize); - if(bForceLineSnap) - { - basegfx::B3DHomMatrix aTransform; - basegfx::B3DPolygon aSnappedHairline(rHairline); - const double fScaleDown(1.0 / mnAntiAlialize); - const double fScaleUp(mnAntiAlialize); - - // take oversampling out - aTransform.scale(fScaleDown, fScaleDown, 1.0); - aSnappedHairline.transform(aTransform); + // take oversampling out + aTransform.scale(fScaleDown, fScaleDown, 1.0); + aSnappedHairline.transform(aTransform); - // snap to integer - aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline); + // snap to integer + aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline); - // add oversampling again - aTransform.identity(); - aTransform.scale(fScaleUp, fScaleUp, 1.0); + // add oversampling again + aTransform.identity(); + aTransform.scale(fScaleUp, fScaleUp, 1.0); - aSnappedHairline.transform(aTransform); + aSnappedHairline.transform(aTransform); - mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize); - } - else - { - mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize); - } + mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, mnStartLine, mnStopLine, mnAntiAlialize); } else { - mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1); + mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, mnAntiAlialize); } } + else + { + mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, mnStartLine, mnStopLine, 1); + } } } void ZBufferProcessor3D::rasterconvertB3DPolyPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolyPolygon& rFill) const { - if(mpBZPixelRaster) + if(getTransparenceCounter()) { - if(getTransparenceCounter()) + // transparent output; record for later sorting and painting from + // back to front + if(!mpRasterPrimitive3Ds) { - // transparent output; record for later sorting and painting from - // back to front - if(!mpRasterPrimitive3Ds) - { - const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >; - } - - mpRasterPrimitive3Ds->push_back(RasterPrimitive3D( - getGeoTexSvx(), - getTransparenceGeoTexSvx(), - rMaterial, - rFill, - getModulate(), - getFilter(), - getSimpleTextureActive(), - false)); - } - else - { - mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial); - mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, 0, mpBZPixelRaster->getHeight()); + const_cast< ZBufferProcessor3D* >(this)->mpRasterPrimitive3Ds = new std::vector< RasterPrimitive3D >; } + + mpRasterPrimitive3Ds->push_back(RasterPrimitive3D( + getGeoTexSvx(), + getTransparenceGeoTexSvx(), + rMaterial, + rFill, + getModulate(), + getFilter(), + getSimpleTextureActive(), + false)); + } + else + { + mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial); + mpZBufferRasterConverter3D->rasterconvertB3DPolyPolygon(rFill, &maInvEyeToView, mnStartLine, mnStopLine); } } ZBufferProcessor3D::ZBufferProcessor3D( const geometry::ViewInformation3D& rViewInformation3D, - const geometry::ViewInformation2D& rViewInformation2D, const attribute::SdrSceneAttribute& rSdrSceneAttribute, const attribute::SdrLightingAttribute& rSdrLightingAttribute, - double fSizeX, - double fSizeY, const basegfx::B2DRange& rVisiblePart, - sal_uInt16 nAntiAlialize) + sal_uInt16 nAntiAlialize, + double fFullViewSizeX, + double fFullViewSizeY, + basegfx::BZPixelRaster& rBZPixelRaster, + sal_uInt32 nStartLine, + sal_uInt32 nStopLine) : DefaultProcessor3D(rViewInformation3D, rSdrSceneAttribute, rSdrLightingAttribute), - mpBZPixelRaster(nullptr), + mrBZPixelRaster(rBZPixelRaster), maInvEyeToView(), mpZBufferRasterConverter3D(nullptr), mnAntiAlialize(nAntiAlialize), - mpRasterPrimitive3Ds(nullptr) + mpRasterPrimitive3Ds(nullptr), + mnStartLine(nStartLine), + mnStopLine(nStopLine) { - // generate ViewSizes - const double fFullViewSizeX((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(fSizeX, 0.0)).getLength()); - const double fFullViewSizeY((rViewInformation2D.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fSizeY)).getLength()); - const double fViewSizeX(fFullViewSizeX * rVisiblePart.getWidth()); - const double fViewSizeY(fFullViewSizeY * rVisiblePart.getHeight()); - - // generate RasterWidth and RasterHeight - const sal_uInt32 nRasterWidth((sal_uInt32)basegfx::fround(fViewSizeX) + 1); - const sal_uInt32 nRasterHeight((sal_uInt32)basegfx::fround(fViewSizeY) + 1); + // create DeviceToView for Z-Buffer renderer since Z is handled + // different from standard 3D transformations (Z is mirrored). Also + // the transformation includes the step from unit device coordinates + // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete] + basegfx::B3DHomMatrix aDeviceToView; - if(nRasterWidth && nRasterHeight) { - // create view unit buffer - mpBZPixelRaster = new basegfx::BZPixelRaster( - mnAntiAlialize ? nRasterWidth * mnAntiAlialize : nRasterWidth, - mnAntiAlialize ? nRasterHeight * mnAntiAlialize : nRasterHeight); - OSL_ENSURE(mpBZPixelRaster, "ZBufferProcessor3D: Could not allocate basegfx::BZPixelRaster (!)"); - - // create DeviceToView for Z-Buffer renderer since Z is handled - // different from standard 3D transformations (Z is mirrored). Also - // the transformation includes the step from unit device coordinates - // to discrete units ([-1.0 .. 1.0] -> [minDiscrete .. maxDiscrete] - - basegfx::B3DHomMatrix aDeviceToView; - - { - // step one: - // - // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also - // necessary to - // - flip Y due to screen orientation - // - flip Z due to Z-Buffer orientation from back to front - - aDeviceToView.scale(0.5, -0.5, -0.5); - aDeviceToView.translate(0.5, 0.5, 0.5); - } + // step one: + // + // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also + // necessary to + // - flip Y due to screen orientation + // - flip Z due to Z-Buffer orientation from back to front + + aDeviceToView.scale(0.5, -0.5, -0.5); + aDeviceToView.translate(0.5, 0.5, 0.5); + } - { - // step two: - // - // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates - // - // #i102611# - // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0] - // could be used, but a 'unused' value is needed, so '0' is used what reduces - // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors - // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen. - // Instead of checking those by basegfx::fTools methods which would cost - // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer - // range, thus resulting in [1.5 .. 65534.5] - const double fMaxZDepth(65533.0); - aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0); - - if(mnAntiAlialize) - aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth); - else - aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth); + { + // step two: + // + // bring from [0.0 .. 1.0] in X,Y and Z to view coordinates + // + // #i102611# + // also: scale Z to [1.5 .. 65534.5]. Normally, a range of [0.0 .. 65535.0] + // could be used, but a 'unused' value is needed, so '0' is used what reduces + // the range to [1.0 .. 65535.0]. It has also shown that small numerical errors + // (smaller as basegfx::fTools::mfSmallValue, which is 0.000000001) happen. + // Instead of checking those by basegfx::fTools methods which would cost + // runtime, just add another 0.5 tolerance to the start and end of the Z-Buffer + // range, thus resulting in [1.5 .. 65534.5] + const double fMaxZDepth(65533.0); + aDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0); - aDeviceToView.translate(0.0, 0.0, 1.5); - } + if(mnAntiAlialize) + aDeviceToView.scale(fFullViewSizeX * mnAntiAlialize, fFullViewSizeY * mnAntiAlialize, fMaxZDepth); + else + aDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth); - // update local ViewInformation3D with own DeviceToView - const geometry::ViewInformation3D aNewViewInformation3D( - getViewInformation3D().getObjectTransformation(), - getViewInformation3D().getOrientation(), - getViewInformation3D().getProjection(), - aDeviceToView, - getViewInformation3D().getViewTime(), - getViewInformation3D().getExtendedInformationSequence()); - updateViewInformation(aNewViewInformation3D); - - // prepare inverse EyeToView transformation. This can be done in constructor - // since changes in object transformations when processing TransformPrimitive3Ds - // do not influence this prepared partial transformation - maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection(); - maInvEyeToView.invert(); - - // prepare maRasterRange - maRasterRange.reset(); - maRasterRange.expand(basegfx::B2DPoint(0.0, 0.0)); - maRasterRange.expand(basegfx::B2DPoint(mpBZPixelRaster->getWidth(), mpBZPixelRaster->getHeight())); - - // create the raster converter - mpZBufferRasterConverter3D = new ZBufferRasterConverter3D(*mpBZPixelRaster, *this); + aDeviceToView.translate(0.0, 0.0, 1.5); } + + // update local ViewInformation3D with own DeviceToView + const geometry::ViewInformation3D aNewViewInformation3D( + getViewInformation3D().getObjectTransformation(), + getViewInformation3D().getOrientation(), + getViewInformation3D().getProjection(), + aDeviceToView, + getViewInformation3D().getViewTime(), + getViewInformation3D().getExtendedInformationSequence()); + updateViewInformation(aNewViewInformation3D); + + // prepare inverse EyeToView transformation. This can be done in constructor + // since changes in object transformations when processing TransformPrimitive3Ds + // do not influence this prepared partial transformation + maInvEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection(); + maInvEyeToView.invert(); + + // prepare maRasterRange + maRasterRange.reset(); + maRasterRange.expand(basegfx::B2DPoint(0.0, nStartLine)); + maRasterRange.expand(basegfx::B2DPoint(mrBZPixelRaster.getWidth(), nStopLine)); + + // create the raster converter + mpZBufferRasterConverter3D = new ZBufferRasterConverter3D(mrBZPixelRaster, *this); } ZBufferProcessor3D::~ZBufferProcessor3D() { - if(mpBZPixelRaster) + if(mpZBufferRasterConverter3D) { delete mpZBufferRasterConverter3D; - delete mpBZPixelRaster; } if(mpRasterPrimitive3Ds) @@ -795,16 +677,6 @@ namespace drawinglayer mpRasterPrimitive3Ds = nullptr; } } - - BitmapEx ZBufferProcessor3D::getBitmapEx() const - { - if(mpBZPixelRaster) - { - return BPixelRasterToBitmapEx(*mpBZPixelRaster, mnAntiAlialize); - } - - return BitmapEx(); - } } // end of namespace processor3d } // end of namespace drawinglayer diff --git a/include/basegfx/matrix/b3dhommatrix.hxx b/include/basegfx/matrix/b3dhommatrix.hxx index b8e1c5b26c9c..ec8ee34f51d5 100644 --- a/include/basegfx/matrix/b3dhommatrix.hxx +++ b/include/basegfx/matrix/b3dhommatrix.hxx @@ -34,7 +34,7 @@ namespace basegfx class BASEGFX_DLLPUBLIC B3DHomMatrix { public: - typedef o3tl::cow_wrapper< Impl3DHomMatrix > ImplType; + typedef o3tl::cow_wrapper< Impl3DHomMatrix, o3tl::ThreadSafeRefCountingPolicy > ImplType; private: ImplType mpImpl; diff --git a/include/basegfx/polygon/b3dpolygon.hxx b/include/basegfx/polygon/b3dpolygon.hxx index 6c9c9b9c0808..d32968b47ac0 100644 --- a/include/basegfx/polygon/b3dpolygon.hxx +++ b/include/basegfx/polygon/b3dpolygon.hxx @@ -42,7 +42,7 @@ namespace basegfx class BASEGFX_DLLPUBLIC B3DPolygon { public: - typedef o3tl::cow_wrapper< ImplB3DPolygon > ImplType; + typedef o3tl::cow_wrapper< ImplB3DPolygon, o3tl::ThreadSafeRefCountingPolicy > ImplType; private: // internal data. diff --git a/include/basegfx/polygon/b3dpolypolygon.hxx b/include/basegfx/polygon/b3dpolypolygon.hxx index ea47e332f63b..9e3472dbb74c 100644 --- a/include/basegfx/polygon/b3dpolypolygon.hxx +++ b/include/basegfx/polygon/b3dpolypolygon.hxx @@ -38,7 +38,7 @@ namespace basegfx class BASEGFX_DLLPUBLIC B3DPolyPolygon { public: - typedef o3tl::cow_wrapper< ImplB3DPolyPolygon > ImplType; + typedef o3tl::cow_wrapper< ImplB3DPolyPolygon, o3tl::ThreadSafeRefCountingPolicy > ImplType; private: ImplType mpPolyPolygon; diff --git a/include/drawinglayer/processor3d/zbufferprocessor3d.hxx b/include/drawinglayer/processor3d/zbufferprocessor3d.hxx index 8e3f6d4f3ac1..0f58a7f1f0ab 100644 --- a/include/drawinglayer/processor3d/zbufferprocessor3d.hxx +++ b/include/drawinglayer/processor3d/zbufferprocessor3d.hxx @@ -56,7 +56,7 @@ namespace drawinglayer { private: /// the raster target, a Z-Buffer - basegfx::BZPixelRaster* mpBZPixelRaster; + basegfx::BZPixelRaster& mrBZPixelRaster; /// inverse of EyeToView for rasterconversion with evtl. Phong shading basegfx::B3DHomMatrix maInvEyeToView; @@ -74,6 +74,9 @@ namespace drawinglayer */ std::vector< RasterPrimitive3D >* mpRasterPrimitive3Ds; + sal_uInt32 mnStartLine; + sal_uInt32 mnStopLine; + // rasterconversions for filled and non-filled polygons virtual void rasterconvertB3DPolygon(const attribute::MaterialAttribute3D& rMaterial, const basegfx::B3DPolygon& rHairline) const override; @@ -82,19 +85,18 @@ namespace drawinglayer public: ZBufferProcessor3D( const geometry::ViewInformation3D& rViewInformation3D, - const geometry::ViewInformation2D& rViewInformation2D, const attribute::SdrSceneAttribute& rSdrSceneAttribute, const attribute::SdrLightingAttribute& rSdrLightingAttribute, - double fSizeX, - double fSizeY, const basegfx::B2DRange& rVisiblePart, - sal_uInt16 nAntiAlialize); + sal_uInt16 nAntiAlialize, + double fFullViewSizeX, + double fFullViewSizeY, + basegfx::BZPixelRaster& rBZPixelRaster, + sal_uInt32 nStartLine, + sal_uInt32 nStopLine); virtual ~ZBufferProcessor3D(); void finish(); - - /// get the result as bitmapEx - BitmapEx getBitmapEx() const; }; } } |