summaryrefslogtreecommitdiff
path: root/sw/source/core/text/porrst.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/porrst.cxx')
-rw-r--r--sw/source/core/text/porrst.cxx342
1 files changed, 307 insertions, 35 deletions
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index 6f578e0744cd..ff1e029ae141 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -22,7 +22,10 @@
#include <editeng/escapementitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/pgrditem.hxx>
+#include <editeng/fontitem.hxx>
#include <vcl/svapp.hxx>
+#include <comphelper/scopeguard.hxx>
+
#include <viewsh.hxx>
#include <viewopt.hxx>
#include <ndtxt.hxx>
@@ -39,12 +42,19 @@
#include "redlnitr.hxx"
#include "atrhndl.hxx"
#include <rootfrm.hxx>
+#include <formatlinebreak.hxx>
+#include <txatbase.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentDeviceAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
#include <crsrsh.hxx>
+#include <swtypes.hxx>
+#include <strings.hrc>
+#include <flyfrms.hxx>
+#include <bodyfrm.hxx>
SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion,
const FontLineStyle eUL,
@@ -66,6 +76,16 @@ void SwTmpEndPortion::Paint( const SwTextPaintInfo &rInf ) const
SwFont aFont(*pOldFnt);
+ const SwDoc& rDoc = rInf.GetTextFrame()->GetDoc();
+ if (aFont.IsSymbol(rDoc.getIDocumentLayoutAccess().GetCurrentViewShell()))
+ {
+ const SvxFontItem& rFontItem = rDoc.GetDefault(RES_CHRATR_FONT);
+ aFont.SetName( rFontItem.GetFamilyName(), SwFontScript::Latin );
+ aFont.SetStyleName( rFontItem.GetStyleName(), SwFontScript::Latin );
+ aFont.SetFamily( rFontItem.GetFamily(), SwFontScript::Latin );
+ aFont.SetPitch( rFontItem.GetPitch(), SwFontScript::Latin );
+ aFont.SetCharSet( rFontItem.GetCharSet(), SwFontScript::Latin );
+ }
// Paint strikeout/underline based on redline color and settings
// (with an extra pilcrow in the background, because there is
// no SetStrikeoutColor(), also SetUnderColor() doesn't work()).
@@ -93,12 +113,19 @@ void SwTmpEndPortion::Paint( const SwTextPaintInfo &rInf ) const
const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt));
}
-SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion )
+SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion, const SwTextAttr* pAttr )
: SwLinePortion( rPortion )
{
mnLineLength = TextFrameIndex(1);
m_eRedline = RedlineType::None;
SetWhichPor( PortionType::Break );
+
+ m_eClear = SwLineBreakClear::NONE;
+ if (pAttr && pAttr->Which() == RES_TXTATR_LINEBREAK)
+ {
+ m_eClear = pAttr->GetLineBreak().GetValue();
+ }
+ m_nTextHeight = 0;
}
TextFrameIndex SwBreakPortion::GetModelPositionForViewPoint(const sal_uInt16) const
@@ -117,37 +144,58 @@ void SwBreakPortion::Paint( const SwTextPaintInfo &rInf ) const
if( !(rInf.OnWin() && rInf.GetOpt().IsLineBreak()) )
return;
+ // Reduce height to text height for the duration of the print, so the vertical height will look
+ // correct for the line break character, even for clearing breaks.
+ SwTwips nHeight = Height();
+ SwTwips nVertPosOffset = (nHeight - m_nTextHeight) / 2;
+ auto pPortion = const_cast<SwBreakPortion*>(this);
+ pPortion->Height(m_nTextHeight, false);
+ if (rInf.GetTextFrame()->IsVertical())
+ {
+ // Compensate for the offset done in SwTextCursor::AdjustBaseLine() for the vertical case.
+ const_cast<SwTextPaintInfo&>(rInf).Y(rInf.Y() + nVertPosOffset);
+ }
+ comphelper::ScopeGuard g(
+ [pPortion, nHeight, &rInf, nVertPosOffset]
+ {
+ if (rInf.GetTextFrame()->IsVertical())
+ {
+ const_cast<SwTextPaintInfo&>(rInf).Y(rInf.Y() - nVertPosOffset);
+ }
+ pPortion->Height(nHeight, false);
+ });
+
rInf.DrawLineBreak( *this );
// paint redlining
- if (m_eRedline != RedlineType::None)
+ if (m_eRedline == RedlineType::None)
+ return;
+
+ sal_Int16 nNoBreakWidth = rInf.GetTextSize(S_NOBREAK_FOR_REDLINE).Width();
+ if ( nNoBreakWidth > 0 )
{
- sal_Int16 nNoBreakWidth = rInf.GetTextSize(S_NOBREAK_FOR_REDLINE).Width();
- if ( nNoBreakWidth > 0 )
- {
- // approximate portion size with multiple no-break spaces
- // and draw these spaces (at least a single one) by DrawText
- // painting the requested redline underline/strikeout
- sal_Int16 nSpaces = (LINE_BREAK_WIDTH + nNoBreakWidth/2) / nNoBreakWidth;
- OUStringBuffer aBuf(S_NOBREAK_FOR_REDLINE);
- for (sal_Int16 i = 1; i < nSpaces; ++i)
- aBuf.append(S_NOBREAK_FOR_REDLINE);
+ // approximate portion size with multiple no-break spaces
+ // and draw these spaces (at least a single one) by DrawText
+ // painting the requested redline underline/strikeout
+ sal_Int16 nSpaces = (LINE_BREAK_WIDTH + nNoBreakWidth/2) / nNoBreakWidth;
+ OUStringBuffer aBuf(S_NOBREAK_FOR_REDLINE);
+ for (sal_Int16 i = 1; i < nSpaces; ++i)
+ aBuf.append(S_NOBREAK_FOR_REDLINE);
- const SwFont* pOldFnt = rInf.GetFont();
+ const SwFont* pOldFnt = rInf.GetFont();
- SwFont aFont(*pOldFnt);
+ SwFont aFont(*pOldFnt);
- if (m_eRedline == RedlineType::Delete)
- aFont.SetUnderline( LINESTYLE_NONE );
- else
- aFont.SetStrikeout( STRIKEOUT_NONE );
+ if (m_eRedline == RedlineType::Delete)
+ aFont.SetUnderline( LINESTYLE_NONE );
+ else
+ aFont.SetStrikeout( STRIKEOUT_NONE );
- const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont);
+ const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont);
- rInf.DrawText(aBuf.makeStringAndClear(), *this);
+ rInf.DrawText(aBuf.makeStringAndClear(), *this);
- const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt));
- }
+ const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt));
}
}
@@ -156,6 +204,29 @@ bool SwBreakPortion::Format( SwTextFormatInfo &rInf )
const SwLinePortion *pRoot = rInf.GetRoot();
Width( 0 );
Height( pRoot->Height() );
+ m_nTextHeight = Height();
+
+ // See if this is a clearing break. If so, calculate how much we need to "jump down" so the next
+ // line can again use the full text width.
+ SwLineBreakClear eClear = m_eClear;
+ if (rInf.GetTextFrame()->IsRightToLeft() && eClear != SwLineBreakClear::ALL)
+ {
+ // RTL ignores left/right breaks.
+ eClear = SwLineBreakClear::NONE;
+ }
+ if (eClear != SwLineBreakClear::NONE)
+ {
+ SwTextFly& rTextFly = rInf.GetTextFly();
+ if (rTextFly.IsOn())
+ {
+ SwTwips nHeight = rTextFly.GetMaxBottom(*this, rInf) - rInf.Y();
+ if (nHeight > Height())
+ {
+ Height(nHeight, /*bText=*/false);
+ }
+ }
+ }
+
SetAscent( pRoot->GetAscent() );
if (rInf.GetIdx() + TextFrameIndex(1) == TextFrameIndex(rInf.GetText().getLength()))
rInf.SetNewLine( true );
@@ -167,6 +238,21 @@ void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const
rPH.Text( GetLen(), GetWhichPor() );
}
+void SwBreakPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex&
+ nOffset) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwBreakPortion"));
+ dumpAsXmlAttributes(pWriter, rText, nOffset);
+ nOffset += GetLen();
+
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("text-height"),
+ BAD_CAST(OString::number(m_nTextHeight).getStr()));
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
+SwLineBreakClear SwBreakPortion::GetClear() const { return m_eClear; }
+
SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn,
bool bBG, bool bGK ) :
m_nKern( nKrn ), m_bBackground( bBG ), m_bGridKern( bGK )
@@ -243,7 +329,7 @@ SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) :
SwArrowPortion::SwArrowPortion( const SwTextPaintInfo &rInf )
: m_bLeft( false )
{
- Height( static_cast<sal_uInt16>(rInf.GetTextFrame()->getFramePrintArea().Height()) );
+ Height( o3tl::narrowing<sal_uInt16>(rInf.GetTextFrame()->getFramePrintArea().Height()) );
m_aPos.setX( rInf.GetTextFrame()->getFrameArea().Left() +
rInf.GetTextFrame()->getFramePrintArea().Right() );
m_aPos.setY( rInf.GetTextFrame()->getFrameArea().Top() +
@@ -338,7 +424,18 @@ bool SwTextFrame::FormatEmpty()
bool bCollapse = EmptyHeight( ) == 1 && IsCollapse( );
// sw_redlinehide: just disable FormatEmpty optimisation for now
- if (HasFollow() || GetMergedPara() || GetTextNodeFirst()->GetpSwpHints() ||
+ // Split fly frames: non-last parts of the anchor want this optimization to clear the old
+ // content.
+ SwFlyAtContentFrame* pNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj();
+ bool bHasNonLastSplitFlyDrawObj = pNonLastSplitFlyDrawObj != nullptr;
+
+ if (pNonLastSplitFlyDrawObj && pNonLastSplitFlyDrawObj->IsWrapOnAllPages())
+ {
+ // Split fly: the anchor is non-empty on all pages in the "wrap on all pages" case.
+ bHasNonLastSplitFlyDrawObj = false;
+ }
+
+ if ((HasFollow() && !bHasNonLastSplitFlyDrawObj) || GetMergedPara() || (GetTextNodeFirst()->GetpSwpHints() && !bHasNonLastSplitFlyDrawObj) ||
nullptr != GetTextNodeForParaProps()->GetNumRule() ||
GetTextNodeFirst()->HasHiddenCharAttribute(true) ||
IsInFootnote() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
@@ -352,18 +449,27 @@ bool SwTextFrame::FormatEmpty()
const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing();
if( !bCollapse && ( SvxLineSpaceRule::Min == rSpacing.GetLineSpaceRule() ||
SvxLineSpaceRule::Fix == rSpacing.GetLineSpaceRule() ||
- aSet.GetLRSpace().IsAutoFirst() ) )
+ aSet.GetFirstLineIndent().IsAutoFirst()))
+ {
return false;
+ }
SwTextFly aTextFly( this );
SwRect aRect;
bool bFirstFlyCheck = 0 != getFramePrintArea().Height();
if ( !bCollapse && bFirstFlyCheck &&
- aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
+ aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) && !bHasNonLastSplitFlyDrawObj )
return false;
+ if (IsEmptyWithSplitFly())
+ {
+ // We don't want this optimization in case the paragraph is not really empty, because it has
+ // a fly frame and it also needs space for the empty paragraph in a next line.
+ return false;
+ }
+
// only need to check one node because of early return on GetMerged()
- for (SwIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
+ for (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
pIndex; pIndex = pIndex->GetNext())
{
sw::mark::IMark const*const pMark = pIndex->GetMark();
@@ -384,7 +490,26 @@ bool SwTextFrame::FormatEmpty()
}
SwRectFnSet aRectFnSet(this);
- const SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea());
+ SwTwips nChg = nHeight - aRectFnSet.GetHeight(getFramePrintArea());
+ const SwBodyFrame* pBody = FindBodyFrame();
+ if (pNonLastSplitFlyDrawObj && pBody)
+ {
+ // See if we need to increase the text frame height due to split flys. This is necessary for
+ // anchors of inner floating tables, where moving to a next page moves indirectly, so we
+ // want a correct text frame height.
+ SwTwips nFrameBottom = aRectFnSet.GetBottom(getFrameArea()) + nChg;
+ SwTwips nFlyBottom = aRectFnSet.GetBottom(pNonLastSplitFlyDrawObj->getFrameArea());
+ SwTwips nBodyBottom = aRectFnSet.GetBottom(pBody->getFrameArea());
+ if (nFlyBottom > nBodyBottom)
+ {
+ // This is the legacy case where flys may overlap with footer frames.
+ nFlyBottom = nBodyBottom;
+ }
+ if (pNonLastSplitFlyDrawObj->isFrameAreaPositionValid() && nFlyBottom > nFrameBottom)
+ {
+ nChg += (nFlyBottom - nFrameBottom);
+ }
+ }
if( !nChg )
SetUndersized( false );
@@ -455,7 +580,7 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff )
pOut = GetDoc().getIDocumentDeviceAccess().getReferenceDevice( true );
if( pSh && !pOut )
- pOut = pSh->GetWin();
+ pOut = pSh->GetWin()->GetOutDev();
if( !pOut )
pOut = Application::GetDefaultDevice();
@@ -493,7 +618,7 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff )
nTmp /= 100;
if( !nTmp )
++nTmp;
- rRegDiff = static_cast<sal_uInt16>(nTmp);
+ rRegDiff = o3tl::narrowing<sal_uInt16>(nTmp);
nNetHeight = rRegDiff;
break;
}
@@ -527,7 +652,7 @@ void SwHiddenTextPortion::Paint( const SwTextPaintInfo & rInf) const
{
#ifdef DBG_UTIL
OutputDevice* pOut = const_cast<OutputDevice*>(rInf.GetOut());
- Color aCol( SwViewOption::GetFieldShadingsColor() );
+ Color aCol( rInf.GetOpt().GetFieldShadingsColor() );
Color aOldColor( pOut->GetFillColor() );
pOut->SetFillColor( aCol );
Point aPos( rInf.GetPos() );
@@ -549,10 +674,10 @@ bool SwHiddenTextPortion::Format( SwTextFormatInfo &rInf )
return false;
};
-bool SwControlCharPortion::DoPaint(SwTextPaintInfo const&,
+bool SwControlCharPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo,
OUString & rOutString, SwFont & rTmpFont, int &) const
{
- if (mcChar == CHAR_WJ || !SwViewOption::IsFieldShadings())
+ if (mcChar == CHAR_WJ || !rTextPaintInfo.GetOpt().IsFieldShadings())
{
return false;
}
@@ -580,6 +705,7 @@ bool SwControlCharPortion::DoPaint(SwTextPaintInfo const&,
bool SwBookmarkPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo,
OUString & rOutString, SwFont & rFont, int & rDeltaY) const
{
+ // custom color is visible without field shading, too
if (!rTextPaintInfo.GetOpt().IsShowBookmarks())
{
return false;
@@ -594,10 +720,11 @@ bool SwBookmarkPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo,
Size aSize(rFont.GetSize(rFont.GetActual()));
// use also the external leading (line gap) of the portion, but don't use
// 100% of it because i can't figure out how to baseline align that
- auto const nFactor = (Height() * 95) / aSize.Height();
+ assert(aSize.Height() != 0);
+ auto const nFactor = aSize.Height() > 0 ? (Height() * 95) / aSize.Height() : Height();
rFont.SetProportion(nFactor);
rFont.SetWeight(WEIGHT_THIN, rFont.GetActual());
- rFont.SetColor(NON_PRINTING_CHARACTER_COLOR);
+ rFont.SetColor(rTextPaintInfo.GetOpt().GetFieldShadingsColor());
// reset these to default...
rFont.SetAlign(ALIGN_BASELINE);
rFont.SetUnderline(LINESTYLE_NONE);
@@ -668,6 +795,151 @@ void SwControlCharPortion::Paint( const SwTextPaintInfo &rInf ) const
const_cast< SwTextPaintInfo& >( rInf ).SetPos( aOldPos );
}
+void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf ) const
+{
+ if ( !Width() ) // is only set during prepaint mode
+ return;
+
+ rInf.DrawViewOpt(*this, GetWhichPor());
+
+ int deltaY(0);
+ SwFont aTmpFont( *rInf.GetFont() );
+ OUString aOutString;
+
+ if (!(rInf.OnWin()
+ && !rInf.GetOpt().IsPagePreview()
+ && !rInf.GetOpt().IsReadonly()
+ && DoPaint(rInf, aOutString, aTmpFont, deltaY)))
+ return;
+
+ SwFontSave aFontSave( rInf, &aTmpFont );
+
+ if ( !mnHalfCharWidth )
+ mnHalfCharWidth = rInf.GetTextSize( aOutString ).Width() / 2;
+
+ Point aOldPos = rInf.GetPos();
+ Point aNewPos( aOldPos );
+ auto const deltaX((Width() / 2) - mnHalfCharWidth);
+ switch (rInf.GetFont()->GetOrientation(rInf.GetTextFrame()->IsVertical()).get())
+ {
+ case 0:
+ aNewPos.AdjustX(deltaX);
+ aNewPos.AdjustY(deltaY);
+ break;
+ case 900:
+ aNewPos.AdjustY(-deltaX);
+ aNewPos.AdjustX(deltaY);
+ break;
+ case 2700:
+ aNewPos.AdjustY(deltaX);
+ aNewPos.AdjustX(-deltaY);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ // draw end marks before the character position
+ if ( m_nStart == 0 || m_nEnd == 0 )
+ {
+ // single type boundary marks are there outside of the bookmark text
+ // some |text| here
+ // [[ ]]
+ if (m_nStart > 1)
+ aNewPos.AdjustX(static_cast<tools::Long>(mnHalfCharWidth) * -2 * (m_aColors.size() - 1));
+ }
+ else if ( m_nStart != 0 && m_nEnd != 0 )
+ // both end and start boundary marks: adjust them around the bookmark position
+ // |te|xt|
+ // ]] [[
+ aNewPos.AdjustX(static_cast<tools::Long>(mnHalfCharWidth) * -(2 * m_nEnd - 1 + m_nPoint) );
+
+ const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
+
+ for ( const auto& it : m_aColors )
+ {
+ // set bold for custom colored bookmark symbol
+ // and draw multiple symbols showing all custom colors
+ aTmpFont.SetWeight( COL_TRANSPARENT == std::get<1>(it) ? WEIGHT_THIN : WEIGHT_BOLD, aTmpFont.GetActual() );
+ aTmpFont.SetColor( COL_TRANSPARENT == std::get<1>(it) ? rInf.GetOpt().GetFieldShadingsColor() : std::get<1>(it) );
+ aOutString = OUString(std::get<0>(it) == SwScriptInfo::MarkKind::Start ? '[' : ']');
+
+ // MarkKind::Point: drawn I-beam (e.g. U+2336) as overlapping ][
+ if ( std::get<0>(it) == SwScriptInfo::MarkKind::Point )
+ {
+ aNewPos.AdjustX(-mnHalfCharWidth * 5/16);
+ const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
+ rInf.DrawText( aOutString, *this );
+
+ // when the overlapping vertical lines are 50 pixel width on the screen,
+ // this distance (half width * 5/8) still results precise overlapping
+ aNewPos.AdjustX(mnHalfCharWidth * 5/8);
+ const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
+ aOutString = OUString('[');
+ }
+ rInf.DrawText( aOutString, *this );
+ // place the next symbol after the previous one
+ // TODO: fix orientation and start/end
+ aNewPos.AdjustX(mnHalfCharWidth * 2);
+ const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
+ }
+
+ const_cast< SwTextPaintInfo& >( rInf ).SetPos( aOldPos );
+}
+
+void SwBookmarkPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ OUStringBuffer aStr;
+ for ( const auto& it : m_aColors )
+ {
+ aStr.append("#" + std::get<2>(it) + " " + SwResId(STR_BOOKMARK_DEF_NAME));
+ switch (std::get<0>(it))
+ {
+ case SwScriptInfo::MarkKind::Point:
+ break;
+ case SwScriptInfo::MarkKind::Start:
+ aStr.append(" " + SwResId(STR_CAPTION_BEGINNING));
+ break;
+ case SwScriptInfo::MarkKind::End:
+ aStr.append(" " + SwResId(STR_CAPTION_END));
+ break;
+ }
+ }
+
+ rPH.Special( GetLen(), aStr.makeStringAndClear(), GetWhichPor() );
+}
+
+void SwBookmarkPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
+{
+ (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwBookmarkPortion"));
+ dumpAsXmlAttributes(pWriter, rText, nOffset);
+ nOffset += GetLen();
+
+ if (!m_aColors.empty())
+ {
+ OUStringBuffer aStr;
+ for (const auto& rColor : m_aColors)
+ {
+ aStr.append("#" + std::get<2>(rColor) + " " + SwResId(STR_BOOKMARK_DEF_NAME));
+ switch (std::get<0>(rColor))
+ {
+ case SwScriptInfo::MarkKind::Point:
+ break;
+ case SwScriptInfo::MarkKind::Start:
+ aStr.append(" " + SwResId(STR_CAPTION_BEGINNING));
+ break;
+ case SwScriptInfo::MarkKind::End:
+ aStr.append(" " + SwResId(STR_CAPTION_END));
+ break;
+ }
+ }
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("colors"),
+ BAD_CAST(aStr.makeStringAndClear().toUtf8().getStr()));
+ }
+
+ (void)xmlTextWriterEndElement(pWriter);
+}
+
bool SwControlCharPortion::Format( SwTextFormatInfo &rInf )
{
const SwLinePortion* pRoot = rInf.GetRoot();