drawinglayer/source/tools/emfphelperdata.cxx              |   28 +++-----
 drawinglayer/source/tools/emfphelperdata.hxx              |    3 
 emfio/qa/cppunit/emf/EmfImportTest.cxx                    |   44 ++++++++++++--
 emfio/qa/cppunit/emf/data/TestEmfPlusSetPageTransform.emf |binary
 4 files changed, 50 insertions(+), 25 deletions(-)

New commits:
commit 8b002437fbe29d5bac7ab0358a4e838a140d4e3c
Author:     Bartosz Kosiorek <[email protected]>
AuthorDate: Sat Feb 14 18:22:57 2026 +0100
Commit:     Bartosz Kosiorek <[email protected]>
CommitDate: Sun Feb 15 12:21:53 2026 +0100

    tdf#168227 EMF+ Fix implementation of SetPageTransform
    
    The implementation of SetPageTransform was incorrectly overwriting mnMmX 
and mnMmY
    with calculated pixel values.
    
    These variables represent the Reference Device size from the EMF+ header 
and should
    remain constant. Overwriting them causes mappingChanged() to calculate an 
incorrect
    transformation matrix, as it relies on the original ratio between reference
    millimeters and pixels. This led to incorrect scaling and cumulative errors
    if multiple SetPageTransform records were present in the document.
    
    This patch ensures that header constants are preserved and the Page Scale
    is applied as a separate step in the transformation pipeline.
    
    Change-Id: I7a957f57894cc079292e8f93c119dd0fdb456fb4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199380
    Tested-by: Jenkins
    Reviewed-by: Bartosz Kosiorek <[email protected]>

diff --git a/drawinglayer/source/tools/emfphelperdata.cxx 
b/drawinglayer/source/tools/emfphelperdata.cxx
index b911e5ec1272..e5bc612b4f40 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -443,6 +443,7 @@ namespace emfplushelper
         // To evtl. correct and see where this came from, please compare with 
the implementations
         // of EmfPlusHelperData::MapToDevice and EmfPlusHelperData::Map* in 
prev versions
         maMapTransform = maWorldTransform;
+        maMapTransform.scale(mfPageScaleX, mfPageScaleY);
         maMapTransform *= 
basegfx::utils::createScaleTranslateB2DHomMatrix(100.0 * mnMmX / mnPixX, 100.0 
* mnMmY / mnPixY,
                                                                            
double(-mnFrameLeft), double(-mnFrameTop));
         maMapTransform *= maBaseTransform;
@@ -907,7 +908,8 @@ namespace emfplushelper
         SvMemoryStream& rMS,
         wmfemfhelper::TargetHolders& rTargetHolders,
         wmfemfhelper::PropertyHolders& rPropertyHolders)
-    :   mfPageScale(0.0),
+    :   mfPageScaleX(1.0),
+        mfPageScaleY(1.0),
         mnOriginX(0),
         mnOriginY(0),
         mnHDPI(0),
@@ -1751,19 +1753,14 @@ namespace emfplushelper
                     }
                     case EmfPlusRecordTypeSetPageTransform:
                     {
-                        rMS.ReadFloat(mfPageScale);
-                        SAL_INFO("drawinglayer.emf", "EMF+      Scale: " << 
mfPageScale << " unit: " << UnitTypeToString(flags));
+                        float pageScale;
+                        rMS.ReadFloat(pageScale);
+                        SAL_INFO("drawinglayer.emf", "EMF+      Scale: " << 
pageScale << " unit: " << UnitTypeToString(flags));
+
+                        mfPageScaleX = unitToPixel(pageScale, flags, 
Direction::horizontal);
+                        mfPageScaleY = unitToPixel(pageScale, flags, 
Direction::vertical);
+                        mappingChanged();
 
-                        if ((flags == UnitTypeDisplay) || (flags == 
UnitTypeWorld))
-                        {
-                            SAL_WARN("drawinglayer.emf", "EMF+  file error. 
UnitTypeDisplay and UnitTypeWorld are not supported by SetPageTransform in EMF+ 
specification.");
-                        }
-                        else
-                        {
-                            mnMmX = 
std::round(unitToPixel(static_cast<double>(mnMmX) * mfPageScale, flags, 
Direction::horizontal));
-                            mnMmY = 
std::round(unitToPixel(static_cast<double>(mnMmY) * mfPageScale, flags, 
Direction::vertical));
-                            mappingChanged();
-                        }
                         break;
                     }
                     case EmfPlusRecordTypeSetRenderingOrigin:
@@ -1847,11 +1844,6 @@ namespace emfplushelper
                         rMS.ReadUInt32(stackIndex);
                         SAL_INFO("drawinglayer.emf", "EMF+      Begin 
Container stack index: " << stackIndex << ", PageUnit: " << flags);
 
-                        if ((flags == UnitTypeDisplay) || (flags == 
UnitTypeWorld))
-                        {
-                            SAL_WARN("drawinglayer.emf", "EMF+  file error. 
UnitTypeDisplay and UnitTypeWorld are not supported by BeginContainer in EMF+ 
specification.");
-                            break;
-                        }
                         GraphicStatePush(mGSContainerStack, stackIndex);
                         const basegfx::B2DHomMatrix transform = 
basegfx::utils::createScaleTranslateB2DHomMatrix(
                             unitToPixel(static_cast<double>(dw) / sw, flags, 
Direction::horizontal),
diff --git a/drawinglayer/source/tools/emfphelperdata.hxx 
b/drawinglayer/source/tools/emfphelperdata.hxx
index 51561e3161fa..610079571828 100644
--- a/drawinglayer/source/tools/emfphelperdata.hxx
+++ b/drawinglayer/source/tools/emfphelperdata.hxx
@@ -183,7 +183,8 @@ namespace emfplushelper
         basegfx::B2DHomMatrix       maMapTransform;
 
         std::unique_ptr<EMFPObject> maEMFPObjects[256];
-        float                       mfPageScale;
+        double                      mfPageScaleX;
+        double                      mfPageScaleY;
         sal_Int32                   mnOriginX;
         sal_Int32                   mnOriginY;
         sal_uInt32                  mnHDPI;
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 659424d97de8..5d134baf3488 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -336,7 +336,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDrawLine)
     assertXPath(pDocument, aXPathPrefix + 
"mask/unifiedtransparence/polypolygonstroke/line",
                 "linecap", u"BUTT");
     assertXPath(pDocument, aXPathPrefix + 
"mask/unifiedtransparence/polypolygonstroke/polypolygon",
-                "path", u"m89.1506452315894 403.573503917507 
895.170581035125-345.821325648415");
+                "path", u"m77.940249951477 403.573552502852 
888.231320530266-345.821343684403");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testDrawLineWithCaps)
@@ -475,7 +475,7 @@ CPPUNIT_TEST_FIXTURE(Test, testLinearGradient)
     assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[1]", 
"opacity",
                 u"0.392156862745098");
     assertXPath(pDocument, aXPathPrefix + 
"mask/svglineargradient[1]/polypolygon", "path",
-                u"m0 
0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z");
+                u"m0 
0.216110019646294h7615.75822989747v7610.21611001965h-7615.75822989747z");
 
     assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", 
"spreadmethod", u"repeat");
     assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", 
"startx", u"-1");
@@ -484,8 +484,8 @@ CPPUNIT_TEST_FIXTURE(Test, testLinearGradient)
     assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", "endy", 
u"-1");
     assertXPath(pDocument, aXPathPrefix + "mask/svglineargradient[2]", 
"opacity", u"1");
     assertXPath(pDocument, aXPathPrefix + 
"mask/svglineargradient[2]/polypolygon", "path",
-                u"m7615.75822989746 "
-                
u"0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z");
+                u"m7615.75822989747 "
+                
u"0.216110019646294h7615.75822989747v7610.21611001965h-7615.75822989747z");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testTextMapMode)
@@ -1061,9 +1061,41 @@ CPPUNIT_TEST_FIXTURE(Test, testEmfPlusGetDC)
     assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[6]/polypolygon", 
"path",
                 u"m19428.4895833333 
6632.22222222222h317.34375v-2398.88888888889h-317.34375z");
     assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[6]", "color", 
u"#fcf2e3");
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testEmfPlusSetPageTransform)
+{
+    // tdf#147818 EMF+ records: GetDC, SetPageTransform, FillRects
+    Primitive2DSequence aSequence
+        = 
parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusSetPageTransform.emf");
+    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+    drawinglayer::Primitive2dXmlDump dumper;
+    xmlDocUniquePtr pDocument = 
dumper.dumpAndParse(Primitive2DContainer(aSequence));
+    CPPUNIT_ASSERT(pDocument);
+
+    assertXPath(pDocument, aXPathPrefix + "textsimpleportion", 2);
+    assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "text",
+                u"Flow Chart LM_SOP_01.04.04_02_Sonderfreigabe 
Lieferant_DE.igx");
+    assertXPath(pDocument, aXPathPrefix + "textsimpleportion[1]", "fontcolor", 
u"#000000");
 
-    assertXPath(pDocument, aXPathPrefix + "polypolygonstroke", 4);
-    assertXPath(pDocument, aXPathPrefix + "polygonstrokearrow", 13);
+    assertXPath(pDocument, aXPathPrefix + "group", 2);
+
+    assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygon", 1);
+    assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor", 1);
+    assertXPath(pDocument, aXPathPrefix + "group[1]/mask/polypolygoncolor", 
"color", u"#4080c0");
+    assertXPath(pDocument, aXPathPrefix + 
"group[1]/mask/polypolygoncolor/polypolygon", "height",
+                u"1620");
+    assertXPath(pDocument, aXPathPrefix + 
"group[1]/mask/polypolygoncolor/polypolygon", "maxy",
+                u"1994");
+
+    assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygon", 1);
+    assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor", 2);
+    assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[1]", 
"color", u"#00eeee");
+    assertXPath(pDocument, aXPathPrefix + 
"group[2]/mask/polypolygoncolor[1]/polypolygon", "height",
+                u"2457");
+    assertXPath(pDocument, aXPathPrefix + "group[2]/mask/polypolygoncolor[2]", 
"color", u"#ee00ee");
+    assertXPath(pDocument, aXPathPrefix + 
"group[2]/mask/polypolygoncolor[2]/polypolygon", "height",
+                u"2457");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testEmfPlusSave)
diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusSetPageTransform.emf 
b/emfio/qa/cppunit/emf/data/TestEmfPlusSetPageTransform.emf
new file mode 100644
index 000000000000..0cc7050fbdfa
Binary files /dev/null and 
b/emfio/qa/cppunit/emf/data/TestEmfPlusSetPageTransform.emf differ

Reply via email to