/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership . The ASF licenses this file to you under the Apache
* License , Version 2 . 0 ( the " License " ) ; you may not use this file
* except in compliance with the License . You may obtain a copy of
* the License at http : //www.apache.org/licenses/LICENSE-2.0 .
*/
#include <swrect.hxx>
#include <viewopt.hxx>
#include "porglue.hxx"
#include "inftxt.hxx"
#include "porlay.hxx"
#include "porfly.hxx"
#include <comphelper/string.hxx>
SwGluePortion::SwGluePortion(const SwTwips nInitFixWidth)
: m_nFixWidth( nInitFixWidth )
{
PrtWidth( m_nFixWidth );
SetWhichPor( PortionType::Glue );
}
TextFrameIndex SwGluePortion::GetModelPositionForViewPoint(const SwTwips nOfst) const
{
// FIXME why nOfst > GetLen() ? is that supposed to be > Width() ?
if ( !GetLen() || nOfst > sal_Int32(GetLen()) || !Width() )
return SwLinePortion::GetModelPositionForViewPoint( nOfst );
else
return TextFrameIndex(nOfst / (Width() / sal_Int32(GetLen())));
}
SwPositiveSize SwGluePortion::GetTextSize( const SwTextSizeInfo &rInf ) const
{
if (TextFrameIndex(1 ) >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen())
return SwPositiveSize(*this );
else
return SwPositiveSize((Width() / sal_Int32(GetLen())) * sal_Int32(rInf.GetLen()), Height());
}
bool SwGluePortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
{
if ( GetLen() && rInf.OnWin() &&
rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
{
rText = OUString::Concat(RepeatedUChar(CH_BULLET, GetLen().get()));
return true ;
}
return false ;
}
void SwGluePortion::Paint( const SwTextPaintInfo &rInf ) const
{
if ( !GetLen() )
return ;
if ( rInf.GetFont()->IsPaintBlank() )
{
const sal_Int32 nCount = GetFixWidth() / sal_Int32(GetLen());
OUString aText(OUString::Concat(RepeatedUChar(' ' , nCount)));
SwTextPaintInfo aInf( rInf, &aText );
aInf.DrawText(*this , TextFrameIndex(aText.getLength()), true );
}
if ( !(rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol()) )
return ;
#if OSL_DEBUG_LEVEL > 0
const sal_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
OSL_ENSURE( CH_BLANK == cChar || CH_BULLET == cChar,
"SwGluePortion::Paint: blank expected" );
#endif
if (TextFrameIndex(1 ) == GetLen())
{
OUString aBullet( CH_BULLET );
SwPositiveSize aBulletSize( rInf.GetTextSize( aBullet ) );
Point aPos( rInf.GetPos() );
aPos.AdjustX((Width()/2 ) - (aBulletSize.Width()/2 ) );
SwTextPaintInfo aInf( rInf, &aBullet );
aInf.SetPos( aPos );
SwTextPortion aBulletPor;
aBulletPor.Width( aBulletSize.Width() );
aBulletPor.Height( aBulletSize.Height() );
aBulletPor.SetAscent( GetAscent() );
aInf.DrawText(aBulletPor, TextFrameIndex(aBullet.getLength()), true );
}
else
{
SwTextSlot aSlot( &rInf, this , true , false );
rInf.DrawText( *this , rInf.GetLen(), true );
}
}
void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const tools::Long nPrtGlue )
{
auto nPrt = std::min( nPrtGlue, GetPrtGlue() );
if ( 0 < nPrt )
{
pTarget->AddPrtWidth( nPrt ); //TODO: overflow
SubPrtWidth( nPrt ); //TODO: overflow
}
}
void SwGluePortion::Join( SwGluePortion *pVictim )
{
// The GluePortion is extracted and flushed away ...
AddPrtWidth( pVictim->PrtWidth() );
SetLen( pVictim->GetLen() + GetLen() );
if ( Height() < pVictim->Height() )
Height( pVictim->Height() );
AdjFixWidth();
Cut( pVictim );
delete pVictim;
}
void SwGluePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText,
TextFrameIndex& nOffset) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SwGluePortion" ));
dumpAsXmlAttributes(pWriter, rText, nOffset);
nOffset += GetLen();
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fix-width" ), BAD_CAST(OString::number(m_nFixWidth).getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
/**
* We ' re expecting a frame - local SwRect !
*/
SwFixPortion::SwFixPortion( const SwRect &rRect )
:SwGluePortion(rRect.Width()), m_nFix(rRect.Left())
{
Height(rRect.Height());
SetWhichPor( PortionType::Fix );
}
SwFixPortion::SwFixPortion()
: SwGluePortion(0 ), m_nFix(0 )
{
SetWhichPor( PortionType::Fix );
}
void SwFixPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
{
(void )xmlTextWriterStartElement(pWriter, BAD_CAST("SwFixPortion" ));
dumpAsXmlAttributes(pWriter, rText, nOffset);
nOffset += GetLen();
(void )xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fix" ),
BAD_CAST(OString::number(m_nFix).getStr()));
(void )xmlTextWriterEndElement(pWriter);
}
SwMarginPortion::SwMarginPortion()
:SwGluePortion( 0 )
{
SetWhichPor( PortionType::Margin );
}
/**
* In the outer loop all portions are inspected - the GluePortions
* at the end are processed first .
* The end is shifted forwardly till no more GluePortions remain .
* Always GluePortion - pairs ( pLeft and pRight ) are treated , where
* textportions between pLeft and pRight are moved at the back of
* pRight if pRight has enough Glue . With every move part of the
* Glue is transferred from pRight to pLeft .
* The next loop starts with the processed pLeft as pRight .
*/
void SwMarginPortion::AdjustRight( const SwLineLayout *pCurr )
{
SwGluePortion *pRight = nullptr;
bool bNoMove = nullptr != pCurr->GetpKanaComp();
while ( pRight != this )
{
// 1) We search for the left Glue
SwLinePortion *pPos = this ;
SwGluePortion *pLeft = nullptr;
while ( pPos )
{
if ( pPos->InFixMargGrp() )
pLeft = static_cast <SwGluePortion*>(pPos);
pPos = pPos->GetNextPortion();
if ( pPos == pRight)
pPos = nullptr;
}
// Two adjoining FlyPortions are merged
if ( pRight && pLeft && pLeft->GetNextPortion() == pRight )
{
pRight->MoveAllGlue( pLeft );
pRight = nullptr;
}
auto nRightGlue = pRight && 0 < pRight->GetPrtGlue()
? pRight->GetPrtGlue() : 0 ;
// 2) balance left and right Glue
// But not for tabs ...
if ( pLeft && nRightGlue && !pRight->InTabGrp() )
{
// pPrev is the portion immediately before pRight
SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
if ( pRight->IsFlyPortion() && pRight->GetLen() )
{
SwFlyPortion *pFly = static_cast <SwFlyPortion *>(pRight);
if ( pFly->GetBlankWidth() < nRightGlue )
{
// Creating new TextPortion, that takes over the
// Blank previously swallowed by the Fly.
nRightGlue = nRightGlue - pFly->GetBlankWidth();
pFly->SubPrtWidth( pFly->GetBlankWidth() );
pFly->SetLen(TextFrameIndex(0 ));
SwTextPortion *pNewPor = new SwTextPortion;
pNewPor->SetLen(TextFrameIndex(1 ));
pNewPor->Height( pFly->Height() );
pNewPor->Width( pFly->GetBlankWidth() );
pFly->Insert( pNewPor );
}
else
pPrev = pLeft;
}
while ( pPrev != pLeft )
{
if ( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
pPrev->InHyphGrp() || pPrev->IsKernPortion() )
{
// The portion before the pRight cannot be moved
// because no Glue is remaining.
// We set the break condition:
pPrev = pLeft;
}
else
{
nRightGlue = nRightGlue - pPrev->PrtWidth();
// pPrev is moved behind pRight. For this the
// Glue value between pRight and pLeft gets balanced.
pRight->MoveGlue( pLeft, pPrev->PrtWidth() );
// Now fix the linking of our portions.
SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
pPrevPrev->SetNextPortion( pRight );
pPrev->SetNextPortion( pRight->GetNextPortion() );
pRight->SetNextPortion( pPrev );
if ( pPrev->GetNextPortion() && pPrev->InTextGrp()
&& pPrev->GetNextPortion()->IsHolePortion() )
{
SwHolePortion *pHolePor =
static_cast <SwHolePortion*>(pPrev->GetNextPortion());
if ( !pHolePor->GetNextPortion() ||
!pHolePor->GetNextPortion()->InFixMargGrp() )
{
pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
pPrev->SetLen(pPrev->GetLen() + TextFrameIndex(1 ));
pPrev->SetNextPortion( pHolePor->GetNextPortion() );
delete pHolePor;
}
}
pPrev = pPrevPrev;
}
}
}
// If no left Glue remains, we set the break condition.
pRight = pLeft ? pLeft : this ;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=94 H=95 G=94
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
*Bot Zugriff