/* -*- 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 .
*/
// 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) return;
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);
// 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);
}
}
}
// sw_redlinehide: just disable FormatEmpty optimisation for now // 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 (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. returnfalse;
}
// only need to check one node because of early return on GetMerged() for (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
pIndex; pIndex = pIndex->GetNext())
{ if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark) continue; autoconst pMark = static_cast<sw::mark::MarkBase const*>(pIndex->GetOwner()); if (dynamic_cast<const sw::mark::Bookmark*>(pMark) != nullptr)
{ // need bookmark portions! returnfalse;
}
}
if (aSet.GetParaGrid().GetValue() &&
IsInDocBody() )
{
SwTextGridItem const*const pGrid(GetGridItem(FindPageFrame())); if ( pGrid )
nHeight = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
}
SwRectFnSet aRectFnSet(this);
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);
}
}
// #i35635# - call method <HideAndShowObjects()> // to assure that objects anchored at the empty paragraph are // correctly visible resp. invisible.
HideAndShowObjects(); returntrue;
}
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())
{ returnfalse;
}
rOutString = OUStringChar(mcChar);
// init font: we want OpenSymbol to ensure it doesn't look too crazy; // thin and a bit higher than the surrounding text autoconst nOrigAscent(rFont.GetAscent(rTextPaintInfo.GetVsh(), *rTextPaintInfo.GetOut()));
rFont.SetName(u"OpenSymbol"_ustr, rFont.GetActual());
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
assert(aSize.Height() != 0); autoconst nFactor = aSize.Height() > 0 ? (Height() * 95) / aSize.Height() : Height();
rFont.SetProportion(nFactor);
rFont.SetWeight(WEIGHT_THIN, rFont.GetActual());
rFont.SetColor(rTextPaintInfo.GetOpt().GetFieldShadingsColor()); // reset these to default...
rFont.SetAlign(ALIGN_BASELINE);
rFont.SetUnderline(LINESTYLE_NONE);
rFont.SetOverline(LINESTYLE_NONE);
rFont.SetStrikeout(STRIKEOUT_NONE);
rFont.SetOutline(false);
rFont.SetShadow(false);
rFont.SetTransparent(false);
rFont.SetEmphasisMark(FontEmphasisMark::NONE);
rFont.SetEscapement(0);
rFont.SetPitch(PITCH_DONTKNOW, rFont.GetActual());
rFont.SetRelief(FontRelief::NONE);
// adjust Y position to account for different baselines of the fonts autoconst nOSAscent(rFont.GetAscent(rTextPaintInfo.GetVsh(), *rTextPaintInfo.GetOut()));
rDeltaY = nOSAscent - nOrigAscent;
returntrue;
}
void SwControlCharPortion::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;
auto nHeight = rInf.GetTextSize( aOutString ).Height();
Point aOldPos = rInf.GetPos();
Point aNewPos( aOldPos ); autoconst 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(mnHalfCharWidth * -2 * (m_aColors.size() - 1));
} elseif ( m_nStart != 0 && m_nEnd != 0 ) // both end and start boundary marks: adjust them around the bookmark position // |te|xt| // ]] [[
aNewPos.AdjustX(mnHalfCharWidth * -(2 * m_nEnd - 1 + m_nPoint) );
// 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 );
// show rdf:type labels, left-aligned top position after the opening brackets // right-aligned bottom position before the closing brackets // if there are multiple opening or closing brackets, collect // their length in nTypePos to show non-overlapping labels
OUString sType = std::get<3>(it); if ( !sType.isEmpty() )
{
Size aTmpSz = aTmpFont.GetSize( SwFontScript::Latin ); auto origSize = aTmpSz;
// restore original position
aNewPos.AdjustX( -nDirection * nTypePos ); if ( nDirection == 1 )
nTypePos += aTextSize.Width() +
rInf.GetTextSize( " " ).Width() - mnHalfCharWidth * 2;
aNewPos.AdjustY(-fPos);
} // restore original text size
aTmpSz.setHeight(origSize.Height());
aTmpSz.setWidth(origSize.Width());
aTmpFont.SetSize( origSize, SwFontScript::Latin );
}
// place the next symbol after the previous one // TODO: fix orientation and start/end
aNewPos.AdjustX(mnHalfCharWidth * 2); const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
}
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.