summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/outdev.hxx23
-rw-r--r--include/vcl/window.hxx2
-rw-r--r--vcl/inc/textlayout.hxx26
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx2
-rw-r--r--vcl/source/gdi/textlayout.cxx396
-rw-r--r--vcl/source/outdev/text.cxx427
-rw-r--r--vcl/source/window/window3.cxx2
7 files changed, 442 insertions, 436 deletions
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 4a6d217c2cb6..bea1e00d9b7f 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -102,7 +102,7 @@ class SalLayoutGlyphs;
namespace vcl
{
class ExtOutDevData;
- class ITextLayout;
+ class TextLayoutCommon;
struct FontCapabilities;
class Window;
class WindowOutputDevice;
@@ -869,11 +869,11 @@ public:
void DrawText( const tools::Rectangle& rRect,
const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::NONE,
std::vector< tools::Rectangle >* pVector = nullptr, OUString* pDisplayText = nullptr,
- vcl::ITextLayout* _pTextLayout = nullptr );
+ vcl::TextLayoutCommon* _pTextLayout = nullptr );
static void ImplDrawText( OutputDevice& rTargetDevice, const tools::Rectangle& rRect,
const OUString& rOrigStr, DrawTextFlags nStyle,
- std::vector< tools::Rectangle >* pVector, OUString* pDisplayText, vcl::ITextLayout& _rLayout );
+ std::vector< tools::Rectangle >* pVector, OUString* pDisplayText, vcl::TextLayoutCommon& _rLayout );
void ImplDrawText( SalLayout& );
@@ -904,7 +904,7 @@ public:
tools::Rectangle GetTextRect( const tools::Rectangle& rRect,
const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::WordBreak,
TextRectInfo* pInfo = nullptr,
- const vcl::ITextLayout* _pTextLayout = nullptr ) const;
+ const vcl::TextLayoutCommon* _pTextLayout = nullptr ) const;
/** Return the exact bounding rectangle of rStr.
@@ -1073,17 +1073,6 @@ public:
protected:
SAL_DLLPRIVATE void ImplInitTextLineSize();
SAL_DLLPRIVATE void ImplInitAboveTextLineSize();
- static
- SAL_DLLPRIVATE tools::Long ImplGetTextLines( const tools::Rectangle& rRect, tools::Long nTextHeight, ImplMultiTextLineInfo& rLineInfo, tools::Long nWidth, const OUString& rStr, DrawTextFlags nStyle, const vcl::ITextLayout& _rLayout );
- static
- SAL_DLLPRIVATE sal_Int32 ImplBreakLinesWithIterator(const tools::Long nWidth, const OUString& rStr, const vcl::ITextLayout& _rLayout,
- const css::uno::Reference<css::linguistic2::XHyphenator>& xHyph,
- const css::uno::Reference<css::i18n::XBreakIterator>& xBI,
- const bool bHyphenate,
- const sal_Int32 nPos, sal_Int32 nBreakPos);
- static
- SAL_DLLPRIVATE sal_Int32 ImplBreakLinesSimple( const tools::Long nWidth, const OUString& rStr,
- const vcl::ITextLayout& _rLayout, const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth );
SAL_DLLPRIVATE float approximate_char_width() const;
virtual bool shouldDrawWavePixelAsRect(tools::Long nLineWidth) const;
@@ -1200,10 +1189,6 @@ private:
SAL_DLLPRIVATE static void ImplUpdateFontDataForAllFrames( FontUpdateHandler_t pHdl, bool bNewFontLists );
- static
- SAL_DLLPRIVATE OUString ImplGetEllipsisString( const OUString& rStr,
- tools::Long nMaxWidth, DrawTextFlags nStyle, const vcl::ITextLayout& _rLayout );
-
SAL_DLLPRIVATE void ImplDrawEmphasisMark( tools::Long nBaseX, tools::Long nX, tools::Long nY, const tools::PolyPolygon& rPolyPoly, bool bPolyLine, const tools::Rectangle& rRect1, const tools::Rectangle& rRect2 );
SAL_DLLPRIVATE void ImplDrawEmphasisMarks( SalLayout& );
///@}
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 73f2e4e5bc03..640e9c6c9983 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -1494,7 +1494,7 @@ public:
tools::Rectangle GetTextRect( const tools::Rectangle& rRect,
const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::WordBreak,
TextRectInfo* pInfo = nullptr,
- const vcl::ITextLayout* _pTextLayout = nullptr ) const;
+ const vcl::TextLayoutCommon* _pTextLayout = nullptr ) const;
float GetDPIScaleFactor() const;
tools::Long GetOutOffXPixel() const;
tools::Long GetOutOffYPixel() const;
diff --git a/vcl/inc/textlayout.hxx b/vcl/inc/textlayout.hxx
index 5938a9d58ef7..ee9eb9e39266 100644
--- a/vcl/inc/textlayout.hxx
+++ b/vcl/inc/textlayout.hxx
@@ -26,6 +26,10 @@
#include <memory>
#include <vector>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
+
class Control;
namespace vcl
@@ -44,10 +48,30 @@ namespace vcl
~ITextLayout() COVERITY_NOEXCEPT_FALSE {}
};
+ class TextLayoutCommon : public ITextLayout
+ {
+ public:
+ OUString GetEllipsisString(OUString const& rOrigStr, tools::Long nMaxWidth, DrawTextFlags nStyle);
+
+ sal_Int32 BreakLinesWithIterator(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,
+ const sal_Int32 nPos, sal_Int32 nBreakPos);
+
+ sal_Int32 BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
+ const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth);
+
+ tools::Long GetTextLines(tools::Rectangle const& rRect, const tools::Long nTextHeight,
+ ImplMultiTextLineInfo& rLineInfo,
+ tools::Long nWidth, OUString const& rStr,
+ DrawTextFlags nStyle);
+ };
+
/** is an implementation of the ITextLayout interface which simply delegates its calls to the respective
methods of an OutputDevice instance, without any inbetween magic.
*/
- class DefaultTextLayout final : public ITextLayout
+ class DefaultTextLayout final : public TextLayoutCommon
{
public:
DefaultTextLayout( OutputDevice& _rTargetDevice )
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 506fde66b6c7..5699b2dc6ddc 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -7304,7 +7304,7 @@ void PDFWriterImpl::drawText( const tools::Rectangle& rRect, const OUString& rOr
{
vcl::DefaultTextLayout aLayout( *this );
OUString aLastLine;
- OutputDevice::ImplGetTextLines( rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle, aLayout );
+ aLayout.GetTextLines( rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle );
sal_Int32 nLines = nHeight/nTextHeight;
nFormatLines = aMultiLineInfo.Count();
if ( !nLines )
diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
index dd559ac470dc..2eaf5746f30b 100644
--- a/vcl/source/gdi/textlayout.cxx
+++ b/vcl/source/gdi/textlayout.cxx
@@ -20,23 +20,409 @@
#include <vcl/ctrl.hxx>
#include <vcl/kernarray.hxx>
#include <vcl/outdev.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp.hxx>
#include <textlayout.hxx>
+#include <textlineinfo.hxx>
#include <osl/diagnose.h>
+#include <osl/file.h>
+#include <rtl/ustrbuf.hxx>
#include <tools/fract.hxx>
#include <sal/log.hxx>
-
-#if OSL_DEBUG_LEVEL > 1
-#include <rtl/strbuf.hxx>
-#endif
+#include <comphelper/processfactory.hxx>
+#include <i18nlangtag/languagetag.hxx>
#include <memory>
#include <iterator>
+static bool ImplIsCharIn(sal_Unicode c, const char* pStr)
+{
+ while ( *pStr )
+ {
+ if ( *pStr == c )
+ return true;
+ pStr++;
+ }
+
+ return false;
+}
+
+ImplMultiTextLineInfo::ImplMultiTextLineInfo()
+{
+}
+
+ImplMultiTextLineInfo::~ImplMultiTextLineInfo()
+{
+}
+
+void ImplMultiTextLineInfo::AddLine( const ImplTextLineInfo& rLine )
+{
+ mvLines.push_back(rLine);
+}
+
+void ImplMultiTextLineInfo::Clear()
+{
+ mvLines.clear();
+}
+
namespace vcl
{
+ OUString TextLayoutCommon::GetEllipsisString(OUString const& rOrigStr, tools::Long nMaxWidth, DrawTextFlags nStyle)
+ {
+ OUString aStr = rOrigStr;
+ sal_Int32 nIndex = GetTextBreak( aStr, nMaxWidth, 0, aStr.getLength() );
+
+ if ( nIndex != -1 )
+ {
+ if( (nStyle & DrawTextFlags::CenterEllipsis) == DrawTextFlags::CenterEllipsis )
+ {
+ OUStringBuffer aTmpStr( aStr );
+ // speed it up by removing all but 1.33x as many as the break pos.
+ sal_Int32 nEraseChars = std::max<sal_Int32>(4, aStr.getLength() - (nIndex*4)/3);
+ while( nEraseChars < aStr.getLength() && GetTextWidth( aTmpStr.toString(), 0, aTmpStr.getLength() ) > nMaxWidth )
+ {
+ aTmpStr = aStr;
+ sal_Int32 i = (aTmpStr.getLength() - nEraseChars)/2;
+ aTmpStr.remove(i, nEraseChars++);
+ aTmpStr.insert(i, "...");
+ }
+ aStr = aTmpStr.makeStringAndClear();
+ }
+ else if ( nStyle & DrawTextFlags::EndEllipsis )
+ {
+ aStr = aStr.copy(0, nIndex);
+ if ( nIndex > 1 )
+ {
+ aStr += "...";
+ while ( !aStr.isEmpty() && ( GetTextWidth( aStr, 0, aStr.getLength() ) > nMaxWidth) )
+ {
+ if ( (nIndex > 1) || (nIndex == aStr.getLength()) )
+ nIndex--;
+ aStr = aStr.replaceAt( nIndex, 1, u"");
+ }
+ }
+
+ if ( aStr.isEmpty() && (nStyle & DrawTextFlags::Clip) )
+ aStr += OUStringChar(rOrigStr[ 0 ]);
+ }
+ else if ( nStyle & DrawTextFlags::PathEllipsis )
+ {
+ OUString aPath( rOrigStr );
+ OUString aAbbreviatedPath;
+ osl_abbreviateSystemPath( aPath.pData, &aAbbreviatedPath.pData, nIndex, nullptr );
+ aStr = aAbbreviatedPath;
+ }
+ else if ( nStyle & DrawTextFlags::NewsEllipsis )
+ {
+ static char const pSepChars[] = ".";
+ // Determine last section
+ sal_Int32 nLastContent = aStr.getLength();
+ while ( nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( aStr[ nLastContent ], pSepChars ) )
+ break;
+ }
+ while ( nLastContent &&
+ ImplIsCharIn( aStr[ nLastContent-1 ], pSepChars ) )
+ nLastContent--;
+
+ OUString aLastStr = aStr.copy(nLastContent);
+ OUString aTempLastStr1 = "..." + aLastStr;
+ if ( GetTextWidth( aTempLastStr1, 0, aTempLastStr1.getLength() ) > nMaxWidth )
+ aStr = GetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis );
+ else
+ {
+ sal_Int32 nFirstContent = 0;
+ while ( nFirstContent < nLastContent )
+ {
+ nFirstContent++;
+ if ( ImplIsCharIn( aStr[ nFirstContent ], pSepChars ) )
+ break;
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( aStr[ nFirstContent ], pSepChars ) )
+ nFirstContent++;
+ // MEM continue here
+ if ( nFirstContent >= nLastContent )
+ aStr = GetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis );
+ else
+ {
+ if ( nFirstContent > 4 )
+ nFirstContent = 4;
+ OUString aFirstStr = OUString::Concat(aStr.subView( 0, nFirstContent )) + "...";
+ OUString aTempStr = aFirstStr + aLastStr;
+ if ( GetTextWidth( aTempStr, 0, aTempStr.getLength() ) > nMaxWidth )
+ aStr = GetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis );
+ else
+ {
+ do
+ {
+ aStr = aTempStr;
+ if( nLastContent > aStr.getLength() )
+ nLastContent = aStr.getLength();
+ while ( nFirstContent < nLastContent )
+ {
+ nLastContent--;
+ if ( ImplIsCharIn( aStr[ nLastContent ], pSepChars ) )
+ break;
+
+ }
+ while ( (nFirstContent < nLastContent) &&
+ ImplIsCharIn( aStr[ nLastContent-1 ], pSepChars ) )
+ nLastContent--;
+
+ if ( nFirstContent < nLastContent )
+ {
+ std::u16string_view aTempLastStr = aStr.subView( nLastContent );
+ aTempStr = aFirstStr + aTempLastStr;
+
+ if ( GetTextWidth( aTempStr, 0, aTempStr.getLength() ) > nMaxWidth )
+ break;
+ }
+ }
+ while ( nFirstContent < nLastContent );
+ }
+ }
+ }
+ }
+ }
+
+ return aStr;
+ }
+
+ sal_Int32 TextLayoutCommon::BreakLinesWithIterator(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,
+ const sal_Int32 nPos, sal_Int32 nBreakPos)
+ {
+ const css::lang::Locale& rDefLocale(Application::GetSettings().GetUILanguageTag().getLocale());
+ sal_Int32 nSoftBreak = GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
+ if (nSoftBreak == -1)
+ {
+ nSoftBreak = nPos;
+ }
+ SAL_WARN_IF( nSoftBreak >= nBreakPos, "vcl", "Break?!" );
+ css::i18n::LineBreakHyphenationOptions aHyphOptions( xHyph, css::uno::Sequence <css::beans::PropertyValue>(), 1 );
+ css::i18n::LineBreakUserOptions aUserOptions;
+ css::i18n::LineBreakResults aLBR = xBI->getLineBreak( rStr, nSoftBreak, rDefLocale, nPos, aHyphOptions, aUserOptions );
+ nBreakPos = aLBR.breakIndex;
+ if ( nBreakPos <= nPos )
+ nBreakPos = nSoftBreak;
+ if ( !bHyphenate )
+ return nBreakPos;
+
+ // Whether hyphen or not: Put the word after the hyphen through
+ // word boundary.
+
+ // nMaxBreakPos the last char that fits into the line
+ // nBreakPos is the word's start
+
+ // 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;
+ sal_Int32 nWordEnd = aBoundary.endPos;
+ SAL_WARN_IF( nWordEnd <= nWordStart, "vcl", "ImpBreakLine: Start >= End?" );
+
+ sal_Int32 nWordLen = nWordEnd - nWordStart;
+ if ( ( nWordEnd < nSoftBreak ) || ( nWordLen <= 3 ) )
+ return nBreakPos;
+
+ // #104415# May happen, because getLineBreak may differ from getWordBoundary with DICTIONARY_WORD
+ // SAL_WARN_IF( nWordEnd < nMaxBreakPos, "vcl", "Hyph: Break?" );
+ 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;
+
+ bool bAlternate = xHyphWord->isAlternativeSpelling();
+ sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos();
+
+ if ( ( _nWordLen < 2 ) || ( (nWordStart+_nWordLen) < 2 ) )
+ return nBreakPos;
+
+ if ( bAlternate )
+ {
+ nBreakPos = nWordStart + _nWordLen;
+ return nBreakPos;
+ }
+
+ OUString aAlt( xHyphWord->getHyphenatedWord() );
+
+ // We can have two cases:
+ // 1) "packen" turns into "pak-ken"
+ // 2) "Schiffahrt" turns into "Schiff-fahrt"
+
+ // In case 1 we need to replace a char
+ // In case 2 we add a char
+
+ // Correct recognition is made harder by words such as
+ // "Schiffahrtsbrennesseln", as the Hyphenator splits all
+ // positions of the word and comes up with "Schifffahrtsbrennnesseln"
+ // Thus, we cannot infer the aWord from the AlternativeWord's
+ // index.
+ // TODO: The whole junk will be made easier by a function in
+ // the Hyphenator, as soon as AMA adds it.
+ sal_Int32 nAltStart = _nWordLen - 1;
+ sal_Int32 nTxtStart = nAltStart - (aAlt.getLength() - aWord.getLength());
+ sal_Int32 nTxtEnd = nTxtStart;
+ sal_Int32 nAltEnd = nAltStart;
+
+ // The area between nStart and nEnd is the difference
+ // between AlternativeString and OriginalString
+ while( nTxtEnd < aWord.getLength() && nAltEnd < aAlt.getLength() &&
+ aWord[nTxtEnd] != aAlt[nAltEnd] )
+ {
+ ++nTxtEnd;
+ ++nAltEnd;
+ }
+
+ // If a char was added, we notice it now:
+ if( nAltEnd > nTxtEnd && nAltStart == nAltEnd &&
+ aWord[ nTxtEnd ] == aAlt[nAltEnd] )
+ {
+ ++nAltEnd;
+ ++nTxtStart;
+ ++nTxtEnd;
+ }
+
+ SAL_INFO_IF( ( nAltEnd - nAltStart ) != 1, "vcl", "Alternate: Wrong assumption!" );
+
+ sal_Unicode cAlternateReplChar = 0;
+ if ( nTxtEnd > nTxtStart )
+ cAlternateReplChar = aAlt[ nAltStart ];
+
+ nBreakPos = nWordStart + nTxtStart;
+ if ( cAlternateReplChar )
+ nBreakPos++;
+ return nBreakPos;
+ }
+
+ sal_Int32 TextLayoutCommon::BreakLinesSimple(const tools::Long nWidth, OUString const& rStr,
+ const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth)
+ {
+ sal_Int32 nSpacePos = rStr.getLength();
+ tools::Long nW = 0;
+ do
+ {
+ nSpacePos = rStr.lastIndexOf( ' ', nSpacePos );
+ if( nSpacePos != -1 )
+ {
+ if( nSpacePos > nPos )
+ nSpacePos--;
+ nW = GetTextWidth( rStr, nPos, nSpacePos-nPos );
+ }
+ } while( nW > nWidth );
+
+ if( nSpacePos != -1 )
+ {
+ nBreakPos = nSpacePos;
+ nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ if( nBreakPos < rStr.getLength()-1 )
+ nBreakPos++;
+ }
+ return nBreakPos;
+ }
+
+ tools::Long TextLayoutCommon::GetTextLines(tools::Rectangle const& rRect, const tools::Long nTextHeight,
+ ImplMultiTextLineInfo& rLineInfo,
+ tools::Long nWidth, OUString const& rStr,
+ DrawTextFlags nStyle)
+ {
+ SAL_WARN_IF( nWidth <= 0, "vcl", "ImplGetTextLines: nWidth <= 0!" );
+
+ if ( nWidth <= 0 )
+ nWidth = 1;
+
+ rLineInfo.Clear();
+ if (rStr.isEmpty())
+ return 0;
+
+ const bool bClipping = (nStyle & DrawTextFlags::Clip) && !(nStyle & DrawTextFlags::EndEllipsis);
+
+ tools::Long nMaxLineWidth = 0;
+ const bool bHyphenate = (nStyle & DrawTextFlags::WordBreakHyphenation) == DrawTextFlags::WordBreakHyphenation;
+ css::uno::Reference< css::linguistic2::XHyphenator > xHyph;
+ if (bHyphenate)
+ {
+ // get service provider
+ css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+ css::uno::Reference<css::linguistic2::XLinguServiceManager2> xLinguMgr = css::linguistic2::LinguServiceManager::create(xContext);
+ xHyph = xLinguMgr->getHyphenator();
+ }
+
+ css::uno::Reference<css::i18n::XBreakIterator> xBI;
+ sal_Int32 nPos = 0;
+ sal_Int32 nLen = rStr.getLength();
+ sal_Int32 nCurrentTextY = 0;
+ while ( nPos < nLen )
+ {
+ sal_Int32 nBreakPos = nPos;
+
+ while ( ( nBreakPos < nLen ) && ( rStr[ nBreakPos ] != '\r' ) && ( rStr[ nBreakPos ] != '\n' ) )
+ nBreakPos++;
+
+ tools::Long nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ if ( ( nLineWidth > nWidth ) && ( nStyle & DrawTextFlags::WordBreak ) )
+ {
+ 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 ( nLineWidth > nMaxLineWidth )
+ nMaxLineWidth = nLineWidth;
+
+ rLineInfo.AddLine( ImplTextLineInfo( nLineWidth, nPos, nBreakPos-nPos ) );
+
+ if ( nBreakPos == nPos )
+ nBreakPos++;
+ nPos = nBreakPos;
+
+ if ( nPos < nLen && ( ( rStr[ nPos ] == '\r' ) || ( rStr[ nPos ] == '\n' ) ) )
+ {
+ nPos++;
+ // CR/LF?
+ if ( ( nPos < nLen ) && ( rStr[ nPos ] == '\n' ) && ( rStr[ nPos-1 ] == '\r' ) )
+ nPos++;
+ }
+ nCurrentTextY += nTextHeight;
+ if (bClipping && nCurrentTextY > rRect.GetHeight())
+ break;
+ }
+
+#ifdef DBG_UTIL
+ for ( sal_Int32 nL = 0; nL < rLineInfo.Count(); nL++ )
+ {
+ ImplTextLineInfo& rLine = rLineInfo.GetLine( nL );
+ OUString aLine = rStr.copy( rLine.GetIndex(), rLine.GetLen() );
+ SAL_WARN_IF( aLine.indexOf( '\r' ) != -1, "vcl", "ImplGetTextLines - Found CR!" );
+ SAL_WARN_IF( aLine.indexOf( '\n' ) != -1, "vcl", "ImplGetTextLines - Found LF!" );
+ }
+#endif
+
+ return nMaxLineWidth;
+ }
+
DefaultTextLayout::~DefaultTextLayout()
{
}
@@ -68,7 +454,7 @@ namespace vcl
return false;
}
- class ReferenceDeviceTextLayout : public ITextLayout
+ class ReferenceDeviceTextLayout : public TextLayoutCommon
{
public:
ReferenceDeviceTextLayout( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice );
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index c2978d971659..1b40a1b2de28 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -19,11 +19,8 @@
#include <sal/config.h>
-#include <osl/file.h>
-#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <comphelper/processfactory.hxx>
#include <tools/lineend.hxx>
#include <tools/debug.hxx>
#include <unotools/configmgr.hxx>
@@ -35,7 +32,6 @@
#include <vcl/textrectinfo.hxx>
#include <vcl/virdev.hxx>
#include <vcl/sysdata.hxx>
-#include <vcl/unohelp.hxx>
#include <ImplLayoutArgs.hxx>
#include <ImplOutDevData.hxx>
@@ -48,10 +44,6 @@
#include <TextLayoutCache.hxx>
#include <font/PhysicalFontFace.hxx>
-#include <com/sun/star/i18n/WordType.hpp>
-#include <com/sun/star/i18n/XBreakIterator.hpp>
-#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
-
#include <memory>
#include <optional>
@@ -79,24 +71,6 @@ void OutputDevice::SetDigitLanguage( LanguageType eTextLanguage )
mpAlphaVDev->SetDigitLanguage( eTextLanguage );
}
-ImplMultiTextLineInfo::ImplMultiTextLineInfo()
-{
-}
-
-ImplMultiTextLineInfo::~ImplMultiTextLineInfo()
-{
-}
-
-void ImplMultiTextLineInfo::AddLine( const ImplTextLineInfo& rLine )
-{
- mvLines.push_back(rLine);
-}
-
-void ImplMultiTextLineInfo::Clear()
-{
- mvLines.clear();
-}
-
void OutputDevice::ImplInitTextColor()
{
DBG_TESTSOLARMUTEX();
@@ -108,6 +82,13 @@ void OutputDevice::ImplInitTextColor()
}
}
+OUString OutputDevice::GetEllipsisString( const OUString& rOrigStr, tools::Long nMaxWidth,
+ DrawTextFlags nStyle ) const
+{
+ vcl::DefaultTextLayout aTextLayout(*const_cast< OutputDevice* >(this));
+ return aTextLayout.GetEllipsisString(rOrigStr, nMaxWidth, nStyle);
+}
+
void OutputDevice::ImplDrawTextRect( tools::Long nBaseX, tools::Long nBaseY,
tools::Long nDistX, tools::Long nDistY, tools::Long nWidth, tools::Long nHeight )
{
@@ -482,237 +463,6 @@ void OutputDevice::ImplDrawText( SalLayout& rSalLayout )
ImplDrawTextDirect( rSalLayout, mbTextLines );
}
-tools::Long OutputDevice::ImplGetTextLines( const tools::Rectangle& rRect, const tools::Long nTextHeight,
- ImplMultiTextLineInfo& rLineInfo,
- tools::Long nWidth, const OUString& rStr,
- DrawTextFlags nStyle, const vcl::ITextLayout& _rLayout )
-{
- SAL_WARN_IF( nWidth <= 0, "vcl", "ImplGetTextLines: nWidth <= 0!" );
-
- if ( nWidth <= 0 )
- nWidth = 1;
-
- rLineInfo.Clear();
- if (rStr.isEmpty())
- return 0;
-
- const bool bClipping = (nStyle & DrawTextFlags::Clip) && !(nStyle & DrawTextFlags::EndEllipsis);
-
- tools::Long nMaxLineWidth = 0;
- const bool bHyphenate = (nStyle & DrawTextFlags::WordBreakHyphenation) == DrawTextFlags::WordBreakHyphenation;
- css::uno::Reference< css::linguistic2::XHyphenator > xHyph;
- if (bHyphenate)
- {
- // get service provider
- css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
- css::uno::Reference<css::linguistic2::XLinguServiceManager2> xLinguMgr = css::linguistic2::LinguServiceManager::create(xContext);
- xHyph = xLinguMgr->getHyphenator();
- }
-
- css::uno::Reference<css::i18n::XBreakIterator> xBI;
- sal_Int32 nPos = 0;
- sal_Int32 nLen = rStr.getLength();
- sal_Int32 nCurrentTextY = 0;
- while ( nPos < nLen )
- {
- sal_Int32 nBreakPos = nPos;
-
- while ( ( nBreakPos < nLen ) && ( rStr[ nBreakPos ] != '\r' ) && ( rStr[ nBreakPos ] != '\n' ) )
- nBreakPos++;
-
- tools::Long nLineWidth = _rLayout.GetTextWidth( rStr, nPos, nBreakPos-nPos );
- if ( ( nLineWidth > nWidth ) && ( nStyle & DrawTextFlags::WordBreak ) )
- {
- if ( !xBI.is() )
- xBI = vcl::unohelper::CreateBreakIterator();
-
- if ( xBI.is() )
- {
- nBreakPos = ImplBreakLinesWithIterator(nWidth, rStr, _rLayout, xHyph, xBI, bHyphenate, nPos, nBreakPos);
- nLineWidth = _rLayout.GetTextWidth(rStr, nPos, nBreakPos - nPos);
- }
- else
- // fallback to something really simple
- nBreakPos = ImplBreakLinesSimple(nWidth, rStr, _rLayout, nPos, nBreakPos, nLineWidth);
- }
-
- if ( nLineWidth > nMaxLineWidth )
- nMaxLineWidth = nLineWidth;
-
- rLineInfo.AddLine( ImplTextLineInfo( nLineWidth, nPos, nBreakPos-nPos ) );
-
- if ( nBreakPos == nPos )
- nBreakPos++;
- nPos = nBreakPos;
-
- if ( nPos < nLen && ( ( rStr[ nPos ] == '\r' ) || ( rStr[ nPos ] == '\n' ) ) )
- {
- nPos++;
- // CR/LF?
- if ( ( nPos < nLen ) && ( rStr[ nPos ] == '\n' ) && ( rStr[ nPos-1 ] == '\r' ) )
- nPos++;
- }
- nCurrentTextY += nTextHeight;
- if (bClipping && nCurrentTextY > rRect.GetHeight())
- break;
- }
-
-#ifdef DBG_UTIL
- for ( sal_Int32 nL = 0; nL < rLineInfo.Count(); nL++ )
- {
- ImplTextLineInfo& rLine = rLineInfo.GetLine( nL );
- OUString aLine = rStr.copy( rLine.GetIndex(), rLine.GetLen() );
- SAL_WARN_IF( aLine.indexOf( '\r' ) != -1, "vcl", "ImplGetTextLines - Found CR!" );
- SAL_WARN_IF( aLine.indexOf( '\n' ) != -1, "vcl", "ImplGetTextLines - Found LF!" );
- }
-#endif
-
- return nMaxLineWidth;
-}
-
-sal_Int32 OutputDevice::ImplBreakLinesWithIterator(const tools::Long nWidth, const OUString& rStr, const vcl::ITextLayout& _rLayout,
- const css::uno::Reference< css::linguistic2::XHyphenator >& xHyph,
- const css::uno::Reference<css::i18n::XBreakIterator>& xBI,
- const bool bHyphenate,
- const sal_Int32 nPos, sal_Int32 nBreakPos)
-{
- const css::lang::Locale& rDefLocale(Application::GetSettings().GetUILanguageTag().getLocale());
- sal_Int32 nSoftBreak = _rLayout.GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
- if (nSoftBreak == -1)
- {
- nSoftBreak = nPos;
- }
- SAL_WARN_IF( nSoftBreak >= nBreakPos, "vcl", "Break?!" );
- css::i18n::LineBreakHyphenationOptions aHyphOptions( xHyph, css::uno::Sequence <css::beans::PropertyValue>(), 1 );
- css::i18n::LineBreakUserOptions aUserOptions;
- css::i18n::LineBreakResults aLBR = xBI->getLineBreak( rStr, nSoftBreak, rDefLocale, nPos, aHyphOptions, aUserOptions );
- nBreakPos = aLBR.breakIndex;
- if ( nBreakPos <= nPos )
- nBreakPos = nSoftBreak;
- if ( !bHyphenate )
- return nBreakPos;
-
- // Whether hyphen or not: Put the word after the hyphen through
- // word boundary.
-
- // nMaxBreakPos the last char that fits into the line
- // nBreakPos is the word's start
-
- // 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;
- sal_Int32 nWordEnd = aBoundary.endPos;
- SAL_WARN_IF( nWordEnd <= nWordStart, "vcl", "ImpBreakLine: Start >= End?" );
-
- sal_Int32 nWordLen = nWordEnd - nWordStart;
- if ( ( nWordEnd < nSoftBreak ) || ( nWordLen <= 3 ) )
- return nBreakPos;
-
- // #104415# May happen, because getLineBreak may differ from getWordBoundary with DICTIONARY_WORD
- // SAL_WARN_IF( nWordEnd < nMaxBreakPos, "vcl", "Hyph: Break?" );
- 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;
-
- bool bAlternate = xHyphWord->isAlternativeSpelling();
- sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos();
-
- if ( ( _nWordLen < 2 ) || ( (nWordStart+_nWordLen) < 2 ) )
- return nBreakPos;
-
- if ( bAlternate )
- {
- nBreakPos = nWordStart + _nWordLen;
- return nBreakPos;
- }
-
-
- OUString aAlt( xHyphWord->getHyphenatedWord() );
-
- // We can have two cases:
- // 1) "packen" turns into "pak-ken"
- // 2) "Schiffahrt" turns into "Schiff-fahrt"
-
- // In case 1 we need to replace a char
- // In case 2 we add a char
-
- // Correct recognition is made harder by words such as
- // "Schiffahrtsbrennesseln", as the Hyphenator splits all
- // positions of the word and comes up with "Schifffahrtsbrennnesseln"
- // Thus, we cannot infer the aWord from the AlternativeWord's
- // index.
- // TODO: The whole junk will be made easier by a function in
- // the Hyphenator, as soon as AMA adds it.
- sal_Int32 nAltStart = _nWordLen - 1;
- sal_Int32 nTxtStart = nAltStart - (aAlt.getLength() - aWord.getLength());
- sal_Int32 nTxtEnd = nTxtStart;
- sal_Int32 nAltEnd = nAltStart;
-
- // The area between nStart and nEnd is the difference
- // between AlternativeString and OriginalString
- while( nTxtEnd < aWord.getLength() && nAltEnd < aAlt.getLength() &&
- aWord[nTxtEnd] != aAlt[nAltEnd] )
- {
- ++nTxtEnd;
- ++nAltEnd;
- }
-
- // If a char was added, we notice it now:
- if( nAltEnd > nTxtEnd && nAltStart == nAltEnd &&
- aWord[ nTxtEnd ] == aAlt[nAltEnd] )
- {
- ++nAltEnd;
- ++nTxtStart;
- ++nTxtEnd;
- }
-
- SAL_INFO_IF( ( nAltEnd - nAltStart ) != 1, "vcl", "Alternate: Wrong assumption!" );
-
- sal_Unicode cAlternateReplChar = 0;
- if ( nTxtEnd > nTxtStart )
- cAlternateReplChar = aAlt[ nAltStart ];
-
- nBreakPos = nWordStart + nTxtStart;
- if ( cAlternateReplChar )
- nBreakPos++;
- return nBreakPos;
-}
-
-sal_Int32 OutputDevice::ImplBreakLinesSimple( const tools::Long nWidth, const OUString& rStr,
- const vcl::ITextLayout& _rLayout, const sal_Int32 nPos, sal_Int32 nBreakPos, tools::Long& nLineWidth )
-{
- sal_Int32 nSpacePos = rStr.getLength();
- tools::Long nW = 0;
- do
- {
- nSpacePos = rStr.lastIndexOf( ' ', nSpacePos );
- if( nSpacePos != -1 )
- {
- if( nSpacePos > nPos )
- nSpacePos--;
- nW = _rLayout.GetTextWidth( rStr, nPos, nSpacePos-nPos );
- }
- } while( nW > nWidth );
-
- if( nSpacePos != -1 )
- {
- nBreakPos = nSpacePos;
- nLineWidth = _rLayout.GetTextWidth( rStr, nPos, nBreakPos-nPos );
- if( nBreakPos < rStr.getLength()-1 )
- nBreakPos++;
- }
- return nBreakPos;
-}
-
-
void OutputDevice::SetTextColor( const Color& rColor )
{
@@ -1538,7 +1288,7 @@ sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, tools::Long nTextWid
void OutputDevice::ImplDrawText( OutputDevice& rTargetDevice, const tools::Rectangle& rRect,
const OUString& rOrigStr, DrawTextFlags nStyle,
std::vector< tools::Rectangle >* pVector, OUString* pDisplayText,
- vcl::ITextLayout& _rLayout )
+ vcl::TextLayoutCommon& _rLayout )
{
Color aOldTextColor;
@@ -1617,7 +1367,7 @@ void OutputDevice::ImplDrawText( OutputDevice& rTargetDevice, const tools::Recta
if ( nTextHeight )
{
- tools::Long nMaxTextWidth = ImplGetTextLines( rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle, _rLayout );
+ tools::Long nMaxTextWidth = _rLayout.GetTextLines(rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle);
sal_Int32 nLines = static_cast<sal_Int32>(nHeight/nTextHeight);
OUString aLastLine;
nFormatLines = aMultiLineInfo.Count();
@@ -1641,7 +1391,7 @@ void OutputDevice::ImplDrawText( OutputDevice& rTargetDevice, const tools::Recta
aLastLineBuffer[ i ] = ' ';
}
aLastLine = aLastLineBuffer.makeStringAndClear();
- aLastLine = ImplGetEllipsisString( aLastLine, nWidth, nStyle, _rLayout );
+ aLastLine = _rLayout.GetEllipsisString(aLastLine, nWidth, nStyle);
nStyle &= ~DrawTextFlags(DrawTextFlags::VCenter | DrawTextFlags::Bottom);
nStyle |= DrawTextFlags::Top;
}
@@ -1728,7 +1478,7 @@ void OutputDevice::ImplDrawText( OutputDevice& rTargetDevice, const tools::Recta
{
if ( nStyle & TEXT_DRAW_ELLIPSIS )
{
- aStr = ImplGetEllipsisString( aStr, nWidth, nStyle, _rLayout );
+ aStr = _rLayout.GetEllipsisString(aStr, nWidth, nStyle);
nStyle &= ~DrawTextFlags(DrawTextFlags::Center | DrawTextFlags::Right);
nStyle |= DrawTextFlags::Left;
nTextWidth = _rLayout.GetTextWidth( aStr, 0, aStr.getLength() );
@@ -1834,7 +1584,7 @@ void OutputDevice::AddTextRectActions( const tools::Rectangle& rRect,
void OutputDevice::DrawText( const tools::Rectangle& rRect, const OUString& rOrigStr, DrawTextFlags nStyle,
std::vector< tools::Rectangle >* pVector, OUString* pDisplayText,
- vcl::ITextLayout* _pTextLayout )
+ vcl::TextLayoutCommon* _pTextLayout )
{
assert(!is_double_buffered_window());
@@ -1881,7 +1631,7 @@ void OutputDevice::DrawText( const tools::Rectangle& rRect, const OUString& rOri
tools::Rectangle OutputDevice::GetTextRect( const tools::Rectangle& rRect,
const OUString& rStr, DrawTextFlags nStyle,
TextRectInfo* pInfo,
- const vcl::ITextLayout* _pTextLayout ) const
+ const vcl::TextLayoutCommon* _pTextLayout ) const
{
tools::Rectangle aRect = rRect;
@@ -1902,7 +1652,12 @@ tools::Rectangle OutputDevice::GetTextRect( const tools::Rectangle& rRect,
nMaxWidth = 0;
vcl::DefaultTextLayout aDefaultLayout( *const_cast< OutputDevice* >( this ) );
- ImplGetTextLines( rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle, _pTextLayout ? *_pTextLayout : aDefaultLayout );
+
+ if (_pTextLayout)
+ const_cast<vcl::TextLayoutCommon*>(_pTextLayout)->GetTextLines(rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle);
+ else
+ aDefaultLayout.GetTextLines(rRect, nTextHeight, aMultiLineInfo, nWidth, aStr, nStyle);
+
nFormatLines = aMultiLineInfo.Count();
if ( !nTextHeight )
nTextHeight = 1;
@@ -2002,150 +1757,6 @@ tools::Rectangle OutputDevice::GetTextRect( const tools::Rectangle& rRect,
return aRect;
}
-static bool ImplIsCharIn( sal_Unicode c, const char* pStr )
-{
- while ( *pStr )
- {
- if ( *pStr == c )
- return true;
- pStr++;
- }
-
- return false;
-}
-
-OUString OutputDevice::GetEllipsisString( const OUString& rOrigStr, tools::Long nMaxWidth,
- DrawTextFlags nStyle ) const
-{
- vcl::DefaultTextLayout aTextLayout( *const_cast< OutputDevice* >( this ) );
- return ImplGetEllipsisString( rOrigStr, nMaxWidth, nStyle, aTextLayout );
-}
-
-OUString OutputDevice::ImplGetEllipsisString( const OUString& rOrigStr, tools::Long nMaxWidth,
- DrawTextFlags nStyle, const vcl::ITextLayout& _rLayout )
-{
- OUString aStr = rOrigStr;
- sal_Int32 nIndex = _rLayout.GetTextBreak( aStr, nMaxWidth, 0, aStr.getLength() );
-
- if ( nIndex != -1 )
- {
- if( (nStyle & DrawTextFlags::CenterEllipsis) == DrawTextFlags::CenterEllipsis )
- {
- OUStringBuffer aTmpStr( aStr );
- // speed it up by removing all but 1.33x as many as the break pos.
- sal_Int32 nEraseChars = std::max<sal_Int32>(4, aStr.getLength() - (nIndex*4)/3);
- while( nEraseChars < aStr.getLength() && _rLayout.GetTextWidth( aTmpStr.toString(), 0, aTmpStr.getLength() ) > nMaxWidth )
- {
- aTmpStr = aStr;
- sal_Int32 i = (aTmpStr.getLength() - nEraseChars)/2;
- aTmpStr.remove(i, nEraseChars++);
- aTmpStr.insert(i, "...");
- }
- aStr = aTmpStr.makeStringAndClear();
- }
- else if ( nStyle & DrawTextFlags::EndEllipsis )
- {
- aStr = aStr.copy(0, nIndex);
- if ( nIndex > 1 )
- {
- aStr += "...";
- while ( !aStr.isEmpty() && (_rLayout.GetTextWidth( aStr, 0, aStr.getLength() ) > nMaxWidth) )
- {
- if ( (nIndex > 1) || (nIndex == aStr.getLength()) )
- nIndex--;
- aStr = aStr.replaceAt( nIndex, 1, u"");
- }
- }
-
- if ( aStr.isEmpty() && (nStyle & DrawTextFlags::Clip) )
- aStr += OUStringChar(rOrigStr[ 0 ]);
- }
- else if ( nStyle & DrawTextFlags::PathEllipsis )
- {
- OUString aPath( rOrigStr );
- OUString aAbbreviatedPath;
- osl_abbreviateSystemPath( aPath.pData, &aAbbreviatedPath.pData, nIndex, nullptr );
- aStr = aAbbreviatedPath;
- }
- else if ( nStyle & DrawTextFlags::NewsEllipsis )
- {
- static char const pSepChars[] = ".";
- // Determine last section
- sal_Int32 nLastContent = aStr.getLength();
- while ( nLastContent )
- {
- nLastContent--;
- if ( ImplIsCharIn( aStr[ nLastContent ], pSepChars ) )
- break;
- }
- while ( nLastContent &&
- ImplIsCharIn( aStr[ nLastContent-1 ], pSepChars ) )
- nLastContent--;
-
- OUString aLastStr = aStr.copy(nLastContent);
- OUString aTempLastStr1 = "..." + aLastStr;
- if ( _rLayout.GetTextWidth( aTempLastStr1, 0, aTempLastStr1.getLength() ) > nMaxWidth )
- aStr = OutputDevice::ImplGetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis, _rLayout );
- else
- {
- sal_Int32 nFirstContent = 0;
- while ( nFirstContent < nLastContent )
- {
- nFirstContent++;
- if ( ImplIsCharIn( aStr[ nFirstContent ], pSepChars ) )
- break;
- }
- while ( (nFirstContent < nLastContent) &&
- ImplIsCharIn( aStr[ nFirstContent ], pSepChars ) )
- nFirstContent++;
- // MEM continue here
- if ( nFirstContent >= nLastContent )
- aStr = OutputDevice::ImplGetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis, _rLayout );
- else
- {
- if ( nFirstContent > 4 )
- nFirstContent = 4;
- OUString aFirstStr = OUString::Concat(aStr.subView( 0, nFirstContent )) + "...";
- OUString aTempStr = aFirstStr + aLastStr;
- if ( _rLayout.GetTextWidth( aTempStr, 0, aTempStr.getLength() ) > nMaxWidth )
- aStr = OutputDevice::ImplGetEllipsisString( aStr, nMaxWidth, nStyle | DrawTextFlags::EndEllipsis, _rLayout );
- else
- {
- do
- {
- aStr = aTempStr;
- if( nLastContent > aStr.getLength() )
- nLastContent = aStr.getLength();
- while ( nFirstContent < nLastContent )
- {
- nLastContent--;
- if ( ImplIsCharIn( aStr[ nLastContent ], pSepChars ) )
- break;
-
- }
- while ( (nFirstContent < nLastContent) &&
- ImplIsCharIn( aStr[ nLastContent-1 ], pSepChars ) )
- nLastContent--;
-
- if ( nFirstContent < nLastContent )
- {
- std::u16string_view aTempLastStr = aStr.subView( nLastContent );
- aTempStr = aFirstStr + aTempLastStr;
-
- if ( _rLayout.GetTextWidth( aTempStr, 0, aTempStr.getLength() ) > nMaxWidth )
- break;
- }
- }
- while ( nFirstContent < nLastContent );
- }
- }
- }
- }
- }
-
- return aStr;
-}
-
void OutputDevice::DrawCtrlText( const Point& rPos, const OUString& rStr,
sal_Int32 nIndex, sal_Int32 nLen,
DrawTextFlags nStyle, std::vector< tools::Rectangle >* pVector, OUString* pDisplayText,
diff --git a/vcl/source/window/window3.cxx b/vcl/source/window/window3.cxx
index 5b8dd5cff4ec..30c41f5e20f0 100644
--- a/vcl/source/window/window3.cxx
+++ b/vcl/source/window/window3.cxx
@@ -200,7 +200,7 @@ Size Window::LogicToLogic(const Size& rSzSource, const MapMode* pMapModeSource,
tools::Rectangle Window::GetTextRect(const tools::Rectangle& rRect, const OUString& rStr,
DrawTextFlags nStyle, TextRectInfo* pInfo,
- const vcl::ITextLayout* _pTextLayout) const
+ const vcl::TextLayoutCommon* _pTextLayout) const
{
return GetOutDev()->GetTextRect(rRect, rStr, nStyle, pInfo, _pTextLayout);
}