/* -*- 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 .
*/
// We lock it, to start with
OSL_ENSURE( !IsLocked(), "SwTextFrame::Hyphenate: this is locked" );
// The frame::Frame must have a valid SSize!
Calc(pRenderContext);
GetFormatted();
bool bRet = false; if( !IsEmpty() )
{ // We always need to enable hyphenation // Don't be afraid: the SwTextIter saves the old row in the hyphenate
TextFrameLockGuard aLock( this );
// If we're within the first word of a row, it could've been hyphenated // in the row earlier. // That's why we go one row back. if( aLine.Prev() )
{
SwLinePortion *pPor = aLine.GetCurr()->GetFirstPortion(); while( pPor->GetNextPortion() )
pPor = pPor->GetNextPortion(); if( pPor->GetWhichPor() == PortionType::SoftHyphen ||
pPor->GetWhichPor() == PortionType::SoftHyphenStr )
aLine.Next();
}
if ( IsVertical() )
SwapWidthAndHeight();
} return bRet;
}
/** * We format a row for interactive hyphenation * We can assume that we've already formatted. * We just reformat the row, the hyphenator will be prepared like * the UI expects it to be. * TODO: We can of course optimize this a lot.
*/ void SetParaPortion( SwTextInfo *pInf, SwParaPortion *pRoot )
{
OSL_ENSURE( pRoot, "SetParaPortion: no root anymore" );
pInf->m_pPara = pRoot;
}
// We never need to hyphenate anything in the last row // Except for, if it contains a FlyPortion or if it's the // last row of the Master if( !GetNext() && !rInf.GetTextFly().IsOn() && !m_pFrame->GetFollow() ) returnfalse;
TextFrameIndex nWrdStart = m_nStart;
// We need to retain the old row // E.g.: The attribute for hyphenation was not set, but // it's always set in SwTextFrame::Hyphenate, because we want // to set breakpoints.
SwLineLayout *pOldCurr = m_pCurr;
InitCntHyph();
// 5298: IsParaLine() (ex.IsFirstLine) calls GetParaPortion(). // We have to create the same conditions: in the first line // we format SwParaPortions... if( pOldCurr->IsParaPortion() )
{
SwParaPortion *pPara = new SwParaPortion();
SetParaPortion( &rInf, pPara );
m_pCurr = pPara;
OSL_ENSURE( IsParaLine(), "SwTextFormatter::Hyphenate: not the first" );
} else
m_pCurr = new SwLineLayout();
nWrdStart = FormatLine( nWrdStart );
// You always should keep in mind that for example there are fields // which can be hyphenated if( m_pCurr->PrtWidth() && m_pCurr->GetLen() )
{ // We must be prepared that there are FlyFrames in the line, // at which line breaking is possible. So we search for the first // HyphPortion in the specified range.
SwLinePortion *pPos = m_pCurr->GetNextPortion(); const TextFrameIndex nPamStart = rHyphInf.m_nStart;
nWrdStart = m_nStart; const TextFrameIndex nEnd = rHyphInf.m_nEnd; while( pPos )
{ // Either we are above or we are running into a HyphPortion // at the end of line or before a Fly. if( nWrdStart >= nEnd )
{
nWrdStart = TextFrameIndex(0); break;
}
nWrdStart = nWrdStart + pPos->GetLen();
pPos = pPos->GetNextPortion();
} // When pPos is null, no hyphen position was found. if( !pPos )
nWrdStart = TextFrameIndex(0);
} else // In case the whole line is zero-length, that's the same situation as // above when the portion iteration ends without explicitly breaking // from the loop.
nWrdStart = TextFrameIndex(0);
// the old LineLayout is set again ... delete m_pCurr;
m_pCurr = pOldCurr;
if( pOldCurr->IsParaPortion() )
{
SetParaPortion( &rInf, static_cast<SwParaPortion*>(pOldCurr) );
OSL_ENSURE( IsParaLine(), "SwTextFormatter::Hyphenate: even not the first" );
}
if (nWrdStart == TextFrameIndex(0)) returnfalse;
// nWrdStart contains the position in string that should be hyphenated
rHyphInf.m_nWordStart = nWrdStart;
OSL_ENSURE( !mpNextPortion, "SwTextPortion::CreateHyphen(): another portion, another planet..." );
OSL_ENSURE( xHyphWord.is(), "SwTextPortion::CreateHyphen(): You are lucky! The code is robust here." );
// first case: hyphenated word has alternative spelling if ( xHyphWord->isAlternativeSpelling() )
{
SvxAlternativeSpelling aAltSpell = SvxGetAltSpelling( xHyphWord );
OSL_ENSURE( aAltSpell.bIsAltSpelling, "no alternative spelling" );
// values required for this
nPorEnd = TextFrameIndex(xHyphWord->getHyphenPos() + 1)
+ rGuess.BreakStart() - rGuess.FieldDiff();
}
// portion end must be in front of us // we do not put hyphens at start of line if ( nPorEnd > rInf.GetIdx() ||
( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
{
aInf.SetLen( nPorEnd - rInf.GetIdx() ); if (auto stClampedContext = aInf.GetLayoutContext(); stClampedContext.has_value())
{
stClampedContext->m_nEnd = nPorEnd.get();
aInf.SetLayoutContext(stClampedContext);
}
SwTwips SwSoftHyphPortion::GetViewWidth(const SwTextSizeInfo& rInf) const
{ // Although we're in the const, nViewWidth should be calculated at // the last possible moment if( !Width() && rInf.OnWin() && rInf.GetOpt().IsSoftHyph() && !IsExpand() )
{ if( !m_nViewWidth ) const_cast<SwSoftHyphPortion*>(this)->m_nViewWidth
= rInf.GetTextSize(OUString('-')).Width();
} else const_cast<SwSoftHyphPortion*>(this)->m_nViewWidth = 0; return m_nViewWidth;
}
/** * Cases: * * 1) SoftHyph is in the line, ViewOpt off * -> invisible, neighbors unchanged * 2) SoftHyph is in the line, ViewOpt on * -> visible, neighbors unchanged * 3) SoftHyph is at the end of the line, ViewOpt on or off * -> always visible, neighbors unchanged
*/ void SwSoftHyphPortion::Paint( const SwTextPaintInfo &rInf ) const
{ if ( Width() )
{
rInf.DrawViewOpt( *this, PortionType::SoftHyphen );
SwExpandPortion::Paint( rInf );
/** * We get the final width from the FormatEOL() * * During the underflow-phase we determine, whether or not * there's an alternative spelling at all ... * * Case 1: "Au-to" * 1) {Au}{-}{to}, {to} does not fit anymore => underflow * 2) {-} calls hyphenate => no alternative * 3) FormatEOL() and bFull = true * * Case 2: "Zuc-ker" * 1) {Zuc}{-}{ker}, {ker} does not fit anymore => underflow * 2) {-} calls hyphenate => alternative! * 3) Underflow() and bFull = true * 4) {Zuc} calls hyphenate => {Zuk}{-}{ker}
*/ bool SwSoftHyphPortion::Format( SwTextFormatInfo &rInf )
{ bool bFull = true;
// special case for old German spelling if( rInf.IsUnderflow() )
{ if( rInf.GetSoftHyphPos() ) returntrue;
constbool bHyph = rInf.ChgHyph( true ); if( rInf.IsHyphenate() )
{
rInf.SetSoftHyphPos( rInf.GetIdx() );
Width(0); // if the soft hyphened word has an alternative spelling // when hyphenated (old German spelling), the soft hyphen // portion has to trigger an underflow
SwTextGuess aGuess;
bFull = rInf.IsInterHyph() ||
!aGuess.AlternativeSpelling(rInf, rInf.GetIdx() - TextFrameIndex(1));
}
rInf.ChgHyph( bHyph );
rInf.SetSoftHyphPos(TextFrameIndex(0));
SetExpand( true );
bFull = SwHyphPortion::Format( rInf );
SetExpand( false ); if( !bFull )
{ // By default, we do not have a width, but we do have a height
Width(0);
} return bFull;
}
/** * Format End of Line
*/ void SwSoftHyphPortion::FormatEOL( SwTextFormatInfo &rInf )
{ if( IsExpand() ) return;
// We need to reset the old values const SwTwips nOldX = rInf.X();
TextFrameIndex const nOldIdx = rInf.GetIdx();
rInf.X( rInf.X() - PrtWidth() );
rInf.SetIdx( rInf.GetIdx() - GetLen() ); constbool bFull = SwHyphPortion::Format( rInf );
// Shady business: We're allowed to get wider, but a Fly is also // being processed, which needs a correct X position if( bFull || !rInf.GetFly() )
rInf.X( nOldX ); else
rInf.X( nOldX + Width() );
rInf.SetIdx( nOldIdx );
}
/** * We're expanding: * - if the special characters should be visible * - if we're at the end of the line * - if we're before a (real/emulated) line break
*/ bool SwSoftHyphPortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
{ if( IsExpand() || ( rInf.OnWin() && rInf.GetOpt().IsSoftHyph() ) ||
( GetNextPortion() && ( GetNextPortion()->InFixGrp() ||
GetNextPortion()->IsDropPortion() || GetNextPortion()->IsLayPortion() ||
GetNextPortion()->IsParaPortion() || GetNextPortion()->IsBreakPortion() ) ) )
{ return SwHyphPortion::GetExpText( rInf, rText );
} returnfalse;
}
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.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.