summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-10-08 09:16:27 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-10-08 14:31:32 +0200
commitdd4a67084853a030bf4b9f1f85d728620e0604a5 (patch)
tree2fe01d5939ee5e1b4f127243561efc56e792b1d6
parentef2ec07b4113fdadf863352c832af657b5ae205c (diff)
vcl: avoid downscale && upscale in DrawTransformedBitmapEx()
If we rotate a bitmap and put it to a metafile, we'll create a MetaBmpExScaleAction. But just because we need to store a transformed bitmap for rotation purposes, it doesn't mean we also need to scale it. This helps in case later the metafile is upscaled and the downscaled bitmap would look blurry. Change-Id: I7d64a88af460e80dffde8052186888eddbb440fe Reviewed-on: https://gerrit.libreoffice.org/80426 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--vcl/qa/cppunit/outdev.cxx32
-rw-r--r--vcl/source/outdev/bitmap.cxx15
2 files changed, 46 insertions, 1 deletions
diff --git a/vcl/qa/cppunit/outdev.cxx b/vcl/qa/cppunit/outdev.cxx
index 0484e4a4143d..53f2424f5dbe 100644
--- a/vcl/qa/cppunit/outdev.cxx
+++ b/vcl/qa/cppunit/outdev.cxx
@@ -13,6 +13,8 @@
#include <vcl/virdev.hxx>
#include <vcl/window.hxx>
#include <vcl/bitmapaccess.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
@@ -27,6 +29,7 @@ public:
void testWindowBackgroundColor();
void testGetReadableFontColorPrinter();
void testGetReadableFontColorWindow();
+ void testDrawTransformedBitmapEx();
CPPUNIT_TEST_SUITE(VclOutdevTest);
CPPUNIT_TEST(testVirtualDevice);
@@ -35,6 +38,7 @@ public:
CPPUNIT_TEST(testWindowBackgroundColor);
CPPUNIT_TEST(testGetReadableFontColorPrinter);
CPPUNIT_TEST(testGetReadableFontColorWindow);
+ CPPUNIT_TEST(testDrawTransformedBitmapEx);
CPPUNIT_TEST_SUITE_END();
};
@@ -132,6 +136,34 @@ void VclOutdevTest::testUseAfterDispose()
pVDev->GetViewTransformation();
}
+void VclOutdevTest::testDrawTransformedBitmapEx()
+{
+ // Create a virtual device, and connect a metafile to it.
+ // Also create a 16x16 bitmap.
+ ScopedVclPtrInstance<VirtualDevice> pVDev;
+ Bitmap aBitmap(Size(16, 16), 24);
+ BitmapEx aBitmapEx(aBitmap);
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.scale(8, 8);
+ aMatrix.rotate(M_PI / 2);
+ GDIMetaFile aMtf;
+ aMtf.Record(pVDev.get());
+
+ // Draw the rotated bitmap on the vdev.
+ pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
+ 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: 16x16
+ // - Actual : 8x8
+ // I.e. the bitmap before scaling was already scaled down, just because it was rotated.
+ CPPUNIT_ASSERT_EQUAL(Size(16, 16), aTransformedSize);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(VclOutdevTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index 7959b13f8f68..2cbdb2fdb2b3 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -1208,7 +1208,7 @@ void OutputDevice::DrawTransformedBitmapEx(
const bool bInvert(RasterOp::Invert == meRasterOp);
const bool bBitmapChangedColor(mnDrawMode & (DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap | DrawModeFlags::GrayBitmap ));
bool bDone(false);
- const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
+ basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile );
if(bTryDirectPaint)
@@ -1272,6 +1272,19 @@ void OutputDevice::DrawTransformedBitmapEx(
aTransformed = BitmapEx(aContent, aMaskBmp);
}
+ // Remove scaling from aFulltransform: we transform due to shearing or rotation, scaling
+ // will happen according to aDestSize.
+ basegfx::B2DVector aFullScale, aFullTranslate;
+ double fFullRotate, fFullShearX;
+ aFullTransform.decompose(aFullScale, aFullTranslate, fFullRotate, fFullShearX);
+ if (aFullScale.getX() != 0 && aFullScale.getY() != 0)
+ {
+ basegfx::B2DHomMatrix aTransform = basegfx::utils::createScaleB2DHomMatrix(
+ rOriginalSizePixel.getWidth() / aFullScale.getX(),
+ rOriginalSizePixel.getHeight() / aFullScale.getY());
+ aFullTransform *= aTransform;
+ }
+
aTransformed = aTransformed.getTransformed(
aFullTransform,
aVisibleRange,