summaryrefslogtreecommitdiff
path: root/sw/source/core/text/inftxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/inftxt.cxx')
-rw-r--r--sw/source/core/text/inftxt.cxx614
1 files changed, 397 insertions, 217 deletions
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index bb63a36ae157..b293f18f824a 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -29,7 +29,6 @@
#include <editeng/hyphenzoneitem.hxx>
#include <editeng/hngpnctitem.hxx>
#include <editeng/scriptspaceitem.hxx>
-#include <editeng/brushitem.hxx>
#include <editeng/splwrap.hxx>
#include <editeng/pgrditem.hxx>
#include <editeng/tstpitem.hxx>
@@ -38,7 +37,6 @@
#include <SwSmartTagMgr.hxx>
#include <breakit.hxx>
#include <editeng/forbiddenruleitem.hxx>
-#include <paintfrm.hxx>
#include <swmodule.hxx>
#include <vcl/svapp.hxx>
#include <viewsh.hxx>
@@ -66,6 +64,18 @@
#include <vcl/gdimtf.hxx>
#include <vcl/virdev.hxx>
#include <vcl/gradient.hxx>
+#include <i18nlangtag/mslangid.hxx>
+#include <formatlinebreak.hxx>
+
+#include <view.hxx>
+#include <wrtsh.hxx>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <unotextrange.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <unoprnms.hxx>
+#include <editeng/unoprnms.hxx>
+#include <unomap.hxx>
+#include <com/sun/star/awt/FontSlant.hpp>
using namespace ::com::sun::star;
using namespace ::com::sun::star::linguistic2;
@@ -99,7 +109,7 @@ SwLineInfo::~SwLineInfo()
void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
const SwTextNode& rTextNode )
{
- m_pRuler.reset( new SvxTabStopItem( rAttrSet.GetTabStops() ) );
+ m_oRuler.emplace( rAttrSet.GetTabStops() );
if ( rTextNode.GetListTabStopPosition( m_nListTabStopPosition ) )
{
m_bListTabStopIncluded = true;
@@ -107,15 +117,15 @@ void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
// insert the list tab stop into SvxTabItem instance <pRuler>
const SvxTabStop aListTabStop( m_nListTabStopPosition,
SvxTabAdjust::Left );
- m_pRuler->Insert( aListTabStop );
+ m_oRuler->Insert( aListTabStop );
// remove default tab stops, which are before the inserted list tab stop
- for ( sal_uInt16 i = 0; i < m_pRuler->Count(); i++ )
+ for ( sal_uInt16 i = 0; i < m_oRuler->Count(); i++ )
{
- if ( (*m_pRuler)[i].GetTabPos() < m_nListTabStopPosition &&
- (*m_pRuler)[i].GetAdjustment() == SvxTabAdjust::Default )
+ if ( (*m_oRuler)[i].GetTabPos() < m_nListTabStopPosition &&
+ (*m_oRuler)[i].GetAdjustment() == SvxTabAdjust::Default )
{
- m_pRuler->Remove(i);
+ m_oRuler->Remove(i);
continue;
}
}
@@ -124,12 +134,12 @@ void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
if ( !rTextNode.getIDocumentSettingAccess()->get(DocumentSettingId::TABS_RELATIVE_TO_INDENT) )
{
// remove default tab stop at position 0
- for ( sal_uInt16 i = 0; i < m_pRuler->Count(); i++ )
+ for ( sal_uInt16 i = 0; i < m_oRuler->Count(); i++ )
{
- if ( (*m_pRuler)[i].GetTabPos() == 0 &&
- (*m_pRuler)[i].GetAdjustment() == SvxTabAdjust::Default )
+ if ( (*m_oRuler)[i].GetTabPos() == 0 &&
+ (*m_oRuler)[i].GetAdjustment() == SvxTabAdjust::Default )
{
- m_pRuler->Remove(i);
+ m_oRuler->Remove(i);
break;
}
}
@@ -191,6 +201,7 @@ SwTextSizeInfo::SwTextSizeInfo()
, m_pText(nullptr)
, m_nIdx(0)
, m_nLen(0)
+, m_nMeasureLen(COMPLETE_STRING)
, m_nKanaIdx(0)
, m_bOnWin (false)
, m_bNotEOL (false)
@@ -221,6 +232,7 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew )
m_pText(&rNew.GetText()),
m_nIdx(rNew.GetIdx()),
m_nLen(rNew.GetLen()),
+ m_nMeasureLen(rNew.GetMeasureLen()),
m_nKanaIdx( rNew.GetKanaIdx() ),
m_bOnWin( rNew.OnWin() ),
m_bNotEOL( rNew.NotEOL() ),
@@ -280,14 +292,14 @@ void SwTextSizeInfo::CtorInitTextSizeInfo( OutputDevice* pRenderContext, SwTextF
// Set default layout mode ( LTR or RTL ).
if ( m_pFrame->IsRightToLeft() )
{
- m_pOut->SetLayoutMode( ComplexTextLayoutFlags::BiDiStrong | ComplexTextLayoutFlags::BiDiRtl );
- m_pRef->SetLayoutMode( ComplexTextLayoutFlags::BiDiStrong | ComplexTextLayoutFlags::BiDiRtl );
+ m_pOut->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::BiDiStrong | vcl::text::ComplexTextLayoutFlags::BiDiRtl );
+ m_pRef->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::BiDiStrong | vcl::text::ComplexTextLayoutFlags::BiDiRtl );
m_nDirection = DIR_RIGHT2LEFT;
}
else
{
- m_pOut->SetLayoutMode( ComplexTextLayoutFlags::BiDiStrong );
- m_pRef->SetLayoutMode( ComplexTextLayoutFlags::BiDiStrong );
+ m_pOut->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::BiDiStrong );
+ m_pRef->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::BiDiStrong );
m_nDirection = DIR_LEFT2RIGHT;
}
@@ -309,7 +321,7 @@ void SwTextSizeInfo::CtorInitTextSizeInfo( OutputDevice* pRenderContext, SwTextF
m_pText = &m_pFrame->GetText();
m_nIdx = nNewIdx;
- m_nLen = TextFrameIndex(COMPLETE_STRING);
+ m_nLen = m_nMeasureLen = TextFrameIndex(COMPLETE_STRING);
m_bNotEOL = false;
m_bStopUnderflow = m_bFootnoteInside = m_bOtherThanFootnoteInside = false;
m_bMulti = m_bFirstMulti = m_bRuby = m_bHanging = m_bScriptSpace =
@@ -332,6 +344,7 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew, const OUString* pTex
m_pText(pText),
m_nIdx(nIndex),
m_nLen(COMPLETE_STRING),
+ m_nMeasureLen(COMPLETE_STRING),
m_nKanaIdx( rNew.GetKanaIdx() ),
m_bOnWin( rNew.OnWin() ),
m_bNotEOL( rNew.NotEOL() ),
@@ -407,6 +420,7 @@ SwPosSize SwTextSizeInfo::GetTextSize() const
0 ;
SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rSI, *m_pText, m_nIdx, m_nLen );
+ aDrawInf.SetMeasureLen( m_nMeasureLen );
aDrawInf.SetFrame( m_pFrame );
aDrawInf.SetFont( m_pFnt );
aDrawInf.SetSnapToGrid( SnapToGrid() );
@@ -417,7 +431,7 @@ SwPosSize SwTextSizeInfo::GetTextSize() const
void SwTextSizeInfo::GetTextSize( const SwScriptInfo* pSI, const TextFrameIndex nIndex,
const TextFrameIndex nLength, const sal_uInt16 nComp,
sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff,
- vcl::TextLayoutCache const*const pCache) const
+ vcl::text::TextLayoutCache const*const pCache) const
{
SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pText, nIndex, nLength,
0, false, pCache);
@@ -426,14 +440,14 @@ void SwTextSizeInfo::GetTextSize( const SwScriptInfo* pSI, const TextFrameIndex
aDrawInf.SetSnapToGrid( SnapToGrid() );
aDrawInf.SetKanaComp( nComp );
SwPosSize aSize( m_pFnt->GetTextSize_( aDrawInf ) );
- nMaxSizeDiff = static_cast<sal_uInt16>(aDrawInf.GetKanaDiff());
+ nMaxSizeDiff = o3tl::narrowing<sal_uInt16>(aDrawInf.GetKanaDiff());
nMinSize = aSize.Width();
}
TextFrameIndex SwTextSizeInfo::GetTextBreak( const tools::Long nLineWidth,
const TextFrameIndex nMaxLen,
const sal_uInt16 nComp,
- vcl::TextLayoutCache const*const pCache) const
+ vcl::text::TextLayoutCache const*const pCache) const
{
const SwScriptInfo& rScriptInfo =
const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo();
@@ -454,7 +468,7 @@ TextFrameIndex SwTextSizeInfo::GetTextBreak( const tools::Long nLineWidth,
const TextFrameIndex nMaxLen,
const sal_uInt16 nComp,
TextFrameIndex& rExtraCharPos,
- vcl::TextLayoutCache const*const pCache) const
+ vcl::text::TextLayoutCache const*const pCache) const
{
const SwScriptInfo& rScriptInfo =
const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo();
@@ -521,39 +535,6 @@ SwTextPaintInfo::SwTextPaintInfo( SwTextFrame *pFrame, const SwRect &rPaint )
CtorInitTextPaintInfo( pFrame->getRootFrame()->GetCurrShell()->GetOut(), pFrame, rPaint );
}
-/// Returns if the current background color is dark.
-static bool lcl_IsDarkBackground( const SwTextPaintInfo& rInf )
-{
- std::optional<Color> pCol = rInf.GetFont()->GetBackColor();
- if( ! pCol || COL_TRANSPARENT == *pCol )
- {
- const SvxBrushItem* pItem;
- SwRect aOrigBackRect;
- drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
-
- // Consider, that [GetBackgroundBrush(...)] can set <pCol>
- // See implementation in /core/layout/paintfrm.cxx
- // There is a background color, if there is a background brush and
- // its color is *not* "no fill"/"auto fill".
- if( rInf.GetTextFrame()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false, /*bConsiderTextBox=*/false ) )
- {
- if ( !pCol )
- pCol = pItem->GetColor();
-
- // Determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
- if ( *pCol == COL_TRANSPARENT)
- pCol.reset();
- }
- else
- pCol.reset();
- }
-
- if( !pCol )
- pCol = aGlobalRetoucheColor;
-
- return pCol->IsDark();
-}
-
namespace
{
/**
@@ -604,7 +585,7 @@ SwTransparentTextGuard::~SwTransparentTextGuard()
Gradient aVCLGradient;
sal_uInt8 nTransPercentVcl = 255 - m_rPaintInf.GetFont()->GetColor().GetAlpha();
const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
- aVCLGradient.SetStyle(GradientStyle::Linear);
+ aVCLGradient.SetStyle(css::awt::GradientStyle_LINEAR);
aVCLGradient.SetStartColor(aTransColor);
aVCLGradient.SetEndColor(aTransColor);
aVCLGradient.SetAngle(0_deg10);
@@ -653,7 +634,7 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
aDrawInf.SetUnderFnt( m_pUnderFnt );
const tools::Long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
- rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
+ rPor.InNumberGrp() ) ? 0 : GetSpaceAdd(/*bShrink=*/true);
if ( nSpaceAdd )
{
TextFrameIndex nCharCnt(0);
@@ -681,7 +662,7 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
// Draw text next to the left border
Point aFontPos(m_aPos);
- if( m_pFnt->GetLeftBorder() && !static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithPrev() )
+ if( m_pFnt->GetLeftBorder() && rPor.InTextGrp() && !static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithPrev() )
{
const sal_uInt16 nLeftBorderSpace = m_pFnt->GetLeftBorderSpace();
if ( GetTextFrame()->IsRightToLeft() )
@@ -716,7 +697,9 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
std::unique_ptr<SwTransparentTextGuard, o3tl::default_delete<SwTransparentTextGuard>> pTransparentText;
if (m_pFnt->GetColor() != COL_AUTO && m_pFnt->GetColor().IsTransparent())
{
- pTransparentText.reset(new SwTransparentTextGuard(rPor, *this, aDrawInf));
+ // if drawing to a backend that supports transparency for text color, then we don't need to use this
+ if (!m_bOnWin || !m_pOut->SupportsOperation(OutDevSupportType::TransparentText) || m_pOut->GetConnectMetaFile())
+ pTransparentText.reset(new SwTransparentTextGuard(rPor, *this, aDrawInf));
}
if( GetTextFly().IsOn() )
@@ -955,7 +938,7 @@ static void lcl_DrawSpecial( const SwTextPaintInfo& rTextPaintInfo, const SwLine
Point aTmpPos( nX, nY );
rNonConstTextPaintInfo.SetPos( aTmpPos );
sal_uInt16 nOldWidth = rPor.Width();
- const_cast<SwLinePortion&>(rPor).Width( static_cast<sal_uInt16>(aFontSize.Width()) );
+ const_cast<SwLinePortion&>(rPor).Width( o3tl::narrowing<sal_uInt16>(aFontSize.Width()) );
rTextPaintInfo.DrawText( aTmp, rPor );
const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
rNonConstTextPaintInfo.SetFont( const_cast<SwFont*>(pOldFnt) );
@@ -996,6 +979,13 @@ void SwTextPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
if( !OnWin() )
return;
+ SwLineBreakClear eClear = SwLineBreakClear::NONE;
+ if (rPor.IsBreakPortion())
+ {
+ const auto& rBreakPortion = static_cast<const SwBreakPortion&>(rPor);
+ eClear = rBreakPortion.GetClear();
+ }
+
sal_uInt16 nOldWidth = rPor.Width();
const_cast<SwLinePortion&>(rPor).Width( LINE_BREAK_WIDTH );
@@ -1008,7 +998,24 @@ void SwTextPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
const sal_uInt8 nOptions = 0;
- lcl_DrawSpecial( *this, rPor, aRect, NON_PRINTING_CHARACTER_COLOR, cChar, nOptions );
+ SwRect aTextRect(aRect);
+ if (eClear == SwLineBreakClear::LEFT || eClear == SwLineBreakClear::ALL)
+ aTextRect.AddLeft(30);
+ if (eClear == SwLineBreakClear::RIGHT || eClear == SwLineBreakClear::ALL)
+ aTextRect.AddRight(-30);
+ lcl_DrawSpecial( *this, rPor, aTextRect, NON_PRINTING_CHARACTER_COLOR, cChar, nOptions );
+
+ if (eClear != SwLineBreakClear::NONE)
+ {
+ // Paint indicator if this clear is left/right/all.
+ m_pOut->Push(vcl::PushFlags::LINECOLOR);
+ m_pOut->SetLineColor(NON_PRINTING_CHARACTER_COLOR);
+ if (eClear != SwLineBreakClear::RIGHT)
+ m_pOut->DrawLine(aRect.BottomLeft(), aRect.TopLeft());
+ if (eClear != SwLineBreakClear::LEFT)
+ m_pOut->DrawLine(aRect.BottomRight(), aRect.TopRight());
+ m_pOut->Pop();
+ }
}
const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
@@ -1089,8 +1096,7 @@ void SwTextPaintInfo::DrawPostIts( bool bScript ) const
if ( GetTextFrame()->IsVertical() )
GetTextFrame()->SwitchHorizontalToVertical( aTmpRect );
- const tools::Rectangle aRect( aTmpRect.SVRect() );
- SwViewOption::PaintPostIts( const_cast<OutputDevice*>(GetOut()), aRect, bScript );
+ GetOpt().PaintPostIts( const_cast<OutputDevice*>(GetOut()), aTmpRect, bScript );
}
@@ -1101,19 +1107,22 @@ void SwTextPaintInfo::DrawCheckBox(const SwFieldFormCheckboxPortion &rPor, bool
if ( !aIntersect.HasArea() )
return;
- if (OnWin() && SwViewOption::IsFieldShadings() &&
+ if (OnWin() && GetOpt().IsFieldShadings() &&
!GetOpt().IsPagePreview())
{
OutputDevice* pOut = const_cast<OutputDevice*>(GetOut());
- pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
- pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
+ pOut->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
+ if( m_pFnt->GetHighlightColor() != COL_TRANSPARENT )
+ pOut->SetFillColor(m_pFnt->GetHighlightColor());
+ else
+ pOut->SetFillColor(GetOpt().GetFieldShadingsColor());
pOut->SetLineColor();
pOut->DrawRect( aIntersect.SVRect() );
pOut->Pop();
}
- const int delta=10;
+ const int delta = 25;
tools::Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
- m_pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
+ m_pOut->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
m_pOut->SetLineColor( Color(0, 0, 0));
m_pOut->SetFillColor();
m_pOut->DrawRect( r );
@@ -1125,7 +1134,7 @@ void SwTextPaintInfo::DrawCheckBox(const SwFieldFormCheckboxPortion &rPor, bool
m_pOut->Pop();
}
-void SwTextPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
+void SwTextPaintInfo::DrawBackground( const SwLinePortion &rPor, const Color *pColor ) const
{
OSL_ENSURE( OnWin(), "SwTextPaintInfo::DrawBackground: printer pollution ?" );
@@ -1136,18 +1145,14 @@ void SwTextPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
return;
OutputDevice* pOut = const_cast<OutputDevice*>(GetOut());
- pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
+ pOut->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
- // For dark background we do not want to have a filled rectangle
- if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
- {
- pOut->SetLineColor( SwViewOption::GetFontColor() );
- }
+ if ( pColor )
+ pOut->SetFillColor( *pColor );
else
- {
- pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
- pOut->SetLineColor();
- }
+ pOut->SetFillColor( GetOpt().GetFieldShadingsColor() );
+
+ pOut->SetLineColor();
DrawRect( aIntersect, true );
pOut->Pop();
@@ -1162,7 +1167,7 @@ void SwTextPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
{
SwPosition const aPosition(m_pFrame->MapViewToModelPos(GetIdx()));
const ::sw::mark::IMark* pFieldmark =
- m_pFrame->GetDoc().getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
+ m_pFrame->GetDoc().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPosition);
bool bIsStartMark = (TextFrameIndex(1) == GetLen()
&& CH_TXT_ATR_FIELDSTART == GetText()[sal_Int32(GetIdx())]);
if(pFieldmark) {
@@ -1171,12 +1176,12 @@ void SwTextPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
if(bIsStartMark)
SAL_INFO("sw.core", "Found StartMark");
if (OnWin() && (pFieldmark!=nullptr || bIsStartMark) &&
- SwViewOption::IsFieldShadings() &&
+ GetOpt().IsFieldShadings() &&
!GetOpt().IsPagePreview())
{
OutputDevice* pOutDev = const_cast<OutputDevice*>(GetOut());
- pOutDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
- pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
+ pOutDev->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
+ pOutDev->SetFillColor( GetOpt().GetFieldShadingsColor() );
pOutDev->SetLineColor( );
pOutDev->DrawRect( aIntersect.SVRect() );
pOutDev->Pop();
@@ -1208,89 +1213,7 @@ void SwTextPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
aFillColor = *m_pFnt->GetBackColor();
}
- // tdf#104349 do not highlight portions of space chars before end of line if the compatibility option is enabled
- // for LTR mode only
- if ( !GetTextFrame()->IsRightToLeft() )
- {
- if (GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS))
- {
- bool draw = false;
- bool full = false;
- SwLinePortion *pPos = const_cast<SwLinePortion *>(&rPor);
- TextFrameIndex nIdx = GetIdx();
- TextFrameIndex nLen;
-
- do
- {
- nLen = pPos->GetLen();
- for (TextFrameIndex i = nIdx; i < (nIdx + nLen); ++i)
- {
- if (i < TextFrameIndex(GetText().getLength())
- && GetText()[sal_Int32(i)] == CH_TXTATR_NEWLINE)
- {
- if ( i >= (GetIdx() + rPor.GetLen()) )
- {
- goto drawcontinue;
- }
- }
- if (i >= TextFrameIndex(GetText().getLength())
- || GetText()[sal_Int32(i)] != CH_BLANK)
- {
- draw = true;
- if ( i >= (GetIdx() + rPor.GetLen()) )
- {
- full = true;
- goto drawcontinue;
- }
- }
- }
- nIdx += nLen;
- pPos = pPos->GetNextPortion();
- } while ( pPos );
-
- drawcontinue:
-
- if ( !draw )
- return;
-
- if ( !full )
- {
- pPos = const_cast<SwLinePortion *>(&rPor);
- nIdx = GetIdx();
-
- nLen = pPos->GetLen();
- for (TextFrameIndex i = nIdx + nLen - TextFrameIndex(1);
- i >= nIdx; --i)
- {
- if (i < TextFrameIndex(GetText().getLength())
- && GetText()[sal_Int32(i)] == CH_TXTATR_NEWLINE)
- {
- continue;
- }
- if (i >= TextFrameIndex(GetText().getLength())
- || GetText()[sal_Int32(i)] != CH_BLANK)
- {
- sal_uInt16 nOldWidth = rPor.Width();
- sal_uInt16 nNewWidth = GetTextSize(m_pOut, nullptr,
- GetText(), nIdx, (i + TextFrameIndex(1) - nIdx)).Width();
-
- const_cast<SwLinePortion&>(rPor).Width( nNewWidth );
- CalcRect( rPor, nullptr, &aIntersect, true );
- const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
-
- if ( !aIntersect.HasArea() )
- {
- return;
- }
-
- break;
- }
- }
- }
- }
- }
-
- pTmpOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
+ pTmpOut->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
pTmpOut->SetFillColor(aFillColor);
pTmpOut->SetLineColor();
@@ -1312,71 +1235,243 @@ void SwTextPaintInfo::DrawBorder( const SwLinePortion &rPor ) const
}
}
-void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
- PortionType nWhich ) const
+namespace {
+
+bool HasValidPropertyValue(const uno::Any& rAny)
{
- if( !OnWin() || IsMulti() )
+ if (bool bValue; rAny >>= bValue)
+ {
+ return true;
+ }
+ else if (OUString aValue; (rAny >>= aValue) && !(aValue.isEmpty()))
+ {
+ return true;
+ }
+ else if (awt::FontSlant eValue; rAny >>= eValue)
+ {
+ return true;
+ }
+ else if (tools::Long nValueLong; rAny >>= nValueLong)
+ {
+ return true;
+ }
+ else if (double fValue; rAny >>= fValue)
+ {
+ return true;
+ }
+ else if (short nValueShort; rAny >>= nValueShort)
+ {
+ return true;
+ }
+ else
+ return false;
+}
+}
+
+void SwTextPaintInfo::DrawCSDFHighlighting(const SwLinePortion &rPor) const
+{
+ // Don't use GetActiveView() as it does not work as expected when there are multiple open
+ // documents.
+ SwView* pView = SwTextFrame::GetView();
+ if (!pView)
return;
- bool bDraw = false;
- switch( nWhich )
- {
- case PortionType::Footnote:
- case PortionType::QuoVadis:
- case PortionType::Number:
- case PortionType::Field:
- case PortionType::Hidden:
- case PortionType::Tox:
- case PortionType::Ref:
- case PortionType::Meta:
- case PortionType::ControlChar:
- if ( !GetOpt().IsPagePreview()
- && !GetOpt().IsReadonly()
- && SwViewOption::IsFieldShadings()
- && ( PortionType::Number != nWhich
- || m_pFrame->GetTextNodeForParaProps()->HasMarkedLabel())) // #i27615#
+ StylesHighlighterColorMap& rCharStylesColorMap = pView->GetStylesHighlighterCharColorMap();
+
+ if (rCharStylesColorMap.empty() && !pView->IsHighlightCharDF())
+ return;
+
+ SwRect aRect;
+ CalcRect(rPor, &aRect, nullptr, true);
+ if(!aRect.HasArea())
+ return;
+
+ SwTextFrame* pFrame = const_cast<SwTextFrame*>(GetTextFrame());
+ if (!pFrame)
+ return;
+
+ SwPosition aPosition(pFrame->MapViewToModelPos(GetIdx()));
+ SwPosition aMarkPosition(pFrame->MapViewToModelPos(GetIdx() + GetLen()));
+
+ rtl::Reference<SwXTextRange> xRange(
+ SwXTextRange::CreateXTextRange(pFrame->GetDoc(), aPosition, &aMarkPosition));
+
+ OUString sCurrentCharStyle;
+ xRange->getPropertyValue("CharStyleName") >>= sCurrentCharStyle;
+
+ std::optional<OUString> sCSNumberOrDF; // CS number or "df" or not used
+ std::optional<Color> aFillColor;
+
+ // check for CS formatting, if not CS formatted check for direct character formatting
+ if (!sCurrentCharStyle.isEmpty())
+ {
+ if (!rCharStylesColorMap.empty())
{
- bDraw = PortionType::Footnote != nWhich || m_pFrame->IsFootnoteAllowed();
+ OUString sCharStyleDisplayName;
+ sCharStyleDisplayName = SwStyleNameMapper::GetUIName(sCurrentCharStyle,
+ SwGetPoolIdFromName::ChrFmt);
+ if (!sCharStyleDisplayName.isEmpty()
+ && rCharStylesColorMap.find(sCharStyleDisplayName)
+ != rCharStylesColorMap.end())
+ {
+ aFillColor = rCharStylesColorMap[sCharStyleDisplayName].first;
+ sCSNumberOrDF = OUString::number(rCharStylesColorMap[sCharStyleDisplayName].second);
+ }
}
- break;
- case PortionType::Bookmark:
- // no shading
- break;
- case PortionType::InputField:
- // input field shading also in read-only mode
- if ( !GetOpt().IsPagePreview()
- && SwViewOption::IsFieldShadings() )
+ }
+ // not character style formatted
+ else if (pView->IsHighlightCharDF())
+ {
+ const std::vector<OUString> aHiddenProperties{ UNO_NAME_RSID,
+ UNO_NAME_PARA_IS_NUMBERING_RESTART,
+ UNO_NAME_PARA_STYLE_NAME,
+ UNO_NAME_PARA_CONDITIONAL_STYLE_NAME,
+ UNO_NAME_PAGE_STYLE_NAME,
+ UNO_NAME_NUMBERING_START_VALUE,
+ UNO_NAME_NUMBERING_IS_NUMBER,
+ UNO_NAME_PARA_CONTINUEING_PREVIOUS_SUB_TREE,
+ UNO_NAME_CHAR_STYLE_NAME,
+ UNO_NAME_NUMBERING_LEVEL,
+ UNO_NAME_SORTED_TEXT_ID,
+ UNO_NAME_PARRSID,
+ UNO_NAME_CHAR_COLOR_THEME,
+ UNO_NAME_CHAR_COLOR_TINT_OR_SHADE };
+
+ SfxItemPropertySet const& rPropSet(
+ *aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
+ SfxItemPropertyMap const& rMap(rPropSet.getPropertyMap());
+
+
+ const uno::Sequence<beans::Property> aProperties
+ = xRange->getPropertySetInfo()->getProperties();
+
+ for (const beans::Property& rProperty : aProperties)
{
- bDraw = true;
+ const OUString& rPropName = rProperty.Name;
+
+ if (!rMap.hasPropertyByName(rPropName))
+ continue;
+
+ if (std::find(aHiddenProperties.begin(), aHiddenProperties.end(), rPropName)
+ != aHiddenProperties.end())
+ continue;
+
+ if (xRange->getPropertyState(rPropName) == beans::PropertyState_DIRECT_VALUE)
+ {
+ const uno::Any aAny = xRange->getPropertyValue(rPropName);
+ if (HasValidPropertyValue(aAny))
+ {
+ sCSNumberOrDF = SwResId(STR_CHARACTER_DIRECT_FORMATTING_TAG);
+ aFillColor = COL_LIGHTGRAY;
+ break;
+ }
+ }
}
- break;
- case PortionType::Table:
- if ( GetOpt().IsTab() ) bDraw = true;
- break;
- case PortionType::SoftHyphen:
- if ( GetOpt().IsSoftHyph() )bDraw = true;
- break;
- case PortionType::Blank:
- if ( GetOpt().IsHardBlank())bDraw = true;
- break;
- default:
+ }
+ if (sCSNumberOrDF)
+ {
+ OutputDevice* pTmpOut = const_cast<OutputDevice*>(GetOut());
+ pTmpOut->Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR
+ | vcl::PushFlags::TEXTLAYOUTMODE | vcl::PushFlags::FONT);
+
+ // draw a filled rectangle at the formatted CS or DF text
+ pTmpOut->SetFillColor(aFillColor.value());
+ pTmpOut->SetLineColor(aFillColor.value());
+ tools::Rectangle aSVRect(aRect.SVRect());
+ pTmpOut->DrawRect(aSVRect);
+
+ // calculate size and position for the CS number or "df" text and rectangle
+ tools::Long nWidth = pTmpOut->GetTextWidth(sCSNumberOrDF.value());
+ tools::Long nHeight = pTmpOut->GetTextHeight();
+ aSVRect.SetSize(Size(nWidth, nHeight));
+ aSVRect.Move(-(nWidth / 1.5), -(nHeight / 1.5));
+
+ vcl::Font aFont(pTmpOut->GetFont());
+ aFont.SetOrientation(Degree10(0));
+ pTmpOut->SetFont(aFont);
+
+ pTmpOut->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::TextOriginLeft);
+ //pTmpOut->SetLayoutMode(vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+
+ pTmpOut->SetTextFillColor(aFillColor.value());
+ pTmpOut->DrawText(aSVRect, sCSNumberOrDF.value(), DrawTextFlags::NONE);
+
+ pTmpOut->Pop();
+ }
+}
+
+void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
+ PortionType nWhich, const Color *pColor ) const
+{
+ if( !OnWin() || IsMulti() )
+ return;
+
+ bool bDraw = false;
+ if ( !GetOpt().IsPagePreview()
+ && !GetOpt().IsReadonly() )
+ {
+ switch( nWhich )
{
- OSL_ENSURE( false, "SwTextPaintInfo::DrawViewOpt: don't know how to draw this" );
+ case PortionType::Tab:
+ if ( GetOpt().IsViewMetaChars() )
+ bDraw = GetOpt().IsTab();
+ break;
+ case PortionType::SoftHyphen:
+ if ( GetOpt().IsViewMetaChars() )
+ bDraw = GetOpt().IsSoftHyph();
+ break;
+ case PortionType::Blank:
+ if ( GetOpt().IsViewMetaChars() )
+ bDraw = GetOpt().IsHardBlank();
+ break;
+ case PortionType::ControlChar:
+ if ( GetOpt().IsViewMetaChars() )
+ bDraw = true;
+ break;
+ case PortionType::Bookmark:
+ // no shading
break;
+ case PortionType::Footnote:
+ case PortionType::QuoVadis:
+ case PortionType::Number:
+ case PortionType::Hidden:
+ case PortionType::Tox:
+ case PortionType::Ref:
+ case PortionType::Meta:
+ case PortionType::ContentControl:
+ case PortionType::Field:
+ case PortionType::InputField:
+ // input field shading also in read-only mode
+ if (GetOpt().IsFieldShadings()
+ && ( PortionType::Number != nWhich
+ || m_pFrame->GetTextNodeForParaProps()->HasMarkedLabel())) // #i27615#
+ {
+ bDraw = PortionType::Footnote != nWhich || m_pFrame->IsFootnoteAllowed();
+ }
+ break;
+ default:
+ {
+ OSL_ENSURE( false, "SwTextPaintInfo::DrawViewOpt: don't know how to draw this" );
+ break;
+ }
}
}
+
if ( bDraw )
- DrawBackground( rPor );
+ DrawBackground( rPor, pColor );
}
static void lcl_InitHyphValues( PropertyValues &rVals,
- sal_Int16 nMinLeading, sal_Int16 nMinTrailing, bool bNoCapsHyphenation )
+ sal_Int16 nMinLeading, sal_Int16 nMinTrailing,
+ bool bNoCapsHyphenation, bool bNoLastWordHyphenation,
+ sal_Int16 nMinWordLength, sal_Int16 nTextHyphZone, bool bKeep, sal_Int16 nKeepType,
+ sal_Int16 nCompoundMinLeading )
{
sal_Int32 nLen = rVals.getLength();
if (0 == nLen) // yet to be initialized?
{
- rVals.realloc( 3 );
+ rVals.realloc( 9 );
PropertyValue *pVal = rVals.getArray();
pVal[0].Name = UPN_HYPH_MIN_LEADING;
@@ -1390,13 +1485,43 @@ static void lcl_InitHyphValues( PropertyValues &rVals,
pVal[2].Name = UPN_HYPH_NO_CAPS;
pVal[2].Handle = UPH_HYPH_NO_CAPS;
pVal[2].Value <<= bNoCapsHyphenation;
+
+ pVal[3].Name = UPN_HYPH_NO_LAST_WORD;
+ pVal[3].Handle = UPH_HYPH_NO_LAST_WORD;
+ pVal[3].Value <<= bNoLastWordHyphenation;
+
+ pVal[4].Name = UPN_HYPH_MIN_WORD_LENGTH;
+ pVal[4].Handle = UPH_HYPH_MIN_WORD_LENGTH;
+ pVal[4].Value <<= nMinWordLength;
+
+ pVal[5].Name = UPN_HYPH_ZONE;
+ pVal[5].Handle = UPH_HYPH_ZONE;
+ pVal[5].Value <<= nTextHyphZone;
+
+ pVal[6].Name = UPN_HYPH_KEEP_TYPE;
+ pVal[6].Handle = UPH_HYPH_KEEP_TYPE;
+ pVal[6].Value <<= nKeepType;
+
+ pVal[7].Name = UPN_HYPH_COMPOUND_MIN_LEADING;
+ pVal[7].Handle = UPH_HYPH_COMPOUND_MIN_LEADING;
+ pVal[7].Value <<= nCompoundMinLeading;
+
+ pVal[8].Name = UPN_HYPH_KEEP;
+ pVal[8].Handle = UPH_HYPH_KEEP;
+ pVal[8].Value <<= bKeep;
}
- else if (3 == nLen) // already initialized once?
+ else if (9 == nLen) // already initialized once?
{
PropertyValue *pVal = rVals.getArray();
pVal[0].Value <<= nMinLeading;
pVal[1].Value <<= nMinTrailing;
pVal[2].Value <<= bNoCapsHyphenation;
+ pVal[3].Value <<= bNoLastWordHyphenation;
+ pVal[4].Value <<= nMinWordLength;
+ pVal[5].Value <<= nTextHyphZone;
+ pVal[6].Value <<= nKeepType;
+ pVal[7].Value <<= nCompoundMinLeading;
+ pVal[8].Value <<= bKeep;
}
else {
OSL_FAIL( "unexpected size of sequence" );
@@ -1405,7 +1530,7 @@ static void lcl_InitHyphValues( PropertyValues &rVals,
const PropertyValues & SwTextFormatInfo::GetHyphValues() const
{
- OSL_ENSURE( 3 == m_aHyphVals.getLength(),
+ OSL_ENSURE( 9 == m_aHyphVals.getLength(),
"hyphenation values not yet initialized" );
return m_aHyphVals;
}
@@ -1423,8 +1548,16 @@ bool SwTextFormatInfo::InitHyph( const bool bAutoHyphen )
{
const sal_Int16 nMinimalLeading = std::max(rAttr.GetMinLead(), sal_uInt8(2));
const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
+ const sal_Int16 nMinimalWordLength = rAttr.GetMinWordLength();
const bool bNoCapsHyphenation = rAttr.IsNoCapsHyphenation();
- lcl_InitHyphValues( m_aHyphVals, nMinimalLeading, nMinimalTrailing, bNoCapsHyphenation);
+ const bool bNoLastWordHyphenation = rAttr.IsNoLastWordHyphenation();
+ const sal_Int16 nTextHyphZone = rAttr.GetTextHyphenZone();
+ const bool bKeep = rAttr.IsKeep();
+ const sal_Int16 nKeepType = rAttr.GetKeepType();
+ const sal_Int16 nCompoundMinimalLeading = std::max(rAttr.GetCompoundMinLead(), sal_uInt8(2));
+ lcl_InitHyphValues( m_aHyphVals, nMinimalLeading, nMinimalTrailing,
+ bNoCapsHyphenation, bNoLastWordHyphenation,
+ nMinimalWordLength, nTextHyphZone, bKeep, nKeepType, nCompoundMinimalLeading );
}
return bAuto;
}
@@ -1456,7 +1589,7 @@ void SwTextFormatInfo::CtorInitTextFormatInfo( OutputDevice* pRenderContext, SwT
SetLineStart(TextFrameIndex(0));
SvtCTLOptions::TextNumerals const nTextNumerals(
- SW_MOD()->GetCTLOptions().GetCTLTextNumerals());
+ SvtCTLOptions::GetCTLTextNumerals());
// cannot cache for NUMERALS_CONTEXT because we need to know the string
// for the whole paragraph now
if (nTextNumerals != SvtCTLOptions::NUMERALS_CONTEXT)
@@ -1483,7 +1616,9 @@ bool SwTextFormatInfo::IsHyphenate() const
return false;
LanguageType eTmp = GetFont()->GetLanguage();
- if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
+ // TODO: check for more ideographic langs w/o hyphenation as a concept
+ if ( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp
+ || !MsLangId::usesHyphenation(eTmp) )
return false;
uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
@@ -1501,7 +1636,7 @@ bool SwTextFormatInfo::IsHyphenate() const
pShell->AppendInfoBarWhenReady(
"hyphenationmissing", SwResId(STR_HYPH_MISSING),
SwResId(STR_HYPH_MISSING_DETAIL)
- .replaceFirst("%1", g_pBreakIt->GetLocale(eTmp).Language),
+ .replaceFirst("%1", LanguageTag::convertToBcp47( g_pBreakIt->GetLocale(eTmp))),
InfobarType::WARNING);
}
}
@@ -1616,6 +1751,37 @@ SwTextFormatInfo::SwTextFormatInfo( const SwTextFormatInfo& rInf,
SetFirstMulti( rInf.IsFirstMulti() );
}
+void SwTextFormatInfo::UpdateTabSeen(PortionType type)
+{
+ switch (type)
+ {
+ case PortionType::TabLeft:
+ m_eLastTabsSeen = TabSeen::Left;
+ break;
+ case PortionType::TabRight:
+ m_eLastTabsSeen = TabSeen::Right;
+ break;
+ case PortionType::TabCenter:
+ m_eLastTabsSeen = TabSeen::Center;
+ break;
+ case PortionType::TabDecimal:
+ m_eLastTabsSeen = TabSeen::Decimal;
+ break;
+ case PortionType::Break:
+ m_eLastTabsSeen = TabSeen::None;
+ break;
+ default:
+ break;
+ }
+}
+
+void SwTextFormatInfo::SetLast(SwLinePortion* pNewLast)
+{
+ m_pLast = pNewLast;
+ assert(pNewLast); // We never pass nullptr here. If we start, then a check is needed below.
+ UpdateTabSeen(pNewLast->GetWhichPor());
+}
+
bool SwTextFormatInfo::CheckFootnotePortion_( SwLineLayout const * pCurr )
{
const sal_uInt16 nHeight = pCurr->GetRealHeight();
@@ -1758,7 +1924,9 @@ SwTwips SwTextFormatInfo::GetLineWidth()
const bool bTabOverMargin = GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
DocumentSettingId::TAB_OVER_MARGIN);
- if (!bTabOverMargin)
+ const bool bTabOverSpacing = GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+ DocumentSettingId::TAB_OVER_SPACING);
+ if (!bTabOverMargin && !bTabOverSpacing)
return nLineWidth;
SwTabPortion* pLastTab = GetLastTab();
@@ -1789,6 +1957,12 @@ SwTwips SwTextFormatInfo::GetLineWidth()
// text frame area to the right (RR above, but not LL).
nLineWidth = nTextFrameWidth - X();
+ if (!bTabOverMargin) // thus bTabOverSpacing only
+ {
+ // right, center, decimal can back-fill all the available space - same as TabOverMargin
+ if (pLastTab->GetWhichPor() == PortionType::TabLeft)
+ nLineWidth = nTextFrameWidth - pLastTab->GetTabPos();
+ }
return nLineWidth;
}
@@ -1803,6 +1977,7 @@ SwTextSlot::SwTextSlot(
, m_pOldGrammarCheckList(nullptr)
, nIdx(0)
, nLen(0)
+ , nMeasureLen(0)
, pInf(nullptr)
{
if( rCh.isEmpty() )
@@ -1822,11 +1997,15 @@ SwTextSlot::SwTextSlot(
pInf = const_cast<SwTextSizeInfo*>(pNew);
nIdx = pInf->GetIdx();
nLen = pInf->GetLen();
+ nMeasureLen = pInf->GetMeasureLen();
pOldText = &(pInf->GetText());
m_pOldCachedVclData = pInf->GetCachedVclData();
pInf->SetText( aText );
pInf->SetIdx(TextFrameIndex(0));
pInf->SetLen(bTextLen ? TextFrameIndex(pInf->GetText().getLength()) : pPor->GetLen());
+ if (nMeasureLen != TextFrameIndex(COMPLETE_STRING))
+ pInf->SetMeasureLen(TextFrameIndex(COMPLETE_STRING));
+
pInf->SetCachedVclData(nullptr);
// ST2
@@ -1900,6 +2079,7 @@ SwTextSlot::~SwTextSlot()
pInf->SetText( *pOldText );
pInf->SetIdx( nIdx );
pInf->SetLen( nLen );
+ pInf->SetMeasureLen( nMeasureLen );
// ST2
// Restore old smart tag list