Summary: | make CppunitTest_emfio_emf CPPUNIT_TEST_NAME=TestLinearGradient fails on Windows with UI scale 150% | ||
---|---|---|---|
Product: | LibreOffice | Reporter: | Mike Kaganski <mikekaganski> |
Component: | LibreOffice | Assignee: | Bartosz <gang65> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | gang65, mikekaganski |
Priority: | medium | Keywords: | bibisectNotNeeded, regression |
Version: | 7.0.0.0.alpha0+ | ||
Hardware: | All | ||
OS: | Windows (All) | ||
Whiteboard: | target:7.0.0 | ||
Crash report or crash signature: | Regression By: |
Description
Mike Kaganski
2020-03-28 12:40:00 UTC
@mike Do you know how to 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? (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... :-( 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.
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? @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 :-) 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. |