https://bugs.documentfoundation.org/show_bug.cgi?id=170136

            Bug ID: 170136
           Summary: OutputDevice::LogicToLogic ignores MapMode scaling
                    factors (SetScaleX/Y) during unit conversion
           Product: LibreOffice
           Version: Inherited From OOo
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: graphics stack
          Assignee: [email protected]
          Reporter: [email protected]

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...

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to