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 <Armin.Le.Grand@me.com>
This commit is contained in:
Armin Le Grand (Collabora) 2025-01-30 20:47:00 +01:00 committed by Armin Le Grand
parent 163ddd7a84
commit 7c0d5fab2b
4 changed files with 73 additions and 15 deletions

View File

@ -55,8 +55,10 @@
#include <basegfx/utils/systemdependentdata.hxx> #include <basegfx/utils/systemdependentdata.hxx>
#include <basegfx/utils/bgradient.hxx> #include <basegfx/utils/bgradient.hxx>
#include <vcl/BitmapReadAccess.hxx> #include <vcl/BitmapReadAccess.hxx>
#include <officecfg/Office/Common.hxx>
#include <vcl/vcllayout.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 <unordered_map>
#include <dlfcn.h> #include <dlfcn.h>
@ -959,6 +961,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D&
officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
, mnClipRecursionCount(0) , mnClipRecursionCount(0)
, mbCairoCoordinateLimitWorkaroundActive(false) , mbCairoCoordinateLimitWorkaroundActive(false)
, maXGraphics()
{ {
if (nWidthPixel <= 0 || nHeightPixel <= 0) if (nWidthPixel <= 0 || nHeightPixel <= 0)
// no size, invalid // no size, invalid
@ -1002,6 +1005,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D&
officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
, mnClipRecursionCount(0) , mnClipRecursionCount(0)
, mbCairoCoordinateLimitWorkaroundActive(false) , mbCairoCoordinateLimitWorkaroundActive(false)
, maXGraphics()
{ {
// no target, nothing to initialize // no target, nothing to initialize
if (nullptr == pTarget) if (nullptr == pTarget)
@ -3881,12 +3885,44 @@ void CairoPixelProcessor2D::processControlPrimitive2D(
return; return;
} }
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 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); process(rControlPrimitive);
}
} }
void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround() void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround()

View File

@ -30,6 +30,8 @@
#include <officecfg/Office/Common.hxx> #include <officecfg/Office/Common.hxx>
#endif #endif
using namespace com::sun::star;
namespace drawinglayer::processor2d namespace drawinglayer::processor2d
{ {
std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromScratch( std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromScratch(
@ -125,8 +127,15 @@ std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice(
rTargetOutDev.GetOutputWidthPixel(), rTargetOutDev.GetOutputHeightPixel())); rTargetOutDev.GetOutputWidthPixel(), rTargetOutDev.GetOutputHeightPixel()));
if (aRetval->valid()) 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; return aRetval;
} }
}
#endif #endif
// default: create VclPixelProcessor2D // default: create VclPixelProcessor2D

View File

@ -657,21 +657,19 @@ void VclPixelProcessor2D::processControlPrimitive2D(
return; return;
} }
// get awt::XControl from control primitive
const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
bool bDone(false); bool bDone(false);
try try
{ {
// remember old graphics and create new const uno::Reference<awt::XGraphics> xTargetGraphics(mpOutputDevice->CreateUnoGraphics());
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());
if (xNewGraphics.is()) if (xTargetGraphics.is())
{ {
// Needs to be drawn. Link new graphics and view // 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 // get position
const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation

View File

@ -13,6 +13,7 @@
#include <basegfx/color/bcolormodifier.hxx> #include <basegfx/color/bcolormodifier.hxx>
#include <tools/long.hxx> #include <tools/long.hxx>
#include <sal/config.h> #include <sal/config.h>
#include <com/sun/star/awt/XGraphics.hpp>
// cairo-specific // cairo-specific
#include <cairo.h> #include <cairo.h>
@ -89,6 +90,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub
// calculated result of if we are in outsideCairoCoordinateLimits mode // calculated result of if we are in outsideCairoCoordinateLimits mode
bool mbCairoCoordinateLimitWorkaroundActive; 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 // helpers for direct paints
void paintPolyPolygonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, void paintPolyPolygonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon,
const basegfx::BColor& rColor, double fTransparency = 0.0); const basegfx::BColor& rColor, double fTransparency = 0.0);
@ -188,10 +192,21 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub
protected: protected:
bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; } bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; }
bool hasRenderTarget() const { return nullptr != mpRT; } bool hasRenderTarget() const { return nullptr != mpRT; }
const com::sun::star::uno::Reference<com::sun::star::awt::XGraphics>& getXGraphics() const
{
return maXGraphics;
}
public: public:
bool valid() const { return hasRenderTarget() && !hasError(); } 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 // read access to CairoCoordinateLimitWorkaround mechanism
bool isCairoCoordinateLimitWorkaroundActive() const bool isCairoCoordinateLimitWorkaroundActive() const
{ {