Bug 131644 - make CppunitTest_emfio_emf CPPUNIT_TEST_NAME=TestLinearGradient fails on Windows with UI scale 150%
Summary: make CppunitTest_emfio_emf CPPUNIT_TEST_NAME=TestLinearGradient fails on Wind...
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
7.0.0.0.alpha0+
Hardware: All Windows (All)
: medium normal
Assignee: Bartosz
URL:
Whiteboard: target:7.0.0
Keywords: bibisectNotNeeded, regression
Depends on:
Blocks:
 
Reported: 2020-03-28 12:40 UTC by Mike Kaganski
Modified: 2020-05-25 12:19 UTC (History)
2 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Kaganski 2020-03-28 12:40:00 UTC
make CppunitTest_emfio_emf CPPUNIT_TEST_NAME=TestLinearGradient fails on Windows with UI scale 150%.

> make CppunitTest_emfio_emf CPPUNIT_TEST_NAME=TestLinearGradient
> C:/cygwin/home/user/lode/opt/bin/make -j 4 -rs -f C:/cygwin/home/user/lode/dev/core/Makefile.gbuild CppunitTest_emfio_
> emf
> [CUT] emfio_emf
> warn:emfio:16536:21072:emfio/source/reader/emfreader.cxx:804:           unknown id: 0x50504e54
> warn:emfio:16536:21072:emfio/source/reader/emfreader.cxx:804:           unknown id: 0x50504e54
> C:/cygwin/home/user/lode/dev/core/test/source/xmltesttools.cxx:168:`anonymous namespace'::Test::TestLinearGradient
> equality assertion failed
> - Expected: m0 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z
> - Actual  : m0 3805.32416502947h11423.6373448462v11415.3241650295h-11423.6373448462z
> - In <>, attribute 'path' of '/primitive2D/metafile/transform/mask/svglineargradient[1]/polypolygon' incorrect value.
> 
> `anonymous namespace'::Test::TestLinearGradient finished in: 91ms
> C:/cygwin/home/user/lode/dev/core/test/source/xmltesttools.cxx(168) : error : Assertion
> Test name: `anonymous namespace'::Test::TestLinearGradient
> equality assertion failed
> - Expected: m0 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z
> - Actual  : m0 3805.32416502947h11423.6373448462v11415.3241650295h-11423.6373448462z
> - In <>, attribute 'path' of '/primitive2D/metafile/transform/mask/svglineargradient[1]/polypolygon' incorrect value.
> 
> Failures !!!
> Run: 1   Failure total: 1   Failures: 1   Errors: 0
> warn:fwk.desktop:16536:21072:framework/source/services/desktop.cxx:1065: Desktop disposed before terminating it
> warn:fwk.desktop:16536:21072:framework/source/services/desktop.cxx:179: Desktop not terminated before being destructed
> 
> Error: a unit test failed, please do one of:
> make CppunitTest_emfio_emf CPPUNITTRACE=TRUE # which is a shortcut for the following line
> make CppunitTest_emfio_emf CPPUNITTRACE="'C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/Common7/IDE/deve
> nv.exe' /debugexe" # for interactive debugging in Visual Studio
> make CppunitTest_emfio_emf CPPUNITTRACE="drmemory -free_max_frames 20" # for memory checking (install Dr.Memory first, a
> nd put it to your PATH)
> 
> You can limit the execution to just one particular test by:
> 
> make CppunitTest_emfio_emf CPPUNIT_TEST_NAME="testXYZ" ...above mentioned params...
> 
> make[1]: *** [C:/cygwin/home/user/lode/dev/core/solenv/gbuild/CppunitTest.mk:113: C:/cygwin/home/user/lode/dev/core/wo
> rkdir/CppunitTest/emfio_emf.test] Error 1
> make: *** [Makefile:166: CppunitTest_emfio_emf] Error 2

Regression after https://git.libreoffice.org/core/+/1f540cc7613cdbc0048f4013efe43886d256f86b

Bartosz, do you have an idea how to exclude it from testing when DPI is not default, or maybe pass some params to the function that will make gradient handling DPI-independent?

(IMO each and every instance of DPI dependence that is not at the time of actual screen output is a bug, so likely your test revealed an actual bug.)
Comment 1 Bartosz 2020-03-30 20:13:41 UTC
@mike Do you know how to
Comment 2 Bartosz 2020-03-30 20:14:49 UTC
Thanks @Mike

I would like to fix this issue, but first I would like to reproduce the issue.
Do you know how to reproduce this issue on Linux/Ubuntu?
Comment 3 Mike Kaganski 2020-03-31 08:00:56 UTC
(In reply to Bartosz from comment #2)
> Do you know how to reproduce this issue on Linux/Ubuntu?

Unfortunately no. I tried some ways (found on askubuntu and superuser) to change DPI on my Ubuntu, and couldn't get the test fail there. Possibly it is handled differently on Linux, or those changes I tried actually didn't translate to DPI change (only resolution), or it uses different VCL plugin when testing on Linux... :-(
Comment 4 Mike Kaganski 2020-03-31 09:51:16 UTC
There's a single call of OutputDevice::GetDPIX() in that test. The call stack is:

> vcllo.dll!OutputDevice::GetDPIX() Line 501
> 	at C:\lo\src\core\include\vcl\outdev.hxx(501)
> drawinglayerlo.dll!emfplushelper::EmfPlusHelperData::getUnitToPixelMultiplier(const emfplushelper::UnitType aUnitType) Line 241
> 	at C:\lo\src\core\drawinglayer\source\tools\emfphelperdata.cxx(241)
> drawinglayerlo.dll!emfplushelper::EmfPlusHelperData::processEmfPlusData(SvMemoryStream & rMS, const drawinglayer::geometry::ViewInformation2D & __formal) Line 1697
> 	at C:\lo\src\core\drawinglayer\source\tools\emfphelperdata.cxx(1697)
> drawinglayerlo.dll!emfplushelper::EmfPlusHelper::processEmfPlusData(SvMemoryStream & rMS, const drawinglayer::geometry::ViewInformation2D & rViewInformation) Line 42
> 	at C:\lo\src\core\drawinglayer\source\tools\emfplushelper.cxx(42)
> drawinglayerlo.dll!wmfemfhelper::implInterpretMetafile(const GDIMetaFile & rMetaFile, wmfemfhelper::TargetHolders & rTargetHolders, wmfemfhelper::PropertyHolders & rPropertyHolders, const drawinglayer::geometry::ViewInformation2D & rViewInformation) Line 3044
> 	at C:\lo\src\core\drawinglayer\source\tools\wmfemfhelper.cxx(3044)
> drawinglayerlo.dll!wmfemfhelper::interpretMetafile(const GDIMetaFile & rMetaFile, const drawinglayer::geometry::ViewInformation2D & rViewInformation) Line 3084
> 	at C:\lo\src\core\drawinglayer\source\tools\wmfemfhelper.cxx(3084)
> drawinglayerlo.dll!drawinglayer::primitive2d::MetafilePrimitive2D::create2DDecomposition(drawinglayer::primitive2d::Primitive2DContainer & rContainer, const drawinglayer::geometry::ViewInformation2D & rViewInformation) Line 37
> 	at C:\lo\src\core\drawinglayer\source\primitive2d\metafileprimitive2d.cxx(37)
> drawinglayerlo.dll!drawinglayer::primitive2d::BufferedDecompositionPrimitive2D::get2DDecomposition(drawinglayer::primitive2d::Primitive2DDecompositionVisitor & rVisitor, const drawinglayer::geometry::ViewInformation2D & rViewInformation) Line 132
> 	at C:\lo\src\core\drawinglayer\source\primitive2d\baseprimitive2d.cxx(132)
> drawinglayerlo.dll!drawinglayer::tools::Primitive2dXmlDump::decomposeAndWrite(const drawinglayer::primitive2d::Primitive2DContainer & rPrimitive2DSequence, tools::XmlWriter & rWriter) Line 354
> 	at C:\lo\src\core\drawinglayer\source\tools\primitive2dxmldump.cxx(354)
> drawinglayerlo.dll!drawinglayer::tools::Primitive2dXmlDump::dumpAndParse(const drawinglayer::primitive2d::Primitive2DContainer & rPrimitive2DSequence, const rtl::OUString & rStreamName) Line 133
> 	at C:\lo\src\core\drawinglayer\source\tools\primitive2dxmldump.cxx(133)
> test_emfio_emf.dll!`anonymous namespace'::Test::TestLinearGradient() Line 166
> 	at C:\lo\src\core\emfio\qa\cppunit\emf\EmfImportTest.cxx(166)
> test_emfio_emf.dll!std::_Invoker_pmf_pointer::_Call<void (__cdecl `anonymous namespace'::Test::*)(void),A0x0a0e3b73::Test * &>(void(`anonymous-namespace'::Test::*)() _Pmf, `anonymous-namespace'::Test * & _Arg1) Line 1610
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1610)
> test_emfio_emf.dll!std::invoke<void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &>(void(`anonymous-namespace'::Test::*)() & _Obj, `anonymous-namespace'::Test * & <_Args_0>) Line 1610
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1610)
> test_emfio_emf.dll!std::_Invoker_ret<std::_Unforced,0>::_Call<void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &>(void(`anonymous-namespace'::Test::*)() & <_Vals_0>, `anonymous-namespace'::Test * & <_Vals_1>) Line 1646
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1646)
> test_emfio_emf.dll!std::_Call_binder<std::_Unforced,0,void (__cdecl `anonymous namespace'::Test::*)(void),std::tuple<`anonymous namespace'::Test *>,std::tuple<>>(std::_Invoker_ret<std::_Unforced,0> __formal, std::integer_sequence<unsigned __int64,0> __formal, void(`anonymous-namespace'::Test::*)() & _Obj, std::tuple<`anonymous namespace'::Test *> & _Tpl, std::tuple<> && _Ut) Line 1433
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\functional(1433)
> test_emfio_emf.dll!std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &>::operator()<>() Line 1473
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\functional(1473)
> test_emfio_emf.dll!std::_Invoker_functor::_Call<std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> &>(std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> & _Obj) Line 1610
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1610)
> test_emfio_emf.dll!std::invoke<std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> &>(std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> & _Obj) Line 1610
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1610)
> test_emfio_emf.dll!std::_Invoker_ret<void,1>::_Call<std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> &>(std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &> & <_Vals_0>) Line 1629
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\type_traits(1629)
> test_emfio_emf.dll!std::_Func_impl_no_alloc<std::_Binder<std::_Unforced,void (__cdecl `anonymous namespace'::Test::*&)(void),A0x0a0e3b73::Test * &>,void>::_Do_call() Line 927
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\functional(927)
> test_emfio_emf.dll!std::_Func_class<void>::operator()() Line 977
> 	at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\functional(977)
> test_emfio_emf.dll!CppUnit::TestCaller<`anonymous namespace'::Test>::runTest() Line 176
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\include\cppunit\TestCaller.h(176)
> cppunitd_dll.dll!CppUnit::TestCaseMethodFunctor::operator()() Line 33
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestCase.cpp(33)
> vclbootstrapprotector.dll!`anonymous namespace'::Protector::protect(const CppUnit::Functor & functor, const CppUnit::ProtectorContext & __formal) Line 46
> 	at C:\lo\src\core\test\source\vclbootstrapprotector.cxx(46)
> cppunitd_dll.dll!CppUnit::ProtectorChain::ProtectFunctor::operator()() Line 21
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\ProtectorChain.cpp(21)
> unobootstrapprotector.dll!`anonymous namespace'::Prot::protect(const CppUnit::Functor & functor, const CppUnit::ProtectorContext & __formal) Line 79
> 	at C:\lo\src\core\unotest\source\cpp\unobootstrapprotector\unobootstrapprotector.cxx(79)
> cppunitd_dll.dll!CppUnit::ProtectorChain::ProtectFunctor::operator()() Line 21
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\ProtectorChain.cpp(21)
> unoexceptionprotector.dll!`anonymous namespace'::Prot::protect(const CppUnit::Functor & functor, const CppUnit::ProtectorContext & context) Line 61
> 	at C:\lo\src\core\unotest\source\cpp\unoexceptionprotector\unoexceptionprotector.cxx(61)
> cppunitd_dll.dll!CppUnit::ProtectorChain::ProtectFunctor::operator()() Line 21
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\ProtectorChain.cpp(21)
> cppunitd_dll.dll!CppUnit::DefaultProtector::protect(const CppUnit::Functor & functor, const CppUnit::ProtectorContext & context) Line 15
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\DefaultProtector.cpp(15)
> cppunitd_dll.dll!CppUnit::ProtectorChain::ProtectFunctor::operator()() Line 21
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\ProtectorChain.cpp(21)
> cppunitd_dll.dll!CppUnit::ProtectorChain::protect(const CppUnit::Functor & functor, const CppUnit::ProtectorContext & context) Line 86
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\ProtectorChain.cpp(86)
> cppunitd_dll.dll!CppUnit::TestResult::protect(const CppUnit::Functor & functor, CppUnit::Test * test, const std::string & shortDescription) Line 182
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestResult.cpp(182)
> cppunitd_dll.dll!CppUnit::TestCase::run(CppUnit::TestResult * result) Line 91
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestCase.cpp(91)
> cppunitd_dll.dll!CppUnit::TestRunner::WrappingSuite::run(CppUnit::TestResult * result) Line 47
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestRunner.cpp(47)
> cppunitd_dll.dll!CppUnit::TestResult::runTest(CppUnit::Test * test) Line 150
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestResult.cpp(150)
> cppunitd_dll.dll!CppUnit::TestRunner::run(CppUnit::TestResult & controller, const std::string & testPath) Line 96
> 	at C:\lo\src\build\workdir\UnpackedTarball\cppunit\src\cppunit\TestRunner.cpp(96)
> cppunittester.exe!`anonymous namespace'::ProtectedFixtureFunctor::run() Line 316
> 	at C:\lo\src\core\sal\cppunittester\cppunittester.cxx(316)
> cppunittester.exe!sal_main() Line 466
> 	at C:\lo\src\core\sal\cppunittester\cppunittester.cxx(466)
> cppunittester.exe!main(int argc, char * * argv) Line 373
> 	at C:\lo\src\core\sal\cppunittester\cppunittester.cxx(373)
> cppunittester.exe!invoke_main() Line 79
> 	at d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(79)
> cppunittester.exe!__scrt_common_main_seh() Line 288
> 	at d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
> cppunittester.exe!__scrt_common_main() Line 331
> 	at d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331)
> cppunittester.exe!mainCRTStartup() Line 17
> 	at d:\agent\_work\4\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp(17)
> kernel32.dll!BaseThreadInitThunk()
> ntdll.dll!RtlUserThreadStart()

Manually making it return 96 instead of actual DPI value there makes the test pass; or we can make it fail by returning something else from there (e.g., 144 for 150%, or 120 for 125%).

The call stack shows interesting piece: the problem happens inside Primitive2dXmlDump::decomposeAndWrite's "case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D", with a comment: "// since the graphic is not rendered in a document, we do not need a concrete view information". This looks like this code path should indeed not depend on actual display; yet, it obviously does, as we see, and which is IMO a clear bug.
Comment 5 Mike Kaganski 2020-03-31 10:00:45 UTC
EmfPlusHelperData::processEmfPlusData has at least two pieces that for unclear reason depend on DPI - by calling EmfPlusHelperData::getUnitToPixelMultiplier - they are cases for EmfPlusRecordTypeSetPageTransform and EmfPlusRecordTypeBeginContainer. Likely fixing those cases to not use the DPI, and only using it when actually rendering, would fix this? is that possible?
Comment 6 Bartosz 2020-03-31 16:21:56 UTC
@Mike Thanks for investigation.
Definitely it is an bug in EMF+ import. I will fix it shortly (I already created Review for it).

Thanks and stay healthy :-)
Comment 7 Commit Notification 2020-04-04 20:54:13 UTC
Bartosz Kosiorek committed a patch related to this issue.
It has been pushed to "master":

https://git.libreoffice.org/core/commit/6c59c9d2b8818674640a50656ffba90f9cd3900e

tdf#131644 Do not depend on actual DPI during EMF+ import

It will be available in 7.0.0.

The patch should be included in the daily builds available at
https://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
https://wiki.documentfoundation.org/Testing_Daily_Builds

Affected users are encouraged to test the fix and report feedback.