diff options
3 files changed, 106 insertions, 34 deletions
diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 1bf2b7dd9324..a1b57ed7940a 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -866,9 +866,12 @@ basegfx::B2DRange getDiscreteViewRange(cairo_t* pRT) namespace drawinglayer::processor2d { CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, - cairo_surface_t* pTarget) + cairo_surface_t* pTarget, tools::Long nOffsetPixelX, + tools::Long nOffsetPixelY, tools::Long nWidthPixel, + tools::Long nHeightPixel) : BaseProcessor2D(rViewInformation) , maBColorModifierStack() + , mpCreateForRectangle(nullptr) , mpRT(nullptr) , mbRenderSimpleTextDirect( officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get()) @@ -878,19 +881,64 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& { if (pTarget) { - cairo_t* pRT = cairo_create(pTarget); - cairo_set_antialias(pRT, rViewInformation.getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT - : CAIRO_ANTIALIAS_NONE); - cairo_set_fill_rule(pRT, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_operator(pRT, CAIRO_OPERATOR_OVER); - setRenderTarget(pRT); + bool bClipNeeded(false); + + if (0 != nOffsetPixelX || 0 != nOffsetPixelY || 0 != nWidthPixel || 0 != nHeightPixel) + { + if (0 != nOffsetPixelX || 0 != nOffsetPixelY) + { + // if offset is used we need initial clip + bClipNeeded = true; + } + else + { + // no offset used, compare to real pixel size + const tools::Long nRealPixelWidth(cairo_image_surface_get_width(pTarget)); + const tools::Long nRealPixelHeight(cairo_image_surface_get_height(pTarget)); + + if (nRealPixelWidth != nWidthPixel || nRealPixelHeight != nHeightPixel) + { + // if size differs we need initial clip + bClipNeeded = true; + } + } + } + + if (bClipNeeded) + { + // optional: if the possibility to add an initial clip relative + // to the real pixel dimensions of the target surface is used, + // aplly it here using that nice existing method of cairo + mpCreateForRectangle = cairo_surface_create_for_rectangle( + pTarget, nOffsetPixelX, nOffsetPixelY, nWidthPixel, nHeightPixel); + + if (nullptr != mpCreateForRectangle) + mpRT = cairo_create(mpCreateForRectangle); + } + else + { + // create RenderTarget for full target + mpRT = cairo_create(pTarget); + } + + if (nullptr != mpRT) + { + // initialize some basic used values/settings + cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() + ? CAIRO_ANTIALIAS_DEFAULT + : CAIRO_ANTIALIAS_NONE); + cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER); + } } } CairoPixelProcessor2D::~CairoPixelProcessor2D() { - if (mpRT) + if (nullptr != mpRT) cairo_destroy(mpRT); + if (nullptr != mpCreateForRectangle) + cairo_surface_destroy(mpCreateForRectangle); } void CairoPixelProcessor2D::processBitmapPrimitive2D( diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx index e11f64a11da9..7930e496664f 100644 --- a/drawinglayer/source/processor2d/processor2dtools.cxx +++ b/drawinglayer/source/processor2d/processor2dtools.cxx @@ -36,31 +36,18 @@ std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice( OutputDevice& rTargetOutDev, const drawinglayer::geometry::ViewInformation2D& rViewInformation2D) { - static bool bUsePrimitiveRenderer( #if defined(_WIN32) - // Windows: make dependent on TEST_SYSTEM_PRIMITIVE_RENDERER - nullptr != std::getenv("TEST_SYSTEM_PRIMITIVE_RENDERER") -#elif USE_HEADLESS_CODE - // Linux/Cairo: activate to check tests/builds. Leave a - // possibility to deactivate for easy test/request testing - nullptr == std::getenv("DISABLE_SYSTEM_DEPENDENT_PRIMITIVE_RENDERER") - - // Use this if all is stable/tested for a while - // true - - // Also possible: make dependent on ExperimentalMode - // officecfg::Office::Common::Misc::ExperimentalMode::get() -#else - // all others: do not use, not (yet) supported - false -#endif - ); + // Windows: make dependent on TEST_SYSTEM_PRIMITIVE_RENDERER + static bool bUsePrimitiveRenderer(nullptr != std::getenv("TEST_SYSTEM_PRIMITIVE_RENDERER")); - if(bUsePrimitiveRenderer) + if (bUsePrimitiveRenderer) { drawinglayer::geometry::ViewInformation2D aViewInformation2D(rViewInformation2D); // if mnOutOffX/mnOutOffY is set (a 'hack' to get a cheap additional offset), apply it additionally + // NOTE: This will also need to take extended size of target device into + // consideration, using D2DPixelProcessor2D *will* have to clip + // against that. Thus for now this is *not* sufficient (see tdf#163125) if(0 != rTargetOutDev.GetOutOffXPixel() || 0 != rTargetOutDev.GetOutOffYPixel()) { basegfx::B2DHomMatrix aTransform(aViewInformation2D.getViewTransformation()); @@ -68,22 +55,45 @@ std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice( aViewInformation2D.setViewTransformation(aTransform); } -#if defined(_WIN32) SystemGraphicsData aData(rTargetOutDev.GetSystemGfxData()); std::unique_ptr<D2DPixelProcessor2D> aRetval( std::make_unique<D2DPixelProcessor2D>(aViewInformation2D, aData.hDC)); if (aRetval->valid()) return aRetval; + } #elif USE_HEADLESS_CODE + // Linux/Cairo: now globally activated in master. Leave a + // possibility to deactivate for easy test/request testing + static bool bUsePrimitiveRenderer(nullptr == std::getenv("DISABLE_SYSTEM_DEPENDENT_PRIMITIVE_RENDERER")); + + if (bUsePrimitiveRenderer) + { SystemGraphicsData aData(rTargetOutDev.GetSystemGfxData()); + const Size aSizePixel(rTargetOutDev.GetOutputSizePixel()); + + // create CairoPixelProcessor2D, make use of the possibility to + // add an initial clip relative to the real pixel dimensions of + // the target surface. This is e.g. needed here due to the + // existance of 'virtual' target surfaces that internally use an + // offset and limitied pixel size, mainly used for UI elements. + // let the CairoPixelProcessor2D do this, it has internal, + // system-specific possibilities to do that in an elegant and + // efficient way (using cairo_surface_create_for_rectangle). std::unique_ptr<CairoPixelProcessor2D> aRetval( - std::make_unique<CairoPixelProcessor2D>(aViewInformation2D, static_cast<cairo_surface_t*>(aData.pSurface))); + std::make_unique<CairoPixelProcessor2D>( + rViewInformation2D, static_cast<cairo_surface_t*>(aData.pSurface), + rTargetOutDev.GetOutOffXPixel(), rTargetOutDev.GetOutOffYPixel(), + aSizePixel.getWidth(), aSizePixel.getHeight())); + if (aRetval->valid()) return aRetval; -#endif } +#endif - // default: create Pixel Vcl-Processor + // default: create VclPixelProcessor2D + // NOTE: Since this uses VCL OutputDevice in the VclPixelProcessor2D + // taking care of virtual devices is not needed, OutputDevice + // and VclPixelProcessor2D will traditionally take care of it return std::make_unique<VclPixelProcessor2D>(rViewInformation2D, rTargetOutDev); } diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index 026c6a0c3086..cd0f8a562e50 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -11,6 +11,7 @@ #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <basegfx/color/bcolormodifier.hxx> +#include <tools/long.hxx> #include <sal/config.h> // cairo-specific @@ -68,6 +69,10 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub // the modifiedColorPrimitive stack basegfx::BColorModifierStack maBColorModifierStack; + // cairo_surface_t created when initial clip from the constructor + // parameters is requested + cairo_surface_t* mpCreateForRectangle; + // cairo specific data cairo_t* mpRT; @@ -173,13 +178,22 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub protected: bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; } - void setRenderTarget(cairo_t* mpNewRT) { mpRT = mpNewRT; } bool hasRenderTarget() const { return nullptr != mpRT; } public: bool valid() const { return hasRenderTarget() && !hasError(); } - CairoPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, - cairo_surface_t* pTarget); + CairoPixelProcessor2D( + // the initial ViewInformation + const geometry::ViewInformation2D& rViewInformation, + + // the cairo render target + cairo_surface_t* pTarget, + + // optional: possibility to add an initial clip relative to + // the real pixel dimensions of the target surface + tools::Long nOffsetPixelX = 0, tools::Long nOffsetPixelY = 0, tools::Long nWidthPixel = 0, + tools::Long nHeightPixel = 0); + virtual ~CairoPixelProcessor2D() override; // access to BColorModifierStack |