From a03a47bb0791d88fedb2650bca412c28469b0b27 Mon Sep 17 00:00:00 2001 From: Paris Oplopoios Date: Wed, 19 Oct 2022 16:57:11 +0300 Subject: tdf#150888 Scale down PPI if it would result in a tiny image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reason for the blurry document in tdf#150888 is that the image is tiny. PPI is 2540 in that image but when using the window bounding box (96, 81) this results in a very small image that the .odt then scales up which makes it blurry. Apart from that, when opening the extracted .wmf in Draw it's also very small, around 0.04" squared. Because MM_ANISOTROPICs definition allows for arbritrary scaling, when an image would be smaller than an inch squared the PPI is scaled down to either the images width or height. This makes the extracted WMF match the size of competitor office suites and fix the blur bug without breaking past tests. Change-Id: I11eab879848d9308f818708a91fd9eb91fc65200 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141533 Tested-by: Jenkins Tested-by: Tomaž Vajngerl Reviewed-by: Tomaž Vajngerl --- emfio/inc/wmfreader.hxx | 1 + emfio/qa/cppunit/wmf/data/TestBigPPI.wmf | Bin 0 -> 3842 bytes emfio/qa/cppunit/wmf/wmfimporttest.cxx | 23 +++++++++++++++++++++++ emfio/source/reader/wmfreader.cxx | 24 ++++++++++++++++++++---- 4 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 emfio/qa/cppunit/wmf/data/TestBigPPI.wmf diff --git a/emfio/inc/wmfreader.hxx b/emfio/inc/wmfreader.hxx index f7788d53651c..5c6979550ef4 100644 --- a/emfio/inc/wmfreader.hxx +++ b/emfio/inc/wmfreader.hxx @@ -33,6 +33,7 @@ namespace emfio private: sal_uInt16 mnUnitsPerInch; sal_uInt32 mnRecSize; + bool mbPlaceable; // embedded EMF data std::optional> mpEMFStream; diff --git a/emfio/qa/cppunit/wmf/data/TestBigPPI.wmf b/emfio/qa/cppunit/wmf/data/TestBigPPI.wmf new file mode 100644 index 000000000000..e120af2790db Binary files /dev/null and b/emfio/qa/cppunit/wmf/data/TestBigPPI.wmf differ diff --git a/emfio/qa/cppunit/wmf/wmfimporttest.cxx b/emfio/qa/cppunit/wmf/wmfimporttest.cxx index a85876e03a7d..c5b2ddbc3205 100644 --- a/emfio/qa/cppunit/wmf/wmfimporttest.cxx +++ b/emfio/qa/cppunit/wmf/wmfimporttest.cxx @@ -52,6 +52,7 @@ public: void testEmfProblem(); void testEmfLineStyles(); void testWorldTransformFontSize(); + void testBigPPI(); void testTdf93750(); void testTdf99402(); void testTdf39894(); @@ -66,6 +67,7 @@ public: CPPUNIT_TEST(testEmfProblem); CPPUNIT_TEST(testEmfLineStyles); CPPUNIT_TEST(testWorldTransformFontSize); + CPPUNIT_TEST(testBigPPI); CPPUNIT_TEST(testTdf93750); CPPUNIT_TEST(testTdf99402); CPPUNIT_TEST(testTdf39894); @@ -310,6 +312,27 @@ void WmfTest::testWorldTransformFontSize() assertXPath(pDoc, "/metafile/font[4]", "weight", "normal"); } +void WmfTest::testBigPPI() +{ + // Test that PPI is reduced from 2540 to 96 (width from META_SETWINDOWEXT) to make the graphic + // bigger + SvFileStream aFileStream(getFullUrl(u"TestBigPPI.wmf"), StreamMode::READ); + GDIMetaFile aGDIMetaFile; + ReadWindowMetafile(aFileStream, aGDIMetaFile); + + MetafileXmlDump dumper; + dumper.filterAllActionTypes(); + dumper.filterActionType(MetaActionType::FONT, false); + xmlDocUniquePtr pDoc = dumpAndParse(dumper, aGDIMetaFile); + + CPPUNIT_ASSERT(pDoc); + + // If the PPI was not reduced the width and height would be <100 which is too small + // Related: tdf#150888 + assertXPath(pDoc, "/metafile", "width", "2540"); + assertXPath(pDoc, "/metafile", "height", "2143"); +} + void WmfTest::testTdf93750() { SvFileStream aFileStream(getFullUrl(u"tdf93750.emf"), StreamMode::READ); diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index 8a54b21f0580..33ef9dd3d0e1 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -1351,11 +1351,11 @@ namespace emfio tools::Rectangle aPlaceableBound; - bool bPlaceable = nPlaceableMetaKey == 0x9ac6cdd7L; + mbPlaceable = nPlaceableMetaKey == 0x9ac6cdd7L; - SAL_INFO("emfio", "Placeable: \"" << (bPlaceable ? "yes" : "no") << "\""); + SAL_INFO("emfio", "Placeable: \"" << (mbPlaceable ? "yes" : "no") << "\""); - if (bPlaceable) + if (mbPlaceable) { //TODO do some real error handling here sal_Int16 nVal(0); @@ -1608,9 +1608,10 @@ namespace emfio Point aViewportOrg(0,0); std::optional aViewportExt; + MappingMode eMapMode = MappingMode::MM_ANISOTROPIC; + if (nEnd - nPos) { - MappingMode eMapMode = MappingMode::MM_ANISOTROPIC; sal_uInt16 nFunction; sal_uInt32 nRSize; @@ -1952,6 +1953,21 @@ namespace emfio if (aWinExt) { rPlaceableBound = tools::Rectangle(aWinOrg, *aWinExt); + if (mbPlaceable && eMapMode == MM_ANISOTROPIC) + { + // It seems that (in MM_ANISOTROPIC WMFs) the "inch" field (PPI) in META_PLACEABLE is + // ignored and instead competitor office suites decide what it should be arbitrarily + // Could have to do with MM_ANISOTROPICs definition: + // Logical units are mapped to arbitrary units with arbitrarily scaled axes. + // The issue is that when PPI is bigger than the window size, the image appears + // tiny (smaller than an inch squared). + // A solution is to scale PPI down in such images to an arbitrary amount that makes + // the image visible: + auto nWidth = rPlaceableBound.GetWidth(); + auto nHeight = rPlaceableBound.GetHeight(); + if (mnUnitsPerInch > nWidth && mnUnitsPerInch > nHeight) + mnUnitsPerInch = std::max(nWidth, nHeight); + } SAL_INFO("emfio", "Window dimension " " left: " << rPlaceableBound.Left() << " top: " << rPlaceableBound.Top() << " right: " << rPlaceableBound.Right() << " bottom: " << rPlaceableBound.Bottom()); -- cgit