1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*efeef26fSAndrew Rist * distributed with this work for additional information
6*efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10*efeef26fSAndrew Rist *
11*efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*efeef26fSAndrew Rist *
13*efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17*efeef26fSAndrew Rist * specific language governing permissions and limitations
18*efeef26fSAndrew Rist * under the License.
19*efeef26fSAndrew Rist *
20*efeef26fSAndrew Rist *************************************************************/
21*efeef26fSAndrew Rist
22*efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir #include <vcl/metric.hxx>
30cdf0e10cSrcweir #include <vcl/window.hxx>
31cdf0e10cSrcweir #include <vcl/svapp.hxx>
32cdf0e10cSrcweir #include <paratr.hxx>
33cdf0e10cSrcweir #include <txtfrm.hxx> // Format()
34cdf0e10cSrcweir #include <charfmt.hxx>
35cdf0e10cSrcweir #include <viewopt.hxx> // SwViewOption
36cdf0e10cSrcweir #include <viewsh.hxx> // ViewShell
37cdf0e10cSrcweir #include <pordrop.hxx>
38cdf0e10cSrcweir #include <itrform2.hxx>
39cdf0e10cSrcweir #include <txtpaint.hxx> // SwSaveClip
40cdf0e10cSrcweir #include <blink.hxx> // pBlink
41cdf0e10cSrcweir #include <breakit.hxx>
42cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptType.hdl>
43cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
44cdf0e10cSrcweir #include <editeng/langitem.hxx>
45cdf0e10cSrcweir #include <charatr.hxx>
46cdf0e10cSrcweir #include <editeng/fhgtitem.hxx>
47cdf0e10cSrcweir #include <switerator.hxx>
48cdf0e10cSrcweir
49cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
50cdf0e10cSrcweir using namespace ::com::sun::star;
51cdf0e10cSrcweir
52cdf0e10cSrcweir /*************************************************************************
53cdf0e10cSrcweir * lcl_IsDropFlyInter
54cdf0e10cSrcweir *
55cdf0e10cSrcweir * Calculates if a drop caps portion intersects with a fly
56cdf0e10cSrcweir * The width and height of the drop caps portion are passed as arguments,
57cdf0e10cSrcweir * the position is calculated from the values in rInf
58cdf0e10cSrcweir *************************************************************************/
59cdf0e10cSrcweir
lcl_IsDropFlyInter(const SwTxtFormatInfo & rInf,sal_uInt16 nWidth,sal_uInt16 nHeight)60cdf0e10cSrcweir sal_Bool lcl_IsDropFlyInter( const SwTxtFormatInfo &rInf,
61cdf0e10cSrcweir sal_uInt16 nWidth, sal_uInt16 nHeight )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir const SwTxtFly *pTxtFly = rInf.GetTxtFly();
64cdf0e10cSrcweir if( pTxtFly && pTxtFly->IsOn() )
65cdf0e10cSrcweir {
66cdf0e10cSrcweir SwRect aRect( rInf.GetTxtFrm()->Frm().Pos(), Size( nWidth, nHeight) );
67cdf0e10cSrcweir aRect.Pos() += rInf.GetTxtFrm()->Prt().Pos();
68cdf0e10cSrcweir aRect.Pos().X() += rInf.X();
69cdf0e10cSrcweir aRect.Pos().Y() = rInf.Y();
70cdf0e10cSrcweir aRect = pTxtFly->GetFrm( aRect );
71cdf0e10cSrcweir return aRect.HasArea();
72cdf0e10cSrcweir }
73cdf0e10cSrcweir
74cdf0e10cSrcweir return sal_False;
75cdf0e10cSrcweir }
76cdf0e10cSrcweir
77cdf0e10cSrcweir /*************************************************************************
78cdf0e10cSrcweir * class SwDropSave
79cdf0e10cSrcweir *************************************************************************/
80cdf0e10cSrcweir
81cdf0e10cSrcweir class SwDropSave
82cdf0e10cSrcweir {
83cdf0e10cSrcweir SwTxtPaintInfo* pInf;
84cdf0e10cSrcweir xub_StrLen nIdx;
85cdf0e10cSrcweir xub_StrLen nLen;
86cdf0e10cSrcweir long nX;
87cdf0e10cSrcweir long nY;
88cdf0e10cSrcweir
89cdf0e10cSrcweir public:
90cdf0e10cSrcweir SwDropSave( const SwTxtPaintInfo &rInf );
91cdf0e10cSrcweir ~SwDropSave();
92cdf0e10cSrcweir };
93cdf0e10cSrcweir
SwDropSave(const SwTxtPaintInfo & rInf)94cdf0e10cSrcweir SwDropSave::SwDropSave( const SwTxtPaintInfo &rInf ) :
95cdf0e10cSrcweir pInf( ((SwTxtPaintInfo*)&rInf) ), nIdx( rInf.GetIdx() ),
96cdf0e10cSrcweir nLen( rInf.GetLen() ), nX( rInf.X() ), nY( rInf.Y() )
97cdf0e10cSrcweir {
98cdf0e10cSrcweir }
99cdf0e10cSrcweir
~SwDropSave()100cdf0e10cSrcweir SwDropSave::~SwDropSave()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir pInf->SetIdx( nIdx );
103cdf0e10cSrcweir pInf->SetLen( nLen );
104cdf0e10cSrcweir pInf->X( nX );
105cdf0e10cSrcweir pInf->Y( nY );
106cdf0e10cSrcweir }
107cdf0e10cSrcweir
108cdf0e10cSrcweir /*************************************************************************
109cdf0e10cSrcweir * SwDropPortionPart DTor
110cdf0e10cSrcweir *************************************************************************/
111cdf0e10cSrcweir
~SwDropPortionPart()112cdf0e10cSrcweir SwDropPortionPart::~SwDropPortionPart()
113cdf0e10cSrcweir {
114cdf0e10cSrcweir if ( pFollow )
115cdf0e10cSrcweir delete pFollow;
116cdf0e10cSrcweir delete pFnt;
117cdf0e10cSrcweir }
118cdf0e10cSrcweir
119cdf0e10cSrcweir /*************************************************************************
120cdf0e10cSrcweir * SwDropPortion CTor, DTor
121cdf0e10cSrcweir *************************************************************************/
122cdf0e10cSrcweir
SwDropPortion(const MSHORT nLineCnt,const KSHORT nDrpHeight,const KSHORT nDrpDescent,const KSHORT nDist)123cdf0e10cSrcweir SwDropPortion::SwDropPortion( const MSHORT nLineCnt,
124cdf0e10cSrcweir const KSHORT nDrpHeight,
125cdf0e10cSrcweir const KSHORT nDrpDescent,
126cdf0e10cSrcweir const KSHORT nDist )
127cdf0e10cSrcweir : pPart( 0 ),
128cdf0e10cSrcweir nLines( nLineCnt ),
129cdf0e10cSrcweir nDropHeight(nDrpHeight),
130cdf0e10cSrcweir nDropDescent(nDrpDescent),
131cdf0e10cSrcweir nDistance(nDist),
132cdf0e10cSrcweir nFix(0),
133cdf0e10cSrcweir nX(0)
134cdf0e10cSrcweir {
135cdf0e10cSrcweir SetWhichPor( POR_DROP );
136cdf0e10cSrcweir }
137cdf0e10cSrcweir
~SwDropPortion()138cdf0e10cSrcweir SwDropPortion::~SwDropPortion()
139cdf0e10cSrcweir {
140cdf0e10cSrcweir delete pPart;
141cdf0e10cSrcweir if( pBlink )
142cdf0e10cSrcweir pBlink->Delete( this );
143cdf0e10cSrcweir }
144cdf0e10cSrcweir
_HasHint(const SwTxtNode * pTxtNode,xub_StrLen nPos)145cdf0e10cSrcweir sal_Bool SwTxtSizeInfo::_HasHint( const SwTxtNode* pTxtNode, xub_StrLen nPos )
146cdf0e10cSrcweir {
147cdf0e10cSrcweir return 0 != pTxtNode->GetTxtAttrForCharAt(nPos);
148cdf0e10cSrcweir }
149cdf0e10cSrcweir
150cdf0e10cSrcweir /*************************************************************************
151cdf0e10cSrcweir * SwTxtNode::GetDropLen()
152cdf0e10cSrcweir *
153cdf0e10cSrcweir * nWishLen = 0 indicates that we want a whole word
154cdf0e10cSrcweir *************************************************************************/
155cdf0e10cSrcweir
GetDropLen(MSHORT nWishLen) const156cdf0e10cSrcweir MSHORT SwTxtNode::GetDropLen( MSHORT nWishLen ) const
157cdf0e10cSrcweir {
158cdf0e10cSrcweir xub_StrLen nEnd = GetTxt().Len();
159cdf0e10cSrcweir if( nWishLen && nWishLen < nEnd )
160cdf0e10cSrcweir nEnd = nWishLen;
161cdf0e10cSrcweir
162cdf0e10cSrcweir if ( ! nWishLen && pBreakIt->GetBreakIter().is() )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir // find first word
165cdf0e10cSrcweir const SwAttrSet& rAttrSet = GetSwAttrSet();
166cdf0e10cSrcweir const sal_uInt16 nTxtScript = pBreakIt->GetRealScriptOfText( GetTxt(), 0 );
167cdf0e10cSrcweir
168cdf0e10cSrcweir LanguageType eLanguage;
169cdf0e10cSrcweir
170cdf0e10cSrcweir switch ( nTxtScript )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir case i18n::ScriptType::ASIAN :
173cdf0e10cSrcweir eLanguage = rAttrSet.GetCJKLanguage().GetLanguage();
174cdf0e10cSrcweir break;
175cdf0e10cSrcweir case i18n::ScriptType::COMPLEX :
176cdf0e10cSrcweir eLanguage = rAttrSet.GetCTLLanguage().GetLanguage();
177cdf0e10cSrcweir break;
178cdf0e10cSrcweir default :
179cdf0e10cSrcweir eLanguage = rAttrSet.GetLanguage().GetLanguage();
180cdf0e10cSrcweir break;
181cdf0e10cSrcweir }
182cdf0e10cSrcweir
183cdf0e10cSrcweir Boundary aBound =
184cdf0e10cSrcweir pBreakIt->GetBreakIter()->getWordBoundary( GetTxt(), 0,
185cdf0e10cSrcweir pBreakIt->GetLocale( eLanguage ), WordType::DICTIONARY_WORD, sal_True );
186cdf0e10cSrcweir
187cdf0e10cSrcweir nEnd = (xub_StrLen)aBound.endPos;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir
190cdf0e10cSrcweir xub_StrLen i = 0;
191cdf0e10cSrcweir for( ; i < nEnd; ++i )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir xub_Unicode cChar = GetTxt().GetChar( i );
194cdf0e10cSrcweir if( CH_TAB == cChar || CH_BREAK == cChar ||
195cdf0e10cSrcweir (( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar )
196cdf0e10cSrcweir && SwTxtSizeInfo::_HasHint( this, i ) ) )
197cdf0e10cSrcweir break;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir return i;
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
202cdf0e10cSrcweir /*************************************************************************
203cdf0e10cSrcweir * SwTxtNode::GetDropSize()
204cdf0e10cSrcweir *
205cdf0e10cSrcweir * If a dropcap is found the return value is true otherwise false. The
206cdf0e10cSrcweir * drop cap sizes passed back by reference are font height, drop height
207cdf0e10cSrcweir * and drop descent.
208cdf0e10cSrcweir *************************************************************************/
GetDropSize(int & rFontHeight,int & rDropHeight,int & rDropDescent) const209cdf0e10cSrcweir bool SwTxtNode::GetDropSize(int& rFontHeight, int& rDropHeight, int& rDropDescent) const
210cdf0e10cSrcweir {
211cdf0e10cSrcweir rFontHeight = 0;
212cdf0e10cSrcweir rDropHeight = 0;
213cdf0e10cSrcweir rDropDescent =0;
214cdf0e10cSrcweir
215cdf0e10cSrcweir const SwAttrSet& rSet = GetSwAttrSet();
216cdf0e10cSrcweir const SwFmtDrop& rDrop = rSet.GetDrop();
217cdf0e10cSrcweir
218cdf0e10cSrcweir // Return (0,0) if there is no drop cap at this paragraph
219cdf0e10cSrcweir if( 1 >= rDrop.GetLines() ||
220cdf0e10cSrcweir ( !rDrop.GetChars() && !rDrop.GetWholeWord() ) )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir return false;
223cdf0e10cSrcweir }
224cdf0e10cSrcweir
225cdf0e10cSrcweir // get text frame
226cdf0e10cSrcweir SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
227cdf0e10cSrcweir for( SwTxtFrm* pLastFrm = aIter.First(); pLastFrm; pLastFrm = aIter.Next() )
228cdf0e10cSrcweir {
229cdf0e10cSrcweir // Only (master-) text frames can have a drop cap.
230cdf0e10cSrcweir if ( !pLastFrm->IsFollow() )
231cdf0e10cSrcweir {
232cdf0e10cSrcweir
233cdf0e10cSrcweir if( !pLastFrm->HasPara() )
234cdf0e10cSrcweir pLastFrm->GetFormatted();
235cdf0e10cSrcweir
236cdf0e10cSrcweir if ( !pLastFrm->IsEmpty() )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir const SwParaPortion* pPara = pLastFrm->GetPara();
239cdf0e10cSrcweir ASSERT( pPara, "GetDropSize could not find the ParaPortion, I'll guess the drop cap size" )
240cdf0e10cSrcweir
241cdf0e10cSrcweir if ( pPara )
242cdf0e10cSrcweir {
243cdf0e10cSrcweir const SwLinePortion* pFirstPor = pPara->GetFirstPortion();
244cdf0e10cSrcweir if (pFirstPor && pFirstPor->IsDropPortion())
245cdf0e10cSrcweir {
246cdf0e10cSrcweir const SwDropPortion* pDrop = (const SwDropPortion*)pFirstPor;
247cdf0e10cSrcweir rDropHeight = pDrop->GetDropHeight();
248cdf0e10cSrcweir rDropDescent = pDrop->GetDropDescent();
249cdf0e10cSrcweir if (const SwFont *pFont = pDrop->GetFnt())
250cdf0e10cSrcweir rFontHeight = pFont->GetSize(pFont->GetActual()).Height();
251cdf0e10cSrcweir else
252cdf0e10cSrcweir {
253cdf0e10cSrcweir const SvxFontHeightItem& rItem = (SvxFontHeightItem&)rSet.Get(RES_CHRATR_FONTSIZE);
254cdf0e10cSrcweir rFontHeight = rItem.GetHeight();
255cdf0e10cSrcweir }
256cdf0e10cSrcweir }
257cdf0e10cSrcweir }
258cdf0e10cSrcweir }
259cdf0e10cSrcweir break;
260cdf0e10cSrcweir }
261cdf0e10cSrcweir }
262cdf0e10cSrcweir
263cdf0e10cSrcweir if (rFontHeight==0 && rDropHeight==0 && rDropDescent==0)
264cdf0e10cSrcweir {
265cdf0e10cSrcweir const sal_uInt16 nLines = rDrop.GetLines();
266cdf0e10cSrcweir
267cdf0e10cSrcweir const SvxFontHeightItem& rItem = (SvxFontHeightItem&)rSet.Get( RES_CHRATR_FONTSIZE );
268cdf0e10cSrcweir rFontHeight = rItem.GetHeight();
269cdf0e10cSrcweir rDropHeight = nLines * rFontHeight;
270cdf0e10cSrcweir rDropDescent = rFontHeight / 5;
271cdf0e10cSrcweir return false;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir
274cdf0e10cSrcweir return true;
275cdf0e10cSrcweir }
276cdf0e10cSrcweir
277cdf0e10cSrcweir /*************************************************************************
278cdf0e10cSrcweir * SwDropPortion::PaintTxt()
279cdf0e10cSrcweir *************************************************************************/
280cdf0e10cSrcweir
281cdf0e10cSrcweir // Die Breite manipulieren, sonst werden die Buchstaben gestretcht
282cdf0e10cSrcweir
PaintTxt(const SwTxtPaintInfo & rInf) const283cdf0e10cSrcweir void SwDropPortion::PaintTxt( const SwTxtPaintInfo &rInf ) const
284cdf0e10cSrcweir {
285cdf0e10cSrcweir if ( rInf.OnWin() &&
286cdf0e10cSrcweir !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
287cdf0e10cSrcweir rInf.DrawBackground( *this );
288cdf0e10cSrcweir
289cdf0e10cSrcweir ASSERT( nDropHeight && pPart && nLines != 1, "Drop Portion painted twice" );
290cdf0e10cSrcweir
291cdf0e10cSrcweir const SwDropPortionPart* pCurrPart = GetPart();
292cdf0e10cSrcweir const xub_StrLen nOldLen = GetLen();
293cdf0e10cSrcweir
294cdf0e10cSrcweir const SwTwips nBasePosY = rInf.Y();
295cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).Y( nBasePosY + nY );
296cdf0e10cSrcweir SwDropSave aSave( rInf );
297cdf0e10cSrcweir // for text inside drop portions we let vcl handle the text directions
298cdf0e10cSrcweir SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
299cdf0e10cSrcweir aLayoutModeModifier.SetAuto();
300cdf0e10cSrcweir
301cdf0e10cSrcweir while ( pCurrPart )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir ((SwDropPortion*)this)->SetLen( pCurrPart->GetLen() );
304cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).SetLen( pCurrPart->GetLen() );
305cdf0e10cSrcweir SwFontSave aFontSave( rInf, &pCurrPart->GetFont() );
306cdf0e10cSrcweir
307cdf0e10cSrcweir SwTxtPortion::Paint( rInf );
308cdf0e10cSrcweir
309cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).SetIdx( rInf.GetIdx() + pCurrPart->GetLen() );
310cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).X( rInf.X() + pCurrPart->GetWidth() );
311cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
312cdf0e10cSrcweir }
313cdf0e10cSrcweir
314cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).Y( nBasePosY );
315cdf0e10cSrcweir ((SwDropPortion*)this)->SetLen( nOldLen );
316cdf0e10cSrcweir }
317cdf0e10cSrcweir
318cdf0e10cSrcweir /*************************************************************************
319cdf0e10cSrcweir * SwDropPortion::Paint()
320cdf0e10cSrcweir *************************************************************************/
321cdf0e10cSrcweir
PaintDrop(const SwTxtPaintInfo & rInf) const322cdf0e10cSrcweir void SwDropPortion::PaintDrop( const SwTxtPaintInfo &rInf ) const
323cdf0e10cSrcweir {
324cdf0e10cSrcweir // ganz normale Ausgabe wird w?hrend des normalen Paints erledigt
325cdf0e10cSrcweir if( ! nDropHeight || ! pPart || nLines == 1 )
326cdf0e10cSrcweir return;
327cdf0e10cSrcweir
328cdf0e10cSrcweir // Luegenwerte einstellen!
329cdf0e10cSrcweir const KSHORT nOldHeight = Height();
330cdf0e10cSrcweir const KSHORT nOldWidth = Width();
331cdf0e10cSrcweir const KSHORT nOldAscent = GetAscent();
332cdf0e10cSrcweir const SwTwips nOldPosY = rInf.Y();
333cdf0e10cSrcweir const KSHORT nOldPosX = (KSHORT)rInf.X();
334cdf0e10cSrcweir const SwParaPortion *pPara = rInf.GetParaPortion();
335cdf0e10cSrcweir const Point aOutPos( nOldPosX + nX, nOldPosY - pPara->GetAscent()
336cdf0e10cSrcweir - pPara->GetRealHeight() + pPara->Height() );
337cdf0e10cSrcweir // Retusche nachholen.
338cdf0e10cSrcweir
339cdf0e10cSrcweir // Set baseline
340cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).Y( aOutPos.Y() + nDropHeight );
341cdf0e10cSrcweir
342cdf0e10cSrcweir // for background
343cdf0e10cSrcweir ((SwDropPortion*)this)->Height( nDropHeight + nDropDescent );
344cdf0e10cSrcweir ((SwDropPortion*)this)->Width( Width() - nX );
345cdf0e10cSrcweir ((SwDropPortion*)this)->SetAscent( nDropHeight );
346cdf0e10cSrcweir
347cdf0e10cSrcweir // Clipregion auf uns einstellen!
348cdf0e10cSrcweir // Und zwar immer, und nie mit dem bestehenden ClipRect
349cdf0e10cSrcweir // verrechnen, weil dies auf die Zeile eingestellt sein koennte.
350cdf0e10cSrcweir
351cdf0e10cSrcweir SwRect aClipRect;
352cdf0e10cSrcweir if ( rInf.OnWin() )
353cdf0e10cSrcweir {
354cdf0e10cSrcweir aClipRect = SwRect( aOutPos, SvLSize() );
355cdf0e10cSrcweir aClipRect.Intersection( rInf.GetPaintRect() );
356cdf0e10cSrcweir }
357cdf0e10cSrcweir SwSaveClip aClip( (OutputDevice*)rInf.GetOut() );
358cdf0e10cSrcweir aClip.ChgClip( aClipRect, rInf.GetTxtFrm() );
359cdf0e10cSrcweir // Das machen, was man sonst nur macht ...
360cdf0e10cSrcweir PaintTxt( rInf );
361cdf0e10cSrcweir
362cdf0e10cSrcweir // Alte Werte sichern
363cdf0e10cSrcweir ((SwDropPortion*)this)->Height( nOldHeight );
364cdf0e10cSrcweir ((SwDropPortion*)this)->Width( nOldWidth );
365cdf0e10cSrcweir ((SwDropPortion*)this)->SetAscent( nOldAscent );
366cdf0e10cSrcweir ((SwTxtPaintInfo&)rInf).Y( nOldPosY );
367cdf0e10cSrcweir }
368cdf0e10cSrcweir
369cdf0e10cSrcweir /*************************************************************************
370cdf0e10cSrcweir * virtual SwDropPortion::Paint()
371cdf0e10cSrcweir *************************************************************************/
372cdf0e10cSrcweir
Paint(const SwTxtPaintInfo & rInf) const373cdf0e10cSrcweir void SwDropPortion::Paint( const SwTxtPaintInfo &rInf ) const
374cdf0e10cSrcweir {
375cdf0e10cSrcweir // ganz normale Ausgabe wird hier erledigt.
376cdf0e10cSrcweir if( ! nDropHeight || ! pPart || 1 == nLines )
377cdf0e10cSrcweir {
378cdf0e10cSrcweir if ( rInf.OnWin() &&
379cdf0e10cSrcweir !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
380cdf0e10cSrcweir rInf.DrawBackground( *this );
381cdf0e10cSrcweir
382cdf0e10cSrcweir // make sure that font is not rotated
383cdf0e10cSrcweir SwFont* pTmpFont = 0;
384cdf0e10cSrcweir if ( rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() ) )
385cdf0e10cSrcweir {
386cdf0e10cSrcweir pTmpFont = new SwFont( *rInf.GetFont() );
387cdf0e10cSrcweir pTmpFont->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
388cdf0e10cSrcweir }
389cdf0e10cSrcweir
390cdf0e10cSrcweir SwFontSave aFontSave( rInf, pTmpFont );
391cdf0e10cSrcweir // for text inside drop portions we let vcl handle the text directions
392cdf0e10cSrcweir SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
393cdf0e10cSrcweir aLayoutModeModifier.SetAuto();
394cdf0e10cSrcweir
395cdf0e10cSrcweir SwTxtPortion::Paint( rInf );
396cdf0e10cSrcweir delete pTmpFont;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir }
399cdf0e10cSrcweir
400cdf0e10cSrcweir /*************************************************************************
401cdf0e10cSrcweir * virtual Format()
402cdf0e10cSrcweir *************************************************************************/
403cdf0e10cSrcweir
404cdf0e10cSrcweir
FormatTxt(SwTxtFormatInfo & rInf)405cdf0e10cSrcweir sal_Bool SwDropPortion::FormatTxt( SwTxtFormatInfo &rInf )
406cdf0e10cSrcweir {
407cdf0e10cSrcweir const xub_StrLen nOldLen = GetLen();
408cdf0e10cSrcweir const xub_StrLen nOldInfLen = rInf.GetLen();
409cdf0e10cSrcweir const sal_Bool bFull = SwTxtPortion::Format( rInf );
410cdf0e10cSrcweir if( bFull )
411cdf0e10cSrcweir {
412cdf0e10cSrcweir // sieht zwar Scheisse aus, aber was soll man schon machen?
413cdf0e10cSrcweir rInf.SetUnderFlow( 0 );
414cdf0e10cSrcweir Truncate();
415cdf0e10cSrcweir SetLen( nOldLen );
416cdf0e10cSrcweir rInf.SetLen( nOldInfLen );
417cdf0e10cSrcweir }
418cdf0e10cSrcweir return bFull;
419cdf0e10cSrcweir }
420cdf0e10cSrcweir
421cdf0e10cSrcweir /*************************************************************************
422cdf0e10cSrcweir * virtual GetTxtSize()
423cdf0e10cSrcweir *************************************************************************/
424cdf0e10cSrcweir
425cdf0e10cSrcweir
GetTxtSize(const SwTxtSizeInfo & rInf) const426cdf0e10cSrcweir SwPosSize SwDropPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
427cdf0e10cSrcweir {
428cdf0e10cSrcweir sal_uInt16 nMyX = 0;
429cdf0e10cSrcweir xub_StrLen nIdx = 0;
430cdf0e10cSrcweir
431cdf0e10cSrcweir const SwDropPortionPart* pCurrPart = GetPart();
432cdf0e10cSrcweir
433cdf0e10cSrcweir // skip parts
434cdf0e10cSrcweir while ( pCurrPart && nIdx + pCurrPart->GetLen() < rInf.GetLen() )
435cdf0e10cSrcweir {
436cdf0e10cSrcweir nMyX = nMyX + pCurrPart->GetWidth();
437cdf0e10cSrcweir nIdx = nIdx + pCurrPart->GetLen();
438cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
439cdf0e10cSrcweir }
440cdf0e10cSrcweir
441cdf0e10cSrcweir xub_StrLen nOldIdx = rInf.GetIdx();
442cdf0e10cSrcweir xub_StrLen nOldLen = rInf.GetLen();
443cdf0e10cSrcweir
444cdf0e10cSrcweir ((SwTxtSizeInfo&)rInf).SetIdx( nIdx );
445cdf0e10cSrcweir ((SwTxtSizeInfo&)rInf).SetLen( rInf.GetLen() - nIdx );
446cdf0e10cSrcweir
447cdf0e10cSrcweir // robust
448cdf0e10cSrcweir SwFontSave aFontSave( rInf, pCurrPart ? &pCurrPart->GetFont() : 0 );
449cdf0e10cSrcweir SwPosSize aPosSize( SwTxtPortion::GetTxtSize( rInf ) );
450cdf0e10cSrcweir aPosSize.Width( aPosSize.Width() + nMyX );
451cdf0e10cSrcweir
452cdf0e10cSrcweir ((SwTxtSizeInfo&)rInf).SetIdx( nOldIdx );
453cdf0e10cSrcweir ((SwTxtSizeInfo&)rInf).SetLen( nOldLen );
454cdf0e10cSrcweir
455cdf0e10cSrcweir return aPosSize;
456cdf0e10cSrcweir }
457cdf0e10cSrcweir
458cdf0e10cSrcweir /*************************************************************************
459cdf0e10cSrcweir * virtual GetCrsrOfst()
460cdf0e10cSrcweir *************************************************************************/
461cdf0e10cSrcweir
GetCrsrOfst(const KSHORT) const462cdf0e10cSrcweir xub_StrLen SwDropPortion::GetCrsrOfst( const KSHORT ) const
463cdf0e10cSrcweir {
464cdf0e10cSrcweir return 0;
465cdf0e10cSrcweir }
466cdf0e10cSrcweir
467cdf0e10cSrcweir /*************************************************************************
468cdf0e10cSrcweir * SwTxtFormatter::CalcDropHeight()
469cdf0e10cSrcweir *************************************************************************/
470cdf0e10cSrcweir
CalcDropHeight(const MSHORT nLines)471cdf0e10cSrcweir void SwTxtFormatter::CalcDropHeight( const MSHORT nLines )
472cdf0e10cSrcweir {
473cdf0e10cSrcweir const SwLinePortion *const pOldCurr = GetCurr();
474cdf0e10cSrcweir KSHORT nDropHght = 0;
475cdf0e10cSrcweir KSHORT nAscent = 0;
476cdf0e10cSrcweir KSHORT nHeight = 0;
477cdf0e10cSrcweir KSHORT nDropLns = 0;
478cdf0e10cSrcweir sal_Bool bRegisterOld = IsRegisterOn();
479cdf0e10cSrcweir bRegisterOn = sal_False;
480cdf0e10cSrcweir
481cdf0e10cSrcweir Top();
482cdf0e10cSrcweir
483cdf0e10cSrcweir while( GetCurr()->IsDummy() )
484cdf0e10cSrcweir {
485cdf0e10cSrcweir if ( !Next() )
486cdf0e10cSrcweir break;
487cdf0e10cSrcweir }
488cdf0e10cSrcweir
489cdf0e10cSrcweir // Wenn wir nur eine Zeile haben returnen wir 0
490cdf0e10cSrcweir if( GetNext() || GetDropLines() == 1 )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir for( ; nDropLns < nLines; nDropLns++ )
493cdf0e10cSrcweir {
494cdf0e10cSrcweir if ( GetCurr()->IsDummy() )
495cdf0e10cSrcweir break;
496cdf0e10cSrcweir else
497cdf0e10cSrcweir {
498cdf0e10cSrcweir CalcAscentAndHeight( nAscent, nHeight );
499cdf0e10cSrcweir nDropHght = nDropHght + nHeight;
500cdf0e10cSrcweir bRegisterOn = bRegisterOld;
501cdf0e10cSrcweir }
502cdf0e10cSrcweir if ( !Next() )
503cdf0e10cSrcweir {
504cdf0e10cSrcweir nDropLns++; // Fix: 11356
505cdf0e10cSrcweir break;
506cdf0e10cSrcweir }
507cdf0e10cSrcweir }
508cdf0e10cSrcweir
509cdf0e10cSrcweir // In der letzten Zeile plumpsen wir auf den Zeilenascent!
510cdf0e10cSrcweir nDropHght = nDropHght - nHeight;
511cdf0e10cSrcweir nDropHght = nDropHght + nAscent;
512cdf0e10cSrcweir Top();
513cdf0e10cSrcweir }
514cdf0e10cSrcweir bRegisterOn = bRegisterOld;
515cdf0e10cSrcweir SetDropDescent( nHeight - nAscent );
516cdf0e10cSrcweir SetDropHeight( nDropHght );
517cdf0e10cSrcweir SetDropLines( nDropLns );
518cdf0e10cSrcweir // Alte Stelle wiederfinden!
519cdf0e10cSrcweir while( pOldCurr != GetCurr() )
520cdf0e10cSrcweir {
521cdf0e10cSrcweir if( !Next() )
522cdf0e10cSrcweir {
523cdf0e10cSrcweir ASSERT( !this, "SwTxtFormatter::_CalcDropHeight: left Toulouse" );
524cdf0e10cSrcweir break;
525cdf0e10cSrcweir }
526cdf0e10cSrcweir }
527cdf0e10cSrcweir }
528cdf0e10cSrcweir
529cdf0e10cSrcweir /*************************************************************************
530cdf0e10cSrcweir * SwTxtFormatter::GuessDropHeight()
531cdf0e10cSrcweir *
532cdf0e10cSrcweir * Wir schaetzen mal, dass die Fonthoehe sich nicht aendert und dass
533cdf0e10cSrcweir * erst mindestens soviele Zeilen gibt, wie die DropCap-Einstellung angibt.
534cdf0e10cSrcweir *
535cdf0e10cSrcweir *************************************************************************/
536cdf0e10cSrcweir
537cdf0e10cSrcweir
538cdf0e10cSrcweir
GuessDropHeight(const MSHORT nLines)539cdf0e10cSrcweir void SwTxtFormatter::GuessDropHeight( const MSHORT nLines )
540cdf0e10cSrcweir {
541cdf0e10cSrcweir ASSERT( nLines, "GuessDropHeight: Give me more Lines!" );
542cdf0e10cSrcweir KSHORT nAscent = 0;
543cdf0e10cSrcweir KSHORT nHeight = 0;
544cdf0e10cSrcweir SetDropLines( nLines );
545cdf0e10cSrcweir if ( GetDropLines() > 1 )
546cdf0e10cSrcweir {
547cdf0e10cSrcweir CalcRealHeight();
548cdf0e10cSrcweir CalcAscentAndHeight( nAscent, nHeight );
549cdf0e10cSrcweir }
550cdf0e10cSrcweir SetDropDescent( nHeight - nAscent );
551cdf0e10cSrcweir SetDropHeight( nHeight * nLines - GetDropDescent() );
552cdf0e10cSrcweir }
553cdf0e10cSrcweir
554cdf0e10cSrcweir /*************************************************************************
555cdf0e10cSrcweir * SwTxtFormatter::NewDropPortion
556cdf0e10cSrcweir *************************************************************************/
557cdf0e10cSrcweir
NewDropPortion(SwTxtFormatInfo & rInf)558cdf0e10cSrcweir SwDropPortion *SwTxtFormatter::NewDropPortion( SwTxtFormatInfo &rInf )
559cdf0e10cSrcweir {
560cdf0e10cSrcweir if( !pDropFmt )
561cdf0e10cSrcweir return 0;
562cdf0e10cSrcweir
563cdf0e10cSrcweir xub_StrLen nPorLen = pDropFmt->GetWholeWord() ? 0 : pDropFmt->GetChars();
564cdf0e10cSrcweir nPorLen = pFrm->GetTxtNode()->GetDropLen( nPorLen );
565cdf0e10cSrcweir if( !nPorLen )
566cdf0e10cSrcweir {
567cdf0e10cSrcweir ((SwTxtFormatter*)this)->ClearDropFmt();
568cdf0e10cSrcweir return 0;
569cdf0e10cSrcweir }
570cdf0e10cSrcweir
571cdf0e10cSrcweir SwDropPortion *pDropPor = 0;
572cdf0e10cSrcweir
573cdf0e10cSrcweir // erste oder zweite Runde?
574cdf0e10cSrcweir if ( !( GetDropHeight() || IsOnceMore() ) )
575cdf0e10cSrcweir {
576cdf0e10cSrcweir if ( GetNext() )
577cdf0e10cSrcweir CalcDropHeight( pDropFmt->GetLines() );
578cdf0e10cSrcweir else
579cdf0e10cSrcweir GuessDropHeight( pDropFmt->GetLines() );
580cdf0e10cSrcweir }
581cdf0e10cSrcweir
582cdf0e10cSrcweir // the DropPortion
583cdf0e10cSrcweir if( GetDropHeight() )
584cdf0e10cSrcweir pDropPor = new SwDropPortion( GetDropLines(), GetDropHeight(),
585cdf0e10cSrcweir GetDropDescent(), pDropFmt->GetDistance() );
586cdf0e10cSrcweir else
587cdf0e10cSrcweir pDropPor = new SwDropPortion( 0,0,0,pDropFmt->GetDistance() );
588cdf0e10cSrcweir
589cdf0e10cSrcweir pDropPor->SetLen( nPorLen );
590cdf0e10cSrcweir
591cdf0e10cSrcweir // If it was not possible to create a proper drop cap portion
592cdf0e10cSrcweir // due to avoiding endless loops. We return a drop cap portion
593cdf0e10cSrcweir // with an empty SwDropCapPart. For these portions the current
594cdf0e10cSrcweir // font is used.
595cdf0e10cSrcweir if ( GetDropLines() < 2 )
596cdf0e10cSrcweir {
597cdf0e10cSrcweir ((SwTxtFormatter*)this)->SetPaintDrop( sal_True );
598cdf0e10cSrcweir return pDropPor;
599cdf0e10cSrcweir }
600cdf0e10cSrcweir
601cdf0e10cSrcweir // build DropPortionParts:
602cdf0e10cSrcweir ASSERT( ! rInf.GetIdx(), "Drop Portion not at 0 position!" );
603cdf0e10cSrcweir xub_StrLen nNextChg = 0;
604cdf0e10cSrcweir const SwCharFmt* pFmt = pDropFmt->GetCharFmt();
605cdf0e10cSrcweir SwDropPortionPart* pCurrPart = 0;
606cdf0e10cSrcweir
607cdf0e10cSrcweir while ( nNextChg < nPorLen )
608cdf0e10cSrcweir {
609cdf0e10cSrcweir // check for attribute changes and if the portion has to split:
610cdf0e10cSrcweir Seek( nNextChg );
611cdf0e10cSrcweir
612cdf0e10cSrcweir // the font is deleted in the destructor of the drop portion part
613cdf0e10cSrcweir SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
614cdf0e10cSrcweir if ( pFmt )
615cdf0e10cSrcweir {
616cdf0e10cSrcweir const SwAttrSet& rSet = pFmt->GetAttrSet();
617cdf0e10cSrcweir pTmpFnt->SetDiffFnt( &rSet, pFrm->GetTxtNode()->getIDocumentSettingAccess() );
618cdf0e10cSrcweir }
619cdf0e10cSrcweir
620cdf0e10cSrcweir // we do not allow a vertical font for the drop portion
621cdf0e10cSrcweir pTmpFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
622cdf0e10cSrcweir
623cdf0e10cSrcweir // find next attribute change / script change
624cdf0e10cSrcweir const xub_StrLen nTmpIdx = nNextChg;
625cdf0e10cSrcweir xub_StrLen nNextAttr = Min( GetNextAttr(), rInf.GetTxt().Len() );
626cdf0e10cSrcweir nNextChg = pScriptInfo->NextScriptChg( nTmpIdx );
627cdf0e10cSrcweir if( nNextChg > nNextAttr )
628cdf0e10cSrcweir nNextChg = nNextAttr;
629cdf0e10cSrcweir if ( nNextChg > nPorLen )
630cdf0e10cSrcweir nNextChg = nPorLen;
631cdf0e10cSrcweir
632cdf0e10cSrcweir SwDropPortionPart* pPart =
633cdf0e10cSrcweir new SwDropPortionPart( *pTmpFnt, nNextChg - nTmpIdx );
634cdf0e10cSrcweir
635cdf0e10cSrcweir if ( ! pCurrPart )
636cdf0e10cSrcweir pDropPor->SetPart( pPart );
637cdf0e10cSrcweir else
638cdf0e10cSrcweir pCurrPart->SetFollow( pPart );
639cdf0e10cSrcweir
640cdf0e10cSrcweir pCurrPart = pPart;
641cdf0e10cSrcweir }
642cdf0e10cSrcweir
643cdf0e10cSrcweir ((SwTxtFormatter*)this)->SetPaintDrop( sal_True );
644cdf0e10cSrcweir return pDropPor;
645cdf0e10cSrcweir }
646cdf0e10cSrcweir
647cdf0e10cSrcweir /*************************************************************************
648cdf0e10cSrcweir * SwTxtPainter::PaintDropPortion()
649cdf0e10cSrcweir *************************************************************************/
650cdf0e10cSrcweir
651cdf0e10cSrcweir
652cdf0e10cSrcweir
PaintDropPortion()653cdf0e10cSrcweir void SwTxtPainter::PaintDropPortion()
654cdf0e10cSrcweir {
655cdf0e10cSrcweir const SwDropPortion *pDrop = GetInfo().GetParaPortion()->FindDropPortion();
656cdf0e10cSrcweir ASSERT( pDrop, "DrapCop-Portion not available." );
657cdf0e10cSrcweir if( !pDrop )
658cdf0e10cSrcweir return;
659cdf0e10cSrcweir
660cdf0e10cSrcweir const SwTwips nOldY = GetInfo().Y();
661cdf0e10cSrcweir
662cdf0e10cSrcweir Top();
663cdf0e10cSrcweir
664cdf0e10cSrcweir GetInfo().SetpSpaceAdd( pCurr->GetpLLSpaceAdd() );
665cdf0e10cSrcweir GetInfo().ResetSpaceIdx();
666cdf0e10cSrcweir GetInfo().SetKanaComp( pCurr->GetpKanaComp() );
667cdf0e10cSrcweir GetInfo().ResetKanaIdx();
668cdf0e10cSrcweir
669cdf0e10cSrcweir // 8047: Drops und Dummies
670cdf0e10cSrcweir while( !pCurr->GetLen() && Next() )
671cdf0e10cSrcweir ;
672cdf0e10cSrcweir
673cdf0e10cSrcweir // MarginPortion und Adjustment!
674cdf0e10cSrcweir const SwLinePortion *pPor = pCurr->GetFirstPortion();
675cdf0e10cSrcweir KSHORT nX = 0;
676cdf0e10cSrcweir while( pPor && !pPor->IsDropPortion() )
677cdf0e10cSrcweir {
678cdf0e10cSrcweir nX = nX + pPor->Width();
679cdf0e10cSrcweir pPor = pPor->GetPortion();
680cdf0e10cSrcweir }
681cdf0e10cSrcweir Point aLineOrigin( GetTopLeft() );
682cdf0e10cSrcweir
683cdf0e10cSrcweir #ifdef NIE
684cdf0e10cSrcweir // Retusche nachholen...
685cdf0e10cSrcweir if( nX )
686cdf0e10cSrcweir {
687cdf0e10cSrcweir const Point aPoint( Left(), Y() );
688cdf0e10cSrcweir const Size aSize( nX - 1, GetDropHeight()+GetDropDescent() );
689cdf0e10cSrcweir SwRect aRetouche( aPoint, aSize );
690cdf0e10cSrcweir GetInfo().DrawRect( aRetouche );
691cdf0e10cSrcweir }
692cdf0e10cSrcweir #endif
693cdf0e10cSrcweir
694cdf0e10cSrcweir aLineOrigin.X() += nX;
695cdf0e10cSrcweir KSHORT nTmpAscent, nTmpHeight;
696cdf0e10cSrcweir CalcAscentAndHeight( nTmpAscent, nTmpHeight );
697cdf0e10cSrcweir aLineOrigin.Y() += nTmpAscent;
698cdf0e10cSrcweir GetInfo().SetIdx( GetStart() );
699cdf0e10cSrcweir GetInfo().SetPos( aLineOrigin );
700cdf0e10cSrcweir GetInfo().SetLen( pDrop->GetLen() );
701cdf0e10cSrcweir
702cdf0e10cSrcweir pDrop->PaintDrop( GetInfo() );
703cdf0e10cSrcweir
704cdf0e10cSrcweir GetInfo().Y( nOldY );
705cdf0e10cSrcweir }
706cdf0e10cSrcweir
707cdf0e10cSrcweir /*************************************************************************
708cdf0e10cSrcweir * clas SwDropCapCache
709cdf0e10cSrcweir *
710cdf0e10cSrcweir * Da die Berechnung der Fontgroesse der Initialen ein teures Geschaeft ist,
711cdf0e10cSrcweir * wird dies durch einen DropCapCache geschleust.
712cdf0e10cSrcweir *************************************************************************/
713cdf0e10cSrcweir
714cdf0e10cSrcweir #define DROP_CACHE_SIZE 10
715cdf0e10cSrcweir
716cdf0e10cSrcweir class SwDropCapCache
717cdf0e10cSrcweir {
718cdf0e10cSrcweir long aMagicNo[ DROP_CACHE_SIZE ];
719cdf0e10cSrcweir XubString aTxt[ DROP_CACHE_SIZE ];
720cdf0e10cSrcweir sal_uInt16 aFactor[ DROP_CACHE_SIZE ];
721cdf0e10cSrcweir KSHORT aWishedHeight[ DROP_CACHE_SIZE ];
722cdf0e10cSrcweir short aDescent[ DROP_CACHE_SIZE ];
723cdf0e10cSrcweir MSHORT nIndex;
724cdf0e10cSrcweir public:
725cdf0e10cSrcweir SwDropCapCache();
~SwDropCapCache()726cdf0e10cSrcweir ~SwDropCapCache(){}
727cdf0e10cSrcweir void CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf );
728cdf0e10cSrcweir };
729cdf0e10cSrcweir
730cdf0e10cSrcweir /*************************************************************************
731cdf0e10cSrcweir * SwDropCapCache Ctor / Dtor
732cdf0e10cSrcweir *************************************************************************/
733cdf0e10cSrcweir
SwDropCapCache()734cdf0e10cSrcweir SwDropCapCache::SwDropCapCache() : nIndex( 0 )
735cdf0e10cSrcweir {
736cdf0e10cSrcweir memset( &aMagicNo, 0, sizeof(aMagicNo) );
737cdf0e10cSrcweir memset( &aWishedHeight, 0, sizeof(aWishedHeight) );
738cdf0e10cSrcweir }
739cdf0e10cSrcweir
DeleteDropCapCache()740cdf0e10cSrcweir void SwDropPortion::DeleteDropCapCache()
741cdf0e10cSrcweir {
742cdf0e10cSrcweir delete pDropCapCache;
743cdf0e10cSrcweir }
744cdf0e10cSrcweir
745cdf0e10cSrcweir /*************************************************************************
746cdf0e10cSrcweir * SwDropCapCache::CalcFontSize
747cdf0e10cSrcweir *************************************************************************/
748cdf0e10cSrcweir
CalcFontSize(SwDropPortion * pDrop,SwTxtFormatInfo & rInf)749cdf0e10cSrcweir void SwDropCapCache::CalcFontSize( SwDropPortion* pDrop, SwTxtFormatInfo &rInf )
750cdf0e10cSrcweir {
751cdf0e10cSrcweir const void* pFntNo = 0;
752cdf0e10cSrcweir MSHORT nTmpIdx = 0;
753cdf0e10cSrcweir
754cdf0e10cSrcweir ASSERT( pDrop->GetPart(),"DropPortion without part during font calculation");
755cdf0e10cSrcweir
756cdf0e10cSrcweir SwDropPortionPart* pCurrPart = pDrop->GetPart();
757cdf0e10cSrcweir const sal_Bool bUseCache = ! pCurrPart->GetFollow();
758cdf0e10cSrcweir xub_StrLen nIdx = rInf.GetIdx();
759cdf0e10cSrcweir XubString aStr( rInf.GetTxt(), nIdx, pCurrPart->GetLen() );
760cdf0e10cSrcweir
761cdf0e10cSrcweir long nAscent = 0;
762cdf0e10cSrcweir long nDescent = 0;
763cdf0e10cSrcweir long nFactor = -1;
764cdf0e10cSrcweir
765cdf0e10cSrcweir if ( bUseCache )
766cdf0e10cSrcweir {
767cdf0e10cSrcweir SwFont& rFnt = pCurrPart->GetFont();
768cdf0e10cSrcweir rFnt.ChkMagic( rInf.GetVsh(), rFnt.GetActual() );
769cdf0e10cSrcweir rFnt.GetMagic( pFntNo, nTmpIdx, rFnt.GetActual() );
770cdf0e10cSrcweir
771cdf0e10cSrcweir nTmpIdx = 0;
772cdf0e10cSrcweir
773cdf0e10cSrcweir while( nTmpIdx < DROP_CACHE_SIZE &&
774cdf0e10cSrcweir ( aTxt[ nTmpIdx ] != aStr || aMagicNo[ nTmpIdx ] != long(pFntNo) ||
775cdf0e10cSrcweir aWishedHeight[ nTmpIdx ] != pDrop->GetDropHeight() ) )
776cdf0e10cSrcweir ++nTmpIdx;
777cdf0e10cSrcweir }
778cdf0e10cSrcweir
779cdf0e10cSrcweir // we have to calculate a new font scaling factor if
780cdf0e10cSrcweir // 1. we did not find a scaling factor in the cache or
781cdf0e10cSrcweir // 2. we are not allowed to use the cache because the drop portion
782cdf0e10cSrcweir // consists of more than one part
783cdf0e10cSrcweir if( nTmpIdx >= DROP_CACHE_SIZE || ! bUseCache )
784cdf0e10cSrcweir {
785cdf0e10cSrcweir ++nIndex;
786cdf0e10cSrcweir nIndex %= DROP_CACHE_SIZE;
787cdf0e10cSrcweir nTmpIdx = nIndex;
788cdf0e10cSrcweir
789cdf0e10cSrcweir long nWishedHeight = pDrop->GetDropHeight();
790cdf0e10cSrcweir
791cdf0e10cSrcweir // find out biggest font size for initial scaling factor
792cdf0e10cSrcweir long nMaxFontHeight = 0;
793cdf0e10cSrcweir while ( pCurrPart )
794cdf0e10cSrcweir {
795cdf0e10cSrcweir const SwFont& rFnt = pCurrPart->GetFont();
796cdf0e10cSrcweir const long nCurrHeight = rFnt.GetHeight( rFnt.GetActual() );
797cdf0e10cSrcweir if ( nCurrHeight > nMaxFontHeight )
798cdf0e10cSrcweir nMaxFontHeight = nCurrHeight;
799cdf0e10cSrcweir
800cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
801cdf0e10cSrcweir }
802cdf0e10cSrcweir
803cdf0e10cSrcweir nFactor = ( 1000 * nWishedHeight ) / nMaxFontHeight;
804cdf0e10cSrcweir
805cdf0e10cSrcweir if ( bUseCache )
806cdf0e10cSrcweir {
807cdf0e10cSrcweir // save keys for cache
808cdf0e10cSrcweir aMagicNo[ nTmpIdx ] = long(pFntNo);
809cdf0e10cSrcweir aTxt[ nTmpIdx ] = aStr;
810cdf0e10cSrcweir aWishedHeight[ nTmpIdx ] = KSHORT(nWishedHeight);
811cdf0e10cSrcweir // save initial scaling factor
812cdf0e10cSrcweir aFactor[ nTmpIdx ] = (sal_uInt16)nFactor;
813cdf0e10cSrcweir }
814cdf0e10cSrcweir
815cdf0e10cSrcweir sal_Bool bGrow = ( pDrop->GetLen() != 0 );
816cdf0e10cSrcweir
817cdf0e10cSrcweir // for growing controll
818cdf0e10cSrcweir long nMax = KSHRT_MAX;
819cdf0e10cSrcweir long nMin = nFactor / 2;
820cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
821cdf0e10cSrcweir long nGrow = 0;
822cdf0e10cSrcweir #endif
823cdf0e10cSrcweir
824cdf0e10cSrcweir sal_Bool bWinUsed = sal_False;
825cdf0e10cSrcweir Font aOldFnt;
826cdf0e10cSrcweir MapMode aOldMap( MAP_TWIP );
827cdf0e10cSrcweir OutputDevice* pOut = rInf.GetOut();
828cdf0e10cSrcweir OutputDevice* pWin;
829cdf0e10cSrcweir if( rInf.GetVsh() && rInf.GetVsh()->GetWin() )
830cdf0e10cSrcweir pWin = rInf.GetVsh()->GetWin();
831cdf0e10cSrcweir else
832cdf0e10cSrcweir pWin = GetpApp()->GetDefaultDevice();
833cdf0e10cSrcweir
834cdf0e10cSrcweir while( bGrow )
835cdf0e10cSrcweir {
836cdf0e10cSrcweir // reset pCurrPart to first part
837cdf0e10cSrcweir pCurrPart = pDrop->GetPart();
838cdf0e10cSrcweir sal_Bool bFirstGlyphRect = sal_True;
839cdf0e10cSrcweir sal_Bool bHaveGlyphRect = sal_False;
840cdf0e10cSrcweir Rectangle aCommonRect, aRect;
841cdf0e10cSrcweir
842cdf0e10cSrcweir while ( pCurrPart )
843cdf0e10cSrcweir {
844cdf0e10cSrcweir // current font
845cdf0e10cSrcweir SwFont& rFnt = pCurrPart->GetFont();
846cdf0e10cSrcweir
847cdf0e10cSrcweir // Get height including proportion
848cdf0e10cSrcweir const sal_uInt16 nCurrHeight =
849cdf0e10cSrcweir (sal_uInt16)rFnt.GetHeight( rFnt.GetActual() );
850cdf0e10cSrcweir
851cdf0e10cSrcweir // Get without proportion
852cdf0e10cSrcweir const sal_uInt8 nOldProp = rFnt.GetPropr();
853cdf0e10cSrcweir rFnt.SetProportion( 100 );
854cdf0e10cSrcweir Size aOldSize = Size( 0, rFnt.GetHeight( rFnt.GetActual() ) );
855cdf0e10cSrcweir
856cdf0e10cSrcweir Size aNewSize( 0, ( nFactor * nCurrHeight ) / 1000 );
857cdf0e10cSrcweir rFnt.SetSize( aNewSize, rFnt.GetActual() );
858cdf0e10cSrcweir rFnt.ChgPhysFnt( rInf.GetVsh(), *pOut );
859cdf0e10cSrcweir
860cdf0e10cSrcweir nAscent = rFnt.GetAscent( rInf.GetVsh(), *pOut );
861cdf0e10cSrcweir
862cdf0e10cSrcweir // Wir besorgen uns das alle Buchstaben umfassende Rechteck:
863cdf0e10cSrcweir bHaveGlyphRect = pOut->GetTextBoundRect( aRect, rInf.GetTxt(), 0,
864cdf0e10cSrcweir nIdx, pCurrPart->GetLen() ) &&
865cdf0e10cSrcweir ! aRect.IsEmpty();
866cdf0e10cSrcweir
867cdf0e10cSrcweir if ( ! bHaveGlyphRect )
868cdf0e10cSrcweir {
869cdf0e10cSrcweir // getting glyph boundaries failed for some reason,
870cdf0e10cSrcweir // we take the window for calculating sizes
871cdf0e10cSrcweir if ( pWin )
872cdf0e10cSrcweir {
873cdf0e10cSrcweir if ( ! bWinUsed )
874cdf0e10cSrcweir {
875cdf0e10cSrcweir bWinUsed = sal_True;
876cdf0e10cSrcweir aOldMap = pWin->GetMapMode( );
877cdf0e10cSrcweir pWin->SetMapMode( MapMode( MAP_TWIP ) );
878cdf0e10cSrcweir aOldFnt = pWin->GetFont();
879cdf0e10cSrcweir }
880cdf0e10cSrcweir pWin->SetFont( rFnt.GetActualFont() );
881cdf0e10cSrcweir
882cdf0e10cSrcweir bHaveGlyphRect = pWin->GetTextBoundRect( aRect, rInf.GetTxt(), 0,
883cdf0e10cSrcweir nIdx, pCurrPart->GetLen() ) &&
884cdf0e10cSrcweir ! aRect.IsEmpty();
885cdf0e10cSrcweir }
886cdf0e10cSrcweir if ( bHaveGlyphRect )
887cdf0e10cSrcweir {
888cdf0e10cSrcweir FontMetric aWinMet( pWin->GetFontMetric() );
889cdf0e10cSrcweir nAscent = (KSHORT) aWinMet.GetAscent();
890cdf0e10cSrcweir }
891cdf0e10cSrcweir else
892cdf0e10cSrcweir // We do not have a window or our window could not
893cdf0e10cSrcweir // give us glyph boundaries.
894cdf0e10cSrcweir aRect = Rectangle( Point( 0, 0 ), Size( 0, nAscent ) );
895cdf0e10cSrcweir }
896cdf0e10cSrcweir
897cdf0e10cSrcweir // Now we (hopefully) have a bounding rectangle for the
898cdf0e10cSrcweir // glyphs of the current portion and the ascent of the current
899cdf0e10cSrcweir // font
900cdf0e10cSrcweir
901cdf0e10cSrcweir // reset font size and proportion
902cdf0e10cSrcweir rFnt.SetSize( aOldSize, rFnt.GetActual() );
903cdf0e10cSrcweir rFnt.SetProportion( nOldProp );
904cdf0e10cSrcweir
905cdf0e10cSrcweir if ( bFirstGlyphRect )
906cdf0e10cSrcweir {
907cdf0e10cSrcweir aCommonRect = aRect;
908cdf0e10cSrcweir bFirstGlyphRect = sal_False;
909cdf0e10cSrcweir }
910cdf0e10cSrcweir else
911cdf0e10cSrcweir aCommonRect.Union( aRect );
912cdf0e10cSrcweir
913cdf0e10cSrcweir nIdx = nIdx + pCurrPart->GetLen();
914cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
915cdf0e10cSrcweir }
916cdf0e10cSrcweir
917cdf0e10cSrcweir // now we have a union ( aCommonRect ) of all glyphs with
918cdf0e10cSrcweir // respect to a common baseline : 0
919cdf0e10cSrcweir
920cdf0e10cSrcweir // get descent and ascent from union
921cdf0e10cSrcweir if ( rInf.GetTxtFrm()->IsVertical() )
922cdf0e10cSrcweir {
923cdf0e10cSrcweir nDescent = aCommonRect.Left();
924cdf0e10cSrcweir nAscent = aCommonRect.Right();
925cdf0e10cSrcweir
926cdf0e10cSrcweir if ( nDescent < 0 )
927cdf0e10cSrcweir nDescent = -nDescent;
928cdf0e10cSrcweir }
929cdf0e10cSrcweir else
930cdf0e10cSrcweir {
931cdf0e10cSrcweir nDescent = aCommonRect.Bottom();
932cdf0e10cSrcweir nAscent = aCommonRect.Top();
933cdf0e10cSrcweir }
934cdf0e10cSrcweir if ( nAscent < 0 )
935cdf0e10cSrcweir nAscent = -nAscent;
936cdf0e10cSrcweir
937cdf0e10cSrcweir const long nHght = nAscent + nDescent;
938cdf0e10cSrcweir if ( nHght )
939cdf0e10cSrcweir {
940cdf0e10cSrcweir if ( nHght > nWishedHeight )
941cdf0e10cSrcweir nMax = nFactor;
942cdf0e10cSrcweir else
943cdf0e10cSrcweir {
944cdf0e10cSrcweir if ( bUseCache )
945cdf0e10cSrcweir aFactor[ nTmpIdx ] = (sal_uInt16)nFactor;
946cdf0e10cSrcweir nMin = nFactor;
947cdf0e10cSrcweir }
948cdf0e10cSrcweir
949cdf0e10cSrcweir nFactor = ( nFactor * nWishedHeight ) / nHght;
950cdf0e10cSrcweir bGrow = ( nFactor > nMin ) && ( nFactor < nMax );
951cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
952cdf0e10cSrcweir if ( bGrow )
953cdf0e10cSrcweir nGrow++;
954cdf0e10cSrcweir #endif
955cdf0e10cSrcweir nIdx = rInf.GetIdx();
956cdf0e10cSrcweir }
957cdf0e10cSrcweir else
958cdf0e10cSrcweir bGrow = sal_False;
959cdf0e10cSrcweir }
960cdf0e10cSrcweir
961cdf0e10cSrcweir if ( bWinUsed )
962cdf0e10cSrcweir {
963cdf0e10cSrcweir // reset window if it has been used
964cdf0e10cSrcweir pWin->SetMapMode( aOldMap );
965cdf0e10cSrcweir pWin->SetFont( aOldFnt );
966cdf0e10cSrcweir }
967cdf0e10cSrcweir
968cdf0e10cSrcweir if ( bUseCache )
969cdf0e10cSrcweir aDescent[ nTmpIdx ] = -short( nDescent );
970cdf0e10cSrcweir }
971cdf0e10cSrcweir
972cdf0e10cSrcweir pCurrPart = pDrop->GetPart();
973cdf0e10cSrcweir
974cdf0e10cSrcweir // did made any new calculations or did we use the cache?
975cdf0e10cSrcweir if ( -1 == nFactor )
976cdf0e10cSrcweir {
977cdf0e10cSrcweir nFactor = aFactor[ nTmpIdx ];
978cdf0e10cSrcweir nDescent = aDescent[ nTmpIdx ];
979cdf0e10cSrcweir }
980cdf0e10cSrcweir else
981cdf0e10cSrcweir nDescent = -nDescent;
982cdf0e10cSrcweir
983cdf0e10cSrcweir while ( pCurrPart )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir // scale current font
986cdf0e10cSrcweir SwFont& rFnt = pCurrPart->GetFont();
987cdf0e10cSrcweir Size aNewSize( 0, ( nFactor * rFnt.GetHeight( rFnt.GetActual() ) ) / 1000 );
988cdf0e10cSrcweir
989cdf0e10cSrcweir const sal_uInt8 nOldProp = rFnt.GetPropr();
990cdf0e10cSrcweir rFnt.SetProportion( 100 );
991cdf0e10cSrcweir rFnt.SetSize( aNewSize, rFnt.GetActual() );
992cdf0e10cSrcweir rFnt.SetProportion( nOldProp );
993cdf0e10cSrcweir
994cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
995cdf0e10cSrcweir }
996cdf0e10cSrcweir pDrop->SetY( (short)nDescent );
997cdf0e10cSrcweir }
998cdf0e10cSrcweir
999cdf0e10cSrcweir /*************************************************************************
1000cdf0e10cSrcweir * virtual Format()
1001cdf0e10cSrcweir *************************************************************************/
1002cdf0e10cSrcweir
Format(SwTxtFormatInfo & rInf)1003cdf0e10cSrcweir sal_Bool SwDropPortion::Format( SwTxtFormatInfo &rInf )
1004cdf0e10cSrcweir {
1005cdf0e10cSrcweir sal_Bool bFull = sal_False;
1006cdf0e10cSrcweir Fix( (sal_uInt16)rInf.X() );
1007cdf0e10cSrcweir
1008cdf0e10cSrcweir SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
1009cdf0e10cSrcweir aLayoutModeModifier.SetAuto();
1010cdf0e10cSrcweir
1011cdf0e10cSrcweir if( nDropHeight && pPart && nLines!=1 )
1012cdf0e10cSrcweir {
1013cdf0e10cSrcweir if( !pDropCapCache )
1014cdf0e10cSrcweir pDropCapCache = new SwDropCapCache();
1015cdf0e10cSrcweir
1016cdf0e10cSrcweir // adjust font sizes to fit into the rectangle
1017cdf0e10cSrcweir pDropCapCache->CalcFontSize( this, rInf );
1018cdf0e10cSrcweir
1019cdf0e10cSrcweir const long nOldX = rInf.X();
1020cdf0e10cSrcweir {
1021cdf0e10cSrcweir SwDropSave aSave( rInf );
1022cdf0e10cSrcweir SwDropPortionPart* pCurrPart = pPart;
1023cdf0e10cSrcweir
1024cdf0e10cSrcweir while ( pCurrPart )
1025cdf0e10cSrcweir {
1026cdf0e10cSrcweir rInf.SetLen( pCurrPart->GetLen() );
1027cdf0e10cSrcweir SwFont& rFnt = pCurrPart->GetFont();
1028cdf0e10cSrcweir {
1029cdf0e10cSrcweir SwFontSave aFontSave( rInf, &rFnt );
1030cdf0e10cSrcweir bFull = FormatTxt( rInf );
1031cdf0e10cSrcweir
1032cdf0e10cSrcweir if ( bFull )
1033cdf0e10cSrcweir break;
1034cdf0e10cSrcweir }
1035cdf0e10cSrcweir
1036cdf0e10cSrcweir const SwTwips nTmpWidth =
1037cdf0e10cSrcweir ( InSpaceGrp() && rInf.GetSpaceAdd() ) ?
1038cdf0e10cSrcweir Width() + CalcSpacing( rInf.GetSpaceAdd(), rInf ) :
1039cdf0e10cSrcweir Width();
1040cdf0e10cSrcweir
1041cdf0e10cSrcweir // set values
1042cdf0e10cSrcweir pCurrPart->SetWidth( (sal_uInt16)nTmpWidth );
1043cdf0e10cSrcweir
1044cdf0e10cSrcweir // Move
1045cdf0e10cSrcweir rInf.SetIdx( rInf.GetIdx() + pCurrPart->GetLen() );
1046cdf0e10cSrcweir rInf.X( rInf.X() + nTmpWidth );
1047cdf0e10cSrcweir pCurrPart = pCurrPart->GetFollow();
1048cdf0e10cSrcweir }
1049cdf0e10cSrcweir
1050cdf0e10cSrcweir Width( (sal_uInt16)(rInf.X() - nOldX) );
1051cdf0e10cSrcweir }
1052cdf0e10cSrcweir
1053cdf0e10cSrcweir // reset my length
1054cdf0e10cSrcweir SetLen( rInf.GetLen() );
1055cdf0e10cSrcweir
1056cdf0e10cSrcweir // 7631, 7633: bei Ueberlappungen mit Flys ist Schluss.
1057cdf0e10cSrcweir if( ! bFull )
1058cdf0e10cSrcweir bFull = lcl_IsDropFlyInter( rInf, Width(), nDropHeight );
1059cdf0e10cSrcweir
1060cdf0e10cSrcweir if( bFull )
1061cdf0e10cSrcweir {
1062cdf0e10cSrcweir // Durch FormatTxt kann nHeight auf 0 gesetzt worden sein
1063cdf0e10cSrcweir if ( !Height() )
1064cdf0e10cSrcweir Height( rInf.GetTxtHeight() );
1065cdf0e10cSrcweir
1066cdf0e10cSrcweir // Jetzt noch einmal der ganze Spass
1067cdf0e10cSrcweir nDropHeight = nLines = 0;
1068cdf0e10cSrcweir delete pPart;
1069cdf0e10cSrcweir pPart = NULL;
1070cdf0e10cSrcweir
1071cdf0e10cSrcweir // meanwhile use normal formatting
1072cdf0e10cSrcweir bFull = SwTxtPortion::Format( rInf );
1073cdf0e10cSrcweir }
1074cdf0e10cSrcweir else
1075cdf0e10cSrcweir rInf.SetDropInit( sal_True );
1076cdf0e10cSrcweir
1077cdf0e10cSrcweir Height( rInf.GetTxtHeight() );
1078cdf0e10cSrcweir SetAscent( rInf.GetAscent() );
1079cdf0e10cSrcweir }
1080cdf0e10cSrcweir else
1081cdf0e10cSrcweir bFull = SwTxtPortion::Format( rInf );
1082cdf0e10cSrcweir
1083cdf0e10cSrcweir if( bFull )
1084cdf0e10cSrcweir nDistance = 0;
1085cdf0e10cSrcweir else
1086cdf0e10cSrcweir {
1087cdf0e10cSrcweir const KSHORT nWant = Width() + GetDistance();
1088cdf0e10cSrcweir const KSHORT nRest = (sal_uInt16)(rInf.Width() - rInf.X());
1089cdf0e10cSrcweir if( ( nWant > nRest ) ||
1090cdf0e10cSrcweir lcl_IsDropFlyInter( rInf, Width() + GetDistance(), nDropHeight ) )
1091cdf0e10cSrcweir nDistance = 0;
1092cdf0e10cSrcweir
1093cdf0e10cSrcweir Width( Width() + nDistance );
1094cdf0e10cSrcweir }
1095cdf0e10cSrcweir return bFull;
1096cdf0e10cSrcweir }
1097cdf0e10cSrcweir
1098