/* -*- 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 .
*/
if(!bHandleContour)
{ // RotateFlyFrame3: Object has no set contour, but for rotated // FlyFrames we can create a 'default' contour to make text // flow around the free, non-covered const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(pAnchoredObj));
void SwTextFly::CtorInitTextFly( const SwTextFrame *pFrame )
{
mbIgnoreCurrentFrame = false;
mbIgnoreContour = false;
mbIgnoreObjsInHeaderFooter = false;
m_pPage = pFrame->FindPageFrame(); const SwFlyFrame* pTmp = pFrame->FindFlyFrame(); // #i68520#
mpCurrAnchoredObj = pTmp;
m_pCurrFrame = pFrame;
m_pMaster = m_pCurrFrame->IsFollow() ? nullptr : m_pCurrFrame; // If we're not overlapped by a frame or if a FlyCollection does not exist // at all, we switch off forever. // It could be, however, that a line is added while formatting, that // extends into a frame. // That's why we do not optimize for: bOn = pSortedFlys && IsAnyFrame();
m_bOn = m_pPage->GetSortedObjs() != nullptr;
m_bTopRule = true;
m_nMinBottom = 0;
m_nNextTop = 0;
m_nCurrFrameNodeIndex = NODE_OFFSET_MAX;
}
const SwSortedObjs *pSorted = m_pPage->GetSortedObjs(); if( pSorted ) // bOn actually makes sure that we have objects on the side, // but who knows who deleted something in the meantime?
{ for ( size_t i = 0; i < pSorted->size(); ++i )
{ const SwAnchoredObject* pObj = (*pSorted)[i];
// #i68520# // bEvade: consider pNew, if we are not inside a fly // consider pNew, if pNew is lower of <mpCurrAnchoredObj> bool bEvade = !mpCurrAnchoredObj ||
Is_Lower_Of( mpCurrAnchoredObj->DynCastFlyFrame(), pNew);
auto pFly = _pAnchoredObj->DynCastFlyFrame(); if (pFly && pFly->IsFlySplitAllowed())
{ // Check if _pAnchoredObj is a split fly inside an other split fly. Always collect such // flys, otherwise the inner anchor text will overlap with the inner fly.
SwFrame* pFlyAnchor = const_cast<SwAnchoredObject*>(_pAnchoredObj)
->GetAnchorFrameContainingAnchPos(); if (pFlyAnchor && pFlyAnchor->IsInFly())
{ auto pOuterFly = pFlyAnchor->FindFlyFrame(); if (pOuterFly && pOuterFly->IsFlySplitAllowed())
{ returntrue;
}
}
}
if ( !bEvade )
{ // We are currently inside a fly frame and pNew is not // inside this fly frame. We can do some more checks if // we have to consider pNew.
// If bTopRule is not set, we ignore the frame types. // We directly check the z-order if ( !m_bTopRule )
bEvade = true; else
{ // Within chained Flys we only avoid Lower // #i68520# const SwFrameFormat* pCurObjFormat = mpCurrAnchoredObj->GetFrameFormat(); const SwFormatChain& rChain = pCurObjFormat->GetChain(); if ( !rChain.GetPrev() && !rChain.GetNext() )
{ // #i26945# const SwFormatAnchor& rNewA = _pAnchoredObj->GetFrameFormat()->GetAnchor(); // #i68520# const SwFormatAnchor& rCurrA = pCurObjFormat->GetAnchor();
// If <mpCurrAnchoredObj> is anchored as character, its content // does not wrap around pNew if (RndStdIds::FLY_AS_CHAR == rCurrA.GetAnchorId()) returnfalse;
// If pNew is anchored to page and <mpCurrAnchoredObj is not anchored // to page, the content of <mpCurrAnchoredObj> does not wrap around pNew // If both pNew and <mpCurrAnchoredObj> are anchored to page, we can do // some more checks if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId())
{ if (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId())
{
bEvade = true;
} else returnfalse;
} elseif (RndStdIds::FLY_AT_PAGE == rCurrA.GetAnchorId()) returnfalse; // Page anchored ones only avoid page anchored ones elseif (RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId())
bEvade = true; // Non-page anchored ones avoid frame anchored ones elseif( RndStdIds::FLY_AT_FLY == rCurrA.GetAnchorId() ) returnfalse; // Frame anchored ones do not avoid paragraph anchored ones // #i57062# // In order to avoid loop situation, it's decided to adjust // the wrapping behaviour of content of at-paragraph/at-character // anchored objects to one in the page header/footer and // the document body --> content of at-paragraph/at-character // anchored objects doesn't wrap around each other. else returnfalse;
}
}
// But: we never avoid a subordinate one and additionally we only avoid when overlapping. // #i68520#
bEvade &= ( mpCurrAnchoredObj->GetDrawObj()->GetOrdNum() < pNew->GetOrdNum() ); if( bEvade )
{ // #i68520# const SwRect& aTmp( _pAnchoredObj->GetObjRectWithSpaces() ); if ( !aTmp.Overlaps( mpCurrAnchoredObj->GetObjRectWithSpaces() ) )
bEvade = false;
}
}
if ( bEvade )
{ // #i26945# if (const SwFrameFormat* pAnchoredObjFormat = _pAnchoredObj->GetFrameFormat())
{ const SwFormatAnchor& rNewA = pAnchoredObjFormat->GetAnchor();
OSL_ENSURE(RndStdIds::FLY_AS_CHAR != rNewA.GetAnchorId(), "Don't call GetTop with a FlyInContentFrame"); if (RndStdIds::FLY_AT_PAGE == rNewA.GetAnchorId()) returntrue; // We always avoid page anchored ones
// If Flys anchored at paragraph are caught in a FlyCnt, then // their influence ends at the borders of the FlyCnt! // If we are currently formatting the text of the FlyCnt, then // it has to get out of the way of the Frame anchored at paragraph! // m_pCurrFrame is the anchor of pNew? // #i26945# const SwFrame* pTmp = _pAnchoredObj->GetAnchorFrame(); if (pTmp == m_pCurrFrame) returntrue; if (pTmp->IsTextFrame() && (pTmp->IsInFly() || pTmp->IsInFootnote()))
{ // #i26945#
Point aPos = _pAnchoredObj->GetObjRect().Pos();
pTmp = GetVirtualUpper(pTmp, aPos);
} // #i26945# // If <pTmp> is a text frame inside a table, take the upper // of the anchor frame, which contains the anchor position. elseif (pTmp->IsTextFrame() && pTmp->IsInTab())
{
pTmp = const_cast<SwAnchoredObject*>(_pAnchoredObj)
->GetAnchorFrameContainingAnchPos()
->GetUpper();
} // #i28701# - consider all objects in same context, // if wrapping style is considered on object positioning. // Thus, text will wrap around negative positioned objects. // #i3317# - remove condition on checking, // if wrappings style is considered on object positioning. // Thus, text is wrapping around negative positioned objects. // #i35640# - no consideration of negative // positioned objects, if wrapping style isn't considered on // object position and former text wrapping is applied. // This condition is typically for documents imported from the // OpenOffice.org file format. const IDocumentSettingAccess* pIDSA
= &m_pCurrFrame->GetDoc().getIDocumentSettingAccess(); if ((pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION)
|| !pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING))
&& ::FindContext(pTmp, SwFrameType::None)
== ::FindContext(m_pCurrFrame, SwFrameType::None))
{ returntrue;
}
const SwFrame* pHeader = nullptr; if (m_pCurrFrame->GetNext() != pTmp
&& (IsFrameInSameContext(pTmp, m_pCurrFrame) || // #i13832#, #i24135# wrap around objects in page header
(!pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING)
&& nullptr != (pHeader = pTmp->FindFooterOrHeader())
&& m_pCurrFrame->IsInDocBody())))
{ if (pHeader || RndStdIds::FLY_AT_FLY == rNewA.GetAnchorId()) returntrue;
// Compare indices: // The Index of the other is retrieved from the anchor attr.
SwNodeOffset nTmpIndex = rNewA.GetAnchorNode()->GetIndex(); // Now check whether the current paragraph is before the anchor // of the displaced object in the text, then we don't have to // get out of its way. // If possible determine Index via SwFormatAnchor because // otherwise it's quite expensive. if (NODE_OFFSET_MAX == m_nCurrFrameNodeIndex)
m_nCurrFrameNodeIndex = m_pCurrFrame->GetTextNodeFirst()->GetIndex();
for( size_t i = 0; i < nCount; ++i )
{ // #i68520# // do not consider hidden objects // check, if object has to be considered for text wrap // #118809# - If requested, do not consider // objects in page header|footer for text frames not in page // header|footer. This is requested for the calculation of // the base offset for objects <SwTextFrame::CalcBaseOfstForFly()> // #i20505# Do not consider oversized objects
SwAnchoredObject* pAnchoredObj = (*pSorted)[ i ];
assert(pAnchoredObj); if ( !pAnchoredObj ||
!rIDDMA.IsVisibleLayerId( pAnchoredObj->GetDrawObj()->GetLayer() ) ||
!pAnchoredObj->ConsiderForTextWrap() ||
( mbIgnoreObjsInHeaderFooter && !bFooterHeader &&
pAnchoredObj->GetAnchorFrame()->FindFooterOrHeader() ) ||
( bAllowCompatWrap && !pAnchoredObj->GetFrameFormat()->GetFollowTextFlow().GetValue() )
)
{ continue;
}
// #i26945# - pass <pAnchoredObj> to method // <GetTop(..)> instead of only the <SdrObject> instance of the // anchored object if (GetTop(pAnchoredObj, m_pCurrFrame->IsInFootnote(), bFooterHeader))
{ // OD 11.03.2003 #107862# - adjust insert position: // overlapping objects should be sorted from left to right and // inside left to right sorting from top to bottom. // If objects on the same position are found, they are sorted // on its width. // #i68520#
{
SwAnchoredObjList::iterator aInsPosIter =
std::lower_bound( mpAnchoredObjList->begin(),
mpAnchoredObjList->end(),
pAnchoredObj,
AnchoredObjOrder( bR2L, aRectFnSet.FnRect() ) );
SwTwips SwTextFly::GetMaxBottom(const SwBreakPortion& rPortion, const SwTextFormatInfo& rInfo) const
{ // Note that m_pCurrFrame is already swapped at this stage, so it's correct to bypass // SwRectFnSet here.
SwTwips nRet = 0;
size_t nCount(m_bOn ? GetAnchoredObjList().size() : 0);
// Get the horizontal position of the break portion in absolute twips. The frame area is in // absolute twips, the frame's print area is relative to the frame area. Finally the portion's // position is relative to the frame's print area.
SwTwips nX = rInfo.X();
nX += m_pCurrFrame->getFrameArea().Left();
nX += m_pCurrFrame->getFramePrintArea().Left();
for (size_t i = 0; i < nCount; ++i)
{ const SwAnchoredObject* pAnchoredObj = (*mpAnchoredObjList)[i];
if (pAnchoredObj->GetAnchorFrame()->FindFooterOrHeader())
{ // Anchored in the header or footer, ignore it for clearing break purposes. continue;
}
const SwFormatSurround& rSurround = pAnchoredObj->GetFrameFormat()->GetSurround(); if (rSurround.GetValue() == text::WrapTextMode_THROUGH)
{ // Wrap through has no influence on clearing breaks. continue;
}
if (m_pCurrFrame->IsVertical())
{
m_pCurrFrame->SwitchVerticalToHorizontal(aRect);
}
if (rPortion.GetClear() == SwLineBreakClear::LEFT)
{ if (nX < aRect.Left())
{ // Want to jump down to the first line that's unblocked on the left. This object is // on the right of the break, ignore it. continue;
}
} if (rPortion.GetClear() == SwLineBreakClear::RIGHT)
{ if (nX > aRect.Right())
{ // Want to jump down to the first line that's unblocked on the right. This object is // on the left of the break, ignore it. continue;
}
}
SwTwips nBottom = aRect.Top() + aRect.Height(); if (nBottom > nRet)
{
nRet = nBottom;
}
} return nRet;
}
// tdf#127235 stop if the area is larger than the page if( aRectFnSet.GetHeight(m_pPage->getFrameArea()) < aRectFnSet.GetHeight(rRect))
{ // get the doc model description const SwPageDesc* pPageDesc = m_pPage->GetPageDesc();
// if there is no next page style or it is the same as the current // => stop trying to place the frame (it would end in an infinite loop) if( pPageDesc &&
( !pPageDesc->GetFollow() || pPageDesc->GetFollow() == pPageDesc) )
{ returnfalse;
}
}
// #i68520# if ( mpCurrAnchoredObj != pAnchoredObj && aRect.Overlaps( rRect ) )
{ // #i68520# const SwFormat* pFormat(pAnchoredObj->GetFrameFormat()); const SwFormatSurround &rSur = pFormat->GetSurround(); if( bAvoid )
{ // If the text flows below, it has no influence on // formatting. In LineIter::DrawText() it is "just" // necessary to cleverly set the ClippingRegions const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); if( ( css::text::WrapTextMode_THROUGH == rSur.GetSurround() &&
( !rSur.IsAnchorOnly() || // #i68520#
GetMaster() == pAnchoredObj->GetAnchorFrame() ||
((RndStdIds::FLY_AT_PARA != rAnchor.GetAnchorId()) &&
(RndStdIds::FLY_AT_CHAR != rAnchor.GetAnchorId())) ) )
|| aRect.Top() == FAR_AWAY ) continue;
}
// #i58642# // Compare <GetMaster()> instead of <m_pCurrFrame> with the // anchor frame of the anchored object, because a follow frame // has to ignore the anchored objects of its master frame. // Note: Anchored objects are always registered at the master // frame, exception are as-character anchored objects, // but these aren't handled here. // #i68520# if ( mbIgnoreCurrentFrame &&
GetMaster() == pAnchoredObj->GetAnchorFrame() ) continue;
// #i68520# void SwTextFly::CalcRightMargin( SwRect &rFly,
SwAnchoredObjList::size_type nFlyPos, const SwRect &rLine ) const
{ // Usually the right margin is the right margin of the Printarea
OSL_ENSURE( !m_pCurrFrame->IsVertical() || !m_pCurrFrame->IsSwapped(), "SwTextFly::CalcRightMargin with swapped frame" );
SwRectFnSet aRectFnSet(m_pCurrFrame); // #118796# - correct determination of right of printing area
SwTwips nRight = aRectFnSet.GetPrtRight(*m_pCurrFrame);
SwTwips nFlyRight = aRectFnSet.GetRight(rFly);
SwRect aLine( rLine );
aRectFnSet.SetRight( aLine, nRight );
aRectFnSet.SetLeft( aLine, aRectFnSet.GetLeft(rFly) );
// It is possible that there is another object that is _above_ us // and protrudes into the same line. // Flys with run-through are invisible for those below, i.e., they // are ignored for computing the margins of other Flys. // 3301: pNext->getFrameArea().Overlaps( rLine ) is necessary // #i68520#
css::text::WrapTextMode eSurroundForTextWrap;
// optimization: // Record in nNextTop at which Y-position frame related changes are // likely. This is so that, despite only looking at frames in the // current line height, for frames without wrap the line height is // incremented so that with a single line the lower border of the frame // (or possibly the upper border of another frame) is reached. // Especially in HTML documents there are often (dummy) paragraphs in // 2 pt font, and they used to only evade big frames after huge numbers // of empty lines. const tools::Long nTmpTop = aRectFnSet.GetTop(aTmp); if( aRectFnSet.YDiff( nTmpTop, aRectFnSet.GetTop(aLine) ) > 0 )
{ if( aRectFnSet.YDiff( m_nNextTop, nTmpTop ) > 0 )
SetNextTop( nTmpTop ); // upper border of next frame
} elseif (!aRectFnSet.GetWidth(aTmp)) // typical for Objects with contour wrap
{ // For Objects with contour wrap that start before the current // line, and end below it, but do not actually overlap it, the // optimization has to be disabled, because the circumstances // can change in the next line. if( ! aRectFnSet.GetHeight(aTmp) ||
aRectFnSet.YDiff( aRectFnSet.GetBottom(aTmp),
aRectFnSet.GetTop(aLine) ) > 0 )
SetNextTop( 0 );
} if( aTmp.Overlaps( aLine ) && nTmpRight > nFlyRight )
{
nFlyRight = nTmpRight; if( css::text::WrapTextMode_RIGHT == eSurroundForTextWrap ||
css::text::WrapTextMode_PARALLEL == eSurroundForTextWrap )
{ // overrule the FlyFrame if( nRight > nFlyRight )
nRight = nFlyRight;
bStop = true;
}
}
}
aRectFnSet.SetRight( rFly, nRight );
}
// #i68520# void SwTextFly::CalcLeftMargin( SwRect &rFly,
SwAnchoredObjList::size_type nFlyPos, const SwRect &rLine ) const
{
OSL_ENSURE( !m_pCurrFrame->IsVertical() || !m_pCurrFrame->IsSwapped(), "SwTextFly::CalcLeftMargin with swapped frame" );
SwRectFnSet aRectFnSet(m_pCurrFrame); // #118796# - correct determination of left of printing area
SwTwips nLeft = aRectFnSet.GetPrtLeft(*m_pCurrFrame); const SwTwips nFlyLeft = aRectFnSet.GetLeft(rFly);
// It is possible that there is another object that is _above_ us // and protrudes into the same line. // Flys with run-through are invisible for those below, i.e., they // are ignored for computing the margins of other Flys. // 3301: pNext->getFrameArea().Overlaps( rLine ) is necessary
// so the line may grow up to the lower edge of the frame
SetNextTop( aRectFnSet.GetBottom(aFly) );
SwAnchoredObjList::size_type nFlyPos = GetPos( pAnchoredObj );
// LEFT and RIGHT, we grow the rectangle. // We have some problems, when several frames are to be seen. // At the moment, only the easier case is assumed: // + LEFT means that the text must flow on the left of the frame, // that is the frame expands to the right edge of the print area // or to the next frame. // + RIGHT is the opposite. // Otherwise the set distance between text and frame is always // added up. switch( GetSurroundForTextWrap( pAnchoredObj ) )
{ case css::text::WrapTextMode_LEFT :
{
CalcRightMargin( aFly, nFlyPos, rLine ); break;
} case css::text::WrapTextMode_RIGHT :
{
CalcLeftMargin( aFly, nFlyPos, rLine ); break;
} case css::text::WrapTextMode_NONE :
{
CalcRightMargin( aFly, nFlyPos, rLine );
CalcLeftMargin( aFly, nFlyPos, rLine ); break;
} default: break;
} return aFly;
}
// #i68520#
// Wrap only on sides with at least 2cm space for the text #define TEXT_MIN 1134
// Wrap on both sides up to a frame width of 1.5cm #define FRAME_MAX 850
// in cause of run-through and nowrap ignore smartly if( css::text::WrapTextMode_THROUGH == eSurroundForTextWrap ||
css::text::WrapTextMode_NONE == eSurroundForTextWrap ) return eSurroundForTextWrap;
// left is left and right is right if (m_pCurrFrame->IsRightToLeft())
{ if ( css::text::WrapTextMode_LEFT == eSurroundForTextWrap )
eSurroundForTextWrap = css::text::WrapTextMode_RIGHT; elseif ( css::text::WrapTextMode_RIGHT == eSurroundForTextWrap )
eSurroundForTextWrap = css::text::WrapTextMode_LEFT;
}
// In case there is no space on either side, then css::text::WrapTextMode_PARALLEL // gives the same result when doing the initial layout or a layout // update after editing, so prefer that over css::text::WrapTextMode_NONE. if (nLeft == 0 && nRight == 0) return css::text::WrapTextMode_PARALLEL;
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.