Files
libreoffice/sw/source/core/text/itrpaint.cxx

676 lines
24 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes: Patches contributed by Oliver-Rainer Wittmann sw34bf06: #i117783# - Writer's implementation of XPagePrintable - apply print settings to new printing routines http://svn.apache.org/viewvc?view=revision&revision=1172115 sw34bf06: #o12311627# use <rtl_random> methods to create unique ids for list styles and list ids http://svn.apache.org/viewvc?view=revision&revision=1172112 sw34bf06 #i114725#,#i115828# - method <SwDoc::ClearDoc()> - clear list structures completely http://svn.apache.org/viewvc?view=revision&revision=1172122 i#118572 - remove ui string and help content regarding usage of Java Mail in Writer's Mail Merge as Java Mail is not used. http://svn.apache.org/viewvc?view=revision&revision=1197035 Patches contributed by Mathias Bauer cws mba34issues01: #i117718#: provide filter name in case storage of medium does not allow to detect one http://svn.apache.org/viewvc?view=revision&revision=1172350 cws mba34issues01: #i117721#: directly provide parameters retrieved from SfxMedium http://svn.apache.org/viewvc?view=revision&revision=1172353 gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 cws mba34issues01: #i117723#: convert assertion into trace http://svn.apache.org/viewvc?view=revision&revision=1172355 cws mba34issues01: #i117699#: keep layout alive until swdoc dies http://svn.apache.org/viewvc?view=revision&revision=1172362 cws mba34issues01: #i117943#: missing color attributes in RTF clipboard http://svn.apache.org/viewvc?view=revision&revision=1172363 Patch contributed by Henning Brinkmann imported patch i#103878 http://svn.apache.org/viewvc?view=revision&revision=1172109 Patches contributed by Michael Stahl sw34bf06: #i117955#: WW8 export: disable storing of section breaks in endnotes http://svn.apache.org/viewvc?view=revision&revision=1172119 Patch contributed by imacat Fixed the Asian language work count. http://svn.apache.org/viewvc?view=revision&revision=1241345 Patch contributed by Pedro Giffuni i#20878 - Add comment with BZ issue for reference. http://svn.apache.org/viewvc?view=revision&revision=1244517 Patch contributed by Andre Fischer Do not add targets for junit tests when junit is disabled. http://svn.apache.org/viewvc?view=revision&revision=1241508 add writerperfect dependency.
2011-03-31 10:05:04 +02:00
/*
* 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 .
*/
2000-09-18 23:08:29 +00:00
#include <hintids.hxx>
#include <flyfrm.hxx>
#include <viewopt.hxx>
#include <txtatr.hxx>
2000-09-18 23:08:29 +00:00
#include <tools/multisel.hxx>
#include <editeng/escapementitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/lrspitem.hxx>
2000-09-18 23:08:29 +00:00
#include <txtinet.hxx>
#include <fchrfmt.hxx>
#include <frmatr.hxx>
#include <sfx2/printer.hxx>
#include <fmtfld.hxx>
#include <fldbas.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <pagedesc.hxx>
#include <tgrditem.hxx>
#include <EnhancedPDFExportHelper.hxx>
#include <IDocumentSettingAccess.hxx>
#include <flyfrms.hxx>
#include <viewsh.hxx>
2000-09-18 23:08:29 +00:00
#include "itrpaint.hxx"
#include <txtfrm.hxx>
#include <txtfly.hxx>
#include <swfont.hxx>
2000-09-18 23:08:29 +00:00
#include "txtpaint.hxx"
#include "portab.hxx"
#include "porfly.hxx"
#include "porfld.hxx"
#include <frmfmt.hxx>
#include <txatbase.hxx>
#include <charfmt.hxx>
#include "redlnitr.hxx"
#include "porrst.hxx"
#include "pormulti.hxx"
// Returns, if we have an underline breaking situation
// Adding some more conditions here means you also have to change them
// in SwTextPainter::CheckSpecialUnderline
bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt )
{
return LINESTYLE_NONE == rFnt.GetUnderline() ||
rPor.IsFlyPortion() || rPor.IsFlyCntPortion() ||
rPor.IsBreakPortion() || rPor.IsMarginPortion() ||
rPor.IsHolePortion() ||
( rPor.IsMultiPortion() && ! static_cast<const SwMultiPortion&>(rPor).IsBidi() ) ||
rFnt.GetEscapement() < 0 || rFnt.IsWordLineMode() ||
SvxCaseMap::SmallCaps == rFnt.GetCaseMap();
}
const Color GetUnderColor( const SwFont *pFont )
{
return pFont->GetUnderColor() == Color( COL_AUTO ) ?
pFont->GetColor() : pFont->GetUnderColor();
}
void SwTextPainter::CtorInitTextPainter( SwTextFrame *pNewFrame, SwTextPaintInfo *pNewInf )
2000-09-18 23:08:29 +00:00
{
CtorInitTextCursor( pNewFrame, pNewInf );
m_pInf = pNewInf;
SwFont *pMyFnt = GetFnt();
GetInfo().SetFont( pMyFnt );
bPaintDrop = false;
2000-09-18 23:08:29 +00:00
}
SwLinePortion *SwTextPainter::CalcPaintOfst( const SwRect &rPaint )
2000-09-18 23:08:29 +00:00
{
SwLinePortion *pPor = m_pCurr->GetFirstPortion();
2000-09-18 23:08:29 +00:00
GetInfo().SetPaintOfst( 0 );
SwTwips nPaintOfst = rPaint.Left();
// nPaintOfst was exactly set to the end, therefore <=
// nPaintOfst is document global, therefore add up nLeftMar
// const sal_uInt16 nLeftMar = sal_uInt16(GetLeftMargin());
// 8310: paint of LineBreaks in empty lines.
if( nPaintOfst && m_pCurr->Width() )
2000-09-18 23:08:29 +00:00
{
SwLinePortion *pLast = nullptr;
// 7529 and 4757: not <= nPaintOfst
2000-09-18 23:08:29 +00:00
while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
< nPaintOfst )
{
2000-10-30 09:00:34 +00:00
if( pPor->InSpaceGrp() && GetInfo().GetSpaceAdd() )
2000-09-18 23:08:29 +00:00
{
2000-10-30 09:00:34 +00:00
long nTmp = GetInfo().X() +pPor->Width() +
pPor->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
2000-09-18 23:08:29 +00:00
if( nTmp + (pPor->Height()/2) >= nPaintOfst )
break;
GetInfo().X( nTmp );
GetInfo().SetIdx( GetInfo().GetIdx() + pPor->GetLen() );
}
else
pPor->Move( GetInfo() );
pLast = pPor;
pPor = pPor->GetPortion();
}
// 7529: if PostIts return also pLast.
2000-09-18 23:08:29 +00:00
if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
{
pPor = pLast;
GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
}
}
return pPor;
}
// There are two possibilities to output transparent font:
// 1) DrawRect on the whole line and DrawText afterwards
// (objectively fast, subjectively slow)
// 2) For every portion a DrawRect with subsequent DrawText is done
// (objectively slow, subjectively fast)
// Since the user usually judges subjectively the second method is set as default.
void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
const bool bUnderSz )
2000-09-18 23:08:29 +00:00
{
#if OSL_DEBUG_LEVEL > 1
// sal_uInt16 nFntHeight = GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), GetInfo().GetOut() );
// sal_uInt16 nFntAscent = GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), GetInfo().GetOut() );
#endif
// maybe catch-up adjustment
2000-09-18 23:08:29 +00:00
GetAdjusted();
GetInfo().SetpSpaceAdd( m_pCurr->GetpLLSpaceAdd() );
2000-09-18 23:08:29 +00:00
GetInfo().ResetSpaceIdx();
GetInfo().SetKanaComp( m_pCurr->GetpKanaComp() );
2001-04-09 09:44:17 +00:00
GetInfo().ResetKanaIdx();
// The size of the frame
2000-09-18 23:08:29 +00:00
GetInfo().SetIdx( GetStart() );
GetInfo().SetPos( GetTopLeft() );
const bool bDrawInWindow = GetInfo().OnWin();
2000-09-18 23:08:29 +00:00
// 6882: blank lines can't be optimized by removing them if Formatting Marks are shown
const bool bEndPor = GetInfo().GetOpt().IsParagraph() && GetInfo().GetText().isEmpty();
2000-09-18 23:08:29 +00:00
SwLinePortion *pPor = bEndPor ? m_pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
2000-09-18 23:08:29 +00:00
// Optimization!
SwTwips nMaxRight = std::min( rPaint.Right(), Right() );
2000-09-18 23:08:29 +00:00
const SwTwips nTmpLeft = GetInfo().X();
//compatibility setting: allow tabstop text to exceed right margin
if( GetInfo().GetTextFrame()->GetTextNode()->getIDocumentSettingAccess()->get(DocumentSettingId::TAB_OVER_MARGIN) )
{
SwLinePortion* pPorIter = pPor;
while( pPorIter )
{
if( pPorIter->InTabGrp() )
{
const SwTabPortion* pTabPor = static_cast<SwTabPortion*>(pPorIter);
const SwTwips nTabPos = nTmpLeft + pTabPor->GetTabPos();
if( nMaxRight < nTabPos )
{
nMaxRight = rPaint.Right();
break;
}
}
pPorIter = pPorIter->GetPortion();
}
}
2000-09-18 23:08:29 +00:00
if( !bEndPor && nTmpLeft >= nMaxRight )
return;
// DropCaps!
// 7538: of course for the printer, too
2000-09-18 23:08:29 +00:00
if( !bPaintDrop )
{
// 8084: Optimization, less painting
// AMA: By 8084 7538 has been revived
// bDrawInWindow removed, so that DropCaps also can be printed
bPaintDrop = pPor == m_pCurr->GetFirstPortion()
2000-09-18 23:08:29 +00:00
&& GetDropLines() >= GetLineNr();
}
sal_uInt16 nTmpHeight, nTmpAscent;
2000-09-18 23:08:29 +00:00
CalcAscentAndHeight( nTmpAscent, nTmpHeight );
// bClip decides if there's a need to clip
// The whole thing must be done before retouching
2000-09-18 23:08:29 +00:00
bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
2000-09-18 23:08:29 +00:00
if( bClip && pPor )
{
// If TopLeft or BottomLeft of the line are outside, the we must clip.
// The check for Right() is done in the output loop ...
2000-09-18 23:08:29 +00:00
if( GetInfo().GetPos().X() < rPaint.Left() ||
GetInfo().GetPos().Y() < rPaint.Top() ||
GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
{
bClip = false;
rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
2000-09-18 23:08:29 +00:00
}
#if OSL_DEBUG_LEVEL > 1
static bool bClipAlways = false;
2000-09-18 23:08:29 +00:00
if( bClip && bClipAlways )
{ bClip = false;
2000-09-18 23:08:29 +00:00
rClip.ChgClip( rPaint );
}
#endif
}
// Alignment
OutputDevice* pOut = GetInfo().GetOut();
2000-09-18 23:08:29 +00:00
Point aPnt1( nTmpLeft, GetInfo().GetPos().Y() );
if ( aPnt1.X() < rPaint.Left() )
aPnt1.X() = rPaint.Left();
if ( aPnt1.Y() < rPaint.Top() )
aPnt1.Y() = rPaint.Top();
Point aPnt2( GetInfo().GetPos().X() + nMaxRight - GetInfo().X(),
GetInfo().GetPos().Y() + nTmpHeight );
if ( aPnt2.X() > rPaint.Right() )
aPnt2.X() = rPaint.Right();
if ( aPnt2.Y() > rPaint.Bottom() )
aPnt2.Y() = rPaint.Bottom();
const SwRect aLineRect( aPnt1, aPnt2 );
if( m_pCurr->IsClipping() )
2000-09-18 23:08:29 +00:00
{
rClip.ChgClip( aLineRect, m_pFrame );
bClip = false;
2000-09-18 23:08:29 +00:00
}
if( !pPor && !bEndPor )
return;
// Baseline output also if non-TextPortion (compare TabPor with Fill)
2001-04-12 06:47:49 +00:00
// if no special vertical alignment is used,
// we calculate Y value for the whole line
SwTextGridItem const*const pGrid(GetGridItem(GetTextFrame()->FindPageFrame()));
const bool bAdjustBaseLine =
GetLineInfo().HasSpecialAlign( GetTextFrame()->IsVertical() ) ||
( nullptr != pGrid );
const SwTwips nLineBaseLine = GetInfo().GetPos().Y() + nTmpAscent;
if ( ! bAdjustBaseLine )
GetInfo().Y( nLineBaseLine );
2000-09-18 23:08:29 +00:00
// 7529: Pre-paint post-its
2000-09-18 23:08:29 +00:00
if( GetInfo().OnWin() && pPor && !pPor->Width() )
{
SeekAndChg( GetInfo() );
if( bAdjustBaseLine )
{
const SwTwips nOldY = GetInfo().Y();
GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *m_pCurr, nullptr,
GetInfo().GetFont()->GetHeight( GetInfo().GetVsh(), *pOut ),
GetInfo().GetFont()->GetAscent( GetInfo().GetVsh(), *pOut )
) );
pPor->PrePaint( GetInfo(), pPor );
GetInfo().Y( nOldY );
}
else
pPor->PrePaint( GetInfo(), pPor );
2000-09-18 23:08:29 +00:00
}
// 7923: EndPortions output chars, too, that's why we change the font
2000-09-18 23:08:29 +00:00
if( bEndPor )
SeekStartAndChg( GetInfo() );
const bool bRest = m_pCurr->IsRest();
bool bFirst = true;
2000-09-18 23:08:29 +00:00
SwArrowPortion *pArrow = nullptr;
2001-06-29 14:50:31 +00:00
// Reference portion for the paragraph end portion
SwLinePortion* pEndTempl = m_pCurr->GetFirstPortion();
2000-09-18 23:08:29 +00:00
while( pPor )
{
bool bSeeked = true;
2000-09-18 23:08:29 +00:00
GetInfo().SetLen( pPor->GetLen() );
2001-04-12 06:47:49 +00:00
const SwTwips nOldY = GetInfo().Y();
if ( bAdjustBaseLine )
{
GetInfo().Y( GetInfo().GetPos().Y() + AdjustBaseLine( *m_pCurr, pPor ) );
// we store the last portion, because a possible paragraph
// end character has the same font as this portion
// (only in special vertical alignment case, otherwise the first
// portion of the line is used)
if ( pPor->Width() && pPor->InTextGrp() )
2001-06-29 14:50:31 +00:00
pEndTempl = pPor;
}
2001-04-12 06:47:49 +00:00
// A special case are GluePortions which output blanks.
2000-09-18 23:08:29 +00:00
// 6168: Avoid that the rest of a FieldPortion gets the attributes of the
// next portion with SeekAndChgBefore():
if( bRest && pPor->InFieldGrp() && !pPor->GetLen() )
2000-09-18 23:08:29 +00:00
SeekAndChgBefore( GetInfo() );
else if ( pPor->IsQuoVadisPortion() )
{
sal_Int32 nOffset = GetInfo().GetIdx();
SeekStartAndChg( GetInfo(), true );
if( GetRedln() && m_pCurr->HasRedline() )
GetRedln()->Seek( *m_pFont, nOffset, 0 );
2000-09-18 23:08:29 +00:00
}
else if( pPor->InTextGrp() || pPor->InFieldGrp() || pPor->InTabGrp() )
2000-09-18 23:08:29 +00:00
SeekAndChg( GetInfo() );
else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
{
// Paragraph symbols should have the same font as the paragraph in front of them,
// except for the case that there's redlining in the paragraph
2000-09-18 23:08:29 +00:00
if( GetRedln() )
SeekAndChg( GetInfo() );
else
SeekAndChgBefore( GetInfo() );
}
else
bSeeked = false;
2000-09-18 23:08:29 +00:00
// bRest = false;
2000-09-18 23:08:29 +00:00
// If the end of the portion juts out, it is clipped.
// A safety distance of half the height is added, so that
// TTF-"f" isn't overlapping into the page margin.
if( bClip &&
GetInfo().X() + pPor->Width() + ( pPor->Height() / 2 ) > nMaxRight )
{
bClip = false;
rClip.ChgClip( rPaint, m_pFrame, m_pCurr->HasUnderscore() );
2000-09-18 23:08:29 +00:00
}
// Portions, which lay "below" the text like post-its
2000-09-18 23:08:29 +00:00
SwLinePortion *pNext = pPor->GetPortion();
if( GetInfo().OnWin() && pNext && !pNext->Width() )
2000-09-18 23:08:29 +00:00
{
// Fix 11289: Fields were omitted here because of Last!=Owner during
// loading Brief.sdw. Now the fields are allowed again,
// by bSeeked Last!=Owner is being avoided.
2000-09-18 23:08:29 +00:00
if ( !bSeeked )
SeekAndChg( GetInfo() );
pNext->PrePaint( GetInfo(), pPor );
}
// We calculate a separate font for underlining.
CheckSpecialUnderline( pPor, bAdjustBaseLine ? nOldY : 0 );
SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
if ( pUnderLineFnt )
{
const Point aTmpPoint( GetInfo().X(),
bAdjustBaseLine ?
pUnderLineFnt->GetPos().Y() :
nLineBaseLine );
pUnderLineFnt->SetPos( aTmpPoint );
}
2000-09-18 23:08:29 +00:00
// in extended input mode we do not want a common underline font.
SwUnderlineFont* pOldUnderLineFnt = nullptr;
if ( GetRedln() && GetRedln()->ExtOn() )
{
pOldUnderLineFnt = GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( nullptr );
}
{
// #i16816# tagged pdf support
Por_Info aPorInfo( *pPor, *this );
SwTaggedPDFHelper aTaggedPDFHelper( nullptr, nullptr, &aPorInfo, *pOut );
if( pPor->IsMultiPortion() )
PaintMultiPortion( rPaint, static_cast<SwMultiPortion&>(*pPor) );
else
pPor->Paint( GetInfo() );
}
2000-09-18 23:08:29 +00:00
// reset underline font
if ( pOldUnderLineFnt )
GetInfo().SetUnderFnt( pOldUnderLineFnt );
2001-04-12 06:47:49 +00:00
// reset (for special vertical alignment)
GetInfo().Y( nOldY );
if( GetFnt()->IsURL() && pPor->InTextGrp() )
2000-09-18 23:08:29 +00:00
GetInfo().NotifyURL( *pPor );
bFirst &= !pPor->GetLen();
if( pNext || !pPor->IsMarginPortion() )
pPor->Move( GetInfo() );
if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
pArrow = static_cast<SwArrowPortion*>(pPor);
2000-09-18 23:08:29 +00:00
pPor = bDrawInWindow || GetInfo().X() <= nMaxRight ||
// #i16816# tagged pdf support
( GetInfo().GetVsh() &&
GetInfo().GetVsh()->GetViewOptions()->IsPDFExport() &&
pNext && pNext->IsHolePortion() ) ?
pNext :
nullptr;
2000-09-18 23:08:29 +00:00
}
2001-04-12 06:47:49 +00:00
// delete underline font
delete GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( nullptr );
2001-04-12 06:47:49 +00:00
// paint remaining stuff
2000-09-18 23:08:29 +00:00
if( bDrawInWindow )
{
// If special vertical alignment is enabled, GetInfo().Y() is the
// top of the current line. Therefore is has to be adjusted for
// the painting of the remaining stuff. We first store the old value.
const SwTwips nOldY = GetInfo().Y();
2000-09-18 23:08:29 +00:00
if( !GetNextLine() &&
GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() &&
GetInfo().GetOpt().IsParagraph() && !GetTextFrame()->GetFollow() &&
GetInfo().GetIdx() >= GetInfo().GetText().getLength() )
2000-09-18 23:08:29 +00:00
{
2001-06-29 14:50:31 +00:00
const SwTmpEndPortion aEnd( *pEndTempl );
GetFnt()->ChgPhysFnt( GetInfo().GetVsh(), *pOut );
2001-06-29 14:50:31 +00:00
if ( bAdjustBaseLine )
GetInfo().Y( GetInfo().GetPos().Y()
+ AdjustBaseLine( *m_pCurr, &aEnd ) );
GetInfo().X( GetInfo().X() +
( GetCurr()->IsHanging() ? GetCurr()->GetHangingMargin() : 0 ) );
aEnd.Paint( GetInfo() );
GetInfo().Y( nOldY );
2000-09-18 23:08:29 +00:00
}
if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreview() )
2000-09-18 23:08:29 +00:00
{
const bool bNextUndersized =
( GetTextFrame()->GetNext() &&
0 == GetTextFrame()->GetNext()->Prt().Height() &&
GetTextFrame()->GetNext()->IsTextFrame() &&
static_cast<SwTextFrame*>(GetTextFrame()->GetNext())->IsUndersized() ) ;
if( bUnderSz || bNextUndersized )
2000-09-18 23:08:29 +00:00
{
if ( bAdjustBaseLine )
GetInfo().Y( GetInfo().GetPos().Y() + m_pCurr->GetAscent() );
2000-09-18 23:08:29 +00:00
if( pArrow )
GetInfo().DrawRedArrow( *pArrow );
// GetInfo().Y() must be current baseline
SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTextFrame()->Frame().Bottom();
if( ( nDiff > 0 &&
( GetEnd() < GetInfo().GetText().getLength() ||
( nDiff > nTmpHeight/2 && GetPrevLine() ) ) ) ||
2010-09-30 15:44:38 +01:00
(nDiff >= 0 && bNextUndersized) )
2000-09-18 23:08:29 +00:00
{
SwArrowPortion aArrow( GetInfo() );
GetInfo().DrawRedArrow( aArrow );
2000-09-18 23:08:29 +00:00
}
GetInfo().Y( nOldY );
2000-09-18 23:08:29 +00:00
}
}
}
2001-04-12 06:47:49 +00:00
if( m_pCurr->IsClipping() )
rClip.ChgClip( rPaint, m_pFrame );
2000-09-18 23:08:29 +00:00
}
void SwTextPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
long nAdjustBaseLine )
2000-09-18 23:08:29 +00:00
{
// Check if common underline should not be continued
if ( IsUnderlineBreak( *pPor, *m_pFont ) )
{
// delete underline font
delete GetInfo().GetUnderFnt();
GetInfo().SetUnderFnt( nullptr );
return;
}
// Reuse calculated underline font as much as possible.
if ( GetInfo().GetUnderFnt() && GetInfo().GetIdx() + pPor->GetLen() <= GetInfo().GetUnderFnt()->GetEnd() + 1 )
{
SwFont &rFont = GetInfo().GetUnderFnt()->GetFont();
const Color aColor = GetUnderColor( GetInfo().GetFont() );
if ( GetUnderColor( &rFont ) != aColor )
rFont.SetColor( aColor );
return;
}
// If current underline matches the common underline font, we continue
// to use the common underline font.
// Bug 120769:Color of underline display wrongly
if ( GetInfo().GetUnderFnt() &&
GetInfo().GetUnderFnt()->GetFont().GetUnderline() == GetFnt()->GetUnderline() &&
GetInfo().GetFont() && GetInfo().GetFont()->GetUnderColor() != Color(COL_AUTO) )
return;
//Bug 120769(End)
OSL_ENSURE( GetFnt() && LINESTYLE_NONE != GetFnt()->GetUnderline(),
"CheckSpecialUnderline without underlined font" );
MultiSelection aUnderMulti( Range( 0, GetInfo().GetText().getLength() ) );
const SwFont* pParaFnt = GetAttrHandler().GetFont();
if( pParaFnt && pParaFnt->GetUnderline() == GetFnt()->GetUnderline() )
aUnderMulti.SelectAll();
2000-09-18 23:08:29 +00:00
if( HasHints() )
{
for ( size_t nTmp = 0; nTmp < m_pHints->Count(); ++nTmp )
2000-09-18 23:08:29 +00:00
{
SwTextAttr* const pTextAttr = m_pHints->Get( nTmp );
const SvxUnderlineItem* pItem =
static_cast<const SvxUnderlineItem*>(CharFormat::GetItem( *pTextAttr, RES_CHRATR_UNDERLINE ));
if ( pItem )
2000-09-18 23:08:29 +00:00
{
const sal_Int32 nSt = pTextAttr->GetStart();
const sal_Int32 nEnd = *pTextAttr->GetEnd();
2000-09-18 23:08:29 +00:00
if( nEnd > nSt )
{
const bool bUnderSelect = m_pFont->GetUnderline() == pItem->GetLineStyle();
aUnderMulti.Select( Range( nSt, nEnd - 1 ), bUnderSelect );
2000-09-18 23:08:29 +00:00
}
}
}
}
const sal_Int32 nIndx = GetInfo().GetIdx();
long nUnderEnd = 0;
const size_t nCnt = aUnderMulti.GetRangeCount();
// find the underline range the current portion is contained in
for( size_t i = 0; i < nCnt; ++i )
{
const Range& rRange = aUnderMulti.GetRange( i );
if( nUnderEnd == rRange.Min() )
nUnderEnd = rRange.Max();
else if( nIndx >= rRange.Min() )
{
nUnderEnd = rRange.Max();
}
else
break;
}
if ( GetEnd() && GetEnd() <= nUnderEnd )
nUnderEnd = GetEnd() - 1;
// calculate the new common underline font
SwFont* pUnderlineFnt = nullptr;
Point aCommonBaseLine;
// check, if underlining is not isolated
if ( nIndx + GetInfo().GetLen() < nUnderEnd + 1 )
{
// here starts the algorithm for calculating the underline font
SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
SwAttrIter aIter( *GetInfo().GetTextFrame()->GetTextNode(),
rScriptInfo );
sal_Int32 nTmpIdx = nIndx;
sal_uLong nSumWidth = 0;
sal_uLong nSumHeight = 0;
sal_uLong nBold = 0;
sal_uInt16 nMaxBaseLineOfst = 0;
int nNumberOfPortions = 0;
while( sal::static_int_cast<long>(nTmpIdx) <= nUnderEnd && pPor )
2000-09-18 23:08:29 +00:00
{
if ( pPor->IsFlyPortion() || pPor->IsFlyCntPortion() ||
pPor->IsBreakPortion() || pPor->IsMarginPortion() ||
pPor->IsHolePortion() ||
( pPor->IsMultiPortion() && ! static_cast<const SwMultiPortion*>(pPor)->IsBidi() ) )
break;
aIter.Seek( nTmpIdx );
if ( aIter.GetFnt()->GetEscapement() < 0 || m_pFont->IsWordLineMode() ||
SvxCaseMap::SmallCaps == m_pFont->GetCaseMap() )
break;
if ( !aIter.GetFnt()->GetEscapement() )
2000-09-18 23:08:29 +00:00
{
nSumWidth += pPor->Width();
const sal_uLong nFontHeight = aIter.GetFnt()->GetHeight();
// If we do not have a common baseline we take the baseline
// and the font of the lowest portion.
if ( nAdjustBaseLine )
{
const sal_uInt16 nTmpBaseLineOfst = AdjustBaseLine( *m_pCurr, pPor );
if ( nMaxBaseLineOfst < nTmpBaseLineOfst )
{
nMaxBaseLineOfst = nTmpBaseLineOfst;
nSumHeight = nFontHeight;
}
}
// in horizontal layout we build a weighted sum of the heights
else
nSumHeight += pPor->Width() * nFontHeight;
if ( WEIGHT_NORMAL != aIter.GetFnt()->GetWeight() )
nBold += pPor->Width();
2000-09-18 23:08:29 +00:00
}
++nNumberOfPortions;
nTmpIdx += pPor->GetLen();
pPor = pPor->GetPortion();
2000-09-18 23:08:29 +00:00
}
// resulting height
if ( nNumberOfPortions > 1 && nSumWidth )
2000-09-18 23:08:29 +00:00
{
const sal_uLong nNewFontHeight = nAdjustBaseLine ?
nSumHeight :
nSumHeight / nSumWidth;
pUnderlineFnt = new SwFont( *GetInfo().GetFont() );
// font height
const SwFontScript nActual = pUnderlineFnt->GetActual();
pUnderlineFnt->SetSize( Size( pUnderlineFnt->GetSize( nActual ).Width(),
nNewFontHeight ), nActual );
// font weight
if ( 2 * nBold > nSumWidth )
pUnderlineFnt->SetWeight( WEIGHT_BOLD, nActual );
2000-09-18 23:08:29 +00:00
else
pUnderlineFnt->SetWeight( WEIGHT_NORMAL, nActual );
// common base line
aCommonBaseLine.Y() = nAdjustBaseLine + nMaxBaseLineOfst;
2000-09-18 23:08:29 +00:00
}
}
// an escaped redlined portion should also have a special underlining
if( ! pUnderlineFnt && m_pFont->GetEscapement() > 0 && GetRedln() &&
GetRedln()->ChkSpecialUnderline() )
pUnderlineFnt = new SwFont( *m_pFont );
delete GetInfo().GetUnderFnt();
if ( pUnderlineFnt )
{
pUnderlineFnt->SetProportion( 100 );
pUnderlineFnt->SetEscapement( 0 );
pUnderlineFnt->SetStrikeout( STRIKEOUT_NONE );
pUnderlineFnt->SetOverline( LINESTYLE_NONE );
const Color aFillColor( COL_TRANSPARENT );
pUnderlineFnt->SetFillColor( aFillColor );
GetInfo().SetUnderFnt( new SwUnderlineFont( *pUnderlineFnt, nUnderEnd,
aCommonBaseLine ) );
}
else
// I'm sorry, we do not have a special underlining font for you.
GetInfo().SetUnderFnt( nullptr );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */