summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2023-10-01 18:08:49 +1100
committerTomaž Vajngerl <quikee@gmail.com>2023-12-28 02:33:50 +0100
commit938d3b35b83093de4e310d32de5137f6bdbcf22b (patch)
treea50d65c7f47243f3c10f7a093959b4323d5fdc29
parent9157281deb81522bb02af73a08c4d7beed7aab75 (diff)
vcl: test BreakLinesWithIterator with hyphens
Change-Id: Ied5e688b9eec19c2f1b3d1289cc4a6605703c3e4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157904 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--vcl/CppunitTest_vcl_textlayout.mk1
-rw-r--r--vcl/inc/textlayout.hxx10
-rw-r--r--vcl/qa/cppunit/textlayout.cxx64
-rw-r--r--vcl/source/text/textlayout.cxx61
4 files changed, 96 insertions, 40 deletions
diff --git a/vcl/CppunitTest_vcl_textlayout.mk b/vcl/CppunitTest_vcl_textlayout.mk
index d7ac49a9e6df..57d5177f2a19 100644
--- a/vcl/CppunitTest_vcl_textlayout.mk
+++ b/vcl/CppunitTest_vcl_textlayout.mk
@@ -55,6 +55,7 @@ $(eval $(call gb_CppunitTest_use_components,vcl_textlayout,\
configmgr/source/configmgr \
i18npool/util/i18npool \
ucb/source/core/ucb1 \
+ linguistic/source/lng \
))
$(eval $(call gb_CppunitTest_use_configuration,vcl_textlayout))
diff --git a/vcl/inc/textlayout.hxx b/vcl/inc/textlayout.hxx
index 58f3bb33469b..d05259475d18 100644
--- a/vcl/inc/textlayout.hxx
+++ b/vcl/inc/textlayout.hxx
@@ -52,14 +52,14 @@ namespace vcl
public:
OUString GetEllipsisString(OUString const& rOrigStr, tools::Long nMaxWidth, DrawTextFlags nStyle);
- sal_Int32 BreakLinesWithIterator(const tools::Long nWidth, OUString const& rStr,
+ std::tuple<sal_Int32, sal_Int32> BreakLines(const tools::Long nWidth, OUString const& rStr,
css::uno::Reference< css::linguistic2::XHyphenator > const& xHyph,
- css::uno::Reference<css::i18n::XBreakIterator> const& xBI,
- const bool bHyphenate,
+ css::uno::Reference<css::i18n::XBreakIterator>& xBI,
+ const bool bHyphenate, const tools::Long nOrigLineWidth,
const sal_Int32 nPos, const sal_Int32 nLen);
- sal_Int32 BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
- const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth);
+ std::tuple<sal_Int32, sal_Int32> BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
+ const sal_Int32 nPos, sal_Int32 nBreakPos, const tools::Long nOrigLineWidth);
tools::Long GetTextLines(tools::Rectangle const& rRect, const tools::Long nTextHeight,
ImplMultiTextLineInfo& rLineInfo,
diff --git a/vcl/qa/cppunit/textlayout.cxx b/vcl/qa/cppunit/textlayout.cxx
index 147826f19842..3ace6a8b836d 100644
--- a/vcl/qa/cppunit/textlayout.cxx
+++ b/vcl/qa/cppunit/textlayout.cxx
@@ -12,6 +12,8 @@
#include <test/bootstrapfixture.hxx>
+#include <comphelper/processfactory.hxx>
+
#include <vcl/unohelp.hxx>
#include <vcl/virdev.hxx>
@@ -28,7 +30,7 @@ public:
#if HAVE_MORE_FONTS
-CPPUNIT_TEST_FIXTURE(VclTextLayoutTest, testBreakLinesWithIterator_invalid_softbreak)
+CPPUNIT_TEST_FIXTURE(VclTextLayoutTest, testBreakLines_invalid_softbreak)
{
ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
device->SetOutputSizePixel(Size(1000, 1000));
@@ -46,9 +48,63 @@ CPPUNIT_TEST_FIXTURE(VclTextLayoutTest, testBreakLinesWithIterator_invalid_softb
const auto nTextLen = 13;
- CPPUNIT_ASSERT_EQUAL(
- static_cast<sal_Int32>(13),
- aTextLayout.BreakLinesWithIterator(nTextWidth, sTestStr, xHyph, xBI, false, nTextLen, 15));
+ auto[nBreakPos, nLineWidth]
+ = aTextLayout.BreakLines(nTextWidth, sTestStr, xHyph, xBI, false, nTextWidth, nTextLen, 15);
+
+ const sal_Int32 nExpectedBreakPos = 13;
+ CPPUNIT_ASSERT_EQUAL(nExpectedBreakPos, nBreakPos);
+}
+
+CPPUNIT_TEST_FIXTURE(VclTextLayoutTest, testBreakLines_hyphens)
+{
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
+ device->SetOutputSizePixel(Size(1000, 1000));
+ device->SetFont(vcl::Font("DejaVu Sans", "Book", Size(0, 11)));
+
+ vcl::DefaultTextLayout aTextLayout(*device);
+
+ const OUString sTestStr = u"textline text-moretext"_ustr;
+ const auto nTextWidth = device->GetTextWidth("textline text-moretex");
+
+ css::uno::Reference<css::uno::XComponentContext> xContext(
+ comphelper::getProcessComponentContext());
+ css::uno::Reference<css::linguistic2::XLinguServiceManager2> xLinguMgr
+ = css::linguistic2::LinguServiceManager::create(xContext);
+
+ css::uno::Reference<css::linguistic2::XHyphenator> xHyph = xLinguMgr->getHyphenator();
+ css::uno::Reference<css::i18n::XBreakIterator> xBI = vcl::unohelper::CreateBreakIterator();
+
+ auto[nBreakPos, nLineWidth]
+ = aTextLayout.BreakLines(nTextWidth, sTestStr, xHyph, xBI, true, nTextWidth, 13, 12);
+
+ const sal_Int32 nExpectedBreakPos = 13;
+ CPPUNIT_ASSERT_EQUAL(nExpectedBreakPos, nBreakPos);
+}
+
+CPPUNIT_TEST_FIXTURE(VclTextLayoutTest, testBreakLines_hyphen_word_under_two_chars)
+{
+ ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
+ device->SetOutputSizePixel(Size(1000, 1000));
+ device->SetFont(vcl::Font("DejaVu Sans", "Book", Size(0, 11)));
+
+ vcl::DefaultTextLayout aTextLayout(*device);
+
+ const OUString sTestStr = u"textline text-moretext"_ustr;
+ const auto nTextWidth = device->GetTextWidth("te-moretex");
+
+ css::uno::Reference<css::uno::XComponentContext> xContext(
+ comphelper::getProcessComponentContext());
+ css::uno::Reference<css::linguistic2::XLinguServiceManager2> xLinguMgr
+ = css::linguistic2::LinguServiceManager::create(xContext);
+
+ css::uno::Reference<css::linguistic2::XHyphenator> xHyph = xLinguMgr->getHyphenator();
+ css::uno::Reference<css::i18n::XBreakIterator> xBI = vcl::unohelper::CreateBreakIterator();
+
+ auto[nBreakPos, nLineWidth]
+ = aTextLayout.BreakLines(nTextWidth, sTestStr, xHyph, xBI, true, nTextWidth, 2, 10);
+
+ const sal_Int32 nExpectedBreakPos = 2;
+ CPPUNIT_ASSERT_EQUAL(nExpectedBreakPos, nBreakPos);
}
#endif
diff --git a/vcl/source/text/textlayout.cxx b/vcl/source/text/textlayout.cxx
index 095c087d5377..e90c56b6355a 100644
--- a/vcl/source/text/textlayout.cxx
+++ b/vcl/source/text/textlayout.cxx
@@ -218,12 +218,18 @@ namespace vcl
return aStr;
}
- sal_Int32 TextLayoutCommon::BreakLinesWithIterator(const tools::Long nWidth, OUString const& rStr,
+ std::tuple<sal_Int32, sal_Int32> TextLayoutCommon::BreakLines(const tools::Long nWidth, OUString const& rStr,
css::uno::Reference< css::linguistic2::XHyphenator > const& xHyph,
- css::uno::Reference<css::i18n::XBreakIterator> const& xBI,
- const bool bHyphenate,
+ css::uno::Reference<css::i18n::XBreakIterator>& xBI,
+ const bool bHyphenate, const tools::Long nOrigLineWidth,
const sal_Int32 nPos, const sal_Int32 nLen)
{
+ if (!xBI.is())
+ xBI = vcl::unohelper::CreateBreakIterator();
+
+ if (!xBI.is())
+ return BreakLinesSimple(nWidth, rStr, nPos, nLen, nOrigLineWidth);
+
const css::lang::Locale& rDefLocale(Application::GetSettings().GetUILanguageTag().getLocale());
sal_Int32 nSoftBreak = GetTextBreak(rStr, nWidth, nPos, nLen - nPos);
@@ -241,16 +247,14 @@ namespace vcl
if (nBreakPos <= nPos)
nBreakPos = nSoftBreak;
- if (!bHyphenate)
- return nBreakPos;
+ if (!bHyphenate || !xHyph.is())
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
// Whether hyphen or not: Put the word after the hyphen through
// the word boundary.
// We run into a problem if the doc is so narrow, that a word
// is broken into more than two lines ...
- if ( !xHyph.is() )
- return nBreakPos;
css::i18n::Boundary aBoundary = xBI->getWordBoundary( rStr, nBreakPos, rDefLocale, css::i18n::WordType::DICTIONARY_WORD, true );
sal_Int32 nWordStart = nPos;
@@ -258,27 +262,28 @@ namespace vcl
SAL_WARN_IF(nWordEnd <= nWordStart, "vcl", "Start >= End?");
sal_Int32 nWordLen = nWordEnd - nWordStart;
- if ( ( nWordEnd < nSoftBreak ) || ( nWordLen <= 3 ) )
- return nBreakPos;
+ if ((nWordEnd < nSoftBreak) || (nWordLen <= 3))
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
OUString aWord = rStr.copy( nWordStart, nWordLen );
sal_Int32 nMinTrail = nWordEnd-nSoftBreak+1; //+1: Before the "broken off" char
css::uno::Reference< css::linguistic2::XHyphenatedWord > xHyphWord;
if (xHyph.is())
xHyphWord = xHyph->hyphenate( aWord, rDefLocale, aWord.getLength() - nMinTrail, css::uno::Sequence< css::beans::PropertyValue >() );
+
if (!xHyphWord.is())
- return nBreakPos;
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
bool bAlternate = xHyphWord->isAlternativeSpelling();
sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos();
- if ( ( _nWordLen < 2 ) || ( (nWordStart+_nWordLen) < 2 ) )
- return nBreakPos;
+ if ((_nWordLen < 2 ) || ( (nWordStart + _nWordLen) < 2))
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
- if ( bAlternate )
+ if (bAlternate)
{
nBreakPos = nWordStart + _nWordLen;
- return nBreakPos;
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
}
OUString aAlt( xHyphWord->getHyphenatedWord() );
@@ -329,14 +334,18 @@ namespace vcl
nBreakPos = nWordStart + nTxtStart;
if ( cAlternateReplChar )
nBreakPos++;
- return nBreakPos;
+
+ return { nBreakPos, GetTextWidth(rStr, nPos, nBreakPos - nPos) };
}
- sal_Int32 TextLayoutCommon::BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
- const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth)
+ std::tuple<sal_Int32, sal_Int32> TextLayoutCommon::BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
+ const sal_Int32 nPos, const sal_Int32 nLen, const tools::Long nOrigLineWidth)
{
+ sal_Int32 nBreakPos = nLen;
+ tools::Long nLineWidth = nOrigLineWidth;
sal_Int32 nSpacePos = rStr.getLength();
tools::Long nW = 0;
+
do
{
nSpacePos = rStr.lastIndexOf( ' ', nSpacePos );
@@ -355,7 +364,8 @@ namespace vcl
if( nBreakPos < rStr.getLength()-1 )
nBreakPos++;
}
- return nBreakPos;
+
+ return { nBreakPos, nLineWidth };
}
namespace
@@ -413,20 +423,9 @@ namespace vcl
sal_Int32 nBreakPos = lcl_GetEndOfLine(rStr, nPos, nLen);
tools::Long nLineWidth = GetTextWidth(rStr, nPos, nBreakPos-nPos);
+
if (lcl_ShouldBreakWord(nLineWidth, nWidth, nStyle))
- {
- if (!xBI.is())
- xBI = vcl::unohelper::CreateBreakIterator();
-
- if (xBI.is())
- {
- nBreakPos = BreakLinesWithIterator(nWidth, rStr, xHyph, xBI, bHyphenate, nPos, nBreakPos);
- nLineWidth = GetTextWidth(rStr, nPos, nBreakPos - nPos);
- }
- else
- // fallback to something really simple
- nBreakPos = BreakLinesSimple(nWidth, rStr, nPos, nBreakPos, nLineWidth);
- }
+ std::tie(nBreakPos, nLineWidth) = BreakLines(nWidth, rStr, xHyph, xBI, bHyphenate, nLineWidth, nPos, nBreakPos);
if ( nLineWidth > nMaxLineWidth )
nMaxLineWidth = nLineWidth;