Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  porrst.cxx   Sprache: C

 
/* -*- 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 <editeng/lspcitem.hxx>
#include <editeng/adjustitem.hxx>
#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>
#include <pagefrm.hxx>
#include <paratr.hxx>
#include <SwPortionHandler.hxx>
#include "porrst.hxx"
#include "inftxt.hxx"
#include "txtpaint.hxx"
#include <swfntcch.hxx>
#include <tgrditem.hxx>
#include <pagedesc.hxx>
#include <frmatr.hxx>
#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,
                const FontStrikeout eStrkout,
                const Color& rCol ) :
    m_eUnderline( eUL ), m_eStrikeout( eStrkout ), m_aColor( rCol )
{
    Height( rPortion.Height() );
    SetAscent( rPortion.GetAscent() );
    SetWhichPor( PortionType::TempEnd );
}

void SwTmpEndPortion::Paint( const SwTextPaintInfo &rInf ) const
{
    if (!(rInf.OnWin() && rInf.GetOpt().IsParagraph()))
        return;

    const SwFont* pOldFnt = rInf.GetFont();

    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()).
    if ( m_eUnderline != LINESTYLE_NONE || m_eStrikeout != STRIKEOUT_NONE )
    {
        aFont.SetColor( m_aColor );
        aFont.SetUnderline( m_eUnderline );
        aFont.SetStrikeout( m_eStrikeout );

        const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont);

        // draw the pilcrow with strikeout/underline in redline color
        rInf.DrawText(CH_PAR, *this);

    }

    aFont.SetColor( SwViewOption::GetCurrentViewOptions().GetNonPrintingCharacterColor() );
    aFont.SetStrikeout( STRIKEOUT_NONE );
    aFont.SetUnderline( LINESTYLE_NONE );
    const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont);

    // draw the pilcrow
    rInf.DrawText(CH_PAR, *this);

    const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt));
}

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 SwTwips) const
{
    return TextFrameIndex(0);
}

SwTwips SwBreakPortion::GetViewWidth(const SwTextSizeInfo&) const { return 0; }

SwLinePortion *SwBreakPortion::Compress()
return (GetNextPortion() && GetNextPortion()->InTextGrp() ? nullptr : this); }

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)
        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);

        const SwFont* pOldFnt = rInf.GetFont();

        SwFont aFont(*pOldFnt);

        if (m_eRedline == RedlineType::Delete)
            aFont.SetUnderline( LINESTYLE_NONE );
        else
            aFont.SetStrikeout( STRIKEOUT_NONE );

        const_cast<SwTextPaintInfo&>(rInf).SetFont(&aFont);

        rInf.DrawText(aBuf.makeStringAndClear(), *this);

        const_cast<SwTextPaintInfo&>(rInf).SetFont(const_cast<SwFont*>(pOldFnt));
    }
}

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 );
    return true;
}

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 )
{
    Height( rPortion.Height() );
    SetAscent( rPortion.GetAscent() );
    mnLineLength = TextFrameIndex(0);
    SetWhichPor( PortionType::Kern );
    if( m_nKern > 0 )
        Width( m_nKern );
    rPortion.Insert( this );
}

SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) :
    m_nKern( 0 ), m_bBackground( false ), m_bGridKern( true )
{
    Height( rPortion.Height() );
    SetAscent( rPortion.GetAscent() );

    mnLineLength = TextFrameIndex(0);
    SetWhichPor( PortionType::Kern );
}

void SwKernPortion::Paint( const SwTextPaintInfo &rInf ) const
{
    if( !Width() )
        return;

    // bBackground is set for Kerning Portions between two fields
    if ( m_bBackground )
        rInf.DrawViewOpt( *this, PortionType::Field );

    rInf.DrawBackBrush( *this );
    if (GetJoinBorderWithNext() ||GetJoinBorderWithPrev())
        rInf.DrawBorder( *this );

    // do we have to repaint a post it portion?
    if( rInf.OnWin() && mpNextPortion && !mpNextPortion->Width() )
        mpNextPortion->PrePaint( rInf, this );

    if( rInf.GetFont()->IsPaintBlank() )
    {
        SwRect aClipRect;
        rInf.CalcRect( *this, &aClipRect );
        SwSaveClip aClip( const_cast<OutputDevice*>(rInf.GetOut()) );
        aClip.ChgClip( aClipRect );
        rInf.DrawText(u" "_ustr, *this, TextFrameIndex(0), TextFrameIndex(2), true );
    }
}

void SwKernPortion::FormatEOL( SwTextFormatInfo &rInf )
{
    if ( m_bGridKern )
        return;

    if( rInf.GetLast() == this )
        rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
    if( m_nKern < 0 )
        Width( -m_nKern );
    else
        Width( 0 );
    rInf.GetLast()->FormatEOL( rInf );
}

SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) :
    m_bLeft( true )
{
    Height( rPortion.Height() );
    SetAscent( rPortion.GetAscent() );
    mnLineLength = TextFrameIndex(0);
    SetWhichPor( PortionType::Arrow );
}

SwArrowPortion::SwArrowPortion( const SwTextPaintInfo &rInf )
    : m_bLeft( false )
{
    Height(rInf.GetTextFrame()->getFramePrintArea().Height());
    m_aPos.setX( rInf.GetTextFrame()->getFrameArea().Left() +
               rInf.GetTextFrame()->getFramePrintArea().Right() );
    m_aPos.setY( rInf.GetTextFrame()->getFrameArea().Top() +
               rInf.GetTextFrame()->getFramePrintArea().Bottom() );
    SetWhichPor( PortionType::Arrow );
}

void SwArrowPortion::Paint( const SwTextPaintInfo &rInf ) const
{
    const_cast<SwArrowPortion*>(this)->m_aPos = rInf.GetPos();
}

SwLinePortion *SwArrowPortion::Compress() { return this; }

SwTwips SwTextFrame::EmptyHeight() const
{
    if (IsCollapse()) {
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( auto pCrSh = dynamic_cast<SwCursorShell*>( pSh ) ) {
            // this is called during formatting so avoid recursive layout
            SwContentFrame const*const pCurrFrame = pCrSh->GetCurrFrame(false);
            if (pCurrFrame==static_cast<SwContentFrame const *>(this)) {
                // do nothing
            } else {
                return 1;
            }
        } else {
            return 1;
        }
    }
    OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTextFrame::EmptyHeight with swapped frame" );

    std::unique_ptr<SwFont> pFnt;
    const SwTextNode& rTextNode = *GetTextNodeForParaProps();
    const IDocumentSettingAccess* pIDSA = rTextNode.getIDocumentSettingAccess();
    SwViewShell *pSh = getRootFrame()->GetCurrShell();
    if ( rTextNode.HasSwAttrSet() )
    {
        const SwAttrSet *pAttrSet = &( rTextNode.GetSwAttrSet() );
        pFnt.reset(new SwFont( pAttrSet, pIDSA ));
    }
    else
    {
        SwFontAccess aFontAccess( &rTextNode.GetAnyFormatColl(), pSh);
        pFnt.reset(new SwFont( aFontAccess.Get()->GetFont() ));
        pFnt->CheckFontCacheId( pSh, pFnt->GetActual() );
    }

    if ( IsVertical() )
        pFnt->SetVertical( 2700_deg10 );

    OutputDevice* pOut = pSh ? pSh->GetOut() : nullptr;
    if ( !pOut || !pSh->GetViewOptions()->getBrowseMode() ||
         pSh->GetViewOptions()->IsPrtFormat() )
    {
        pOut = rTextNode.getIDocumentDeviceAccess().getReferenceDevice(true);
    }

    const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
    if (IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
        && !getRootFrame()->IsHideRedlines())
    {
        const SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, RedlineType::Any );
        if( SwRedlineTable::npos != nRedlPos )
        {
            SwAttrHandler aAttrHandler;
            aAttrHandler.Init(rTextNode.GetSwAttrSet(),
                              *rTextNode.getIDocumentSettingAccess());
            SwRedlineItr aRedln( rTextNode, *pFnt, aAttrHandler,
                                 nRedlPos, SwRedlineItr::Mode::Show);
        }
    }

    SwTwips nRet;
    if( !pOut )
        nRet = IsVertical() ?
               getFramePrintArea().SSize().Width() + 1 :
               getFramePrintArea().SSize().Height() + 1;
    else
    {
        pFnt->SetFntChg( true );
        pFnt->ChgPhysFnt( pSh, *pOut );
        nRet = pFnt->GetHeight( pSh, *pOut );
    }
    return nRet;
}

bool SwTextFrame::FormatEmpty()
{
    OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTextFrame::FormatEmpty with swapped frame" );

    SwTwips nHeight = EmptyHeight();
    bool bCollapse = nHeight == 1 && IsCollapse();

    // 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 ((HasFollow() && !bHasNonLastSplitFlyDrawObj) || GetMergedPara() || (GetTextNodeFirst()->GetpSwpHints() && !bHasNonLastSplitFlyDrawObj) ||
        nullptr != GetTextNodeForParaProps()->GetNumRule() ||
        GetTextNodeFirst()->HasHiddenCharAttribute(true) ||
         IsInFootnote() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
        return false;
    const SwAttrSet& aSet = GetTextNodeForParaProps()->GetSwAttrSet();
    const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
    if( !bCollapse && ( ( ( ! IsRightToLeft() && ( SvxAdjust::Left != nAdjust ) ) ||
          (   IsRightToLeft() && ( SvxAdjust::Right != nAdjust ) ) ) ||
          aSet.GetRegister().GetValue() ) )
        return false;
    const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing();
    if( !bCollapse && ( SvxLineSpaceRule::Min == rSpacing.GetLineSpaceRule() ||
        SvxLineSpaceRule::Fix == rSpacing.GetLineSpaceRule() ||
        (rSpacing.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop
            && rSpacing.GetPropLineSpace() < 100) ||
        aSet.GetFirstLineIndent().IsAutoFirst()))
    {
        return false;
    }

    SwTextFly aTextFly( this );
    SwRect aRect;
    bool bFirstFlyCheck = 0 != getFramePrintArea().Height();
    if ( !bCollapse && bFirstFlyCheck &&
            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 (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
         pIndex; pIndex = pIndex->GetNext())
    {
        if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark)
            continue;
        auto const pMark = static_cast<sw::mark::MarkBase const*>(pIndex->GetOwner());
        if (dynamic_cast<const sw::mark::Bookmark*>(pMark) != nullptr)
        {   // need bookmark portions!
            return false;
        }
    }

    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);
        }
    }

    if( !nChg )
        SetUndersized( false );
    AdjustFrame( nChg );

    if (GetHasRotatedPortions())
    {
        ClearPara();
        SetHasRotatedPortions(false);
    }

    RemoveFromCache();
    if( !IsEmpty() )
    {
        SetEmpty( true );
        SetCompletePaint();
    }
    if( !bCollapse && !bFirstFlyCheck &&
            aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
        return false;

    // #i35635# - call method <HideAndShowObjects()>
    // to assure that objects anchored at the empty paragraph are
    // correctly visible resp. invisible.
    HideAndShowObjects();
    return true;
}

bool SwTextFrame::FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff )
{
    const SwFrame *pFrame = this;
    rRegDiff = 0;
    while( !( ( SwFrameType::Body | SwFrameType::Fly )
           & pFrame->GetType() ) && pFrame->GetUpper() )
        pFrame = pFrame->GetUpper();
    if( ( SwFrameType::Body| SwFrameType::Fly ) & pFrame->GetType() )
    {
        SwRectFnSet aRectFnSet(pFrame);
        rRegStart = aRectFnSet.GetPrtTop(*pFrame);
        pFrame = pFrame->FindPageFrame();
        if( pFrame->IsPageFrame() )
        {
            SwPageDesc* pDesc = const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pFrame))->FindPageDesc();
            if( pDesc )
            {
                rRegDiff = pDesc->GetRegHeight();
                if( !rRegDiff )
                {
                    const SwTextFormatColl *pFormat = pDesc->GetRegisterFormatColl();
                    if( pFormat )
                    {
                        const SvxLineSpacingItem &rSpace = pFormat->GetLineSpacing();
                        if( SvxLineSpaceRule::Fix == rSpace.GetLineSpaceRule() )
                        {
                            rRegDiff = rSpace.GetLineHeight();
                            pDesc->SetRegHeight( rRegDiff );
                            pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 );
                        }
                        else
                        {
                            SwViewShell *pSh = getRootFrame()->GetCurrShell();
                            SwFontAccess aFontAccess( pFormat, pSh );
                            SwFont aFnt( aFontAccess.Get()->GetFont() );

                            OutputDevice *pOut = nullptr;
                            if( !pSh || !pSh->GetViewOptions()->getBrowseMode() ||
                                pSh->GetViewOptions()->IsPrtFormat() )
                                pOut = GetDoc().getIDocumentDeviceAccess().getReferenceDevice( true );

                            if( pSh && !pOut )
                                pOut = pSh->GetWin()->GetOutDev();

                            if( !pOut )
                                pOut = Application::GetDefaultDevice();

                            MapMode aOldMap( pOut->GetMapMode() );
                            pOut->SetMapMode( MapMode( MapUnit::MapTwip ) );

                            aFnt.ChgFnt( pSh, *pOut );
                            rRegDiff = aFnt.GetHeight( pSh, *pOut );
                            sal_uInt16 nNetHeight = rRegDiff;

                            switch( rSpace.GetLineSpaceRule() )
                            {
                                case SvxLineSpaceRule::Auto:
                                break;
                                case SvxLineSpaceRule::Min:
                                {
                                    if( rRegDiff < rSpace.GetLineHeight() )
                                        rRegDiff = rSpace.GetLineHeight();
                                    break;
                                }
                                default:
                                    OSL_FAIL( ": unknown LineSpaceRule" );
                            }
                            switch( rSpace.GetInterLineSpaceRule() )
                            {
                                case SvxInterLineSpaceRule::Off:
                                break;
                                case SvxInterLineSpaceRule::Prop:
                                {
                                    tools::Long nTmp = rSpace.GetPropLineSpace();
                                    if( nTmp < 50 )
                                        nTmp = nTmp ? 50 : 100;
                                    nTmp *= rRegDiff;
                                    nTmp /= 100;
                                    if( !nTmp )
                                        ++nTmp;
                                    rRegDiff = o3tl::narrowing<sal_uInt16>(nTmp);
                                    nNetHeight = rRegDiff;
                                    break;
                                }
                                case SvxInterLineSpaceRule::Fix:
                                {
                                    rRegDiff = rRegDiff + rSpace.GetInterLineSpace();
                                    nNetHeight = rRegDiff;
                                    break;
                                }
                                default: OSL_FAIL( ": unknown InterLineSpaceRule" );
                            }
                            pDesc->SetRegHeight( rRegDiff );
                            pDesc->SetRegAscent( rRegDiff - nNetHeight +
                                                 aFnt.GetAscent( pSh, *pOut ) );
                            pOut->SetMapMode( aOldMap );
                        }
                    }
                }
                const tools::Long nTmpDiff = pDesc->GetRegAscent() - rRegDiff;
                if ( aRectFnSet.IsVert() )
                    rRegStart -= nTmpDiff;
                else
                    rRegStart += nTmpDiff;
            }
        }
    }
    return ( 0 != rRegDiff );
}

void SwHiddenTextPortion::Paint( const SwTextPaintInfo & rInf) const
{
#ifdef DBG_UTIL
    OutputDevice* pOut = const_cast<OutputDevice*>(rInf.GetOut());
    pOut->Push(vcl::PushFlags::FILLCOLOR);
    pOut->SetFillColor( rInf.GetOpt().GetFieldShadingsColor() );
    Point aPos( rInf.GetPos() );
    aPos.AdjustY( -150 );
    aPos.AdjustX( -25 );
    SwRect aRect( aPos, Size( 100, 200 ) );
    pOut->DrawRect( aRect.SVRect() );
    pOut->Pop();
#else
    (void)rInf;
#endif
}

bool SwHiddenTextPortion::Format( SwTextFormatInfo &rInf )
{
    Width( 0 );
    rInf.GetTextFrame()->HideFootnotes( rInf.GetIdx(), rInf.GetIdx() + GetLen() );

    return false;
};

bool SwControlCharPortion::DoPaint(SwTextPaintInfo const& rTextPaintInfo,
        OUString & rOutString, SwFont & rTmpFont, int &) const
{
    if (mcChar == CHAR_WJ || !rTextPaintInfo.GetOpt().IsViewMetaChars())
    {
        return false;
    }

    switch (mcChar)
    {
        case CHAR_ZWSP:
            rOutString = "/"break;
//      case CHAR_LRM :
//          rText = sal_Unicode(0x2514); break;
//      case CHAR_RLM :
//          rText = sal_Unicode(0x2518); break;
        default:
            assert(false);
            break;
    }

    rTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
    rTmpFont.SetColor( SwViewOption::GetCurrentViewOptions().GetNonPrintingCharacterColor() );
    const sal_uInt16 nProp = 40;
    rTmpFont.SetProportion( nProp );  // a smaller font

    return true;
}

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;
    }

    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
    auto const 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);
    auto const 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
    auto const nOSAscent(rFont.GetAscent(rTextPaintInfo.GetVsh(), *rTextPaintInfo.GetOut()));
    rDeltaY = nOSAscent - nOrigAscent;

    return true;
}

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;

    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;
    }
    const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );

    rInf.DrawText( aOutString, *this );

    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;

    auto nHeight = rInf.GetTextSize( aOutString ).Height();

    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(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(mnHalfCharWidth * -(2 * m_nEnd - 1 + m_nPoint) );

    const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );

    SwTwips nTypePos = 0; // shift to the position of the next rdf:type label
    sal_Int32 nDirection = -1; // start with the closing brackets
    bool bStart = true;
    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 ? '[' : ']');

        if (nDirection == -1 && std::get<0>(it) != SwScriptInfo::MarkKind::End)
        {
            nDirection = 1;
            nTypePos = mnHalfCharWidth * 2; // start label after the opening bracket
        }

        // 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 );

        // 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;

            // calculate label size
            aTmpSz.setHeight( std::min( tools::Long(60), 100 * aTmpSz.Height() / 250 ) );
            aTmpSz.setWidth( std::min( tools::Long(60), 100 * aTmpSz.Width() / 250 ) );

            // vertical rdf:type label position for the opening and closing brackets
            sal_Int32 fPos = std::get<0>(it) == SwScriptInfo::MarkKind::Start
                    ? -0.65 * nHeight
                    : aTmpSz.Height();

            if ( aTmpSz.Width() || aTmpSz.Height() )
            {
                aTmpFont.SetSize( aTmpSz, SwFontScript::Latin );
                auto aTextSize =  rInf.GetTextSize(sType);

                aNewPos.AdjustY(fPos);
                if ( nDirection == -1 )
                {
                    if (bStart)
                    {
                        nTypePos += aTextSize.Width();
                        bStart = false;
                    }
                    else
                        nTypePos += aTextSize.Width() +
                                        rInf.GetTextSize( " " ).Width() + 2 * mnHalfCharWidth;
                }
                aNewPos.AdjustX( nDirection * nTypePos );

                const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );

                SwRect aRect( rInf.GetPos(), Size(aTextSize.Width(), -aTextSize.Height() * 0.8) );
                rInf.DrawRect( aRect, true );  // white background
                rInf.DrawText( sType, *this ); // label

                // 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 );
    }

    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).toString() + " " + 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).toString() + " " + 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();
    Width( 0 );
    Height( pRoot->Height() );
    SetAscent( pRoot->GetAscent() );

    return false;
}

SwTwips SwControlCharPortion::GetViewWidth(const SwTextSizeInfo& rInf) const
{
    if( !mnViewWidth )
        mnViewWidth = rInf.GetTextSize(OUString(' ')).Width();

    return mnViewWidth;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=93 H=94 G=93

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge