From 168065841250c190808261cf65afa00f9ecd52e7 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 13 Sep 2021 19:27:48 +0200 Subject: tdf#144305 sw: fix rendering of ruby portions with non-default ruby alignment Regression from 301278b656e76b6f42af5cf8a6f5c6c02acfffeb (sw: allow the height of a line to be larger than 65536 twips, 2021-05-20), the problem was that changing from sal_uInt16 to sal_uInt32 broke SwRubyPortion::Adjust_(), which relied on integer promotion rules to have a negative diff. Old storage size was smaller than int, so got promoted to signed int, so the result could be a small negative number. New storage size is an unsigned int, so no promotion happens, so the new result was a large positive number. Fix this by casting to signed int explicitly. Change-Id: I8778c1bd0d62e27c99d4ceb1bb7bc6107a179803 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122048 Tested-by: Jenkins Reviewed-by: Miklos Vajna (cherry picked from commit 0c3e47cc2f0570a7cd8ff4889763991a86b29f26) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122066 Reviewed-by: Michael Stahl --- sw/CppunitTest_sw_core_text.mk | 1 + sw/qa/core/text/data/ruby.fodt | 25 ++++++++++++++++++++++ sw/qa/core/text/text.cxx | 46 ++++++++++++++++++++++++++++++++++++++++ sw/source/core/text/porlay.hxx | 2 +- sw/source/core/text/pormulti.cxx | 2 +- 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 sw/qa/core/text/data/ruby.fodt diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk index cb4801accac9..6f19ff690f5a 100644 --- a/sw/CppunitTest_sw_core_text.mk +++ b/sw/CppunitTest_sw_core_text.mk @@ -40,6 +40,7 @@ $(eval $(call gb_CppunitTest_use_externals,sw_core_text,\ $(eval $(call gb_CppunitTest_set_include,sw_core_text,\ -I$(SRCDIR)/sw/inc \ -I$(SRCDIR)/sw/source/core/inc \ + -I$(SRCDIR)/sw/source/core/text \ -I$(SRCDIR)/sw/source/uibase/inc \ -I$(SRCDIR)/sw/qa/inc \ $$(INCLUDE) \ diff --git a/sw/qa/core/text/data/ruby.fodt b/sw/qa/core/text/data/ruby.fodt new file mode 100644 index 000000000000..b5a0e23d2c53 --- /dev/null +++ b/sw/qa/core/text/data/ruby.fodt @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + Ruby test: base textruby (left) base textruby (center) base textruby (right) + + + diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx index be6406f6b654..6832ad2cb436 100644 --- a/sw/qa/core/text/text.cxx +++ b/sw/qa/core/text/text.cxx @@ -21,6 +21,12 @@ #include #include #include +#include +#include +#include + +#include +#include constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/text/data/"; @@ -170,6 +176,46 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testLineWidth) CPPUNIT_ASSERT_GREATER(static_cast(65536), nNewLeft - nOldLeft); } +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testRuby) +{ + // Given a document with multiple ruby portions: + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "ruby.fodt"); + + // When laying out that document: + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + + // Then make sure that no unwanted margin portions are created, making the actual text + // invisible: + SwFrame* pPageFrame = pLayout->GetLower(); + SwFrame* pBodyFrame = pPageFrame->GetLower(); + SwFrame* pFrame = pBodyFrame->GetLower(); + CPPUNIT_ASSERT(pFrame->IsTextFrame()); + auto pTextFrame = static_cast(pFrame); + SwParaPortion* pPara = pTextFrame->GetPara(); + bool bFirst = true; + for (SwLinePortion* pPor = pPara->GetFirstPortion(); pPor; pPor = pPor->GetNextPortion()) + { + // Look for multi-portions in the only paragraph of the document. + if (pPor->GetWhichPor() != PortionType::Multi) + { + continue; + } + + if (bFirst) + { + bFirst = false; + continue; + } + + // The second multi-portion has two lines, check the start of the second line. + auto pMulti = static_cast(pPor); + // Without the accompanying fix in place, this test would have failed, as the portion was a + // margin portion, not a text portion. The margin was so large that the actual text portion was + // hidden. No margin is needed here at all. + CPPUNIT_ASSERT(pMulti->GetRoot().GetNext()->GetFirstPortion()->IsTextPortion()); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/porlay.hxx b/sw/source/core/text/porlay.hxx index 5234a537fa4c..bff0bd559309 100644 --- a/sw/source/core/text/porlay.hxx +++ b/sw/source/core/text/porlay.hxx @@ -75,7 +75,7 @@ public: /// Collection of SwLinePortion instances, representing one line of text. /// Typically owned by an SwParaPortion. -class SwLineLayout : public SwTextPortion +class SW_DLLPUBLIC SwLineLayout : public SwTextPortion { private: SwLineLayout *m_pNext; // The next Line diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx index b94302bd8ed7..98b8df7b643f 100644 --- a/sw/source/core/text/pormulti.cxx +++ b/sw/source/core/text/pormulti.cxx @@ -630,7 +630,7 @@ SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt, // If there is a tabulator in smaller line, no adjustment is possible. void SwRubyPortion::Adjust_( SwTextFormatInfo &rInf ) { - SwTwips nLineDiff = GetRoot().Width() - GetRoot().GetNext()->Width(); + SwTwips nLineDiff = o3tl::narrowing(GetRoot().Width()) - GetRoot().GetNext()->Width(); TextFrameIndex const nOldIdx = rInf.GetIdx(); if( !nLineDiff ) return; -- cgit