sw/qa/extras/ooxmlexport/data/tdf139418.docx   |binary
 sw/qa/extras/ooxmlexport/ooxmlexport22.cxx     |   26 +++++++++++++++++++
 sw/source/core/text/itrform2.cxx               |    8 +++---
 sw/source/core/txtnode/fntcache.cxx            |    9 ++++++
 sw/source/writerfilter/dmapper/PropertyMap.cxx |   33 ++++++++++++++++++++-----
 5 files changed, 66 insertions(+), 10 deletions(-)

New commits:
commit 756bcac94f122b0bed6f2835ec1170406e1b8606
Author:     Jonathan Clark <[email protected]>
AuthorDate: Wed Apr 9 03:52:44 2025 -0600
Commit:     Jonathan Clark <[email protected]>
CommitDate: Thu Apr 10 11:41:55 2025 +0200

    tdf#139418 DOCX import: Fix generated genko yoshi grid layout issues
    
    This change includes fixes for three minor grid layout issues affecting
    correct display of generated genko yoshi manuscript documents.
    
    - Due to the way OOXML stores grid parameters, the default Asian font
      height must be known in order to correctly calculate the grid
      character pitch. This change fixes a regression from tdf#107359 which
      caused the OOXML importer to always use the hard-coded default
      character width in certain situations.
    
    - The fix for tdf#149089 caused a regression by also removing the grid
      kerning portions from vertical text, when it correctly should only
      have affected horizontal text.
    
    - For correct interop, the ADD_EXT_LEADING compatibility flag is now
      ignored for vertical text when the MS_WORD_COMP_GRID_METRICS
      compatibility flag is set.
    
    Change-Id: I5aaa245293932d64ff5c4dd4a3f45c4d8bc4a22e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183959
    Reviewed-by: Jonathan Clark <[email protected]>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/ooxmlexport/data/tdf139418.docx 
b/sw/qa/extras/ooxmlexport/data/tdf139418.docx
new file mode 100644
index 000000000000..e32747e818d3
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf139418.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
index b7d4bd049395..8bcf3ca68762 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
@@ -208,6 +208,32 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf165933_noDelTextOnMove)
     assertXPath(pXmlDoc, "//w:moveFrom/w:r/w:delText", 0);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf139418, "tdf139418.docx")
+{
+    uno::Reference<beans::XPropertySet> xPropertySet(
+        getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), 
uno::UNO_QUERY);
+
+    sal_Int32 nBaseWidth;
+    xPropertySet->getPropertyValue(u"GridBaseWidth"_ustr) >>= nBaseWidth;
+    // Without the fix, this will fail with
+    // - Expected: ~795
+    // - Actual  : 848
+    CPPUNIT_ASSERT_GREATEREQUAL(sal_Int32(794), nBaseWidth);
+    CPPUNIT_ASSERT_LESSEQUAL(sal_Int32(796), nBaseWidth);
+
+    auto pXmlDoc = parseLayoutDump();
+
+    // Vertical DOCX should insert kern portions to align text to the grid
+    sal_Int32 nPorLen1 = getXPath(pXmlDoc, "(//SwLinePortion)[1]", 
"length").toInt32();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nPorLen1);
+
+    sal_Int32 nPorLen2 = getXPath(pXmlDoc, "(//SwLinePortion)[2]", 
"length").toInt32();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(42), nPorLen2);
+
+    sal_Int32 nPorLen3 = getXPath(pXmlDoc, "(//SwLinePortion)[3]", 
"length").toInt32();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nPorLen3);
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 16d5fbc31c45..d90ed4de435b 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -445,10 +445,12 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo 
&rInf )
     // tdf#149089: For compatibility with MSO grid layout, do not insert kern 
portions to
     // align successive portions to the char grid when 
MS_WORD_COMP_GRID_METRICS is set.
     // See also tdf#161145.
+    // tdf#139418: However, in testing, this only seems to apply to horizontal 
text.
+    const bool bUseGridKernPors = GetTextFrame()->IsVertical()
+                                  || 
!GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+                                      
DocumentSettingId::MS_WORD_COMP_GRID_METRICS);
     const bool bHasGrid = pGrid && rInf.SnapToGrid()
-                          && SwTextGrid::LinesAndChars == pGrid->GetGridType()
-                          && 
!GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
-                              DocumentSettingId::MS_WORD_COMP_GRID_METRICS);
+                          && SwTextGrid::LinesAndChars == pGrid->GetGridType() 
&& bUseGridKernPors;
 
     const SwDoc & rDoc = rInf.GetTextFrame()->GetDoc();
     const sal_uInt16 nGridWidth = bHasGrid ? GetGridWidth(*pGrid, rDoc) : 0;
diff --git a/sw/source/core/txtnode/fntcache.cxx 
b/sw/source/core/txtnode/fntcache.cxx
index c8e065707618..b84f301944f8 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -384,7 +384,14 @@ sal_uInt16 SwFntObj::GetFontLeading( const SwViewShell 
*pSh, const OutputDevice&
                                pSh->GetViewOptions()->getBrowseMode() &&
                               !pSh->GetViewOptions()->IsPrtFormat() );
 
-        if ( !bBrowse && rIDSA.get(DocumentSettingId::ADD_EXT_LEADING) )
+        const bool bAddExtLeading = 
rIDSA.get(DocumentSettingId::ADD_EXT_LEADING);
+
+        // tdf#139418: MSO never applies ext leading to vertical text, even if 
the
+        // NoLeading compatibility flag is unset.
+        const bool bDisableExtLeading
+            = rIDSA.get(DocumentSettingId::MS_WORD_COMP_GRID_METRICS) && 
GetFont().IsVertical();
+
+        if (!bBrowse && bAddExtLeading && !bDisableExtLeading)
             nRet = m_nExtLeading;
         else
             nRet = m_nGuessedLeading;
diff --git a/sw/source/writerfilter/dmapper/PropertyMap.cxx 
b/sw/source/writerfilter/dmapper/PropertyMap.cxx
index dc80bbc1a362..6e6f5f5791b4 100644
--- a/sw/source/writerfilter/dmapper/PropertyMap.cxx
+++ b/sw/source/writerfilter/dmapper/PropertyMap.cxx
@@ -1866,15 +1866,36 @@ void SectionPropertyMap::CloseSectionGroup( 
DomainMapper_Impl& rDM_Impl )
         Insert( PROP_GRID_MODE, uno::Any( nGridType ) );
 
         sal_Int32 nCharWidth = 423; //240 twip/ 12 pt
-        const StyleSheetEntryPtr pEntry = 
rDM_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName( u"Standard" 
);
-        if ( pEntry )
+
+        // tdf#139418: Fetch the default Asian text height for grid pitch 
calculation
+        if (const auto pEntry = 
rDM_Impl.GetStyleSheetTable()->GetDefaultCharProps(); pEntry)
         {
-            std::optional< PropertyMap::Property > pPropHeight = 
pEntry->m_pProperties->getProperty( PROP_CHAR_HEIGHT_ASIAN );
-            if ( pPropHeight )
+            const auto pPropHeight = 
pEntry->getProperty(PROP_CHAR_HEIGHT_ASIAN);
+            if (pPropHeight.has_value())
             {
                 double fHeight = 0;
-                if ( pPropHeight->second >>= fHeight )
-                    nCharWidth = ConversionHelper::convertTwipToMm100_Limited( 
static_cast<sal_Int32>(fHeight * 20.0 + 0.5) );
+                if (pPropHeight->second >>= fHeight)
+                {
+                    nCharWidth = ConversionHelper::convertTwipToMm100_Limited(
+                        static_cast<sal_Int32>(fHeight * 20.0 + 0.5));
+                }
+            }
+        }
+
+        // tdf#107359: Override the default Asian height from the Standard 
style, if present.
+        if (const auto pEntry
+            = 
rDM_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(u"Standard");
+            pEntry)
+        {
+            const auto pPropHeight = 
pEntry->m_pProperties->getProperty(PROP_CHAR_HEIGHT_ASIAN);
+            if (pPropHeight.has_value())
+            {
+                double fHeight = 0;
+                if (pPropHeight->second >>= fHeight)
+                {
+                    nCharWidth = ConversionHelper::convertTwipToMm100_Limited(
+                        static_cast<sal_Int32>(fHeight * 20.0 + 0.5));
+                }
             }
         }
 

Reply via email to