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)); + } } }
