drawinglayer/source/primitive2d/glowprimitive2d.cxx | 16 -- drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 97 +++++++++++++ drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx | 5 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 15 -- include/drawinglayer/primitive2d/glowprimitive2d.hxx | 5 5 files changed, 109 insertions(+), 29 deletions(-)
New commits: commit f510bdfa98014ca0ae596dcd0dfd487cfc90f3eb Author: Mike Kaganski <[email protected]> AuthorDate: Thu May 28 17:51:15 2020 +0300 Commit: Mike Kaganski <[email protected]> CommitDate: Fri May 29 10:31:31 2020 +0200 tdf#101181: use buffer device with alpha in glow effect Change-Id: Iddc94a5cfdee03befdf245ee086a872f0bfaf7a3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95051 Tested-by: Jenkins Tested-by: Mike Kaganski <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> (cherry picked from commit c9f4952b98da9adad1b556414c5fcecafedca473) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95082 diff --git a/drawinglayer/source/primitive2d/glowprimitive2d.cxx b/drawinglayer/source/primitive2d/glowprimitive2d.cxx index bf49b8e215b5..fb6a599ab4e2 100644 --- a/drawinglayer/source/primitive2d/glowprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/glowprimitive2d.cxx @@ -60,22 +60,6 @@ GlowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation return aRetval; } -void GlowPrimitive2D::get2DDecomposition( - Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& /*rViewInformation*/) const -{ - if (getChildren().empty()) - return; - - // create a modifiedColorPrimitive containing the *black* color and the content. Using black - // on white allows creating useful mask in VclPixelProcessor2D::processGlowPrimitive2D. - basegfx::BColorModifierSharedPtr aBColorModifier - = std::make_shared<basegfx::BColorModifier_replace>(basegfx::BColor()); - - const Primitive2DReference xRef(new ModifiedColorPrimitive2D(getChildren(), aBColorModifier)); - rVisitor.append(xRef); -} - // provide unique ID ImplPrimitive2DIDBlock(GlowPrimitive2D, PRIMITIVE2D_ID_GLOWPRIMITIVE2D) diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 3c1a1087adcf..d4ee5f39b7a0 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -983,30 +983,29 @@ void VclPixelProcessor2D::processGlowPrimitive2D(const primitive2d::GlowPrimitiv // Consider glow transparency (initial transparency near the object edge) const sal_uInt8 nTransparency = rCandidate.getGlowColor().GetTransparency(); - impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); if (aBufferDevice.isVisible()) { // remember last OutDev and set to content OutputDevice* pLastOutputDevice = mpOutputDevice; mpOutputDevice = &aBufferDevice.getContent(); - // Processing will draw whatever geometry on white background, applying *black* - // replacement color. The black color replacement is added in 2d decomposition of - // glow primitive. mpOutputDevice->Erase(); process(rCandidate); const tools::Rectangle aRect(static_cast<long>(std::floor(aRange.getMinX())), static_cast<long>(std::floor(aRange.getMinY())), static_cast<long>(std::ceil(aRange.getMaxX())), static_cast<long>(std::ceil(aRange.getMaxY()))); - Bitmap bitmap = mpOutputDevice->GetBitmap(aRect.TopLeft(), aRect.GetSize()); + BitmapEx bmpEx = mpOutputDevice->GetBitmapEx(aRect.TopLeft(), aRect.GetSize()); - AlphaMask mask = ProcessAndBlurAlphaMask(bitmap, fBlurRadius, fBlurRadius, nTransparency); + AlphaMask mask + = ProcessAndBlurAlphaMask(bmpEx.GetAlpha(), fBlurRadius, fBlurRadius, nTransparency); // The end result is the bitmap filled with glow color and blurred 8-bit alpha mask const basegfx::BColor aGlowColor( maBColorModifierStack.getModifiedColor(rCandidate.getGlowColor().getBColor())); - bitmap.Erase(Color(aGlowColor)); - BitmapEx result(bitmap, mask); + Bitmap bmp = bmpEx.GetBitmap(); + bmp.Erase(Color(aGlowColor)); + BitmapEx result(bmp, mask); // back to old OutDev mpOutputDevice = pLastOutputDevice; diff --git a/include/drawinglayer/primitive2d/glowprimitive2d.hxx b/include/drawinglayer/primitive2d/glowprimitive2d.hxx index 5c3029882de2..62a585276b85 100644 --- a/include/drawinglayer/primitive2d/glowprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/glowprimitive2d.hxx @@ -52,11 +52,6 @@ public: virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override; - /// create decomposition - virtual void - get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, - const geometry::ViewInformation2D& rViewInformation) const override; - /// provide unique ID virtual sal_uInt32 getPrimitive2DID() const override; }; commit c8787b8469053bfa1105697d7852dbdac4a184ba Author: Mike Kaganski <[email protected]> AuthorDate: Thu May 14 14:42:24 2020 +0300 Commit: Mike Kaganski <[email protected]> CommitDate: Fri May 29 10:31:21 2020 +0200 tdf#49247, tdf#101181: output glow and soft edge effects to metafile Change-Id: Ie660ae372fc0b5f97f685b6d1e82b9e8a12e7e30 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94192 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> (cherry picked from commit 9dcbf7b0098e59c22ec17d86c270d610e0416f72) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95081 diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 231bf8bc9259..297fd725c7b7 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -38,6 +38,8 @@ #include <vcl/graph.hxx> // for PDFExtOutDevData Graphic support #include <toolkit/helper/formpdfexport.hxx> // for PDFExtOutDevData Graphic support #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/glowprimitive2d.hxx> +#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> #include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx> #include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx> @@ -927,6 +929,12 @@ void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimi static_cast<const primitive2d::ObjectInfoPrimitive2D&>(rCandidate)); break; } + case PRIMITIVE2D_ID_GLOWPRIMITIVE2D: + case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D: + { + processPrimitive2DOnPixelProcessor(rCandidate); + break; + } default: { // process recursively @@ -2312,6 +2320,95 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D( } } +VclPtr<VirtualDevice> VclMetafileProcessor2D::CreateBufferDevice( + const basegfx::B2DRange& rCandidateRange, const double fMaxQuadratPixels, + geometry::ViewInformation2D& rViewInfo, tools::Rectangle& rRectLogic, Size& rSizePixel) +{ + basegfx::B2DRange aViewRange(rCandidateRange); + aViewRange.transform(maCurrentTransformation); + rRectLogic = tools::Rectangle(static_cast<long>(std::floor(aViewRange.getMinX())), + static_cast<long>(std::floor(aViewRange.getMinY())), + static_cast<long>(std::ceil(aViewRange.getMaxX())), + static_cast<long>(std::ceil(aViewRange.getMaxY()))); + const tools::Rectangle aRectPixel(mpOutputDevice->LogicToPixel(rRectLogic)); + rSizePixel = aRectPixel.GetSize(); + const double fViewVisibleArea(rSizePixel.getWidth() * rSizePixel.getHeight()); + double fReduceFactor(1.0); + + if (fViewVisibleArea > fMaxQuadratPixels) + { + // reduce render size + fReduceFactor = sqrt(fMaxQuadratPixels / fViewVisibleArea); + rSizePixel = Size(basegfx::fround(rSizePixel.getWidth() * fReduceFactor), + basegfx::fround(rSizePixel.getHeight() * fReduceFactor)); + } + + VclPtrInstance<VirtualDevice> pBufferDevice(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + if (pBufferDevice->SetOutputSizePixel(rSizePixel)) + { + // create and set MapModes for target devices + MapMode aNewMapMode(mpOutputDevice->GetMapMode()); + aNewMapMode.SetOrigin(Point(-rRectLogic.Left(), -rRectLogic.Top())); + pBufferDevice->SetMapMode(aNewMapMode); + + // prepare view transformation for target renderers + // ATTENTION! Need to apply another scaling because of the potential DPI differences + // between Printer and VDev (mpOutputDevice and pBufferDevice here). + // To get the DPI, LogicToPixel from (1,1) from MapUnit::MapInch needs to be used. + basegfx::B2DHomMatrix aViewTransform(pBufferDevice->GetViewTransformation()); + const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch))); + const Size aDPINew(pBufferDevice->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch))); + const double fDPIXChange(static_cast<double>(aDPIOld.getWidth()) + / static_cast<double>(aDPINew.getWidth())); + const double fDPIYChange(static_cast<double>(aDPIOld.getHeight()) + / static_cast<double>(aDPINew.getHeight())); + + if (!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0)) + { + aViewTransform.scale(fDPIXChange, fDPIYChange); + } + + // also take scaling from Size reduction into account + if (!basegfx::fTools::equal(fReduceFactor, 1.0)) + { + aViewTransform.scale(fReduceFactor, fReduceFactor); + } + + // create view information and pixel renderer. Reuse known ViewInformation + // except new transformation and range + rViewInfo = geometry::ViewInformation2D( + getViewInformation2D().getObjectTransformation(), aViewTransform, aViewRange, + getViewInformation2D().getVisualizedPage(), getViewInformation2D().getViewTime(), + getViewInformation2D().getExtendedInformationSequence()); + } + else + pBufferDevice.disposeAndClear(); + + return std::move(pBufferDevice); +} + +void VclMetafileProcessor2D::processPrimitive2DOnPixelProcessor( + const primitive2d::BasePrimitive2D& rCandidate) +{ + basegfx::B2DRange aViewRange(rCandidate.getB2DRange(getViewInformation2D())); + geometry::ViewInformation2D aViewInfo; + tools::Rectangle aRectLogic; + Size aSizePixel; + auto pBufferDevice(CreateBufferDevice(aViewRange, 500000, aViewInfo, aRectLogic, aSizePixel)); + if (pBufferDevice) + { + VclPixelProcessor2D aBufferProcessor(aViewInfo, *pBufferDevice); + + // draw content using pixel renderer + primitive2d::Primitive2DReference aRef( + &const_cast<primitive2d::BasePrimitive2D&>(rCandidate)); + aBufferProcessor.process({ aRef }); + const BitmapEx aBmContent(pBufferDevice->GetBitmapEx(Point(), aSizePixel)); + mpOutputDevice->DrawBitmapEx(aRectLogic.TopLeft(), aRectLogic.GetSize(), aBmContent); + pBufferDevice.disposeAndClear(); + } +} + } // end of namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx index 0393039f4455..5febad18c3d7 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx @@ -144,6 +144,11 @@ private: const primitive2d::TransparencePrimitive2D& rTransparenceCandidate); void processStructureTagPrimitive2D( const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate); + void processPrimitive2DOnPixelProcessor(const primitive2d::BasePrimitive2D& rCandidate); + VclPtr<VirtualDevice> CreateBufferDevice(const basegfx::B2DRange& rCandidateRange, + const double fMaxQuadratPixels, + geometry::ViewInformation2D& rViewInfo, + tools::Rectangle& rRectLogic, Size& rSizePixel); /// Convert the fWidth to the same space as its coordinates. double getTransformedLineWidth(double fWidth) const; _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
