drawinglayer/source/processor2d/cairopixelprocessor2d.cxx | 41 ++++++++++---- sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 2 2 files changed, 32 insertions(+), 11 deletions(-)
New commits: commit 9a95a2f948d8eb673b7c789401928d62dff35e2a Author: Armin Le Grand (collabora) <[email protected]> AuthorDate: Tue Jul 15 17:48:11 2025 +0200 Commit: Andras Timar <[email protected]> CommitDate: Thu Jan 8 16:34:30 2026 +0100 tdf#166734 CairoSDPR: use sub-pixel correct transformation When parts of the output need to be pre-rendered (e.g. transparencies) the temp target is of course pixel-aligned, bit the mapping for the rendering was not yet. Added that now. This could lead to sub-pixel displacements which are usually not recognizable, but also like here make the PixelSnap fail. Change-Id: I877987947bdcc7521580de9287894ca70b17763c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187928 Reviewed-by: Armin Le Grand <[email protected]> Tested-by: Jenkins Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196859 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 9768fc7c669c..98b8d43f1a5d 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -1626,6 +1626,13 @@ void CairoPixelProcessor2D::processTransparencePrimitive2D( cairo_save(mpRT); + // tdf#166734 need to expand to full pixels due to pre-rendering + // will use discrete pixels/top-left position + aVisibleRange.expand( + basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY()))); + aVisibleRange.expand( + basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY()))); + // create embedding transformation for sub-surface const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix( -aVisibleRange.getMinX(), -aVisibleRange.getMinY())); @@ -1635,8 +1642,8 @@ void CairoPixelProcessor2D::processTransparencePrimitive2D( // draw mask to temporary surface cairo_surface_t* pTarget(cairo_get_target(mpRT)); - const double fContainedWidth(ceil(aVisibleRange.getWidth())); - const double fContainedHeight(ceil(aVisibleRange.getHeight())); + const double fContainedWidth(aVisibleRange.getWidth()); + const double fContainedHeight(aVisibleRange.getHeight()); cairo_surface_t* pMask(cairo_surface_create_similar_image(pTarget, CAIRO_FORMAT_ARGB32, fContainedWidth, fContainedHeight)); CairoPixelProcessor2D aMaskRenderer(aViewInformation2D, pMask); @@ -1690,6 +1697,13 @@ void CairoPixelProcessor2D::processInvertPrimitive2D( cairo_save(mpRT); + // tdf#166734 need to expand to full pixels due to pre-rendering + // will use discrete pixels/top-left position + aVisibleRange.expand( + basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY()))); + aVisibleRange.expand( + basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY()))); + // create embedding transformation for sub-surface const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix( -aVisibleRange.getMinX(), -aVisibleRange.getMinY())); @@ -1699,8 +1713,8 @@ void CairoPixelProcessor2D::processInvertPrimitive2D( // draw sub-content to temporary surface cairo_surface_t* pTarget(cairo_get_target(mpRT)); - const double fContainedWidth(ceil(aVisibleRange.getWidth())); - const double fContainedHeight(ceil(aVisibleRange.getHeight())); + const double fContainedWidth(aVisibleRange.getWidth()); + const double fContainedHeight(aVisibleRange.getHeight()); cairo_surface_t* pContent(cairo_surface_create_similar_image( pTarget, CAIRO_FORMAT_ARGB32, fContainedWidth, fContainedHeight)); CairoPixelProcessor2D aContent(aViewInformation2D, pContent); @@ -1743,8 +1757,8 @@ void CairoPixelProcessor2D::processInvertPrimitive2D( unsigned char* pFrontDataRoot(cairo_image_surface_get_data(pContent)); // in parallel, iterate over original data (call it Back) - const sal_uInt32 nBackOffX(floor(aVisibleRange.getMinX())); - const sal_uInt32 nBackOffY(floor(aVisibleRange.getMinY())); + const sal_uInt32 nBackOffX(aVisibleRange.getMinX()); + const sal_uInt32 nBackOffY(aVisibleRange.getMinY()); const sal_uInt32 nBackStride(cairo_image_surface_get_stride(pRenderTarget)); unsigned char* pBackDataRoot(cairo_image_surface_get_data(pRenderTarget)); const bool bBackPreMultiply(CAIRO_FORMAT_ARGB32 @@ -1986,8 +2000,6 @@ void CairoPixelProcessor2D::processUnifiedTransparencePrimitive2D( return; } - cairo_save(mpRT); - // calculate visible range, create only for that range basegfx::B2DRange aDiscreteRange( rTransCandidate.getChildren().getB2DRange(getViewInformation2D())); @@ -2001,6 +2013,15 @@ void CairoPixelProcessor2D::processUnifiedTransparencePrimitive2D( return; } + cairo_save(mpRT); + + // tdf#166734 need to expand to full pixels due to pre-rendering + // will use discrete pixels/top-left position + aVisibleRange.expand( + basegfx::B2DPoint(floor(aVisibleRange.getMinX()), floor(aVisibleRange.getMinY()))); + aVisibleRange.expand( + basegfx::B2DPoint(ceil(aVisibleRange.getMaxX()), ceil(aVisibleRange.getMaxY()))); + // create embedding transformation for sub-surface const basegfx::B2DHomMatrix aEmbedTransform(basegfx::utils::createTranslateB2DHomMatrix( -aVisibleRange.getMinX(), -aVisibleRange.getMinY())); @@ -2010,8 +2031,8 @@ void CairoPixelProcessor2D::processUnifiedTransparencePrimitive2D( // draw content to temporary surface cairo_surface_t* pTarget(cairo_get_target(mpRT)); - const double fContainedWidth(ceil(aVisibleRange.getWidth())); - const double fContainedHeight(ceil(aVisibleRange.getHeight())); + const double fContainedWidth(aVisibleRange.getWidth()); + const double fContainedHeight(aVisibleRange.getHeight()); cairo_surface_t* pContent(cairo_surface_create_similar( pTarget, cairo_surface_get_content(pTarget), fContainedWidth, fContainedHeight)); CairoPixelProcessor2D aContent(aViewInformation2D, pContent); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx index 14abb6b3ee5d..137d60a6452d 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx @@ -772,7 +772,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf136841, "tdf136841.docx") CPPUNIT_ASSERT_EQUAL( Color(228,71,69), bitmap.GetPixelColor(38,38)); #else // NOTE: For CairoSDPR the Color changes slightly from (228,71,69) - CPPUNIT_ASSERT_EQUAL( Color(229,71,70), bitmap.GetPixelColor(38,38)); + CPPUNIT_ASSERT_EQUAL( Color(228,72,70), bitmap.GetPixelColor(38,38)); #endif }
