Description: he static method OutputDevice::LogicToLogic(Point, MapMode, MapMode) fails to account for user-defined scaling factors (SetScaleX / SetScaleY) when converting between different MapUnit types. While the function correctly handles Origin shifts (SetOrigin), it seems to calculate the conversion factor solely based on the physical unit ratio (e.g., MapMM vs MapInch) and ignores the specific scaling fraction set on the MapMode. This means that if a Source MapMode is set to MapMM with a scale of 0.5 (50% Zoom), and the Destination is Map100thMM (scale 1.0), the function performs a purely physical conversion (10mm -> 1000 100thMM) rather than the expected scaled conversion (10mm * 0.5 -> 500 100thMM). Steps to Reproduce: So I stumbled across this whilst trying to write some unit tests for LogicToLogic(). The following function in a unit test shows the issue: void testCombinedScaleAndOrigin() { // Scenario: Source is MM with 50% scale. Dest is 100thMM. // We expect the result to be scaled by 0.5. MapMode aSource(MapUnit::MapMM); aSource.SetScaleX(Fraction(1, 2)); // 0.5 Scale aSource.SetScaleY(Fraction(1, 2)); aSource.SetOrigin(Point(10, 0)); MapMode aDest(MapUnit::Map100thMM); Point aPt(30, 0); // Expected Calculation: // 1. Remove Origin: 30 - 10 = 20 // 2. Apply Scale: 20 * 0.5 = 10 (Physical MM) // 3. Convert Unit: 10 MM -> 1000 100thMM // Expected Result: 1000 Point aResult = OutputDevice::LogicToLogic(aPt, aSource, aDest); // Actual Result: 2000 // The scale factor (0.5) was ignored. CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aResult.X()); } Actual Results: The function returns 2000 (it calculated (30-10) * 1.0 * UnitFactor). Expected Results: The function should return 1000 (it should calculate (30-10) * 0.5 * UnitFactor). Reproducible: Always User Profile Reset: No Additional Info: The issue is located in vcl/source/outdev/map.cxx. The implementation calculates the unit conversion factors (likely via lcl_calcConversionMapRes) but never multiplies them by rMapModeSource.GetScaleX() or rMapModeDest.GetScaleX(). This affects any stateless coordinate conversion that passes explicit MapMode objects, particularly in: * PDF Export (vcl/source/pdf/pdfwriter_impl2.cxx) * SVG/Metafile Export (filter/source/svg/svgwriter.cxx, vcl/source/gdi/gdimtf.cxx) * EditEngine text layout (editeng/source/editeng/impedit.cxx) Member functions like OutputDevice::LogicToPixel (which rely on mnMapScNumX member variables) are seemingly unaffected as SetMapMode correctly pre-calculates the factors. Now... I can fix the function, but the issue is: I don't know what impact this would have on anything that is relying on this existing functionality! However, I'm pretty sure this is causing a lot of weird issues in exports...
Apologies, I had started to refactor some code and had already switched to using the function lcl_calcConversionMapRes() and I accidentally referred to this in my report. My code refactoring efforts will shortly be pushed to gerrit - they haven't changed any functionality, but the unit tests I wrote did find this particular issue.
I'm mistaken.