vcl/qa/cppunit/outdev.cxx      |   33 +++++++++++++++++++++++++++++++++
 vcl/source/outdev/bitmapex.cxx |   11 +++++++++++
 2 files changed, 44 insertions(+)

New commits:
commit cdd4166b9445f99c5e404393407f31b8072a06ab
Author:     Miklos Vajna <[email protected]>
AuthorDate: Thu Sep 25 08:48:07 2025 +0200
Commit:     Caolán McNamara <[email protected]>
CommitDate: Thu Sep 25 12:05:17 2025 +0200

    tdf#166338 vcl: avoid unwanted downscale in DrawTransformedBitmapEx()
    
    Open the Impress bugdoc, the "Annotated result:" image's "red cable"
    bitmap is sharp in edit mode, but is blurry when presenting.
    
    This went wrong in commit 7c94d7267bc8b5f43185204ab4953c4b188214bf
    (tdf#149943 vcl: fix pixelated PDF export and print for a rotated image,
    2022-08-03), which stopped changing the scale part of the transform
    matrix. The old problem was that the transform resulted in a downscale:
    debug:5739:5739: OutputDevice::DrawTransformedBitmapEx: aOriginalScale w,h 
is 226,100, aFullScale is (906.698,6277.69) -> for w, we go from 906 to 226
    
    The new use-case is that this transform used to upscale in the past,
    which preserved more pixels from the original bitmap:
    debug:5632:5632: OutputDevice::DrawTransformedBitmapEx: aOriginalScale w,h 
is 326,1125, aFullScale is (21.1276,76.1197) -> for w, we go from 21 to 326
    Fix the problem by conditionally restore the change of the scale in the
    transform matrix: only do it when we would upscale. This was the
    presented bitmap is sharp again, but the old use-case continues to work.
    
    The deeper problem is why slideshow goes via a metafile at all, but
    that's not changed here.
    
    Change-Id: I73ef426dc9d047a0231a700b0fe7ed0e4747d81b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191473
    Tested-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/vcl/qa/cppunit/outdev.cxx b/vcl/qa/cppunit/outdev.cxx
index 67489665ebbb..7fb6c9ace0db 100644
--- a/vcl/qa/cppunit/outdev.cxx
+++ b/vcl/qa/cppunit/outdev.cxx
@@ -17,6 +17,7 @@
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/vector/b2enums.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 #include <vcl/gradient.hxx>
 #include <vcl/lineinfo.hxx>
@@ -339,6 +340,38 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawGrayBitmap)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapExScale)
+{
+    // Given a 100x100 bitmap:
+    ScopedVclPtrInstance<VirtualDevice> pVDev;
+    Bitmap aBitmap(Size(100, 100), vcl::PixelFormat::N24_BPP);
+    basegfx::B2DVector aScale(20, 80);
+    basegfx::B2DVector aTranslate(80, 0);
+    double fRotate = M_PI / 2;
+    double fShearX = 0;
+    basegfx::B2DHomMatrix aMatrix = 
basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+        aScale, fShearX, fRotate, aTranslate);
+    BitmapEx aBitmapEx(aBitmap);
+    GDIMetaFile aMtf;
+    aMtf.Record(pVDev.get());
+
+    // When drawing that with a transform:
+    pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
+
+    // Then make sure the bitmap recorded in the metafile doesn't get a scaled 
down width:
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
+    MetaAction* pAction = aMtf.GetAction(0);
+    CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
+    auto pBitmapAction = static_cast<MetaBmpExScaleAction*>(pAction);
+    const BitmapEx& rBitmapEx = pBitmapAction->GetBitmapEx();
+    Size aTransformedSize = rBitmapEx.GetSizePixel();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected greater or equal than: 100
+    // - Actual  : 80
+    // i.e. an unwanted scaling down lead to blurry presentation output.
+    CPPUNIT_ASSERT_GREATEREQUAL(static_cast<tools::Long>(100), 
aTransformedSize.getWidth());
+}
+
 CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapEx)
 {
     // Create a virtual device, and connect a metafile to it.
diff --git a/vcl/source/outdev/bitmapex.cxx b/vcl/source/outdev/bitmapex.cxx
index 3024b7ba86ed..3d6b4ff28727 100644
--- a/vcl/source/outdev/bitmapex.cxx
+++ b/vcl/source/outdev/bitmapex.cxx
@@ -540,6 +540,17 @@ void OutputDevice::DrawTransformedBitmapEx(
     basegfx::B2DVector aFullScale, aFullTranslate;
     double fFullRotate, fFullShearX;
     aFullTransform.decompose(aFullScale, aFullTranslate, fFullRotate, 
fFullShearX);
+    if (aFullScale.getX() > 0 && aFullScale.getY() > 0
+        && rOriginalSizePixel.getWidth() > aFullScale.getX()
+        && rOriginalSizePixel.getHeight() > aFullScale.getY())
+    {
+        // aFullTransform would downscale the bitmap: avoid this, so the 
recorded metafile can be
+        // better upscaled later.
+        basegfx::B2DHomMatrix aTransform = 
basegfx::utils::createScaleB2DHomMatrix(
+                rOriginalSizePixel.getWidth() / aFullScale.getX(),
+                rOriginalSizePixel.getHeight() / aFullScale.getY());
+        aFullTransform *= aTransform;
+    }
 
     double fSourceRatio = 1.0;
     if (rOriginalSizePixel.getHeight() != 0)

Reply via email to