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>
This commit is contained in:
parent
9157281deb
commit
938d3b35b8
4 changed files with 96 additions and 40 deletions
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
if (lcl_ShouldBreakWord(nLineWidth, nWidth, nStyle))
|
||||
std::tie(nBreakPos, nLineWidth) = BreakLines(nWidth, rStr, xHyph, xBI, bHyphenate, nLineWidth, nPos, nBreakPos);
|
||||
|
||||
if ( nLineWidth > nMaxLineWidth )
|
||||
nMaxLineWidth = nLineWidth;
|
||||
|
|
Loading…
Reference in a new issue