diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index ffb8fcff165e..e7156bdb3238 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -55,8 +55,10 @@ #include #include #include -#include #include +#include +#include +#include #include #include @@ -959,6 +961,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) , mbCairoCoordinateLimitWorkaroundActive(false) + , maXGraphics() { if (nWidthPixel <= 0 || nHeightPixel <= 0) // no size, invalid @@ -1002,6 +1005,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) , mbCairoCoordinateLimitWorkaroundActive(false) + , maXGraphics() { // no target, nothing to initialize if (nullptr == pTarget) @@ -3881,12 +3885,44 @@ void CairoPixelProcessor2D::processControlPrimitive2D( return; } - // process recursively and use the decomposition as Bitmap - // NOTE: The VclPixelProcessor2D tries to paint it using - // UNO API and awt::XView/awt::XGraphics to directly paint the - // control. To do so would need the target OutDev which we - // want to avoid here - process(rControlPrimitive); + bool bDone(false); + + try + { + if (getXGraphics().is()) + { + // Needs to be drawn. Link new graphics and view + const uno::Reference& rXControl(rControlPrimitive.getXControl()); + uno::Reference xControlView(rXControl, uno::UNO_QUERY_THROW); + const uno::Reference xOriginalGraphics(xControlView->getGraphics()); + xControlView->setGraphics(getXGraphics()); + + // get position + const basegfx::B2DHomMatrix aObjectToPixel( + getViewInformation2D().getObjectToViewTransformation() + * rControlPrimitive.getTransform()); + const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0)); + + xControlView->draw(basegfx::fround(aTopLeftPixel.getX()), + basegfx::fround(aTopLeftPixel.getY())); + + // restore original graphics + xControlView->setGraphics(xOriginalGraphics); + bDone = true; + } + } + catch (const uno::Exception&) + { + // #i116763# removing since there is a good alternative when the xControlView + // is not found and it is allowed to happen + // DBG_UNHANDLED_EXCEPTION(); + } + + if (!bDone) + { + // process recursively and use the decomposition as Bitmap + process(rControlPrimitive); + } } void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround() diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx index f87bffea6b21..b4a453a7edec 100644 --- a/drawinglayer/source/processor2d/processor2dtools.cxx +++ b/drawinglayer/source/processor2d/processor2dtools.cxx @@ -30,6 +30,8 @@ #include #endif +using namespace com::sun::star; + namespace drawinglayer::processor2d { std::unique_ptr createPixelProcessor2DFromScratch( @@ -125,7 +127,14 @@ std::unique_ptr createPixelProcessor2DFromOutputDevice( rTargetOutDev.GetOutputWidthPixel(), rTargetOutDev.GetOutputHeightPixel())); if (aRetval->valid()) + { + // if we construct a CairoPixelProcessor2D from OutputDevice, + // additionally set the XGraphics that can be obtained from + // there. It may be used e.g. to render FormControls directly + aRetval->setXGraphics(rTargetOutDev.CreateUnoGraphics()); + return aRetval; + } } #endif diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 79eba7bb0024..98182a43a758 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -657,21 +657,19 @@ void VclPixelProcessor2D::processControlPrimitive2D( return; } - // get awt::XControl from control primitive - const uno::Reference& rXControl(rControlPrimitive.getXControl()); bool bDone(false); try { - // remember old graphics and create new - uno::Reference xControlView(rXControl, uno::UNO_QUERY_THROW); - const uno::Reference xOriginalGraphics(xControlView->getGraphics()); - const uno::Reference xNewGraphics(mpOutputDevice->CreateUnoGraphics()); + const uno::Reference xTargetGraphics(mpOutputDevice->CreateUnoGraphics()); - if (xNewGraphics.is()) + if (xTargetGraphics.is()) { // Needs to be drawn. Link new graphics and view - xControlView->setGraphics(xNewGraphics); + const uno::Reference& rXControl(rControlPrimitive.getXControl()); + uno::Reference xControlView(rXControl, uno::UNO_QUERY_THROW); + const uno::Reference xOriginalGraphics(xControlView->getGraphics()); + xControlView->setGraphics(xTargetGraphics); // get position const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index 1a211806713b..2e9c2ad2ce45 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -13,6 +13,7 @@ #include #include #include +#include // cairo-specific #include @@ -89,6 +90,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub // calculated result of if we are in outsideCairoCoordinateLimits mode bool mbCairoCoordinateLimitWorkaroundActive; + // the XGraphics which may be set using setXGraphics() + com::sun::star::uno::Reference maXGraphics; + // helpers for direct paints void paintPolyPolygonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rColor, double fTransparency = 0.0); @@ -188,10 +192,21 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub protected: bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; } bool hasRenderTarget() const { return nullptr != mpRT; } + const com::sun::star::uno::Reference& getXGraphics() const + { + return maXGraphics; + } public: bool valid() const { return hasRenderTarget() && !hasError(); } + // set a XGraphics for this CairoPixelProcessor2D when it is available + void + setXGraphics(const com::sun::star::uno::Reference& rXGraphics) + { + maXGraphics = rXGraphics; + } + // read access to CairoCoordinateLimitWorkaround mechanism bool isCairoCoordinateLimitWorkaroundActive() const {