diff options
-rw-r--r-- | sw/source/core/text/itrform2.cxx | 11 | ||||
-rw-r--r-- | sw/source/core/text/itrform2.hxx | 8 | ||||
-rw-r--r-- | sw/source/core/text/pordrop.hxx | 53 | ||||
-rw-r--r-- | sw/source/core/text/txtdrop.cxx | 695 | ||||
-rw-r--r-- | sw/source/core/text/txtio.cxx | 8 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/drpcps.cxx | 17 |
6 files changed, 572 insertions, 220 deletions
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index b016bea3bdfa..e5003619cfbb 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -2,9 +2,9 @@ * * $RCSfile: itrform2.cxx,v $ * - * $Revision: 1.43 $ + * $Revision: 1.44 $ * - * last change: $Author: fme $ $Date: 2001-10-11 10:54:19 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:38:42 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -583,6 +583,7 @@ void SwTxtFormatter::BuildPortions( SwTxtFormatInfo &rInf ) // 1. Underlined portions due to special underline feature // 2. Right Tab // 3. Multiportions + // 4. DropCaps else if ( ( ! rInf.GetPaintOfst() || nUnderLineStart < rInf.GetPaintOfst() ) && // 1. Underlined portions nUnderLineStart && @@ -599,8 +600,8 @@ void SwTxtFormatter::BuildPortions( SwTxtFormatInfo &rInf ) else if ( ! rInf.GetPaintOfst() && // 2. Right Tab ( ( pPor->InTabGrp() && !pPor->IsTabLeftPortion() ) || - // 3. Multi Portion - ( pPor->IsMultiPortion() && + // 3. Multi Portion and 4. Drop Caps + ( ( pPor->IsDropPortion() || pPor->IsMultiPortion() )&& rInf.GetReformatStart() >= rInf.GetIdx() && rInf.GetReformatStart() <= rInf.GetIdx() + pPor->GetLen() ) ) @@ -894,7 +895,7 @@ SwTxtPortion *SwTxtFormatter::NewTxtPortion( SwTxtFormatInfo &rInf ) * SwTxtFormatter::WhichFirstPortion() *************************************************************************/ -SwLinePortion *SwTxtFormatter::WhichFirstPortion(SwTxtFormatInfo &rInf) const +SwLinePortion *SwTxtFormatter::WhichFirstPortion(SwTxtFormatInfo &rInf) { SwLinePortion *pPor = 0; diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx index 0c988b64f8e4..accb3543bb12 100644 --- a/sw/source/core/text/itrform2.hxx +++ b/sw/source/core/text/itrform2.hxx @@ -2,9 +2,9 @@ * * $RCSfile: itrform2.hxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: fme $ $Date: 2001-05-28 16:20:44 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:38:42 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -97,7 +97,7 @@ class SwTxtFormatter : public SwTxtPainter SwLinePortion *NewExtraPortion( SwTxtFormatInfo &rInf ); SwTabPortion *NewTabPortion( SwTxtFormatInfo &rInf ) const; SwNumberPortion *NewNumberPortion( SwTxtFormatInfo &rInf ) const; - SwDropPortion *NewDropPortion( SwTxtFormatInfo &rInf ) const; + SwDropPortion *NewDropPortion( SwTxtFormatInfo &rInf ); SwNumberPortion *NewFtnNumPortion( SwTxtFormatInfo &rInf ) const; SwErgoSumPortion *NewErgoSumPortion( SwTxtFormatInfo &rInf ) const; SwExpandPortion *NewFldPortion( SwTxtFormatInfo &rInf, @@ -105,7 +105,7 @@ class SwTxtFormatter : public SwTxtPainter SwFtnPortion *NewFtnPortion( SwTxtFormatInfo &rInf, SwTxtAttr *pHt ); SwFlyCntPortion *NewFlyCntPortion( SwTxtFormatInfo &rInf, SwTxtAttr *pHt ) const; - SwLinePortion *WhichFirstPortion( SwTxtFormatInfo &rInf ) const; + SwLinePortion *WhichFirstPortion( SwTxtFormatInfo &rInf ); SwTxtPortion *WhichTxtPor( SwTxtFormatInfo &rInf ) const; // Das Herzstueck der Formatierung diff --git a/sw/source/core/text/pordrop.hxx b/sw/source/core/text/pordrop.hxx index 183a327f7d16..20b85d9cb36b 100644 --- a/sw/source/core/text/pordrop.hxx +++ b/sw/source/core/text/pordrop.hxx @@ -2,9 +2,9 @@ * * $RCSfile: pordrop.hxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: fme $ $Date: 2001-05-28 16:20:44 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:38:42 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -72,30 +72,57 @@ class SwDropCapCache; extern SwDropCapCache *pDropCapCache; /************************************************************************* + * class SwDropPortionPart + * + * A drop portion can consist of one or more parts in order to allow + * attribute changes inside them. + *************************************************************************/ + +class SwDropPortionPart +{ + SwDropPortionPart* pFollow; + SwFont* pFnt; + xub_StrLen nLen; + USHORT nWidth; + +public: + SwDropPortionPart( SwFont& rFont, const xub_StrLen nL ) + : pFollow( 0 ), pFnt( &rFont ), nLen( nL ), nWidth( 0 ) {}; + ~SwDropPortionPart(); + + inline SwDropPortionPart* GetFollow() const { return pFollow; }; + inline void SetFollow( SwDropPortionPart* pNew ) { pFollow = pNew; }; + inline SwFont& GetFont() const { return *pFnt; } + inline xub_StrLen GetLen() const { return nLen; } + inline USHORT GetWidth() const { return nWidth; } + inline void SetWidth( USHORT nNew ) { nWidth = nNew; } +}; + +/************************************************************************* * class SwDropPortion *************************************************************************/ class SwDropPortion : public SwTxtPortion { friend class SwDropCapCache; - SwFont *pFnt; // der Font + SwDropPortionPart* pPart; // due to script / attribute changes MSHORT nLines; // Anzahl der Zeilen KSHORT nDropHeight; // Hoehe KSHORT nDropDescent; // Abstand zur naechsten Zeile KSHORT nDistance; // Abstand zum Text KSHORT nFix; // Fixposition short nX; // X-PaintOffset - short nY; // Y-PaintOffset + short nY; // Y-Offset sal_Bool FormatTxt( SwTxtFormatInfo &rInf ); - void PaintTxt( const SwTxtPaintInfo &rInf /*, const sal_Bool bBack */) const; + void PaintTxt( const SwTxtPaintInfo &rInf ) const; inline void Fix( const KSHORT nNew ) { nFix = nNew; } public: - SwDropPortion( SwFont *pFnt, const MSHORT nLineCnt, - const KSHORT nDropHeight, - const KSHORT nDropDescent, - const KSHORT nDistance ); + SwDropPortion( const MSHORT nLineCnt, + const KSHORT nDropHeight, + const KSHORT nDropDescent, + const KSHORT nDistance ); virtual ~SwDropPortion(); virtual void Paint( const SwTxtPaintInfo &rInf ) const; @@ -109,7 +136,13 @@ public: inline KSHORT GetDropHeight() const { return nDropHeight; } inline KSHORT GetDropDescent() const { return nDropDescent; } inline KSHORT GetDropLeft() const { return Width() + nFix; } - inline SwFont* GetFnt() { return pFnt; } + + inline SwDropPortionPart* GetPart() const { return pPart; } + inline void SetPart( SwDropPortionPart* pNew ) { pPart = pNew; } + + inline void SetY( short nNew ) { nY = nNew; } + + inline SwFont* GetFnt() { return pPart ? &pPart->GetFont() : NULL; } static void DeleteDropCapCache(); diff --git a/sw/source/core/text/txtdrop.cxx b/sw/source/core/text/txtdrop.cxx index 01166c232961..12e6584046fb 100644 --- a/sw/source/core/text/txtdrop.cxx +++ b/sw/source/core/text/txtdrop.cxx @@ -2,9 +2,9 @@ * * $RCSfile: txtdrop.cxx,v $ * - * $Revision: 1.6 $ + * $Revision: 1.7 $ * - * last change: $Author: fme $ $Date: 2001-07-17 09:11:33 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:38:42 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -116,32 +116,114 @@ #ifndef _TXATBASE_HXX #include <txatbase.hxx> #endif +#ifndef _BREAKIT_HXX +#include <breakit.hxx> +#endif +#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_ +#include <com/sun/star/i18n/ScriptType.hdl> +#endif +#ifndef _COM_SUN_STAR_I18N_WORDTYPE_HPP_ +#include <com/sun/star/i18n/WordType.hpp> +#endif +#ifndef _SVX_LANGITEM_HXX //autogen +#include <svx/langitem.hxx> +#endif +#ifndef _CHARATR_HXX +#include <charatr.hxx> +#endif + +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star; + +/************************************************************************* + * lcl_IsDropFlyInter + * + * Calculates if a drop caps portion intersects with a fly + * The width and height of the drop caps portion are passed as arguments, + * the position is calculated from the values in rInf + *************************************************************************/ + +sal_Bool lcl_IsDropFlyInter( const SwTxtFormatInfo &rInf, + USHORT nWidth, USHORT nHeight ) +{ + const SwTxtFly *pTxtFly = rInf.GetTxtFly(); + if( pTxtFly && pTxtFly->IsOn() ) + { + SwRect aRect( rInf.GetTxtFrm()->Frm().Pos(), Size( nWidth, nHeight) ); + aRect.Pos() += rInf.GetTxtFrm()->Prt().Pos(); + aRect.Pos().X() += rInf.X(); + aRect.Pos().Y() = rInf.Y(); + aRect = pTxtFly->GetFrm( aRect ); + return aRect.HasArea(); + } + + return sal_False; +} + +/************************************************************************* + * class SwDropSave + *************************************************************************/ + +class SwDropSave +{ + SwTxtPaintInfo* pInf; + xub_StrLen nIdx; + xub_StrLen nLen; + long nX; + long nY; + +public: + SwDropSave( const SwTxtPaintInfo &rInf ); + ~SwDropSave(); +}; + +SwDropSave::SwDropSave( const SwTxtPaintInfo &rInf ) : + pInf( ((SwTxtPaintInfo*)&rInf) ), nIdx( rInf.GetIdx() ), + nLen( rInf.GetLen() ), nX( rInf.X() ), nY( rInf.Y() ) +{ +} + +SwDropSave::~SwDropSave() +{ + pInf->SetIdx( nIdx ); + pInf->SetLen( nLen ); + pInf->X( nX ); + pInf->Y( nY ); +} + +/************************************************************************* + * SwDropPortionPart DTor + *************************************************************************/ + +SwDropPortionPart::~SwDropPortionPart() +{ + if ( pFollow ) + delete pFollow; + delete pFnt; +} /************************************************************************* * SwDropPortion CTor, DTor *************************************************************************/ -SwDropPortion::SwDropPortion( SwFont *pF, const MSHORT nLineCnt, - const KSHORT nDropHeight, - const KSHORT nDropDescent, - const KSHORT nDistance ) - : pFnt( pF ), +SwDropPortion::SwDropPortion( const MSHORT nLineCnt, + const KSHORT nDropHeight, + const KSHORT nDropDescent, + const KSHORT nDistance ) + : pPart( 0 ), nLines( nLineCnt ), nDropHeight(nDropHeight), nDropDescent(nDropDescent), nDistance(nDistance), nX(0), - nY(0), nFix(0) { SetWhichPor( POR_DROP ); } - - SwDropPortion::~SwDropPortion() { - delete pFnt; + delete pPart; if( pBlink ) pBlink->Delete( this ); } @@ -165,6 +247,8 @@ sal_Bool SwTxtSizeInfo::_HasHint( const SwTxtNode* pTxtNode, xub_StrLen nPos ) /************************************************************************* * SwTxtNode::GetDropLen() + * + * nWishLen = 0 indicates that we want a whole word *************************************************************************/ MSHORT SwTxtNode::GetDropLen( MSHORT nWishLen ) const @@ -172,12 +256,39 @@ MSHORT SwTxtNode::GetDropLen( MSHORT nWishLen ) const xub_StrLen nEnd = GetTxt().Len(); if( nWishLen && nWishLen < nEnd ) nEnd = nWishLen; + + if ( ! nWishLen && pBreakIt->xBreak.is() ) + { + // find first word + const SwAttrSet& rAttrSet = GetSwAttrSet(); + const USHORT nTxtScript = pBreakIt->xBreak->getScriptType( GetTxt(),0 ); + LanguageType eLanguage; + + switch ( nTxtScript ) + { + case i18n::ScriptType::ASIAN : + eLanguage = rAttrSet.GetCJKLanguage().GetLanguage(); + break; + case i18n::ScriptType::COMPLEX : + eLanguage = rAttrSet.GetCTLLanguage().GetLanguage(); + break; + default : + eLanguage = rAttrSet.GetLanguage().GetLanguage(); + break; + } + + Boundary aBound = + pBreakIt->xBreak->getWordBoundary( GetTxt(), 0, + pBreakIt->GetLocale( eLanguage ), WordType::DICTIONARY_WORD, sal_True ); + + nEnd = (xub_StrLen)aBound.endPos; + } + xub_StrLen i = 0; for( ; i < nEnd; ++i ) { xub_Unicode cChar = GetTxt().GetChar( i ); if( CH_TAB == cChar || CH_BREAK == cChar || - ( !nWishLen && CH_BLANK == cChar ) || (( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar ) && SwTxtSizeInfo::_HasHint( this, i ) ) ) break; @@ -191,37 +302,46 @@ MSHORT SwTxtNode::GetDropLen( MSHORT nWishLen ) const // Die Breite manipulieren, sonst werden die Buchstaben gestretcht +void SwDropPortion::PaintTxt( const SwTxtPaintInfo &rInf ) const +{ + if ( rInf.OnWin() && rInf.GetOpt().IsField() ) + rInf.DrawBackground( *this ); + ASSERT( nDropHeight && pPart && nLines != 1, "Drop Portion painted twice" ); -void SwDropPortion::PaintTxt( const SwTxtPaintInfo &rInf /*, const sal_Bool bBack*/ ) - const -{ - if ( rInf.OnWin() ) + const SwDropPortionPart* pCurrPart = GetPart(); + const xub_StrLen nOldLen = GetLen(); + + const SwTwips nBasePosY = rInf.Y(); + ((SwTxtPaintInfo&)rInf).Y( nBasePosY + nY ); + SwDropSave aSave( rInf ); + + while ( pCurrPart ) { - if( rInf.GetOpt().IsField() ) - rInf.DrawBackground( *this ); -// else if ( bBack ) -// rInf.DrawRect( *this ); + ((SwDropPortion*)this)->SetLen( pCurrPart->GetLen() ); + ((SwTxtPaintInfo&)rInf).SetLen( pCurrPart->GetLen() ); + SwFontSave aSave( rInf, &pCurrPart->GetFont() ); + + SwTxtPortion::Paint( rInf ); + + ((SwTxtPaintInfo&)rInf).SetIdx( rInf.GetIdx() + pCurrPart->GetLen() ); + ((SwTxtPaintInfo&)rInf).X( rInf.X() + pCurrPart->GetWidth() ); + pCurrPart = pCurrPart->GetFollow(); } - ((SwDropPortion*)this)->Width( Width() - nDistance ); - SwTxtPortion::Paint( rInf ); - ((SwDropPortion*)this)->Width( Width() + nDistance ); + + ((SwTxtPaintInfo&)rInf).Y( nBasePosY ); + ((SwDropPortion*)this)->SetLen( nOldLen ); } /************************************************************************* * SwDropPortion::Paint() *************************************************************************/ - void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const { - // ganz normale Ausgabe - if( !nDropHeight || !pFnt || nLines == 1 ) - { - SwFontSave aTmp( rInf, pFnt ); - PaintTxt( rInf /*, sal_False */); + // ganz normale Ausgabe wird während des normalen Paints erledigt + if( ! nDropHeight || ! pPart || nLines == 1 ) return; - } // Luegenwerte einstellen! const KSHORT nOldHeight = Height(); @@ -234,10 +354,13 @@ void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const - pPara->GetRealHeight() + pPara->Height() ); // Retusche nachholen. - ((SwTxtPaintInfo&)rInf).Y( aOutPos.Y() + nDropHeight + nY ); - ((SwDropPortion*)this)->Height( nDropHeight+nDropDescent ); + // Set baseline + ((SwTxtPaintInfo&)rInf).Y( aOutPos.Y() + nDropHeight ); + + // for background + ((SwDropPortion*)this)->Height( nDropHeight + nDropDescent ); ((SwDropPortion*)this)->Width( Width() - nX ); - ((SwDropPortion*)this)->SetAscent( nDropHeight + nY ); + ((SwDropPortion*)this)->SetAscent( nDropHeight ); // Clipregion auf uns einstellen! // Und zwar immer, und nie mit dem bestehenden ClipRect @@ -253,16 +376,13 @@ void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const aClip.ChgClip( aClipRect ); // Das machen, was man sonst nur macht ... - SwFontSave aSave( rInf, pFnt ); - PaintTxt( rInf /*, sal_True */); + PaintTxt( rInf ); // Alte Werte sichern ((SwDropPortion*)this)->Height( nOldHeight ); ((SwDropPortion*)this)->Width( nOldWidth ); ((SwDropPortion*)this)->SetAscent( nOldAscent ); ((SwTxtPaintInfo&)rInf).Y( nOldPosY ); - ((SwTxtPaintInfo&)rInf).X( nOldPosX ); - } /************************************************************************* @@ -273,8 +393,13 @@ void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const void SwDropPortion::Paint( const SwTxtPaintInfo &rInf ) const { // ganz normale Ausgabe wird hier erledigt. - if( !nDropHeight || !pFnt ) - PaintTxt( rInf /*, sal_False */); + if( ! nDropHeight || ! pPart || 1 == nLines ) + { + if ( rInf.OnWin() && rInf.GetOpt().IsField() ) + rInf.DrawBackground( *this ); + + SwTxtPortion::Paint( rInf ); + } } /************************************************************************* @@ -305,8 +430,34 @@ sal_Bool SwDropPortion::FormatTxt( SwTxtFormatInfo &rInf ) SwPosSize SwDropPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const { - SwFontSave aSave( rInf, pFnt ); - return SwTxtPortion::GetTxtSize( rInf ); + USHORT nX = 0; + xub_StrLen nIdx = 0; + + const SwDropPortionPart* pCurrPart = GetPart(); + + // skip parts + while ( pCurrPart && nIdx + pCurrPart->GetLen() < rInf.GetLen() ) + { + nX += pCurrPart->GetWidth(); + nIdx += pCurrPart->GetLen(); + pCurrPart = pCurrPart->GetFollow(); + } + + xub_StrLen nOldIdx = rInf.GetIdx(); + xub_StrLen nOldLen = rInf.GetLen(); + + ((SwTxtSizeInfo&)rInf).SetIdx( nIdx ); + ((SwTxtSizeInfo&)rInf).SetLen( rInf.GetLen() - nIdx ); + + // robust + SwFontSave aSave( rInf, pCurrPart ? &pCurrPart->GetFont() : 0 ); + SwPosSize aPosSize( SwTxtPortion::GetTxtSize( rInf ) ); + aPosSize.Width( aPosSize.Width() + nX ); + + ((SwTxtSizeInfo&)rInf).SetIdx( nOldIdx ); + ((SwTxtSizeInfo&)rInf).SetLen( nOldLen ); + + return aPosSize; } /************************************************************************* @@ -409,8 +560,7 @@ void SwTxtFormatter::GuessDropHeight( const MSHORT nLines ) * SwTxtFormatter::NewDropPortion *************************************************************************/ - -SwDropPortion *SwTxtFormatter::NewDropPortion( SwTxtFormatInfo &rInf ) const +SwDropPortion *SwTxtFormatter::NewDropPortion( SwTxtFormatInfo &rInf ) { if( !pDropFmt ) return 0; @@ -429,27 +579,73 @@ SwDropPortion *SwTxtFormatter::NewDropPortion( SwTxtFormatInfo &rInf ) const if ( !( GetDropHeight() || IsOnceMore() ) ) { if ( GetNext() ) - ((SwTxtFormatter*)this)->CalcDropHeight( pDropFmt->GetLines() ); + CalcDropHeight( pDropFmt->GetLines() ); else - ((SwTxtFormatter*)this)->GuessDropHeight( pDropFmt->GetLines() ); + GuessDropHeight( pDropFmt->GetLines() ); } - SwFont *pTmpFnt = new SwFont( pDropFmt->GetCharFmt() - ? &pDropFmt->GetCharFmt()->GetAttrSet() - : &rInf.GetCharAttr(), rInf.GetDoc() ); - // we do not allow a vertical font for the drop portion - pTmpFnt->SetVertical( 0 ); - - // the constructor above does not set the right script - pTmpFnt->SetActual( rInf.GetFont()->GetActual() ); + // the DropPortion if( GetDropHeight() ) - pDropPor = new SwDropPortion( pTmpFnt, GetDropLines(), - GetDropHeight(), GetDropDescent(), - pDropFmt->GetDistance() ); + pDropPor = new SwDropPortion( GetDropLines(), GetDropHeight(), + GetDropDescent(), pDropFmt->GetDistance() ); else - pDropPor = new SwDropPortion( pTmpFnt,0,0,0,pDropFmt->GetDistance() ); + pDropPor = new SwDropPortion( 0,0,0,pDropFmt->GetDistance() ); pDropPor->SetLen( nPorLen ); + + // If it was not possible to create a proper drop cap portion + // due to avoiding endless loops. We return a drop cap portion + // with an empty SwDropCapPart. For these portions the current + // font is used. + if ( GetDropLines() < 2 ) + { + ((SwTxtFormatter*)this)->SetPaintDrop( sal_True ); + return pDropPor; + } + + // build DropPortionParts: + ASSERT( ! rInf.GetIdx(), "Drop Portion not at 0 position!" ); + xub_StrLen nIdx = rInf.GetIdx(); + xub_StrLen nNextChg = 0; + const SwCharFmt* pFmt = pDropFmt->GetCharFmt(); + SwDropPortionPart* pCurrPart = 0; + + while ( nNextChg < nPorLen ) + { + // check for attribute changes and if the portion has to split: + Seek( nNextChg ); + + // the font is deleted in the destructor of the drop portion part + SwFont* pTmpFnt = new SwFont( *rInf.GetFont() ); + if ( pFmt ) + { + const SwAttrSet& rSet = pFmt->GetAttrSet(); + pTmpFnt->SetDiffFnt( &rSet, rInf.GetDoc() ); + } + + // we do not allow a vertical font for the drop portion + pTmpFnt->SetVertical( 0 ); + + // find next attribute change / script change + const xub_StrLen nIdx = nNextChg; + xub_StrLen nNextAttr = Min( GetNextAttr(), rInf.GetTxt().Len() ); + nNextChg = pScriptInfo->NextScriptChg( nIdx ); + if( nNextChg > nNextAttr ) + nNextChg = nNextAttr; + if ( nNextChg > nPorLen ) + nNextChg = nPorLen; + + SwDropPortionPart* pPart = + new SwDropPortionPart( *pTmpFnt, nNextChg - nIdx ); + + if ( ! pCurrPart ) + pDropPor->SetPart( pPart ); + else + pCurrPart->SetFollow( pPart ); + + pCurrPart = pPart; + } + ((SwTxtFormatter*)this)->SetPaintDrop( sal_True ); return pDropPor; } @@ -515,6 +711,8 @@ void SwTxtPainter::PaintDropPortion() } /************************************************************************* + * clas SwDropCapCache + * * Da die Berechnung der Fontgroesse der Initialen ein teures Geschaeft ist, * wird dies durch einen DropCapCache geschleust. *************************************************************************/ @@ -525,7 +723,7 @@ class SwDropCapCache { long aMagicNo[ DROP_CACHE_SIZE ]; XubString aTxt[ DROP_CACHE_SIZE ]; - Size aSize[ DROP_CACHE_SIZE ]; + USHORT aFactor[ DROP_CACHE_SIZE ]; KSHORT aWishedHeight[ DROP_CACHE_SIZE ]; short aDescent[ DROP_CACHE_SIZE ]; MSHORT nIndex; @@ -535,7 +733,9 @@ public: void CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf ); }; - +/************************************************************************* + * SwDropCapCache Ctor / Dtor + *************************************************************************/ SwDropCapCache::SwDropCapCache() : nIndex( 0 ) { @@ -543,224 +743,353 @@ SwDropCapCache::SwDropCapCache() : nIndex( 0 ) memset( &aWishedHeight, 0, sizeof(aWishedHeight) ); } +void SwDropPortion::DeleteDropCapCache() +{ + delete pDropCapCache; +} +/************************************************************************* + * SwDropCapCache::CalcFontSize + *************************************************************************/ void SwDropCapCache::CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf ) { const void* pFntNo; - MSHORT nTmpIdx; - SwFont *pFnt = pDrop->pFnt; - pFnt->GetMagic( pFntNo, nTmpIdx, pFnt->GetActual() ); - XubString aStr( rInf.GetTxt(), rInf.GetIdx(), pDrop->GetLen() ); - - nTmpIdx = 0; - while( nTmpIdx < DROP_CACHE_SIZE && - ( aTxt[ nTmpIdx ] != aStr || aMagicNo[ nTmpIdx ] != long(pFntNo) || - aWishedHeight[ nTmpIdx ] != pDrop->GetDropHeight() ) ) - ++nTmpIdx; - if( nTmpIdx >= DROP_CACHE_SIZE ) + MSHORT nTmpIdx = 0; + + ASSERT( pDrop->GetPart(),"DropPortion without part during font calculation"); + + SwDropPortionPart* pCurrPart = pDrop->GetPart(); + const sal_Bool bUseCache = ! pCurrPart->GetFollow(); + xub_StrLen nIdx = rInf.GetIdx(); + XubString aStr( rInf.GetTxt(), nIdx, pCurrPart->GetLen() ); + + long nAscent = 0; + long nDescent = 0; + long nFactor = -1; + + if ( bUseCache ) + { + SwFont& rFnt = pCurrPart->GetFont(); + rFnt.ChkMagic( rInf.GetVsh(), rFnt.GetActual() ); + rFnt.GetMagic( pFntNo, nTmpIdx, rFnt.GetActual() ); + + nTmpIdx = 0; + + while( nTmpIdx < DROP_CACHE_SIZE && + ( aTxt[ nTmpIdx ] != aStr || aMagicNo[ nTmpIdx ] != long(pFntNo) || + aWishedHeight[ nTmpIdx ] != pDrop->GetDropHeight() ) ) + ++nTmpIdx; + } + + // we have to calculate a new font scaling factor if + // 1. we did not find a scaling factor in the cache or + // 2. we are not allowed to use the cache because the drop portion + // consists of more than one part + if( nTmpIdx >= DROP_CACHE_SIZE || ! bUseCache ) { ++nIndex; nIndex %= DROP_CACHE_SIZE; nTmpIdx = nIndex; - aMagicNo[ nTmpIdx ] = long(pFntNo); - aTxt[ nTmpIdx ] = aStr; long nWishedHeight = pDrop->GetDropHeight(); - Size aNewSize = Size( 0, nWishedHeight ); + // find out biggest font size for initial scaling factor + long nMaxFontHeight = 0; + while ( pCurrPart ) + { + const SwFont& rFnt = pCurrPart->GetFont(); + const long nCurrHeight = rFnt.GetHeight( rFnt.GetActual() ); + if ( nCurrHeight > nMaxFontHeight ) + nMaxFontHeight = nCurrHeight; - aSize[ nTmpIdx ] = aNewSize; + pCurrPart = pCurrPart->GetFollow(); + } - long nAscent = 0; - long nDescent = 0; + nFactor = ( 1000 * nWishedHeight ) / nMaxFontHeight; - OutputDevice *pOut = rInf.GetOut(); + if ( bUseCache ) + { + // save keys for cache + aMagicNo[ nTmpIdx ] = long(pFntNo); + aTxt[ nTmpIdx ] = aStr; + aWishedHeight[ nTmpIdx ] = KSHORT(nWishedHeight); + // save initial scaling factor + aFactor[ nTmpIdx ] = (USHORT)nFactor; + } - xub_StrLen nLen = aStr.Len(); + sal_Bool bGrow = ( pDrop->GetLen() != 0 ); - sal_Bool bGrow = ( nLen != 0 ); + // for growing controll + long nMax = KSHRT_MAX; + long nMin = nFactor / 2; #ifdef DEBUG long nGrow = 0; #endif - long nMin, nMax = KSHRT_MAX; - nMin = aNewSize.Height()/2; sal_Bool bWinUsed = sal_False; Font aOldFnt; MapMode aOldMap( MAP_TWIP ); + OutputDevice *pOut = rInf.GetOut(); OutputDevice *pWin; if( rInf.GetVsh() && rInf.GetVsh()->GetWin() ) pWin = rInf.GetVsh()->GetWin(); else pWin = GetpApp()->GetDefaultDevice(); + while( bGrow ) { - pFnt->SetSize( aNewSize, pFnt->GetActual() ); - pFnt->ChgPhysFnt( rInf.GetVsh(), pOut ); - nAscent = pFnt->GetAscent( rInf.GetVsh(), pOut ); - - // Wir besorgen uns das alle Buchstaben umfassende Rechteck: - Rectangle aRect, aTmp; - sal_Bool bTakeRect = sal_False; - for ( xub_StrLen i = 0; i < nLen; i++ ) + // reset pCurrPart to first part + pCurrPart = pDrop->GetPart(); + sal_Bool bFirstGlyphRect = sal_True; + sal_Bool bHaveGlyphRect = sal_False; + Rectangle aCommonRect, aTmp, aRect; + + while ( pCurrPart ) { - if( pOut->GetGlyphBoundRect( aStr.GetChar(i), aTmp, sal_False ) - && !aTmp.IsEmpty() ) + XubString aTmpStr( rInf.GetTxt(), nIdx, pCurrPart->GetLen() ); + + // current font + SwFont& rFnt = pCurrPart->GetFont(); + + // Get height including proportion + const USHORT nCurrHeight = + (USHORT)rFnt.GetHeight( rFnt.GetActual() ); + + // Get without proportion + const BYTE nOldProp = rFnt.GetPropr(); + rFnt.SetProportion( 100 ); + Size aOldSize = Size( 0, rFnt.GetHeight( rFnt.GetActual() ) ); + + Size aNewSize( 0, ( nFactor * nCurrHeight ) / 1000 ); + rFnt.SetSize( aNewSize, rFnt.GetActual() ); + rFnt.ChgPhysFnt( rInf.GetVsh(), pOut ); + nAscent = rFnt.GetAscent( rInf.GetVsh(), pOut ) - + rFnt.GetLeading( rInf.GetVsh(), pOut ); + + // Wir besorgen uns das alle Buchstaben umfassende Rechteck: + bHaveGlyphRect = sal_False; + for ( xub_StrLen i = 0; i < pCurrPart->GetLen(); i++ ) { - if ( bTakeRect ) - aRect.Union( aTmp ); - else + if( pOut->GetGlyphBoundRect( aTmpStr.GetChar(i), aTmp, sal_False ) + && !aTmp.IsEmpty() ) { - aRect = aTmp; - bTakeRect = sal_True; + if ( bHaveGlyphRect ) + aRect.Union( aTmp ); + else + { + aRect = aTmp; + bHaveGlyphRect = sal_True; + } } } - } - if ( bTakeRect ) - { - // Der tiefste Punkt der Buchstaben - nDescent = aRect.Bottom()-nAscent; - // Der hoechste Punkt der Buchstaben - nAscent = nAscent-aRect.Top(); - } - // Wenn kein Rectangle ermittelt werden konnte, nehmen wir weiterhin - // einfach den Ascent mit all den bekannten Folgen (Q,g etc.) - else - { - if ( pWin ) + + if ( ! bHaveGlyphRect ) { - if ( bWinUsed ) - pWin->SetFont( pFnt->GetActualFont() ); - else + // getting glyph boundaries failed for some reason, + // we take the window for calculating sizes + if ( pWin ) { - bWinUsed = sal_True; - aOldMap = pWin->GetMapMode( ); - pWin->SetMapMode( MapMode( MAP_TWIP ) ); - aOldFnt = pWin->GetFont(); - pWin->SetFont( pFnt->GetActualFont() ); - } - for ( xub_StrLen i = 0; i < nLen; i++ ) - { - if( pWin->GetGlyphBoundRect( aStr.GetChar(i), aTmp, sal_False ) - && !aTmp.IsEmpty() ) + if ( ! bWinUsed ) + { + bWinUsed = sal_True; + aOldMap = pWin->GetMapMode( ); + pWin->SetMapMode( MapMode( MAP_TWIP ) ); + aOldFnt = pWin->GetFont(); + } + pWin->SetFont( rFnt.GetActualFont() ); + + for ( xub_StrLen i = 0; i < pCurrPart->GetLen(); i++ ) { - if ( bTakeRect ) - aRect.Union( aTmp ); - else + if( pWin->GetGlyphBoundRect( aTmpStr.GetChar(i), aTmp, sal_False ) + && !aTmp.IsEmpty() ) { - aRect = aTmp; - bTakeRect = sal_True; + if ( bHaveGlyphRect ) + aRect.Union( aTmp ); + else + { + aRect = aTmp; + bHaveGlyphRect = sal_True; + } } } } + if ( bHaveGlyphRect ) + { + FontMetric aWinMet( pWin->GetFontMetric() ); + nAscent = (KSHORT) aWinMet.GetAscent(); + } + else + // We do not have a window or our window could not + // give us glyph boundaries. + aRect = Rectangle( Point( 0, 0 ), Size( 0, nAscent ) ); } - if ( bTakeRect ) + + // Now we (hopefully) have a bounding rectangle for the + // glyphs of the current portion and the ascent of the current + // font + + // reset font size and proportion + rFnt.SetSize( aOldSize, rFnt.GetActual() ); + rFnt.SetProportion( nOldProp ); + + // shift aRect to have baseline 0 + aRect.Top() -= nAscent; + aRect.Bottom() -= nAscent; + + if ( bFirstGlyphRect ) { - FontMetric aWinMet( pWin->GetFontMetric() ); - nAscent = (KSHORT) aWinMet.GetAscent(); - // Der tiefste Punkt der Buchstaben - nDescent = aRect.Bottom()-nAscent; - // Der hoechste Punkt der Buchstaben - nAscent = nAscent-aRect.Top(); + aCommonRect = aRect; + bFirstGlyphRect = sal_False; } else - nDescent = 0; // nAscent stimmt eh noch. + aCommonRect.Union( aRect ); + + nIdx += pCurrPart->GetLen(); + pCurrPart = pCurrPart->GetFollow(); } + + // now we have a union ( aCommonRect ) of all glyphs with + // respect to a common baseline : 0 + + // get descent and ascent from union + nDescent = aCommonRect.Bottom(); + nAscent = aCommonRect.Top(); + if ( nAscent < 0 ) + nAscent = -nAscent; + const long nHght = nAscent + nDescent; if ( nHght ) { if ( nHght > nWishedHeight ) - nMax = aNewSize.Height(); + nMax = nFactor; else { - aSize[ nTmpIdx ] = aNewSize; - nMin = aNewSize.Height(); + if ( bUseCache ) + aFactor[ nTmpIdx ] = (USHORT)nFactor; + nMin = nFactor; } - const long nNewHeight = ( aNewSize.Height() * nWishedHeight ) - / nHght; - bGrow = ( nNewHeight > nMin ) && ( nNewHeight < nMax ); + + nFactor = ( nFactor * nWishedHeight ) / nHght; + bGrow = ( nFactor > nMin ) && ( nFactor < nMax ); #ifdef DEBUG if ( bGrow ) nGrow++; #endif - aNewSize.Height() = KSHORT( nNewHeight ); + nIdx = rInf.GetIdx(); } else bGrow = sal_False; } + if ( bWinUsed ) { - nDescent += pFnt->GetLeading( rInf.GetVsh(), pWin ); + // reset window if it has been used pWin->SetMapMode( aOldMap ); pWin->SetFont( aOldFnt ); } - else - nDescent += pFnt->GetLeading( rInf.GetVsh(), pOut ); - aDescent[ nTmpIdx ] = -short( nDescent ); - aWishedHeight[ nTmpIdx ] = KSHORT(nWishedHeight); + if ( bUseCache ) + aDescent[ nTmpIdx ] = -short( nDescent ); } - pDrop->nY = aDescent[ nTmpIdx ]; - pFnt->SetSize( aSize[ nTmpIdx ], pFnt->GetActual() ); -} + pCurrPart = pDrop->GetPart(); + // did made any new calculations or did we use the cache? + if ( -1 == nFactor ) + { + nFactor = aFactor[ nTmpIdx ]; + nDescent = aDescent[ nTmpIdx ]; + } + else + nDescent = -nDescent; -void SwDropPortion::DeleteDropCapCache() -{ - delete pDropCapCache; + while ( pCurrPart ) + { + // scale current font + SwFont& rFnt = pCurrPart->GetFont(); + Size aNewSize( 0, ( nFactor * rFnt.GetHeight( rFnt.GetActual() ) ) / 1000 ); + + const BYTE nOldProp = rFnt.GetPropr(); + rFnt.SetProportion( 100 ); + rFnt.SetSize( aNewSize, rFnt.GetActual() ); + rFnt.SetProportion( nOldProp ); + + pCurrPart = pCurrPart->GetFollow(); + } + pDrop->SetY( (short)nDescent ); } /************************************************************************* * virtual Format() *************************************************************************/ - sal_Bool SwDropPortion::Format( SwTxtFormatInfo &rInf ) { sal_Bool bFull = sal_False; Fix( (USHORT)rInf.X() ); - if( nDropHeight && pFnt && nLines!=1 ) + if( nDropHeight && pPart && nLines!=1 ) { - pFnt->ChkMagic( rInf.GetVsh(), pFnt->GetActual() ); if( !pDropCapCache ) pDropCapCache = new SwDropCapCache(); + + // adjust font sizes to fit into the rectangle pDropCapCache->CalcFontSize( this, rInf ); + + const long nOldX = rInf.X(); { - SwFontSave aSave( rInf, pFnt ); - bFull = FormatTxt( rInf ); - if( !bFull ) + SwDropSave aSave( rInf ); + SwDropPortionPart* pCurrPart = pPart; + + while ( pCurrPart ) { - // 7631, 7633: bei Ueberlappungen mit Flys ist Schluss. - const SwTxtFly *pTxtFly = rInf.GetTxtFly(); - if( pTxtFly && pTxtFly->IsOn() ) + rInf.SetLen( pCurrPart->GetLen() ); + SwFont& rFnt = pCurrPart->GetFont(); { - SwRect aRect( rInf.GetTxtFrm()->Frm().Pos(), SvLSize() ); - aRect.Height( nDropHeight ); - aRect.Pos() += rInf.GetTxtFrm()->Prt().Pos(); - aRect.Pos().X() += rInf.X(); - aRect.Pos().Y() = rInf.Y(); - aRect = pTxtFly->GetFrm( aRect ); - bFull = aRect.HasArea(); + SwFontSave aSave( rInf, &rFnt ); + bFull = FormatTxt( rInf ); + + if ( bFull ) + break; } + + SwTwips nTmpWidth = + ( InSpaceGrp() && rInf.GetSpaceAdd() ) ? + Width() + CalcSpacing( rInf.GetSpaceAdd(), rInf ) : + Width(); + + // set values + pCurrPart->SetWidth( (USHORT)nTmpWidth ); + + // Move + rInf.SetIdx( rInf.GetIdx() + pCurrPart->GetLen() ); + rInf.X( rInf.X() + nTmpWidth ); + pCurrPart = pCurrPart->GetFollow(); } + + Width( (USHORT)(rInf.X() - nOldX) ); } + + // reset my length + SetLen( rInf.GetLen() ); + + // 7631, 7633: bei Ueberlappungen mit Flys ist Schluss. + if( ! bFull ) + bFull = lcl_IsDropFlyInter( rInf, Width(), nDropHeight ); + if( bFull ) { // Durch FormatTxt kann nHeight auf 0 gesetzt worden sein if ( !Height() ) Height( rInf.GetTxtHeight() ); + // Jetzt noch einmal der ganze Spass + nDropHeight = nLines = 0; + delete pPart; + pPart = NULL; + + // meanwhile use normal formatting bFull = SwTxtPortion::Format( rInf ); - if ( !bFull ) - { - // Jetzt noch einmal der ganze Spass - nDropHeight = nLines = 0; - delete pFnt; - pFnt = NULL; - } -// bFull = FormatTxt( rInf ); } else rInf.SetDropInit( sal_True ); @@ -770,18 +1099,15 @@ sal_Bool SwDropPortion::Format( SwTxtFormatInfo &rInf ) } else bFull = SwTxtPortion::Format( rInf ); -// bFull = FormatTxt( rInf ); if( bFull ) nDistance = 0; else { const KSHORT nWant = Width() + GetDistance(); - const KSHORT nRest = rInf.Width() - rInf.X(); - if( nWant > nRest ) - // Robust: Kann die gewuenschte Distance nicht eingehalten werden, - // gibt es gar keine! - // nDistance = nWant - nRest; + const KSHORT nRest = (USHORT)(rInf.Width() - rInf.X()); + if( ( nWant > nRest ) || + lcl_IsDropFlyInter( rInf, Width() + GetDistance(), nDropHeight ) ) nDistance = 0; Width( Width() + nDistance ); @@ -789,6 +1115,3 @@ sal_Bool SwDropPortion::Format( SwTxtFormatInfo &rInf ) return bFull; } - - - diff --git a/sw/source/core/text/txtio.cxx b/sw/source/core/text/txtio.cxx index db8559c24e3a..ee23f6fa9a3c 100644 --- a/sw/source/core/text/txtio.cxx +++ b/sw/source/core/text/txtio.cxx @@ -2,9 +2,9 @@ * * $RCSfile: txtio.cxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: ama $ $Date: 2000-12-06 15:24:45 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:38:42 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -1138,11 +1138,11 @@ SvStream &SwDropPortion::operator<<( SvStream &rOs ) const //$ ostream CONSTCHAR( pTxt, " {DROP:" ); rOs << pTxt; SwTxtPortion::operator<<( rOs ); - if( pFnt && nDropHeight ) + if( pPart && nDropHeight ) { rOs << " H:" << nDropHeight; rOs << " L:" << nLines; - rOs <<" Fnt:" << pFnt->GetHeight(); + rOs <<" Fnt:" << pPart->GetFont().GetHeight(); if( nX || nY ) rOs << " [" << nX << '/' << nY << ']'; } diff --git a/sw/source/ui/chrdlg/drpcps.cxx b/sw/source/ui/chrdlg/drpcps.cxx index 22997c39fdfe..81713dca08f6 100644 --- a/sw/source/ui/chrdlg/drpcps.cxx +++ b/sw/source/ui/chrdlg/drpcps.cxx @@ -2,9 +2,9 @@ * * $RCSfile: drpcps.cxx,v $ * - * $Revision: 1.2 $ + * $Revision: 1.3 $ * - * last change: $Author: fme $ $Date: 2001-05-30 16:28:21 $ + * last change: $Author: fme $ $Date: 2001-10-19 08:41:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -496,7 +496,7 @@ IMPL_LINK( SwDropCapsPage, ModifyHdl, Edit *, pEdit ) if (!aWholeWordCB.IsChecked()) nVal = (USHORT)aDropCapsField.GetValue(); else - nVal = (USHORT)aDropCapsField.GetMax(); + nVal = 0; if (bFormat || !rSh.GetDropTxt(1).Len()) sPreview = GetDefaultString(nVal); @@ -514,14 +514,6 @@ IMPL_LINK( SwDropCapsPage, ModifyHdl, Edit *, pEdit ) bSetText = FALSE; } - if (aWholeWordCB.IsChecked()) // Nur erstes Wort anzeigen - { - USHORT nPos = sPreview.Search(' '); - - if (nPos != STRING_NOTFOUND) - sPreview.Erase(nPos); - } - if (bSetText) aTextEdit.SetText(sPreview); } @@ -616,6 +608,9 @@ void SwDropCapsPage::FillSet( SfxItemSet &rSet ) /*-------------------------------------------------- $Log: not supported by cvs2svn $ + Revision 1.2 2001/05/30 16:28:21 fme + Fix #86988#: Redesign of dialogs + Revision 1.1.1.1 2000/09/18 17:14:32 hr initial import |