sw/source/core/inc/fntcache.hxx | 3 +++ sw/source/core/inc/swfont.hxx | 4 ++++ sw/source/core/text/inftxt.hxx | 7 +++++++ sw/source/core/text/itrform2.cxx | 3 +++ sw/source/core/text/itrpaint.cxx | 2 +- sw/source/core/text/itrtxt.cxx | 9 ++++++++- sw/source/core/text/porlin.cxx | 1 + sw/source/core/text/porlin.hxx | 5 +++++ sw/source/core/txtnode/fntcache.cxx | 17 +++++++++++++++++ sw/source/core/txtnode/swfont.cxx | 6 ++++++ 10 files changed, 55 insertions(+), 2 deletions(-)
New commits: commit fb8eb0ad9c3a5957a6e131490a7a8c97e5353ba2 Author: Mark Hung <mark...@gmail.com> AuthorDate: Sun May 1 14:07:01 2022 +0800 Commit: Mark Hung <mark...@gmail.com> CommitDate: Fri May 13 01:32:22 2022 +0200 tdf#104930 aligning CTL text with hanging baseline. 1. SwTextSizeInfo::GetHangingBaseline() calls SwFont::GetHangingBaseline() to obtain the hanging baseline value. Only CTL script handled, it always return 0 for other two scripts. Eventually Outdev::GetFontMetric() and TextMetric::GetHangingBaseline() are called to obtain the hanging baseline value from vcl. 2. SwTextFormatter::CalcAscent() sets the baseline value for the portion via SwTextSizeInfo::GetHangingBaseline(). 3. SwTextFormatter::InsertPortion() sets the maximum baseline value for the whole line. 4. SwTextCursor::AdjustBaseLine() calculates the new baseline in case hanging baseline is available. Change-Id: I1aae7a34dfc953227b7873fc8e3af5cc7e2fbbff Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133668 Tested-by: Jenkins Reviewed-by: Mark Hung <mark...@gmail.com> diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx index 4f58be568951..bea6663e1420 100644 --- a/sw/source/core/inc/fntcache.hxx +++ b/sw/source/core/inc/fntcache.hxx @@ -74,6 +74,8 @@ class SwFntObj final : public SwCacheObj sal_uInt16 m_nScrHeight; sal_uInt16 m_nPrtHeight; sal_uInt16 m_nPropWidth; + sal_uInt16 m_nScrHangingBaseline; + sal_uInt16 m_nPrtHangingBaseline; sal_uInt16 m_nZoom; bool m_bSymbol : 1; bool m_bPaintBlank : 1; @@ -97,6 +99,7 @@ public: sal_uInt16 GetFontAscent( const SwViewShell *pSh, const OutputDevice& rOut ); sal_uInt16 GetFontHeight( const SwViewShell *pSh, const OutputDevice& rOut ); sal_uInt16 GetFontLeading( const SwViewShell *pSh, const OutputDevice& rOut ); + sal_uInt16 GetFontHangingBaseline( const SwViewShell *pSh, const OutputDevice& rOut ); void GuessLeading( const SwViewShell& rSh, const FontMetric& rMet ); diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx index 40a4c2e8d66c..38936574a471 100644 --- a/sw/source/core/inc/swfont.hxx +++ b/sw/source/core/inc/swfont.hxx @@ -72,6 +72,7 @@ class SwSubFont final : public SvxFont bool IsSymbol( SwViewShell const *pSh ); sal_uInt16 GetAscent( SwViewShell const *pSh, const OutputDevice& rOut ); sal_uInt16 GetHeight( SwViewShell const *pSh, const OutputDevice& rOut ); + sal_uInt16 GetHangingBaseline( SwViewShell const *pSh, const OutputDevice& rOut ); Size GetTextSize_( SwDrawTextInfo& rInf ); Size GetCapitalSize( SwDrawTextInfo& rInf ); void DrawText_( SwDrawTextInfo &rInf, const bool bGrey ); @@ -328,6 +329,9 @@ public: sal_uInt16 GetHeight( SwViewShell const *pSh, const OutputDevice& rOut ) { return m_aSub[m_nActual].GetHeight( pSh, rOut ); } + sal_uInt16 GetHangingBaseline( SwViewShell const *pSh, const OutputDevice& rOut ) + { return m_nActual == SwFontScript::CTL ? m_aSub[m_nActual].GetHangingBaseline( pSh, rOut ) : 0; } + void Invalidate() { m_bFontChg = m_bOrgChg = true; } diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx index 7c7bf57afa56..1621b4f35a8f 100644 --- a/sw/source/core/text/inftxt.hxx +++ b/sw/source/core/text/inftxt.hxx @@ -267,6 +267,7 @@ public: vcl::text::TextLayoutCache const*) const; sal_uInt16 GetAscent() const; + sal_uInt16 GetHangingBaseline() const; TextFrameIndex GetIdx() const { return m_nIdx; } void SetIdx(const TextFrameIndex nNew) { m_nIdx = nNew; } @@ -715,6 +716,12 @@ inline sal_uInt16 SwTextSizeInfo::GetTextHeight() const return const_cast<SwFont*>(GetFont())->GetHeight( m_pVsh, *GetOut() ); } +inline sal_uInt16 SwTextSizeInfo::GetHangingBaseline() const +{ + assert(GetOut()); + return const_cast<SwFont*>(GetFont())->GetHangingBaseline( m_pVsh, *GetOut() ); +} + inline SwPosSize SwTextSizeInfo::GetTextSize( const OUString &rText ) const { return GetTextSize(m_pOut, nullptr, rText, TextFrameIndex(0), TextFrameIndex(rText.getLength())); diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 52d13e690481..e7bcde5983b8 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -341,6 +341,8 @@ void SwTextFormatter::InsertPortion( SwTextFormatInfo &rInf, m_pCurr->Height( pPor->Height(), pPor->IsTextPortion() ); if( m_pCurr->GetAscent() < pPor->GetAscent() ) m_pCurr->SetAscent( pPor->GetAscent() ); + if( m_pCurr->GetHangingBaseline() < pPor->GetHangingBaseline() ) + m_pCurr->SetHangingBaseline( pPor->GetHangingBaseline() ); if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_MIN_LINE_HEIGHT_BY_FLY)) { @@ -831,6 +833,7 @@ void SwTextFormatter::CalcAscent( SwTextFormatInfo &rInf, SwLinePortion *pPor ) if( bChg || bFirstPor || !pPor->GetAscent() || !rInf.GetLast()->InTextGrp() ) { + pPor->SetHangingBaseline( rInf.GetHangingBaseline() ); pPor->SetAscent( rInf.GetAscent() ); pPor->Height( rInf.GetTextHeight() ); bCalc = true; diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx index 7f783e40428f..3935630192dd 100644 --- a/sw/source/core/text/itrpaint.cxx +++ b/sw/source/core/text/itrpaint.cxx @@ -243,7 +243,7 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip, SwTextGridItem const*const pGrid(GetGridItem(GetTextFrame()->FindPageFrame())); const bool bAdjustBaseLine = GetLineInfo().HasSpecialAlign( GetTextFrame()->IsVertical() ) || - ( nullptr != pGrid ); + ( nullptr != pGrid ) || m_pCurr->GetHangingBaseline(); const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent; if ( ! bAdjustBaseLine ) GetInfo().Y( nLineBaseLine ); diff --git a/sw/source/core/text/itrtxt.cxx b/sw/source/core/text/itrtxt.cxx index 8fb8334a83fa..53e084b03736 100644 --- a/sw/source/core/text/itrtxt.cxx +++ b/sw/source/core/text/itrtxt.cxx @@ -289,7 +289,14 @@ SwTwips SwTextCursor::AdjustBaseLine( const SwLineLayout& rLine, [[fallthrough]]; case SvxParaVertAlignItem::Align::Baseline : // base line - nOfst = nOfst + rLine.GetAscent(); + if (pPor && pPor->GetHangingBaseline()) + { + nOfst += rLine.GetAscent() // Romn baseline of the line. + - rLine.GetHangingBaseline() // Hanging baseline of the line. + + pPor->GetHangingBaseline(); // Romn baseline of the portion. + } + else + nOfst = nOfst + rLine.GetAscent(); break; } } diff --git a/sw/source/core/text/porlin.cxx b/sw/source/core/text/porlin.cxx index d7b3a1a41e5b..d2e95e88249a 100644 --- a/sw/source/core/text/porlin.cxx +++ b/sw/source/core/text/porlin.cxx @@ -67,6 +67,7 @@ SwLinePortion::SwLinePortion( ) : mpNextPortion( nullptr ), mnLineLength( 0 ), mnAscent( 0 ), + mnHangingBaseline( 0 ), mnWhichPor( PortionType::NONE ), m_bJoinBorderWithPrev(false), m_bJoinBorderWithNext(false) diff --git a/sw/source/core/text/porlin.hxx b/sw/source/core/text/porlin.hxx index fb820f9bc577..3cd1d9fff942 100644 --- a/sw/source/core/text/porlin.hxx +++ b/sw/source/core/text/porlin.hxx @@ -56,6 +56,7 @@ protected: // Count of chars and spaces on the line TextFrameIndex mnLineLength; SwTwips mnAscent; // Maximum ascender + SwTwips mnHangingBaseline; SwLinePortion(); private: @@ -82,6 +83,8 @@ public: SwTwips PrtWidth() const { return Width(); } void AddPrtWidth( const SwTwips nNew ) { Width( Width() + nNew ); } void SubPrtWidth( const SwTwips nNew ) { Width( Width() - nNew ); } + SwTwips GetHangingBaseline() const { return mnHangingBaseline; } + void SetHangingBaseline( const SwTwips nNewBaseline ) { mnHangingBaseline = nNewBaseline; } // Insert methods virtual SwLinePortion *Insert( SwLinePortion *pPortion ); @@ -184,6 +187,7 @@ inline SwLinePortion &SwLinePortion::operator=(const SwLinePortion &rPortion) *static_cast<SwPosSize*>(this) = rPortion; mnLineLength = rPortion.mnLineLength; mnAscent = rPortion.mnAscent; + mnHangingBaseline = rPortion.mnHangingBaseline; mnWhichPor = rPortion.mnWhichPor; m_bJoinBorderWithPrev = rPortion.m_bJoinBorderWithPrev; m_bJoinBorderWithNext = rPortion.m_bJoinBorderWithNext; @@ -195,6 +199,7 @@ inline SwLinePortion::SwLinePortion(const SwLinePortion &rPortion) : mpNextPortion( nullptr ), mnLineLength( rPortion.mnLineLength ), mnAscent( rPortion.mnAscent ), + mnHangingBaseline( rPortion.mnHangingBaseline ), mnWhichPor( rPortion.mnWhichPor ), m_bJoinBorderWithPrev( rPortion.m_bJoinBorderWithPrev ), m_bJoinBorderWithNext( rPortion.m_bJoinBorderWithNext ) diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 5623a35e1677..b3fe68906821 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -290,6 +290,7 @@ sal_uInt16 SwFntObj::GetFontAscent( const SwViewShell *pSh, const OutputDevice& const_cast<OutputDevice&>(rRefDev).SetFont( *m_pPrtFont ); const FontMetric aOutMet( rRefDev.GetFontMetric() ); m_nPrtAscent = o3tl::narrowing<sal_uInt16>(aOutMet.GetAscent()); + m_nPrtHangingBaseline = o3tl::narrowing<sal_uInt16>(aOutMet.GetHangingBaseline()); const_cast<OutputDevice&>(rRefDev).SetFont( aOldFnt ); } @@ -397,6 +398,21 @@ sal_uInt16 SwFntObj::GetFontLeading( const SwViewShell *pSh, const OutputDevice& return nRet; } +sal_uInt16 SwFntObj::GetFontHangingBaseline( const SwViewShell* pSh, const OutputDevice& rOut ) +{ + sal_uInt16 nRet = 0; + const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut; + + GetFontAscent(pSh, rOut); + + if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) ) + nRet = m_nScrHangingBaseline; + else + nRet = m_nPrtHangingBaseline; + + return nRet; +} + // pOut is the output device, not the reference device void SwFntObj::CreateScrFont( const SwViewShell& rSh, const OutputDevice& rOut ) { @@ -465,6 +481,7 @@ void SwFntObj::CreateScrFont( const SwViewShell& rSh, const OutputDevice& rOut ) } m_nScrAscent = o3tl::narrowing<sal_uInt16>(pOut->GetFontMetric().GetAscent()); + m_nScrHangingBaseline = o3tl::narrowing<sal_uInt16>(pOut->GetFontMetric().GetHangingBaseline()); if ( USHRT_MAX == m_nScrHeight ) m_nScrHeight = o3tl::narrowing<sal_uInt16>(pOut->GetTextHeight()); diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx index eb08f33696cc..30cd44851081 100644 --- a/sw/source/core/txtnode/swfont.cxx +++ b/sw/source/core/txtnode/swfont.cxx @@ -965,6 +965,12 @@ sal_uInt16 SwSubFont::GetHeight( SwViewShell const *pSh, const OutputDevice& rOu return nHeight; // + nLeading; } +sal_uInt16 SwSubFont::GetHangingBaseline( SwViewShell const *pSh, const OutputDevice& rOut ) +{ + SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh ); + return aFntAccess.Get()->GetFontHangingBaseline( pSh, rOut ); +} + Size SwSubFont::GetTextSize_( SwDrawTextInfo& rInf ) { // Robust: the font is supposed to be set already, but better safe than