summaryrefslogtreecommitdiff
path: root/sw/source/core/text/itrpaint.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/itrpaint.cxx')
-rw-r--r--sw/source/core/text/itrpaint.cxx548
1 files changed, 548 insertions, 0 deletions
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
new file mode 100644
index 000000000000..885297f47f46
--- /dev/null
+++ b/sw/source/core/text/itrpaint.cxx
@@ -0,0 +1,548 @@
+/*************************************************************************
+ *
+ * $RCSfile: itrpaint.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-19 00:08:25 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifdef PRECOMPILED
+#include "core_pch.hxx"
+#endif
+
+#pragma hdrstop
+
+#include "hintids.hxx"
+#include "flyfrm.hxx" // SwFlyInCntFrm
+#include "viewopt.hxx" // SwViewOptions
+#include "errhdl.hxx"
+#include "txtatr.hxx" // SwINetFmt
+
+#ifndef _SV_MULTISEL_HXX //autogen
+#include <tools/multisel.hxx>
+#endif
+#ifndef _SVX_ESCPITEM_HXX //autogen
+#include <svx/escpitem.hxx>
+#endif
+#ifndef _SVX_UDLNITEM_HXX //autogen
+#include <svx/udlnitem.hxx>
+#endif
+#ifndef _SVX_LRSPITEM_HXX //autogen
+#include <svx/lrspitem.hxx>
+#endif
+
+#ifndef _TXTINET_HXX //autogen
+#include <txtinet.hxx>
+#endif
+#ifndef _FCHRFMT_HXX //autogen
+#include <fchrfmt.hxx>
+#endif
+#ifndef _FRMATR_HXX
+#include <frmatr.hxx>
+#endif
+#include "flyfrms.hxx"
+#include "viewsh.hxx"
+#include "txtcfg.hxx"
+#include "itrpaint.hxx"
+#include "txtfrm.hxx" // pFrm
+#include "txtfly.hxx"
+#include "swfont.hxx"
+#include "txtpaint.hxx"
+#include "portab.hxx" // SwTabPortion::IsFilled
+#include "porfly.hxx" // SwFlyCntPortion
+#include "porfld.hxx" // SwGrfNumPortion
+#include "frmfmt.hxx" // LRSpace
+#include "txatbase.hxx" // SwTxtAttr
+#include "charfmt.hxx" // SwFmtCharFmt
+#include "redlnitr.hxx" // SwRedlineItr
+#include "porrst.hxx" // SwArrowPortion
+
+/*************************************************************************
+ * SwTxtPainter::CtorInit()
+ *************************************************************************/
+void SwTxtPainter::CtorInit( SwTxtFrm *pFrm, SwTxtPaintInfo *pNewInf )
+{
+ SwTxtCursor::CtorInit( pFrm, pNewInf );
+ pInf = pNewInf;
+ SwFont *pFnt = GetFnt();
+ GetInfo().SetFont( pFnt );
+#ifndef PRODUCT
+ if( ALIGN_BASELINE != pFnt->GetAlign() )
+ {
+ ASSERT( ALIGN_BASELINE == pFnt->GetAlign(),
+ "+SwTxtPainter::CTOR: font alignment revolution" );
+ pFnt->SetAlign( ALIGN_BASELINE );
+ }
+#endif
+ bPaintDrop = sal_False;
+}
+
+
+/*************************************************************************
+ * SwTxtPainter::CalcPaintOfst()
+ *************************************************************************/
+SwLinePortion *SwTxtPainter::CalcPaintOfst( const SwRect &rPaint )
+{
+ SwLinePortion *pPor = pCurr->GetFirstPortion();
+ GetInfo().SetPaintOfst( 0 );
+ SwTwips nPaintOfst = rPaint.Left();
+
+ // nPaintOfst wurde exakt auf das Ende eingestellt, deswegen <=
+ // nPaintOfst ist dokumentglobal, deswegen nLeftMar aufaddieren
+ // const KSHORT nLeftMar = KSHORT(GetLeftMargin());
+ // 8310: painten von LineBreaks in leeren Zeilen.
+ if( nPaintOfst && pCurr->Width() )
+ {
+ SwLinePortion *pLast = 0;
+ // 7529 und 4757: nicht <= nPaintOfst
+ while( pPor && GetInfo().X() + pPor->Width() + (pPor->Height()/2)
+ < nPaintOfst )
+ {
+ DBG_LOOP;
+ if( pPor->InTxtGrp() && GetInfo().GetSpaceAdd() )
+ {
+ long nTmp = GetInfo().X() +pPor->Width() +((SwTxtPortion*)pPor)
+ ->CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
+ 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();
+ }
+
+#ifndef USED
+ // 7529: bei PostIts auch pLast returnen.
+ if( pLast && !pLast->Width() && pLast->IsPostItsPortion() )
+ {
+ pPor = pLast;
+ GetInfo().SetIdx( GetInfo().GetIdx() - pPor->GetLen() );
+ }
+#endif
+ }
+ return pPor;
+}
+
+/*************************************************************************
+ * SwTxtPainter::DrawTextLine()
+ *
+ * Es gibt zwei Moeglichkeiten bei transparenten Font auszugeben:
+ * 1) DrawRect auf die ganze Zeile und die DrawText hinterher
+ * (objektiv schnell, subjektiv langsam).
+ * 2) Fuer jede Portion ein DrawRect mit anschliessendem DrawText
+ * ausgefuehrt (objektiv langsam, subjektiv schnell).
+ * Da der User in der Regel subjektiv urteilt, wird die 2. Methode
+ * als Default eingestellt.
+ *************************************************************************/
+void SwTxtPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
+ const sal_Bool bUnderSz )
+{
+ // Adjustierung ggf. nachholen
+ GetAdjusted();
+ GetInfo().SetSpaceAdd( pCurr->GetpSpaceAdd() );
+ GetInfo().ResetSpaceIdx();
+ // Die Groesse des Frames
+ GetInfo().SetIdx( GetStart() );
+ GetInfo().SetPos( GetTopLeft() );
+
+ const sal_Bool bDrawInWindow = GetInfo().OnWin();
+
+ // 6882: Leerzeilen duerfen nicht wegoptimiert werden bei Paragraphzeichen.
+ const sal_Bool bEndPor = GetInfo().GetOpt().IsParagraph() && !GetInfo().GetTxt().Len();
+
+ SwLinePortion *pPor = bEndPor ? pCurr->GetFirstPortion() : CalcPaintOfst( rPaint );
+
+ // Optimierung!
+ const SwTwips nMaxRight = Min( rPaint.Right(), Right() );
+ const SwTwips nTmpLeft = GetInfo().X();
+ if( !bEndPor && nTmpLeft >= nMaxRight )
+ return;
+
+ // DropCaps!
+ // 7538: natuerlich auch auf dem Drucker
+ if( !bPaintDrop )
+ {
+ // 8084: Optimierung, weniger Painten.
+ // AMA: Durch 8084 wurde 7538 wiederbelebt!
+ // bDrawInWindow entfernt, damit DropCaps auch gedruckt werden
+ bPaintDrop = pPor == pCurr->GetFirstPortion()
+ && GetDropLines() >= GetLineNr();
+ }
+
+ KSHORT nTmpHeight, nTmpAscent;
+ CalcAscentAndHeight( nTmpAscent, nTmpHeight );
+
+ // bClip entscheidet darueber, ob geclippt werden muss.
+ // Das Ganze muss vor der Retusche stehen
+
+ sal_Bool bClip = ( bDrawInWindow || bUnderSz ) && !rClip.IsChg();
+ if( bClip && pPor )
+ {
+ // Wenn TopLeft oder BottomLeft der Line ausserhalb liegen,
+ // muss geclippt werden. Die Ueberpruefung auf Right() erfolgt
+ // in der folgenden Ausgabeschleife...
+
+ if( GetInfo().GetPos().X() < rPaint.Left() ||
+ GetInfo().GetPos().Y() < rPaint.Top() ||
+ GetInfo().GetPos().Y() + nTmpHeight > rPaint.Top() + rPaint.Height() )
+ {
+ bClip = sal_False;
+ rClip.ChgClip( rPaint );
+ }
+#ifdef DEBUG
+ static sal_Bool bClipAlways = sal_False;
+ if( bClip && bClipAlways )
+ { bClip = sal_False;
+ rClip.ChgClip( rPaint );
+ }
+#endif
+ }
+
+ // Alignment:
+ sal_Bool bPlus = sal_False;
+ OutputDevice *pOut = GetInfo().GetOut();
+ 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();
+ bPlus = sal_True;
+ }
+
+ const SwRect aLineRect( aPnt1, aPnt2 );
+
+ if( pCurr->IsClipping() )
+ {
+ rClip.ChgClip( aLineRect );
+ bClip = sal_False;
+ }
+
+ if( !pPor && !bEndPor )
+ {
+#ifdef DBGTXT
+ aDbstream << "PAINTER: done nothing" << endl;
+#endif
+ return;
+ }
+
+ // Baseline-Ausgabe auch bei nicht-TxtPortions (vgl. TabPor mit Fill)
+ const SwTwips nY = GetInfo().GetPos().Y() + nTmpAscent;
+ GetInfo().Y( nY );
+
+ // 7529: PostIts prepainten
+ if( GetInfo().OnWin() && pPor && !pPor->Width() )
+ {
+ SeekAndChg( GetInfo() );
+ pPor->PrePaint( GetInfo(), pPor );
+ }
+
+ // 7923: EndPortions geben auch Zeichen aus, deswegen den Fnt wechseln!
+ if( bEndPor )
+ SeekStartAndChg( GetInfo() );
+
+ sal_Bool bRest = pCurr->IsRest();
+ sal_Bool bFirst = sal_True;
+
+ SwArrowPortion *pArrow = NULL;
+
+ while( pPor )
+ {
+ DBG_LOOP;
+ sal_Bool bSeeked = sal_True;
+ GetInfo().SetLen( pPor->GetLen() );
+ GetInfo().SetSpecialUnderline( sal_False );
+ // Ein Sonderfall sind GluePortions, die Blanks ausgeben.
+
+ // 6168: Der Rest einer FldPortion zog sich die Attribute der naechsten
+ // Portion an, dies wird durch SeekAndChgBefore vermieden:
+ if( ( bRest && pPor->InFldGrp() && !pPor->GetLen() ) )
+ SeekAndChgBefore( GetInfo() );
+ else if ( pPor->IsQuoVadisPortion() )
+ {
+ xub_StrLen nOffset = GetInfo().GetIdx();
+ SeekStartAndChg( GetInfo(), sal_True );
+ if( GetRedln() && pCurr->HasRedline() )
+ GetRedln()->Seek( *pFnt, nOffset, 0 );
+ }
+ else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
+ SeekAndChg( GetInfo() );
+ else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
+ {
+ // Paragraphzeichen sollten den gleichen Font wie das Zeichen vor
+ // haben, es sei denn, es gibt Redlining in dem Absatz.
+ if( GetRedln() )
+ SeekAndChg( GetInfo() );
+ else
+ SeekAndChgBefore( GetInfo() );
+ }
+ else
+ bSeeked = sal_False;
+
+// bRest = sal_False;
+
+ ASSERT( GetInfo().Y() == nY, "DrawTextLine: Y() has changed" );
+
+ // Wenn das Ende der Portion hinausragt, wird geclippt.
+ // Es wird ein Sicherheitsabstand von Height-Halbe aufaddiert,
+ // damit die TTF-"f" nicht im Seitenrand haengen...
+ if(bClip && GetInfo().X() + pPor->Width() + (pPor->Height()/2) > nMaxRight)
+ { bClip = sal_False;
+ rClip.ChgClip( rPaint );
+ }
+
+ // Portions, die "unter" dem Text liegen wie PostIts
+ SwLinePortion *pNext = pPor->GetPortion();
+ if(GetInfo().OnWin() && pNext && !pNext->Width() )
+ {
+ // Fix 11289: Felder waren hier ausgeklammert wg. Last!=Owner beim
+ // Laden von Brief.sdw. Jetzt sind die Felder wieder zugelassen,
+ // durch bSeeked wird Last!=Owner vermieden.
+ if ( !bSeeked )
+ SeekAndChg( GetInfo() );
+ pNext->PrePaint( GetInfo(), pPor );
+ }
+
+ if( pFnt->GetEscapement() && UNDERLINE_NONE != pFnt->GetUnderline() )
+ CheckSpecialUnderline();
+
+ pPor->Paint( GetInfo() );
+
+ if( GetFnt()->IsURL() && pPor->InTxtGrp() )
+ GetInfo().NotifyURL( *pPor );
+
+ bFirst &= !pPor->GetLen();
+ if( pNext || !pPor->IsMarginPortion() )
+ pPor->Move( GetInfo() );
+ if( pPor->IsArrowPortion() && GetInfo().OnWin() && !pArrow )
+ pArrow = (SwArrowPortion*)pPor;
+
+ pPor = !bDrawInWindow && GetInfo().X() > nMaxRight ? 0 : pNext;
+ }
+ if( bDrawInWindow )
+ {
+ if( !GetNextLine() &&
+ GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() &&
+ GetInfo().GetOpt().IsParagraph() && !GetTxtFrm()->GetFollow() &&
+ GetInfo().GetIdx() >= GetInfo().GetTxt().Len() )
+ {
+ SwTmpEndPortion aEnd( *pCurr->GetFirstPortion() );
+ aEnd.Paint( GetInfo() );
+ }
+ if( bUnderSz )
+ {
+ if( GetInfo().GetVsh() && !GetInfo().GetVsh()->IsPreView() )
+ {
+ if( pArrow )
+ pArrow->PaintIt( pOut );
+ if( !GetTxtFrm()->GetFollow() )
+ {
+ SwTwips nDiff = GetInfo().Y() + nTmpHeight - nTmpAscent - GetTxtFrm()->Frm().Bottom();
+ if( nDiff > 0 && ( GetEnd() < GetInfo().GetTxt().Len() ||
+ ( nDiff > nTmpHeight/2 && GetPrevLine() ) ) )
+ {
+ SwArrowPortion aArrow( GetInfo() );
+ aArrow.PaintIt( pOut );
+ }
+ }
+ }
+ }
+ }
+ if( pCurr->IsClipping() )
+ rClip.ChgClip( rPaint );
+}
+
+void SwTxtPainter::CheckSpecialUnderline()
+{
+ sal_Bool bSpecial = sal_False;
+ if( HasHints() )
+ {
+ sal_Bool bINet = sal_False;
+ MSHORT nTmp = 0;
+ Range aRange( 0, GetInfo().GetTxt().Len() );
+ MultiSelection aUnderMulti( aRange );
+ if( bUnderPara )
+ aUnderMulti.SelectAll();
+ MultiSelection aEscMulti( aRange );
+ if( bEscPara )
+ aEscMulti.SelectAll();
+ SwTxtAttr* pTxtAttr;
+ sal_Bool bUnder = sal_False;
+ sal_Bool bEsc = sal_False;
+ while( nTmp < pHints->GetStartCount() )
+ {
+ pTxtAttr = pHints->GetStart( nTmp++ );
+ sal_Bool bUnderSelect;
+ sal_Bool bEscSelect;
+ switch ( pTxtAttr->Which() )
+ {
+ case RES_CHRATR_UNDERLINE:
+ {
+ bUnder = sal_True;
+ bUnderSelect = UNDERLINE_NONE != pTxtAttr->GetUnderline().
+ GetUnderline();
+ }
+ break;
+ case RES_CHRATR_ESCAPEMENT:
+ {
+ bEsc = sal_True;
+ bEscSelect = 0 != pTxtAttr->GetEscapement().GetEsc();
+ }
+ break;
+ case RES_TXTATR_FTN:
+ {
+ xub_StrLen nStrt = *pTxtAttr->GetStart();
+ Range aRg( nStrt, nStrt + 1 );
+ aEscMulti.Select( aRg );
+ }
+ break;
+ case RES_TXTATR_INETFMT: bINet = sal_True;
+ case RES_TXTATR_CHARFMT:
+ {
+ SwCharFmt* pFmt;
+ const SfxPoolItem* pItem;
+ if( bINet )
+ {
+ pFmt = ((SwTxtINetFmt*)pTxtAttr)->GetCharFmt();
+ bINet = sal_False;
+ }
+ else
+ pFmt = pTxtAttr->GetCharFmt().GetCharFmt();
+ if ( pFmt )
+ {
+ if( SFX_ITEM_SET == pFmt->GetAttrSet().
+ GetItemState( RES_CHRATR_ESCAPEMENT, sal_True, &pItem) )
+ {
+ bEscSelect = 0 !=
+ ((SvxEscapementItem *)pItem)->GetEsc();
+ bEsc = sal_True;
+ }
+ if( SFX_ITEM_SET == pFmt->GetAttrSet().
+ GetItemState( RES_CHRATR_UNDERLINE, sal_True, &pItem ) )
+ {
+ bUnderSelect = UNDERLINE_NONE !=
+ ((SvxUnderlineItem*)pItem)->GetUnderline();
+ bUnder = sal_True;
+ }
+ }
+ }
+ break;
+ }
+ if( bUnder || bEsc )
+ {
+ xub_StrLen nSt = *pTxtAttr->GetStart();
+ xub_StrLen nEnd = *pTxtAttr->GetEnd();
+ if( nEnd > nSt )
+ {
+ Range aTmp( nSt, nEnd - 1 );
+ if( bUnder )
+ aUnderMulti.Select( aTmp, bUnderSelect );
+ if( bEsc )
+ aEscMulti.Select( aTmp, bEscSelect );
+ }
+ bUnder = sal_False;
+ bEsc = sal_False;
+ }
+ }
+ MSHORT i;
+ xub_StrLen nEscStart = 0;
+ xub_StrLen nEscEnd = 0;
+ xub_StrLen nIndx = GetInfo().GetIdx();
+ MSHORT nCnt = (MSHORT)aEscMulti.GetRangeCount();
+ for( i = 0; i < nCnt; ++i )
+ {
+ const Range& rRange = aEscMulti.GetRange( i );
+ if( nEscEnd == rRange.Min() )
+ nEscEnd = rRange.Max();
+ else if( nIndx >= rRange.Min() )
+ {
+ nEscStart = rRange.Min();
+ nEscEnd = rRange.Max();
+ }
+ else
+ break;
+ }
+ xub_StrLen nUnderStart = 0;
+ xub_StrLen nUnderEnd = 0;
+ nCnt = (MSHORT)aUnderMulti.GetRangeCount();
+ for( i = 0; i < nCnt; ++i )
+ {
+ const Range& rRange = aUnderMulti.GetRange( i );
+ if( nUnderEnd == rRange.Min() )
+ nUnderEnd = rRange.Max();
+ else if( nIndx >= rRange.Min() )
+ {
+ nUnderStart = rRange.Min();
+ nUnderEnd = rRange.Max();
+ }
+ else
+ break;
+ }
+ bSpecial = nEscStart > nUnderStart || nEscEnd < nUnderEnd;
+ }
+ if( bSpecial || ( GetRedln() && GetRedln()->ChkSpecialUnderline() ) )
+ GetInfo().SetSpecialUnderline( sal_True );
+}
+