summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx2
-rw-r--r--editeng/source/items/svxfont.cxx6
-rw-r--r--filter/source/svg/svgwriter.cxx3
-rw-r--r--include/vcl/outdev.hxx25
-rw-r--r--sw/source/core/inc/drawfont.hxx36
-rw-r--r--sw/source/core/text/frmform.cxx21
-rw-r--r--sw/source/core/text/guess.cxx45
-rw-r--r--sw/source/core/text/inftxt.cxx19
-rw-r--r--sw/source/core/text/inftxt.hxx12
-rw-r--r--sw/source/core/text/itrform2.cxx2
-rw-r--r--sw/source/core/text/itrpaint.cxx6
-rw-r--r--sw/source/core/text/porfld.cxx4
-rw-r--r--sw/source/core/text/porlay.cxx3
-rw-r--r--sw/source/core/text/porlay.hxx11
-rw-r--r--sw/source/core/text/txtpaint.cxx7
-rw-r--r--sw/source/core/text/txtpaint.hxx15
-rw-r--r--sw/source/core/txtnode/fntcache.cxx41
-rw-r--r--toolkit/source/awt/vclxfont.cxx2
-rw-r--r--vcl/qa/cppunit/complextext.cxx60
-rw-r--r--vcl/qa/cppunit/text.cxx15
-rw-r--r--vcl/source/filter/wmf/emfwr.cxx2
-rw-r--r--vcl/source/filter/wmf/wmfwr.cxx3
-rw-r--r--vcl/source/outdev/text.cxx47
-rw-r--r--vcl/source/text/textlayout.cxx7
24 files changed, 263 insertions, 131 deletions
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index e0a090cf9ecd..45825a2a477b 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -337,7 +337,7 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
tools::Long nWidthToFill = rTextCandidate.getWidthToFill();
tools::Long nWidth = basegfx::fround<tools::Long>(
- mpOutputDevice->GetTextArray(rTextCandidate.getText(), &aDXArray, 0, 1));
+ mpOutputDevice->GetTextArray(rTextCandidate.getText(), &aDXArray, 0, 1).nWidth);
sal_Int32 nChars = 2;
if (nWidth)
nChars = nWidthToFill / nWidth;
diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx
index 253c78f8dea4..2df18feb449f 100644
--- a/editeng/source/items/svxfont.cxx
+++ b/editeng/source/items/svxfont.cxx
@@ -38,7 +38,8 @@ static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr,
{
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
- return basegfx::fround<tools::Long>(pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, true, nullptr, layoutGlyphs));
+ return basegfx::fround<tools::Long>(
+ pOut->GetTextArray(rStr, pDXAry, nIndex, nLen, true, nullptr, layoutGlyphs).nWidth);
}
SvxFont::SvxFont()
@@ -719,7 +720,8 @@ void SvxDoGetCapitalSize::Do( const OUString &_rTxt, const sal_Int32 _nIdx,
if (pDXAry)
{
KernArray aKernArray;
- aPartSize.setWidth(basegfx::fround<tools::Long>(pOut->GetTextArray(_rTxt, &aKernArray, _nIdx, _nLen)));
+ aPartSize.setWidth(basegfx::fround<tools::Long>(
+ pOut->GetTextArray(_rTxt, &aKernArray, _nIdx, _nLen).nWidth));
assert(pDXAry->get_factor() == aKernArray.get_factor());
auto& dest = pDXAry->get_subunit_array();
sal_Int32 nStart = dest.empty() ? 0 : dest.back();
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index e4c885cd6ca4..57a039f32a18 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -2679,7 +2679,8 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
}
else
{
- aNormSize = Size(basegfx::fround<tools::Long>(mpVDev->GetTextArray(rText, &aTmpArray)), 0);
+ aNormSize
+ = Size(basegfx::fround<tools::Long>(mpVDev->GetTextArray(rText, &aTmpArray).nWidth), 0);
}
// if text is rotated, set transform matrix at new g element
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 347d5bb82226..2fddb3c3f24a 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -160,6 +160,12 @@ class OutputDevice;
namespace vcl {
typedef OutputDevice RenderContext;
+
+ struct TextArrayMetrics
+ {
+ std::optional<tools::Rectangle> aBounds;
+ double nWidth = 0.0;
+ };
}
VCL_DLLPUBLIC void InvertFocusRect(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect);
@@ -1059,20 +1065,23 @@ public:
sal_Int32 nLen,
SalLayoutFlags flags = SalLayoutFlags::NONE,
const SalLayoutGlyphs* pLayoutCache = nullptr);
- double GetTextArray( const OUString& rStr, KernArray* pDXAry,
- sal_Int32 nIndex = 0, sal_Int32 nLen = -1, bool bCaret = false,
- vcl::text::TextLayoutCache const* = nullptr,
- SalLayoutGlyphs const*const pLayoutCache = nullptr) const;
+ vcl::TextArrayMetrics GetTextArray(const OUString& rStr, KernArray* pDXAry,
+ sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
+ bool bCaret = false,
+ vcl::text::TextLayoutCache const* = nullptr,
+ SalLayoutGlyphs const* const pLayoutCache = nullptr) const;
void DrawPartialTextArray(const Point& rStartPt, const OUString& rStr, KernArraySpan aKernArray,
std::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex,
sal_Int32 nLen, sal_Int32 nPartIndex, sal_Int32 nPartLen,
SalLayoutFlags flags = SalLayoutFlags::NONE,
const SalLayoutGlyphs* pLayoutCache = nullptr);
- double GetPartialTextArray(const OUString& rStr, KernArray* pDXAry, sal_Int32 nIndex,
- sal_Int32 nLen, sal_Int32 nPartIndex, sal_Int32 nPartLen,
- bool bCaret = false, const vcl::text::TextLayoutCache* = nullptr,
- const SalLayoutGlyphs* pLayoutCache = nullptr) const;
+ vcl::TextArrayMetrics GetPartialTextArray(const OUString& rStr, KernArray* pDXAry,
+ sal_Int32 nIndex, sal_Int32 nLen,
+ sal_Int32 nPartIndex, sal_Int32 nPartLen,
+ bool bCaret = false,
+ const vcl::text::TextLayoutCache* = nullptr,
+ const SalLayoutGlyphs* pLayoutCache = nullptr) const;
SAL_DLLPRIVATE void GetCaretPositions( const OUString&, KernArray& rCaretXArray,
sal_Int32 nIndex, sal_Int32 nLen,
diff --git a/sw/source/core/inc/drawfont.hxx b/sw/source/core/inc/drawfont.hxx
index 646ab21c60b7..c262cb931581 100644
--- a/sw/source/core/inc/drawfont.hxx
+++ b/sw/source/core/inc/drawfont.hxx
@@ -60,6 +60,8 @@ class SW_DLLPUBLIC SwDrawTextInfo
SwUnderlineFont* m_pUnderFnt = nullptr;
TextFrameIndex* m_pHyphPos = nullptr;
tools::Long m_nKanaDiff = 0;
+ SwTwips m_nExtraAscent = 0;
+ SwTwips m_nExtraDescent = 0;
TextFrameIndex m_nIdx;
TextFrameIndex m_nLen;
TextFrameIndex m_nMeasureLen = TextFrameIndex{ COMPLETE_STRING };
@@ -105,6 +107,8 @@ class SW_DLLPUBLIC SwDrawTextInfo
bool m_bNumberOfBlanks : 1 = false;
bool m_bUppr : 1 = false;
bool m_bDrawSp : 1 = false;
+ bool m_bExtraAscent : 1 = false;
+ bool m_bExtraDescent : 1 = false;
#endif
public:
@@ -271,6 +275,22 @@ public:
return m_nKanaDiff;
}
+ SwTwips GetExtraAscent() const
+ {
+#ifdef DBG_UTIL
+ OSL_ENSURE(m_bExtraAscent, "DrawTextInfo: Undefined extra ascent");
+#endif
+ return m_nExtraAscent;
+ }
+
+ SwTwips GetExtraDescent() const
+ {
+#ifdef DBG_UTIL
+ OSL_ENSURE(m_bExtraDescent, "DrawTextInfo: Undefined extra descent");
+#endif
+ return m_nExtraDescent;
+ }
+
sal_uInt16 GetWidth() const
{
return m_nWidth;
@@ -490,6 +510,22 @@ public:
#endif
}
+ void SetExtraAscent(SwTwips nNew)
+ {
+ m_nExtraAscent = nNew;
+#ifdef DBG_UTIL
+ m_bExtraAscent = true;
+#endif
+ }
+
+ void SetExtraDescent(SwTwips nNew)
+ {
+ m_nExtraDescent = nNew;
+#ifdef DBG_UTIL
+ m_bExtraDescent = true;
+#endif
+ }
+
void SetWidth( sal_uInt16 nNew )
{
m_nWidth = nNew;
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 4e2caf27b276..0d9a8c7ae9ff 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -1465,13 +1465,20 @@ bool SwTextFrame::FormatLine( SwTextFormatter &rLine, const bool bPrev )
rRepaint.SetRightOfst( nRght );
// Finally we enlarge the repaint rectangle if we found an underscore
- // within our line. 40 Twips should be enough
- const bool bHasUnderscore =
- ( rLine.GetInfo().GetUnderScorePos() < nNewStart );
- if ( bHasUnderscore || rLine.GetCurr()->HasUnderscore() )
- rRepaint.Bottom( rRepaint.Bottom() + 40 );
-
- const_cast<SwLineLayout*>(rLine.GetCurr())->SetUnderscore( bHasUnderscore );
+ // or another glyph extending beyond the line height within the line.
+ auto nBaseAscent = pNew->GetAscent();
+ auto nMaxExtraAscent
+ = std::max({ SwTwips{ 0 }, rLine.GetInfo().GetExtraAscent() - nBaseAscent,
+ rLine.GetCurr()->GetExtraAscent() });
+ rRepaint.Top(rRepaint.Top() - nMaxExtraAscent);
+ const_cast<SwLineLayout*>(rLine.GetCurr())->SetExtraAscent(nMaxExtraAscent);
+
+ auto nBaseDescent = pNew->Height() - pNew->GetAscent();
+ auto nMaxExtraDescent
+ = std::max({ SwTwips{ 0 }, rLine.GetInfo().GetExtraDescent() - nBaseDescent,
+ rLine.GetCurr()->GetExtraDescent() });
+ rRepaint.Bottom(rRepaint.Bottom() + nMaxExtraDescent);
+ const_cast<SwLineLayout*>(rLine.GetCurr())->SetExtraDescent(nMaxExtraDescent);
}
// Calculating the good ol' nDelta
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index c476de7110cc..f49f6fccd3d2 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -79,6 +79,7 @@ bool hasBlanksInLine(const SwTextFormatInfo& rInf, TextFrameIndex end)
bool maybeAdjustPositionsForBlockAdjust(TextFrameIndex& rCutPos, TextFrameIndex& rBreakPos,
TextFrameIndex& rBreakStart, SwTwips& rBreakWidth,
SwTwips& rExtraBlankWidth, tools::Long& rMaxSizeDiff,
+ SwTwips& rExtraAscent, SwTwips& rExtraDescent,
const SwTextFormatInfo& rInf, const SwScriptInfo& rSI,
sal_uInt16 maxComp,
std::optional<SwLinePortionLayoutContext> nLayoutContext)
@@ -141,9 +142,11 @@ bool maybeAdjustPositionsForBlockAdjust(TextFrameIndex& rCutPos, TextFrameIndex&
rBreakPos = breakPos;
rInf.GetTextSize(&rSI, rInf.GetIdx(), breakPos - rInf.GetIdx(), nLayoutContext, maxComp,
- rBreakWidth, rMaxSizeDiff, rInf.GetCachedVclData().get());
+ rBreakWidth, rMaxSizeDiff, rExtraAscent, rExtraDescent,
+ rInf.GetCachedVclData().get());
rInf.GetTextSize(&rSI, breakPos, rBreakStart - breakPos, nLayoutContext, maxComp,
- rExtraBlankWidth, rMaxSizeDiff, rInf.GetCachedVclData().get());
+ rExtraBlankWidth, rMaxSizeDiff, rExtraAscent, rExtraDescent,
+ rInf.GetCachedVclData().get());
return false; // require SwHolePortion creation
}
@@ -168,6 +171,8 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
OSL_ENSURE( nPorHeight, "+SwTextGuess::Guess: no height" );
tools::Long nMaxSizeDiff;
+ SwTwips nExtraAscent = 0;
+ SwTwips nExtraDescent = 0;
const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
@@ -249,17 +254,17 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
{
// call GetTextSize with maximum compression (for kanas)
rInf.GetTextSize(&rSI, rInf.GetIdx(), nMaxLen, rInf.GetLayoutContext(), nMaxComp,
- m_nBreakWidth, nMaxSizeDiff);
+ m_nBreakWidth, nMaxSizeDiff, nExtraAscent, nExtraDescent);
if ( ( m_nBreakWidth <= nLineWidth ) || ( bUnbreakableNumberings && rPor.IsNumberPortion() ) )
{
// portion fits to line
m_nCutPos = rInf.GetIdx() + nMaxLen;
bool bRet = rPor.InFieldGrp()
- || maybeAdjustPositionsForBlockAdjust(m_nCutPos, m_nBreakPos, m_nBreakStart,
- m_nBreakWidth, m_nExtraBlankWidth,
- nMaxSizeDiff, rInf, rSI, nMaxComp,
- rInf.GetLayoutContext());
+ || maybeAdjustPositionsForBlockAdjust(
+ m_nCutPos, m_nBreakPos, m_nBreakStart, m_nBreakWidth,
+ m_nExtraBlankWidth, nMaxSizeDiff, nExtraAscent, nExtraDescent, rInf,
+ rSI, nMaxComp, rInf.GetLayoutContext());
if( nItalic &&
(m_nCutPos >= TextFrameIndex(rInf.GetText().getLength()) ||
// #i48035# Needed for CalcFitToContent
@@ -271,6 +276,9 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
if ( nMaxSizeDiff )
rInf.SetMaxWidthDiff( &rPor, nMaxSizeDiff );
+ rInf.SetExtraAscent(nExtraAscent);
+ rInf.SetExtraDescent(nExtraDescent);
+
m_nBreakWidth += nLeftRightBorderSpace;
return bRet;
@@ -422,7 +430,7 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
{
SwTwips nMinSize;
rInf.GetTextSize(&rSI, rInf.GetIdx(), m_nCutPos - rInf.GetIdx(), std::nullopt, nMaxComp,
- nMinSize, nMaxSizeDiff);
+ nMinSize, nMaxSizeDiff, nExtraAscent, nExtraDescent);
OSL_ENSURE( nMinSize <= nLineWidth, "What a Guess!!!" );
}
#endif
@@ -433,17 +441,17 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
// second check if everything fits to line
m_nCutPos = m_nBreakPos = rInf.GetIdx() + nMaxLen - TextFrameIndex(1);
rInf.GetTextSize(&rSI, rInf.GetIdx(), nMaxLen, rInf.GetLayoutContext(), nMaxComp,
- m_nBreakWidth, nMaxSizeDiff);
+ m_nBreakWidth, nMaxSizeDiff, nExtraAscent, nExtraDescent);
// The following comparison should always give true, otherwise
// there likely has been a pixel rounding error in GetTextBreak
if ( m_nBreakWidth <= nLineWidth )
{
bool bRet = rPor.InFieldGrp()
- || maybeAdjustPositionsForBlockAdjust(m_nCutPos, m_nBreakPos, m_nBreakStart,
- m_nBreakWidth, m_nExtraBlankWidth,
- nMaxSizeDiff, rInf, rSI, nMaxComp,
- rInf.GetLayoutContext());
+ || maybeAdjustPositionsForBlockAdjust(
+ m_nCutPos, m_nBreakPos, m_nBreakStart, m_nBreakWidth,
+ m_nExtraBlankWidth, nMaxSizeDiff, nExtraAscent, nExtraDescent, rInf,
+ rSI, nMaxComp, rInf.GetLayoutContext());
if (nItalic && (m_nBreakPos + TextFrameIndex(1)) >= TextFrameIndex(rInf.GetText().getLength()))
m_nBreakWidth += nItalic;
@@ -452,6 +460,9 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
if ( nMaxSizeDiff )
rInf.SetMaxWidthDiff( &rPor, nMaxSizeDiff );
+ rInf.SetExtraAscent(nExtraAscent);
+ rInf.SetExtraDescent(nExtraDescent);
+
m_nBreakWidth += nLeftRightBorderSpace;
return bRet;
@@ -736,12 +747,15 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
if( nPorLen )
{
rInf.GetTextSize(&rSI, rInf.GetIdx(), nPorLen, std::nullopt, nMaxComp, m_nBreakWidth,
- nMaxSizeDiff, rInf.GetCachedVclData().get());
+ nMaxSizeDiff, nExtraAscent, nExtraDescent, rInf.GetCachedVclData().get());
// save maximum width for later use
if ( nMaxSizeDiff )
rInf.SetMaxWidthDiff( &rPor, nMaxSizeDiff );
+ rInf.SetExtraAscent(nExtraAscent);
+ rInf.SetExtraDescent(nExtraDescent);
+
m_nBreakWidth += nItalic + nLeftRightBorderSpace;
}
else
@@ -751,7 +765,8 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf,
{
rInf.GetTextSize(&rSI, rInf.GetIdx() + nPorLen,
m_nBreakStart - rInf.GetIdx() - nPorLen - m_nFieldDiff, std::nullopt,
- nMaxComp, m_nExtraBlankWidth, nMaxSizeDiff, rInf.GetCachedVclData().get());
+ nMaxComp, m_nExtraBlankWidth, nMaxSizeDiff, nExtraAscent, nExtraDescent,
+ rInf.GetCachedVclData().get());
}
if( m_pHanging )
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 40b113fa41da..25bd4578e025 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -86,7 +86,6 @@ using namespace ::com::sun::star::linguistic2;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
-#define CHAR_UNDERSCORE u'_'
#define CHAR_LEFT_ARROW u'\x25C0'
#define CHAR_RIGHT_ARROW u'\x25B6'
#define CHAR_TAB u'\x2192'
@@ -438,7 +437,8 @@ void SwTextSizeInfo::GetTextSize(const SwScriptInfo* pSI, const TextFrameIndex n
const TextFrameIndex nLength,
std::optional<SwLinePortionLayoutContext> nLayoutContext,
const sal_uInt16 nComp, SwTwips& nMinSize,
- tools::Long& nMaxSizeDiff,
+ tools::Long& nMaxSizeDiff, SwTwips& nExtraAscent,
+ SwTwips& nExtraDescent,
vcl::text::TextLayoutCache const* const pCache) const
{
SwDrawTextInfo aDrawInf(m_pVsh, *m_pOut, pSI, *m_pText, nIndex, nLength, nLayoutContext, 0,
@@ -449,6 +449,8 @@ void SwTextSizeInfo::GetTextSize(const SwScriptInfo* pSI, const TextFrameIndex n
aDrawInf.SetKanaComp( nComp );
SwPosSize aSize( m_pFnt->GetTextSize_( aDrawInf ) );
nMaxSizeDiff = aDrawInf.GetKanaDiff();
+ nExtraAscent = aDrawInf.GetExtraAscent();
+ nExtraDescent = aDrawInf.GetExtraDescent();
nMinSize = aSize.Width();
}
@@ -1624,6 +1626,8 @@ void SwTextFormatInfo::CtorInitTextFormatInfo( OutputDevice* pRenderContext, SwT
m_nFirst = 0;
m_nRealWidth = 0;
m_nForcedLeftMargin = 0;
+ m_nExtraAscent = 0;
+ m_nExtraDescent = 0;
m_pRest = nullptr;
m_nLineHeight = 0;
m_nLineNetHeight = 0;
@@ -1722,8 +1726,9 @@ void SwTextFormatInfo::Init()
m_cTabDecimal = 0;
m_nWidth = m_nRealWidth;
m_nForcedLeftMargin = 0;
+ m_nExtraAscent = 0;
+ m_nExtraDescent = 0;
m_nSoftHyphPos = TextFrameIndex(0);
- m_nUnderScorePos = TextFrameIndex(COMPLETE_STRING);
m_nLastBookmarkPos = TextFrameIndex(-1);
m_cHookChar = 0;
SetIdx(TextFrameIndex(0));
@@ -1756,7 +1761,6 @@ SwTextFormatInfo::SwTextFormatInfo( const SwTextFormatInfo& rInf,
m_pLastTab(nullptr),
m_nSoftHyphPos(TextFrameIndex(0)),
m_nLineStart(rInf.GetIdx()),
- m_nUnderScorePos(TextFrameIndex(COMPLETE_STRING)),
m_nLeft(rInf.m_nLeft),
m_nRight(rInf.m_nRight),
m_nFirst(rInf.m_nLeft),
@@ -1765,6 +1769,8 @@ SwTextFormatInfo::SwTextFormatInfo( const SwTextFormatInfo& rInf,
m_nLineHeight(0),
m_nLineNetHeight(0),
m_nForcedLeftMargin(0),
+ m_nExtraAscent(0),
+ m_nExtraDescent(0),
m_bFull(false),
m_bFootnoteDone(true),
m_bErgoDone(true),
@@ -1875,11 +1881,6 @@ TextFrameIndex SwTextFormatInfo::ScanPortionEnd(TextFrameIndex const nStart,
m_cHookChar = cPos;
return i;
- case CHAR_UNDERSCORE:
- if (TextFrameIndex(COMPLETE_STRING) == m_nUnderScorePos)
- m_nUnderScorePos = i;
- break;
-
default:
if ( cTabDec )
{
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 4cc49a0e3e57..4a79177366c9 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -254,6 +254,7 @@ public:
void GetTextSize(const SwScriptInfo* pSI, TextFrameIndex nIdx, TextFrameIndex nLen,
std::optional<SwLinePortionLayoutContext> nLayoutContext,
const sal_uInt16 nComp, SwTwips& nMinSize, tools::Long& nMaxSizeDiff,
+ SwTwips& nExtraAscent, SwTwips& nExtraDescent,
vcl::text::TextLayoutCache const* = nullptr) const;
inline SwPosSize GetTextSize(const SwScriptInfo* pSI, TextFrameIndex nIdx,
TextFrameIndex nLen) const;
@@ -493,7 +494,6 @@ class SwTextFormatInfo : public SwTextPaintInfo
TextFrameIndex m_nSoftHyphPos; ///< SoftHyphPos for Hyphenation
TextFrameIndex m_nLineStart; ///< Current line start in rText
- TextFrameIndex m_nUnderScorePos; ///< enlarge repaint if underscore has been found
TextFrameIndex m_nLastBookmarkPos; ///< need to check for bookmarks at every portion
// #i34348# Changed type from sal_uInt16 to SwTwips
SwTwips m_nLeft; // Left margin
@@ -506,6 +506,8 @@ class SwTextFormatInfo : public SwTextPaintInfo
SwTwips m_nLineHeight; // Final height after CalcLine
SwTwips m_nLineNetHeight; // line height without spacing
SwTwips m_nForcedLeftMargin; // Shift of left margin due to frame
+ SwTwips m_nExtraAscent = 0; // Enlarge clipping area for glyphs above the line height
+ SwTwips m_nExtraDescent = 0; // Enlarge clipping area for glyphs below the line height
bool m_bFull : 1; // Line is full
bool m_bFootnoteDone : 1; // Footnote already formatted
@@ -678,8 +680,12 @@ public:
// Should the hyphenate helper be discarded?
bool IsHyphenate() const;
- TextFrameIndex GetUnderScorePos() const { return m_nUnderScorePos; }
- void SetUnderScorePos(TextFrameIndex const nNew) { m_nUnderScorePos = nNew; }
+
+ SwTwips GetExtraAscent() const { return m_nExtraAscent; }
+ void SetExtraAscent(SwTwips nNew) { m_nExtraAscent = std::max(m_nExtraAscent, nNew); }
+
+ SwTwips GetExtraDescent() const { return m_nExtraDescent; }
+ void SetExtraDescent(SwTwips nNew) { m_nExtraDescent = std::max(m_nExtraDescent, nNew); }
// Calls HyphenateWord() of Hyphenator
css::uno::Reference< css::linguistic2::XHyphenatedWord >
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 9d8e9ae0b77a..430e8d9aa778 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -177,7 +177,6 @@ SwLinePortion *SwTextFormatter::Underflow( SwTextFormatInfo &rInf )
// Can be seen in 8081.sdw, if you enter text in the first line
TextFrameIndex const nSoftHyphPos = rInf.GetSoftHyphPos();
- TextFrameIndex const nUnderScorePos = rInf.GetUnderScorePos();
// Save flys and set to 0, or else segmentation fault
// Not ClearFly(rInf) !
@@ -190,7 +189,6 @@ SwLinePortion *SwTextFormatter::Underflow( SwTextFormatInfo &rInf )
// Truncate()
rInf.SetUnderflow(nullptr);
rInf.SetSoftHyphPos( nSoftHyphPos );
- rInf.SetUnderScorePos( nUnderScorePos );
rInf.SetPaintOfst( GetLeftMargin() );
// We look for the portion with the under-flow position
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
index f02beed8ce5b..2a19650acb92 100644
--- a/sw/source/core/text/itrpaint.cxx
+++ b/sw/source/core/text/itrpaint.cxx
@@ -222,7 +222,7 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
{
bClip = false;
- rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
+ rClip.ChgClip(rPaint, m_pFrame, m_pCurr->GetExtraAscent(), m_pCurr->GetExtraDescent());
}
#if OSL_DEBUG_LEVEL > 1
static bool bClipAlways = false;
@@ -255,7 +255,7 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
// tdf#117448 at small fixed line height, enlarge clipping area in table cells
// to show previously clipped text content on the area of paragraph margins
if ( rFrame.IsInTab() )
- rClip.ChgClip( aLineRect, m_pFrame, false, rFrame.GetTopMargin(), rFrame.GetBottomMargin() );
+ rClip.ChgClip(aLineRect, m_pFrame, rFrame.GetTopMargin(), rFrame.GetBottomMargin());
else
rClip.ChgClip( aLineRect, m_pFrame );
bClip = false;
@@ -377,7 +377,7 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
{
bClip = false;
- rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
+ rClip.ChgClip(rPaint, m_pFrame, m_pCurr->GetExtraAscent(), m_pCurr->GetExtraDescent());
}
// Portions, which lay "below" the text like post-its
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index 6e8cfa4a3770..459486b99ba5 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -337,10 +337,6 @@ bool SwFieldPortion::Format( SwTextFormatInfo &rInf )
}
rInf.SetLen( nFullLen );
- if (TextFrameIndex(COMPLETE_STRING) != rInf.GetUnderScorePos() &&
- rInf.GetUnderScorePos() > rInf.GetIdx() )
- rInf.SetUnderScorePos( rInf.GetIdx() );
-
if( m_pFont )
m_pFont->AllocFontCacheId( rInf.GetVsh(), m_pFont->GetActual() );
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 44f709eec1f1..bb33c11bf8b4 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -844,8 +844,7 @@ void SwLineLayout::ResetFlags()
SwLineLayout::SwLineLayout()
: m_pNext( nullptr ),
m_nRealHeight( 0 ),
- m_nTextHeight( 0 ),
- m_bUnderscore( false )
+ m_nTextHeight( 0 )
{
ResetFlags();
SetWhichPor( PortionType::Lay );
diff --git a/sw/source/core/text/porlay.hxx b/sw/source/core/text/porlay.hxx
index fe8aeb861e50..3d0ce27e3884 100644
--- a/sw/source/core/text/porlay.hxx
+++ b/sw/source/core/text/porlay.hxx
@@ -83,6 +83,8 @@ private:
std::unique_ptr<std::deque<sal_uInt16>> m_pKanaComp; // Used for Kana compression
SwTwips m_nRealHeight; // The height resulting from line spacing and register
SwTwips m_nTextHeight; // The max height of all non-FlyCnt portions in this Line
+ SwTwips m_nExtraAscent = 0;
+ SwTwips m_nExtraDescent = 0;
bool m_bFormatAdj : 1;
bool m_bDummy : 1;
bool m_bEndHyph : 1;
@@ -97,7 +99,6 @@ private:
bool m_bRedlineEnd: 1; // Redlining for paragraph mark: tracked change at the end
bool m_bForcedLeftMargin : 1; // Left adjustment moved by the Fly
bool m_bHanging : 1; // Contains a hanging portion in the margin
- bool m_bUnderscore : 1;
enum RedlineType m_eRedlineEnd; // redline type of pilcrow and line break symbols
@@ -146,8 +147,6 @@ public:
bool HasForcedLeftMargin() const { return m_bForcedLeftMargin; }
void SetHanging( const bool bNew ) { m_bHanging = bNew; }
bool IsHanging() const { return m_bHanging; }
- void SetUnderscore( const bool bNew ) { m_bUnderscore = bNew; }
- bool HasUnderscore() const { return m_bUnderscore; }
// Respecting empty dummy lines
void SetDummy( const bool bNew ) { m_bDummy = bNew; }
@@ -173,6 +172,12 @@ public:
SwTwips GetTextHeight() const { return m_nTextHeight; }
+ void SetExtraAscent(SwTwips nNew) { m_nExtraAscent = nNew; }
+ SwTwips GetExtraAscent() const { return m_nExtraAscent; }
+
+ void SetExtraDescent(SwTwips nNew) { m_nExtraDescent = nNew; }
+ SwTwips GetExtraDescent() const { return m_nExtraDescent; }
+
// Creates the glue chain for short lines
SwMarginPortion *CalcLeftMargin();
diff --git a/sw/source/core/text/txtpaint.cxx b/sw/source/core/text/txtpaint.cxx
index ccd9647bd99c..5b05b413fab9 100644
--- a/sw/source/core/text/txtpaint.cxx
+++ b/sw/source/core/text/txtpaint.cxx
@@ -41,7 +41,6 @@ SwSaveClip::~SwSaveClip()
}
void SwSaveClip::ChgClip_( const SwRect &rRect, const SwTextFrame* pFrame,
- bool bEnlargeRect,
sal_Int32 nEnlargeTop,
sal_Int32 nEnlargeBottom )
{
@@ -74,12 +73,6 @@ void SwSaveClip::ChgClip_( const SwRect &rRect, const SwTextFrame* pFrame,
{
tools::Rectangle aRect( rRect.SVRect() );
- // Having underscores in our line, we enlarged the repaint area
- // (see frmform.cxx) because for some fonts it could be too small.
- // Consequently, we have to enlarge the clipping rectangle as well.
- if ( bEnlargeRect && ! bVertical )
- aRect.AdjustBottom(40 );
-
// enlarge clip for paragraph margins at small fixed line height
if ( nEnlargeTop > 0 )
aRect.AdjustTop( -nEnlargeTop );
diff --git a/sw/source/core/text/txtpaint.hxx b/sw/source/core/text/txtpaint.hxx
index 1f9700af4c96..3554a2421415 100644
--- a/sw/source/core/text/txtpaint.hxx
+++ b/sw/source/core/text/txtpaint.hxx
@@ -32,7 +32,6 @@ class SwSaveClip final
VclPtr<OutputDevice> m_pOut;
void ChgClip_( const SwRect &rRect, const SwTextFrame* pFrame,
- bool bEnlargeRect,
sal_Int32 nEnlargeTop,
sal_Int32 nEnlargeBottom );
public:
@@ -44,12 +43,14 @@ public:
}
~SwSaveClip();
- void ChgClip( const SwRect &rRect, const SwTextFrame* pFrame = nullptr,
- bool bEnlargeRect = false,
- sal_Int32 nEnlargeTop = 0,
- sal_Int32 nEnlargeBottom = 0)
- { if( m_pOut ) ChgClip_( rRect, pFrame,
- bEnlargeRect, nEnlargeTop, nEnlargeBottom ); }
+ void ChgClip(const SwRect& rRect, const SwTextFrame* pFrame = nullptr,
+ sal_Int32 nEnlargeTop = 0, sal_Int32 nEnlargeBottom = 0)
+ {
+ if (m_pOut)
+ {
+ ChgClip_(rRect, pFrame, nEnlargeTop, nEnlargeBottom);
+ }
+ }
bool IsOn() const { return m_bOn; }
bool IsChg() const { return m_bChg; }
};
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index fd42378b1bdc..52a9e71dff1d 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -745,9 +745,12 @@ static void lcl_DrawLineForWrongListData(
static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, KernArray& rDXAry,
sal_Int32 nIndex, sal_Int32 nLen,
std::optional<SwLinePortionLayoutContext> nLayoutContext,
+ SwTwips* nMaxAscent = nullptr, SwTwips* nMaxDescent = nullptr,
bool bCaret = false,
const vcl::text::TextLayoutCache* layoutCache = nullptr)
{
+ vcl::TextArrayMetrics stMetrics;
+
if (nLayoutContext.has_value())
{
auto nStrEnd = nIndex + nLen;
@@ -757,14 +760,28 @@ static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, Kern
const SalLayoutGlyphs* pLayoutCache = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
&rDevice, rStr, nContextBegin, nContextLen, nIndex, nIndex + nLen, 0, layoutCache);
- rDevice.GetPartialTextArray(rStr, &rDXAry, nContextBegin, nContextLen, nIndex, nLen, bCaret,
- layoutCache, pLayoutCache);
+ stMetrics = rDevice.GetPartialTextArray(rStr, &rDXAry, nContextBegin, nContextLen, nIndex,
+ nLen, bCaret, layoutCache, pLayoutCache);
}
else
{
const SalLayoutGlyphs* pLayoutCache = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
&rDevice, rStr, nIndex, nLen, 0, layoutCache);
- rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, bCaret, layoutCache, pLayoutCache);
+ stMetrics
+ = rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, bCaret, layoutCache, pLayoutCache);
+ }
+
+ if (stMetrics.aBounds.has_value())
+ {
+ if (nMaxAscent)
+ {
+ *nMaxAscent = static_cast<SwTwips>(std::ceil(-stMetrics.aBounds->Top()));
+ }
+
+ if (nMaxDescent)
+ {
+ *nMaxDescent = static_cast<SwTwips>(std::ceil(stMetrics.aBounds->Bottom()));
+ }
}
}
@@ -772,16 +789,16 @@ static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo
KernArray& rDXAry, bool bCaret = false)
{
GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), rInf.GetLen().get(),
- rInf.GetLayoutContext(), bCaret, rInf.GetVclCache());
+ rInf.GetLayoutContext(), nullptr, nullptr, bCaret, rInf.GetVclCache());
}
static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf,
- KernArray& rDXAry, sal_Int32 nLen, bool bCaret = false)
+ KernArray& rDXAry, sal_Int32 nLen, SwTwips *nMaxAscent = nullptr, SwTwips *nMaxDescent = nullptr, bool bCaret = false)
{
// Substring is fine.
assert(nLen <= rInf.GetLen().get());
GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), nLen,
- rInf.GetLayoutContext(), bCaret, rInf.GetVclCache());
+ rInf.GetLayoutContext(), nMaxAscent, nMaxDescent, bCaret, rInf.GetVclCache());
}
static void DrawTextArray(OutputDevice& rOutputDevice, const Point& rStartPt, const OUString& rStr,
@@ -1581,6 +1598,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
{
Size aTextSize;
+ SwTwips nMaxAscent = 0;
+ SwTwips nMaxDescent = 0;
const TextFrameIndex nLn = (TextFrameIndex(COMPLETE_STRING) != rInf.GetLen())
? rInf.GetLen()
: TextFrameIndex(rInf.GetText().getLength());
@@ -1631,7 +1650,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
GetFontLeading( rInf.GetShell(), rInf.GetOut() ) );
KernArray aKernArray;
- GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(nLn), bCaret);
+ GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(nLn), &nMaxAscent, &nMaxDescent,
+ bCaret);
if (pGrid->IsSnapToChars())
{
sw::Justify::SnapToGrid(aKernArray, rInf.GetText(), sal_Int32(rInf.GetIdx()),
@@ -1674,7 +1694,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
rInf.GetOut().SetFont( *m_pScrFont );
GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, sal_Int32(rInf.GetIdx()),
- sal_Int32(nLn), rInf.GetLayoutContext(), bCaret);
+ sal_Int32(nLn), rInf.GetLayoutContext(), &nMaxAscent, &nMaxDescent, bCaret);
}
else
{
@@ -1682,9 +1702,12 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
rInf.GetOut().SetFont( *m_pPrtFont );
aTextSize.setHeight( rInf.GetOut().GetTextHeight() );
- GetTextArray(rInf.GetOut(), rInf, aKernArray, nLn.get(), bCaret);
+ GetTextArray(rInf.GetOut(), rInf, aKernArray, nLn.get(), &nMaxAscent, &nMaxDescent, bCaret);
}
+ rInf.SetExtraAscent(std::max(SwTwips{ 0 }, nMaxAscent));
+ rInf.SetExtraDescent(std::max(SwTwips{ 0 }, nMaxDescent));
+
if (bCompress)
{
rInf.SetKanaDiff(rInf.GetScriptInfo()->Compress(aKernArray, rInf.GetIdx(), nLn, rInf.GetKanaComp(),
diff --git a/toolkit/source/awt/vclxfont.cxx b/toolkit/source/awt/vclxfont.cxx
index 47fad780d73b..32a42dec7579 100644
--- a/toolkit/source/awt/vclxfont.cxx
+++ b/toolkit/source/awt/vclxfont.cxx
@@ -153,7 +153,7 @@ sal_Int32 VCLXFont::getStringWidthArray( const OUString& str, css::uno::Sequence
vcl::Font aOldFont = pOutDev->GetFont();
pOutDev->SetFont( maFont );
KernArray aDXA;
- nRet = basegfx::fround(pOutDev->GetTextArray(str, &aDXA));
+ nRet = basegfx::fround(pOutDev->GetTextArray(str, &aDXA).nWidth);
rDXArray.realloc(aDXA.size());
sal_Int32* pArray = rDXArray.getArray();
for (size_t i = 0, nLen = aDXA.size(); i < nLen; ++i)
diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx
index 24958c0b0637..b7a04d98ad80 100644
--- a/vcl/qa/cppunit/complextext.cxx
+++ b/vcl/qa/cppunit/complextext.cxx
@@ -86,7 +86,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testArabic)
3899, 4550, 5119, 5689, 5689, 6307, 6925, 8484, 9135, 9705, 10927,
10927, 11497, 12595, 12595 };
KernArray aCharWidths;
- tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aOneTwoThree, &aCharWidths));
+ tools::Long nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aOneTwoThree, &aCharWidths).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
// this sporadically returns 75 or 74 on some of the windows tinderboxes eg. tb73
@@ -267,7 +268,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testCaret)
// and the next ones are all zero width.
nRefTextWidth = 3611;
aRefCharWidths = { 1168, 1168, 1819, 2389, 3611, 3611 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ false).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -275,7 +277,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testCaret)
// 2) Caret placement DX array, ligature width is distributed over its
// components.
aRefCharWidths = { 584, 1168, 1819, 2389, 3000, 3611 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -284,7 +287,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testCaret)
// component count.
aText = u"لَاَ بلَاَ"_ustr;
aRefCharWidths = { 584, 584, 1168, 1168, 1819, 2389, 3000, 3000, 3611, 3611 };
- nTextWidth2 = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth2 = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aCharWidths[0], aCharWidths[1]);
CPPUNIT_ASSERT_EQUAL(aCharWidths[2], aCharWidths[3]);
CPPUNIT_ASSERT_EQUAL(aCharWidths[6], aCharWidths[7]);
@@ -301,7 +305,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testCaret)
// and the next ones are all zero width.
nRefTextWidth = 8493;
aRefCharWidths = { 1290, 1290, 1941, 3231, 3231, 3882, 5862, 5862, 5862, 6513, 8493, 8493, 8493 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ false).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -309,7 +314,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testCaret)
// 2) Caret placement DX array, ligature width is distributed over its
// components.
aRefCharWidths = { 645, 1290, 1941, 2586, 3231, 3882, 4542, 5202, 5862, 6513, 7173, 7833, 8493 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -340,7 +346,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testGdefCaret)
// and the next ones are all zero width.
nRefTextWidth = 1710;
aRefCharWidths= { 582, 582, 842, 1111, 1710, 1710 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ false).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -348,7 +355,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testGdefCaret)
// 2) Caret placement DX array, ligature width is distributed over its
// components.
aRefCharWidths = { 291, 582, 842, 1111, 1410, 1710 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -357,7 +365,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testGdefCaret)
// component count.
aText = u"لَاَ بلَاَ"_ustr;
aRefCharWidths = { 291, 291, 582, 582, 842, 1111, 1410, 1410, 1710, 1710 };
- nTextWidth2 = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth2 = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aCharWidths[0], aCharWidths[1]);
CPPUNIT_ASSERT_EQUAL(aCharWidths[2], aCharWidths[3]);
CPPUNIT_ASSERT_EQUAL(aCharWidths[6], aCharWidths[7]);
@@ -379,7 +388,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testGdefCaret)
nRefTextWidth = 5996;
aRefCharWidths = { 519, 519, 811, 1606, 1606, 1606, 1898, 2439, 2439, 2731,
3544, 3544, 3544, 3836, 4634, 4634, 4926, 5996, 5996, 5996 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ false).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -388,7 +398,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testGdefCaret)
// components.
aRefCharWidths = { 269, 519, 811, 1080, 1348, 1606, 1898, 2171, 2439, 2731,
3004, 3278, 3544, 3836, 4138, 4634, 4926, 5199, 5494, 5996 };
- nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true));
+ nTextWidth = basegfx::fround<tools::Long>(
+ pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/ true).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back());
@@ -410,7 +421,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf152048)
tools::Long nRefTextWidth(5495);
KernArray aCharWidths;
- tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths));
+ tools::Long nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aText, &aCharWidths).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
@@ -443,7 +455,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf152048_2)
// get an compare the default text array
KernArray aCharWidths;
- auto nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(u"ع a ع"_ustr, &aCharWidths));
+ auto nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(u"ع a ع"_ustr, &aCharWidths).nWidth);
// Text width should always be equal to the width of the last glyph in the
// kern array.
@@ -514,7 +527,8 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testMixedCJKLatinScript_glyph_advanceme
tools::Long nRefTextWidth = 704;
std::vector<sal_Int32> aRefCharWidths = { 72, 144, 190, 236, 259, 305, 333, 379, 425, 474, 523, 551, 567, 612, 658, 704 };
KernArray aCharWidths;
- tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aTestScript, &aCharWidths));
+ tools::Long nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aTestScript, &aCharWidths).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array());
CPPUNIT_ASSERT_EQUAL(nRefTextWidth, nTextWidth);
@@ -621,7 +635,7 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testPartialKoreanJamoComposition)
// Absolute character widths for the complete array.
KernArray aCompleteWidths;
- auto nCompleteWidth = pOutDev->GetTextArray(aStr, &aCompleteWidths);
+ auto nCompleteWidth = pOutDev->GetTextArray(aStr, &aCompleteWidths).nWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 3 }, aCompleteWidths.size());
@@ -632,8 +646,11 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testPartialKoreanJamoComposition)
for (sal_Int32 i = 0; i < 3; ++i)
{
KernArray aFragmentWidths;
- auto nFragmentWidth = pOutDev->GetPartialTextArray(
- aStr, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 3, /*nPartIndex*/ i, /*nPartLen*/ 1);
+ auto nFragmentWidth
+ = pOutDev
+ ->GetPartialTextArray(aStr, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 3,
+ /*nPartIndex*/ i, /*nPartLen*/ 1)
+ .nWidth;
nPartialWidth += nFragmentWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 1 }, aFragmentWidths.size());
@@ -654,7 +671,7 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testPartialArabicComposition)
// Absolute character widths for the complete array.
KernArray aCompleteWidths;
- auto nCompleteWidth = pOutDev->GetTextArray(aStr, &aCompleteWidths);
+ auto nCompleteWidth = pOutDev->GetTextArray(aStr, &aCompleteWidths).nWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 7 }, aCompleteWidths.size());
@@ -665,8 +682,11 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testPartialArabicComposition)
for (sal_Int32 i = 0; i < 7; ++i)
{
KernArray aFragmentWidths;
- auto nFragmentWidth = pOutDev->GetPartialTextArray(
- aStr, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 7, /*nPartIndex*/ i, /*nPartLen*/ 1);
+ auto nFragmentWidth
+ = pOutDev
+ ->GetPartialTextArray(aStr, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 7,
+ /*nPartIndex*/ i, /*nPartLen*/ 1)
+ .nWidth;
nPartialWidth += nFragmentWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 1 }, aFragmentWidths.size());
diff --git a/vcl/qa/cppunit/text.cxx b/vcl/qa/cppunit/text.cxx
index b8847f5c6247..3cf88138eb29 100644
--- a/vcl/qa/cppunit/text.cxx
+++ b/vcl/qa/cppunit/text.cxx
@@ -242,7 +242,8 @@ CPPUNIT_TEST_FIXTURE(VclTextTest, testSimpleTextFontSpecificKerning)
tools::Long nRefTextWidth = 2671;
std::vector<sal_Int32> aRefCharWidths = { 1270, 2671 };
KernArray aCharWidths;
- tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aAV, &aCharWidths));
+ tools::Long nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aAV, &aCharWidths).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths[0], aCharWidths.get_subunit_array()[0]);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths[1], aCharWidths.get_subunit_array()[1]);
@@ -291,7 +292,8 @@ CPPUNIT_TEST_FIXTURE(VclTextTest, testSimpleTextNoKerning)
tools::Long nRefTextWidth = 2802;
std::vector<sal_Int32> aRefCharWidths = { 1401, 2802 };
KernArray aCharWidths;
- tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aAV, &aCharWidths));
+ tools::Long nTextWidth
+ = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aAV, &aCharWidths).nWidth);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths[0], aCharWidths.get_subunit_array()[0]);
CPPUNIT_ASSERT_EQUAL(aRefCharWidths[1], aCharWidths.get_subunit_array()[1]);
@@ -1029,7 +1031,7 @@ CPPUNIT_TEST_FIXTURE(VclTextTest, testPartialTextArraySizeMatch)
// Absolute character widths for the complete array.
KernArray aCompleteWidths;
- auto nCompleteWidth = pOutDev->GetTextArray(aWater, &aCompleteWidths);
+ auto nCompleteWidth = pOutDev->GetTextArray(aWater, &aCompleteWidths).nWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 5 }, aCompleteWidths.size());
@@ -1040,8 +1042,11 @@ CPPUNIT_TEST_FIXTURE(VclTextTest, testPartialTextArraySizeMatch)
for (sal_Int32 i = 0; i < 5; ++i)
{
KernArray aFragmentWidths;
- auto nFragmentWidth = pOutDev->GetPartialTextArray(
- aWater, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 5, /*nPartIndex*/ i, /*nPartLen*/ 1);
+ auto nFragmentWidth
+ = pOutDev
+ ->GetPartialTextArray(aWater, &aFragmentWidths, /*nIndex*/ 0, /*nLen*/ 5,
+ /*nPartIndex*/ i, /*nPartLen*/ 1)
+ .nWidth;
nPartialWidth += nFragmentWidth;
CPPUNIT_ASSERT_EQUAL(size_t{ 1 }, aFragmentWidths.size());
diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx
index 3b349b9f70ac..92a2320369c1 100644
--- a/vcl/source/filter/wmf/emfwr.cxx
+++ b/vcl/source/filter/wmf/emfwr.cxx
@@ -882,7 +882,7 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, K
}
else
{
- nNormWidth = basegfx::fround<sal_uInt32>(maVDev->GetTextArray(rText, &aOwnArray));
+ nNormWidth = basegfx::fround<sal_uInt32>(maVDev->GetTextArray(rText, &aOwnArray).nWidth);
pDX = aOwnArray;
}
diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx
index 3f975ec5e659..70b00a895720 100644
--- a/vcl/source/filter/wmf/wmfwr.cxx
+++ b/vcl/source/filter/wmf/wmfwr.cxx
@@ -1198,7 +1198,8 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
pVirDev->SetFont( aSrcFont );
const sal_Int32 nLen = aTemp.getLength();
KernArray aDXAry;
- const sal_Int32 nNormSize = basegfx::fround(pVirDev->GetTextArray( aTemp, nLen ? &aDXAry : nullptr ));
+ const sal_Int32 nNormSize = basegfx::fround(
+ pVirDev->GetTextArray(aTemp, nLen ? &aDXAry : nullptr).nWidth);
if (nLen && nNormSize == 0)
{
OSL_FAIL("Impossible div by 0 action: MetaStretchTextAction!");
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 5c5edd3b0612..d0bdd7ccf68f 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -650,7 +650,7 @@ double OutputDevice::GetTextWidthDouble(const OUString& rStr, sal_Int32 nIndex,
vcl::text::TextLayoutCache const* const pLayoutCache,
SalLayoutGlyphs const* const pSalLayoutCache) const
{
- return GetTextArray(rStr, nullptr, nIndex, nLen, false, pLayoutCache, pSalLayoutCache);
+ return GetTextArray(rStr, nullptr, nIndex, nLen, false, pLayoutCache, pSalLayoutCache).nWidth;
}
tools::Long OutputDevice::GetTextHeight() const
@@ -781,27 +781,26 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, flags );
}
-double OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernArray,
- sal_Int32 nIndex, sal_Int32 nLen, bool bCaret,
- vcl::text::TextLayoutCache const*const pLayoutCache,
- SalLayoutGlyphs const*const pSalLayoutCache) const
+vcl::TextArrayMetrics
+OutputDevice::GetTextArray(const OUString& rStr, KernArray* pKernArray, sal_Int32 nIndex,
+ sal_Int32 nLen, bool bCaret,
+ vcl::text::TextLayoutCache const* const pLayoutCache,
+ SalLayoutGlyphs const* const pSalLayoutCache) const
{
return GetPartialTextArray(rStr, pKernArray, nIndex, nLen, nIndex, nLen, bCaret, pLayoutCache,
pSalLayoutCache);
}
-double OutputDevice::GetPartialTextArray(const OUString &rStr,
- KernArray* pKernArray,
- sal_Int32 nIndex,
- sal_Int32 nLen,
- sal_Int32 nPartIndex,
- sal_Int32 nPartLen,
- bool bCaret,
- const vcl::text::TextLayoutCache* pLayoutCache,
- const SalLayoutGlyphs* pSalLayoutCache) const
+vcl::TextArrayMetrics
+OutputDevice::GetPartialTextArray(const OUString& rStr, KernArray* pKernArray, sal_Int32 nIndex,
+ sal_Int32 nLen, sal_Int32 nPartIndex, sal_Int32 nPartLen,
+ bool bCaret, const vcl::text::TextLayoutCache* pLayoutCache,
+ const SalLayoutGlyphs* pSalLayoutCache) const
{
- if( nIndex >= rStr.getLength() )
- return 0; // TODO: this looks like a buggy caller?
+ if (nIndex >= rStr.getLength())
+ {
+ return {}; // TODO: this looks like a buggy caller?
+ }
if( nLen < 0 || nIndex + nLen >= rStr.getLength() )
{
@@ -844,7 +843,8 @@ double OutputDevice::GetPartialTextArray(const OUString &rStr,
pDXAry->resize(nPartLen);
std::fill(pDXAry->begin(), pDXAry->end(), 0);
}
- return 0;
+
+ return {};
}
std::unique_ptr<std::vector<double>> xDXPixelArray;
@@ -902,7 +902,18 @@ double OutputDevice::GetPartialTextArray(const OUString &rStr,
(*pDXAry)[i] = basegfx::fround((*pDXPixelArray)[i]);
}
- return ImplDevicePixelToLogicWidthDouble(nWidth);
+ vcl::TextArrayMetrics stReturnValue;
+
+ basegfx::B2DRectangle stRect;
+ if (pSalLayout->GetBoundRect(stRect))
+ {
+ auto stRect2 = SalLayout::BoundRect2Rectangle(stRect);
+ stReturnValue.aBounds = ImplDevicePixelToLogic(stRect2);
+ }
+
+ stReturnValue.nWidth = ImplDevicePixelToLogicWidthDouble(nWidth);
+
+ return stReturnValue;
}
void OutputDevice::GetCaretPositions( const OUString& rStr, KernArray& rCaretXArray,
diff --git a/vcl/source/text/textlayout.cxx b/vcl/source/text/textlayout.cxx
index d43549a589d3..5621a9d4c1f6 100644
--- a/vcl/source/text/textlayout.cxx
+++ b/vcl/source/text/textlayout.cxx
@@ -486,7 +486,8 @@ namespace vcl
tools::Long DefaultTextLayout::GetTextArray( const OUString& _rText, KernArray* _pDXArray,
sal_Int32 _nStartIndex, sal_Int32 _nLength, bool bCaret ) const
{
- return basegfx::fround<tools::Long>(m_rTargetDevice.GetTextArray( _rText, _pDXArray, _nStartIndex, _nLength, bCaret ));
+ return basegfx::fround<tools::Long>(
+ m_rTargetDevice.GetTextArray(_rText, _pDXArray, _nStartIndex, _nLength, bCaret).nWidth);
}
sal_Int32 DefaultTextLayout::GetTextBreak( const OUString& _rText, tools::Long _nMaxTextWidth, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const
@@ -594,7 +595,9 @@ namespace vcl
return 0;
// retrieve the character widths from the reference device
- tools::Long nTextWidth = basegfx::fround<tools::Long>(m_rReferenceDevice.GetTextArray( _rText, _pDXAry, _nStartIndex, _nLength, bCaret ));
+ tools::Long nTextWidth = basegfx::fround<tools::Long>(
+ m_rReferenceDevice.GetTextArray(_rText, _pDXAry, _nStartIndex, _nLength, bCaret)
+ .nWidth);
#if OSL_DEBUG_LEVEL > 1
if ( _pDXAry )
{