drawinglayer/source/processor2d/cairopixelprocessor2d.cxx  |   50 +++++++++++--
 drawinglayer/source/processor2d/processor2dtools.cxx       |    9 ++
 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx    |   14 +--
 include/drawinglayer/processor2d/cairopixelprocessor2d.hxx |   15 +++
 4 files changed, 73 insertions(+), 15 deletions(-)

New commits:
commit 17b5cc20e14a1abfbcb20a99122f71c970e59b7a
Author:     Armin Le Grand (Collabora) <[email protected]>
AuthorDate: Thu Jan 30 20:47:00 2025 +0100
Commit:     Xisco Fauli <[email protected]>
CommitDate: Fri Feb 14 09:49:34 2025 +0100

    tdf#164476 CiaroSDPR: improve ControlPrimitive2D rendering
    
    The task shows that for some situations the Controls do not
    get vbisualized. These *should* be child windows of the
    panel containing them, but fir some reason these seem to
    get incarnated by being 'painted'.
    Problem is that for SDPRs an OutputDevice to do so is not
    available - by purpose. Luckily it is possible to use a
    awt::XGraphics and 'paint' from there.
    It would also be possible to find out why the child windows
    do not get constructed and where this may need to be done,
    but for now just add 'painting' the Controls by using the
    path utilizing the awt::XGraphics mechanism. For that
    purpose, do set an awt::XGraphics at the CairoSDPR if it
    gets constructed using an OutputDevice.
    It may be that we need to think about how to solve this
    for SDPRs that get constructed from scratch, e.g.
    when using createPixelProcessor2DFromScratch. This would
    mean to somehow construct a awt::XGraphics from a cairo
    surface, probably using an OutputDevice as in-betwen
    step, but for now this change solves the problem.
    
    Change-Id: I3bc653deab7f0b2902081b0fdbd501dfcc78383b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180967
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <[email protected]>
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181551

diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
index 36bb4bb1b3b9..dc6c637e9330 100644
--- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -55,8 +55,10 @@
 #include <basegfx/utils/systemdependentdata.hxx>
 #include <basegfx/utils/bgradient.hxx>
 #include <vcl/BitmapReadAccess.hxx>
-#include <officecfg/Office/Common.hxx>
 #include <vcl/vcllayout.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <com/sun/star/awt/XView.hpp>
+#include <com/sun/star/awt/XControl.hpp>
 #include <unordered_map>
 #include <dlfcn.h>
 
@@ -951,6 +953,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
@@ -994,6 +997,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)
@@ -3873,12 +3877,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<awt::XControl>& 
rXControl(rControlPrimitive.getXControl());
+            uno::Reference<awt::XView> xControlView(rXControl, 
uno::UNO_QUERY_THROW);
+            const uno::Reference<awt::XGraphics> 
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 e90cac41a6c1..f892acfc1563 100644
--- a/drawinglayer/source/processor2d/processor2dtools.cxx
+++ b/drawinglayer/source/processor2d/processor2dtools.cxx
@@ -30,6 +30,8 @@
 #include <officecfg/Office/Common.hxx>
 #endif
 
+using namespace com::sun::star;
+
 namespace drawinglayer::processor2d
 {
 std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromScratch(
@@ -128,7 +130,14 @@ std::unique_ptr<BaseProcessor2D> 
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 d5f878768918..3264cdfc2a4a 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -653,21 +653,19 @@ void VclPixelProcessor2D::processControlPrimitive2D(
         return;
     }
 
-    // get awt::XControl from control primitive
-    const uno::Reference<awt::XControl>& 
rXControl(rControlPrimitive.getXControl());
     bool bDone(false);
 
     try
     {
-        // remember old graphics and create new
-        uno::Reference<awt::XView> xControlView(rXControl, 
uno::UNO_QUERY_THROW);
-        const uno::Reference<awt::XGraphics> 
xOriginalGraphics(xControlView->getGraphics());
-        const uno::Reference<awt::XGraphics> 
xNewGraphics(mpOutputDevice->CreateUnoGraphics());
+        const uno::Reference<awt::XGraphics> 
xTargetGraphics(mpOutputDevice->CreateUnoGraphics());
 
-        if (xNewGraphics.is())
+        if (xTargetGraphics.is())
         {
             // Needs to be drawn. Link new graphics and view
-            xControlView->setGraphics(xNewGraphics);
+            const uno::Reference<awt::XControl>& 
rXControl(rControlPrimitive.getXControl());
+            uno::Reference<awt::XView> xControlView(rXControl, 
uno::UNO_QUERY_THROW);
+            const uno::Reference<awt::XGraphics> 
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 3d20f300a972..6f505f8eeb98 100644
--- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
@@ -13,6 +13,7 @@
 #include <basegfx/color/bcolormodifier.hxx>
 #include <tools/long.hxx>
 #include <sal/config.h>
+#include <com/sun/star/awt/XGraphics.hpp>
 
 // cairo-specific
 #include <cairo.h>
@@ -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<com::sun::star::awt::XGraphics> maXGraphics;
+
     // helpers for direct paints
     void paintPolyPoylgonRGBA(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<com::sun::star::awt::XGraphics>& 
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<com::sun::star::awt::XGraphics>& rXGraphics)
+    {
+        maXGraphics = rXGraphics;
+    }
+
     // read access to CairoCoordinateLimitWorkaround mechanism
     bool isCairoCoordinateLimitWorkaroundActive() const
     {

Reply via email to