drawinglayer/source/processor2d/cairopixelprocessor2d.cxx | 41 ++++++++++---- sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 2 2 files changed, 32 insertions(+), 11 deletions(-)
New commits: commit 15a5d633fec3c3c62870ab4168a1886796350031 Author: Armin Le Grand (collabora) <armin.legr...@collabora.com> AuthorDate: Tue Jul 15 17:48:11 2025 +0200 Commit: Armin Le Grand <armin.le.gr...@me.com> CommitDate: Wed Jul 16 10:52:38 2025 +0200 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 <armin.le.gr...@me.com> Tested-by: Jenkins diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index b48cfd465025..167caaad50f4 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -1635,6 +1635,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())); @@ -1644,8 +1651,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); @@ -1699,6 +1706,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())); @@ -1708,8 +1722,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); @@ -1752,8 +1766,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 @@ -1995,8 +2009,6 @@ void CairoPixelProcessor2D::processUnifiedTransparencePrimitive2D( return; } - cairo_save(mpRT); - // calculate visible range, create only for that range basegfx::B2DRange aDiscreteRange( rTransCandidate.getChildren().getB2DRange(getViewInformation2D())); @@ -2010,6 +2022,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())); @@ -2019,8 +2040,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 f4dbdaec15bc..21aabad8e892 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 }