xref: /aoo42x/main/sw/source/core/txtnode/fntcache.cxx (revision 56b35d86)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #ifndef _OUTDEV_HXX //autogen
29cdf0e10cSrcweir #include <vcl/outdev.hxx>
30cdf0e10cSrcweir #endif
31cdf0e10cSrcweir #ifndef _PRINT_HXX //autogen
32cdf0e10cSrcweir #include <vcl/print.hxx>
33cdf0e10cSrcweir #endif
34cdf0e10cSrcweir #include <vcl/lineinfo.hxx>
35cdf0e10cSrcweir #ifndef _METRIC_HXX //autogen
36cdf0e10cSrcweir #include <vcl/metric.hxx>
37cdf0e10cSrcweir #endif
38cdf0e10cSrcweir #include <vcl/window.hxx>
39cdf0e10cSrcweir #include <vcl/svapp.hxx>
40cdf0e10cSrcweir #ifndef _COM_SUN_STAR_I18N_CHARACTERITERATORMODE_HDL_
41cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hdl>
42cdf0e10cSrcweir #endif
43cdf0e10cSrcweir #ifndef _COM_SUN_STAR_I18N_WORDTYPE_HDL
44cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hdl>
45cdf0e10cSrcweir #endif
46cdf0e10cSrcweir #include <breakit.hxx>
47cdf0e10cSrcweir #include <viewsh.hxx>		// Bildschirmabgleich
48cdf0e10cSrcweir #include <viewopt.hxx>		// Bildschirmabgleich abschalten, ViewOption
49cdf0e10cSrcweir #include <fntcache.hxx>
50cdf0e10cSrcweir #include <IDocumentSettingAccess.hxx>
51cdf0e10cSrcweir #include <swfont.hxx>       // CH_BLANK + CH_BULLET
52cdf0e10cSrcweir #include <wrong.hxx>
53cdf0e10cSrcweir #include "dbg_lay.hxx"
54cdf0e10cSrcweir #include <txtfrm.hxx>       // SwTxtFrm
55cdf0e10cSrcweir #include <pagefrm.hxx>
56cdf0e10cSrcweir #include <pagedesc.hxx> // SwPageDesc
57cdf0e10cSrcweir #include <tgrditem.hxx>
58cdf0e10cSrcweir #include <scriptinfo.hxx>
59cdf0e10cSrcweir #include <editeng/brshitem.hxx>
60cdf0e10cSrcweir #include <tools/shl.hxx>
61cdf0e10cSrcweir #include <swmodule.hxx>
62cdf0e10cSrcweir #include <accessibilityoptions.hxx>
63cdf0e10cSrcweir #include <svtools/accessibilityoptions.hxx>
64cdf0e10cSrcweir #include <doc.hxx>
65cdf0e10cSrcweir #include <editeng/fhgtitem.hxx>
66cdf0e10cSrcweir #include <docsh.hxx>
67cdf0e10cSrcweir #ifndef _POOLFMT_HRC
68cdf0e10cSrcweir #include <poolfmt.hrc>
69cdf0e10cSrcweir #endif
70cdf0e10cSrcweir 
71cdf0e10cSrcweir using namespace ::com::sun::star;
72cdf0e10cSrcweir 
73cdf0e10cSrcweir // globale Variablen, werden in FntCache.Hxx bekanntgegeben
74cdf0e10cSrcweir // Der FontCache wird in TxtInit.Cxx _TXTINIT erzeugt und in _TXTEXIT geloescht
75cdf0e10cSrcweir SwFntCache *pFntCache = NULL;
76cdf0e10cSrcweir // Letzter Font, der durch ChgFntCache eingestellt wurde.
77cdf0e10cSrcweir SwFntObj *pLastFont = NULL;
78cdf0e10cSrcweir // Die "MagicNumber", die den Fonts zur Identifizierung verpasst wird
79cdf0e10cSrcweir sal_uInt8* pMagicNo = NULL;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir Color *pWaveCol = 0;
82cdf0e10cSrcweir 
83cdf0e10cSrcweir long SwFntObj::nPixWidth;
84cdf0e10cSrcweir MapMode* SwFntObj::pPixMap = NULL;
85cdf0e10cSrcweir OutputDevice* SwFntObj::pPixOut = NULL;
86cdf0e10cSrcweir 
87cdf0e10cSrcweir extern sal_uInt16 UnMapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat );
GetDefaultFontHeight(SwDrawTextInfo & rInf)88cdf0e10cSrcweir sal_uInt16 GetDefaultFontHeight( SwDrawTextInfo &rInf )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir     SwDocShell* pDocShell = rInf.GetShell()->GetDoc()->GetDocShell();
91cdf0e10cSrcweir     SfxStyleSheetBasePool* pBasePool = pDocShell->GetStyleSheetPool();
92cdf0e10cSrcweir 
93cdf0e10cSrcweir     String aString(SW_RES(STR_POOLCOLL_STANDARD));
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     SfxStyleSheetBase* pStyle = pBasePool->Find( aString, (SfxStyleFamily)SFX_STYLE_FAMILY_PARA );
96cdf0e10cSrcweir     SfxItemSet& aTmpSet = pStyle->GetItemSet();
97cdf0e10cSrcweir     SvxFontHeightItem &aDefaultFontItem = (SvxFontHeightItem&)aTmpSet.Get(RES_CHRATR_CJK_FONTSIZE);
98cdf0e10cSrcweir     return (sal_uInt16)aDefaultFontItem.GetHeight();
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 
103cdf0e10cSrcweir /*************************************************************************
104cdf0e10cSrcweir |*
105cdf0e10cSrcweir |*	SwFntCache::Flush()
106cdf0e10cSrcweir |*
107cdf0e10cSrcweir |*	Ersterstellung		AMA 16. Dez. 94
108cdf0e10cSrcweir |*	Letzte Aenderung	AMA 16. Dez. 94
109cdf0e10cSrcweir |*
110cdf0e10cSrcweir |*************************************************************************/
111cdf0e10cSrcweir 
Flush()112cdf0e10cSrcweir void SwFntCache::Flush( )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir 	if ( pLastFont )
115cdf0e10cSrcweir 	{
116cdf0e10cSrcweir 		pLastFont->Unlock();
117cdf0e10cSrcweir 		pLastFont = NULL;
118cdf0e10cSrcweir 	}
119cdf0e10cSrcweir 	SwCache::Flush( );
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir /*************************************************************************
123cdf0e10cSrcweir |*
124cdf0e10cSrcweir |*	SwFntObj::SwFntObj(), ~SwFntObj()
125cdf0e10cSrcweir |*
126cdf0e10cSrcweir |*	Ersterstellung		AMA 7. Nov. 94
127cdf0e10cSrcweir |*	Letzte Aenderung	AMA 7. Nov. 94
128cdf0e10cSrcweir |*
129cdf0e10cSrcweir |*************************************************************************/
130cdf0e10cSrcweir 
SwFntObj(const SwSubFont & rFont,const void * pOwn,ViewShell * pSh)131cdf0e10cSrcweir SwFntObj::SwFntObj( const SwSubFont &rFont, const void *pOwn, ViewShell *pSh ) :
132cdf0e10cSrcweir     SwCacheObj( (void*)pOwn ),
133cdf0e10cSrcweir 	aFont( rFont ),
134cdf0e10cSrcweir 	pScrFont( NULL ),
135cdf0e10cSrcweir 	pPrtFont( &aFont ),
136cdf0e10cSrcweir 	pPrinter( NULL ),
137cdf0e10cSrcweir 	nPropWidth( rFont.GetPropWidth() )
138cdf0e10cSrcweir {
139cdf0e10cSrcweir 	nZoom = pSh ? pSh->GetViewOptions()->GetZoom() : USHRT_MAX;
140cdf0e10cSrcweir     nGuessedLeading = USHRT_MAX;
141cdf0e10cSrcweir     nExtLeading = USHRT_MAX;
142cdf0e10cSrcweir 	nPrtAscent = USHRT_MAX;
143cdf0e10cSrcweir 	nPrtHeight = USHRT_MAX;
144cdf0e10cSrcweir 	bPaintBlank = ( UNDERLINE_NONE != aFont.GetUnderline()
145cdf0e10cSrcweir 				 || UNDERLINE_NONE != aFont.GetOverline()
146cdf0e10cSrcweir 				 || STRIKEOUT_NONE != aFont.GetStrikeout() )
147cdf0e10cSrcweir 				 && !aFont.IsWordLineMode();
148cdf0e10cSrcweir 	aFont.SetLanguage(rFont.GetLanguage());
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
~SwFntObj()151cdf0e10cSrcweir SwFntObj::~SwFntObj()
152cdf0e10cSrcweir {
153cdf0e10cSrcweir 	if ( pScrFont != pPrtFont )
154cdf0e10cSrcweir 		delete pScrFont;
155cdf0e10cSrcweir 	if ( pPrtFont != &aFont )
156cdf0e10cSrcweir 		delete pPrtFont;
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
CreatePrtFont(const OutputDevice & rPrt)159cdf0e10cSrcweir void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
160cdf0e10cSrcweir {
161cdf0e10cSrcweir     if ( nPropWidth != 100 && pPrinter != &rPrt )
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir         if( pScrFont != pPrtFont )
164cdf0e10cSrcweir             delete pScrFont;
165cdf0e10cSrcweir         if( pPrtFont != &aFont )
166cdf0e10cSrcweir             delete pPrtFont;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir         const Font aOldFnt( rPrt.GetFont() );
169cdf0e10cSrcweir         ((OutputDevice&)rPrt).SetFont( aFont );
170cdf0e10cSrcweir         const FontMetric aWinMet( rPrt.GetFontMetric() );
171cdf0e10cSrcweir         ((OutputDevice&)rPrt).SetFont( aOldFnt );
172cdf0e10cSrcweir         long nWidth = ( aWinMet.GetSize().Width() * nPropWidth ) / 100;
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         if( !nWidth )
175cdf0e10cSrcweir             ++nWidth;
176cdf0e10cSrcweir         pPrtFont = new Font( aFont );
177cdf0e10cSrcweir         pPrtFont->SetSize( Size( nWidth, aFont.GetSize().Height() ) );
178cdf0e10cSrcweir         pScrFont = NULL;
179cdf0e10cSrcweir     }
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir /*************************************************************************
183cdf0e10cSrcweir  *
184cdf0e10cSrcweir  *  bool lcl_IsFontAdjustNecessary( rOutDev, rRefDev )
185cdf0e10cSrcweir  *
186cdf0e10cSrcweir  *  returns whether we have to adjust the output font to resemble
187cdf0e10cSrcweir  *  the formatting font
188cdf0e10cSrcweir  *
189cdf0e10cSrcweir  *  _Not_ necessary if
190cdf0e10cSrcweir  *
191cdf0e10cSrcweir  *  1. RefDef == OutDev (text formatting, online layout...)
192cdf0e10cSrcweir  *  2. PDF export from online layout
193cdf0e10cSrcweir  *  3. Prospect/PagePreview pringing
194cdf0e10cSrcweir  *
195cdf0e10cSrcweir  *************************************************************************/
196cdf0e10cSrcweir 
lcl_IsFontAdjustNecessary(const OutputDevice & rOutDev,const OutputDevice & rRefDev)197cdf0e10cSrcweir bool lcl_IsFontAdjustNecessary( const OutputDevice& rOutDev,
198cdf0e10cSrcweir                                 const OutputDevice& rRefDev )
199cdf0e10cSrcweir {
200cdf0e10cSrcweir     return &rRefDev != &rOutDev &&
201cdf0e10cSrcweir            OUTDEV_WINDOW != rRefDev.GetOutDevType() &&
202cdf0e10cSrcweir            ( OUTDEV_PRINTER != rRefDev.GetOutDevType() ||
203cdf0e10cSrcweir              OUTDEV_PRINTER != rOutDev.GetOutDevType() );
204cdf0e10cSrcweir }
205cdf0e10cSrcweir 
206cdf0e10cSrcweir struct CalcLinePosData
207cdf0e10cSrcweir {
208cdf0e10cSrcweir     SwDrawTextInfo& rInf;
209cdf0e10cSrcweir     Font& rFont;
210cdf0e10cSrcweir     xub_StrLen nCnt;
211cdf0e10cSrcweir     const sal_Bool bSwitchH2V;
212cdf0e10cSrcweir     const sal_Bool bSwitchL2R;
213cdf0e10cSrcweir     long nHalfSpace;
214cdf0e10cSrcweir     sal_Int32* pKernArray;
215cdf0e10cSrcweir     const sal_Bool bBidiPor;
216cdf0e10cSrcweir 
CalcLinePosDataCalcLinePosData217cdf0e10cSrcweir     CalcLinePosData( SwDrawTextInfo& _rInf, Font& _rFont,
218cdf0e10cSrcweir                       xub_StrLen _nCnt, const sal_Bool _bSwitchH2V, const sal_Bool _bSwitchL2R,
219cdf0e10cSrcweir                       long _nHalfSpace, sal_Int32* _pKernArray, const sal_Bool _bBidiPor) :
220cdf0e10cSrcweir         rInf( _rInf ),
221cdf0e10cSrcweir         rFont( _rFont ),
222cdf0e10cSrcweir         nCnt( _nCnt ),
223cdf0e10cSrcweir         bSwitchH2V( _bSwitchH2V ),
224cdf0e10cSrcweir         bSwitchL2R( _bSwitchL2R ),
225cdf0e10cSrcweir         nHalfSpace( _nHalfSpace ),
226cdf0e10cSrcweir         pKernArray( _pKernArray ),
227cdf0e10cSrcweir         bBidiPor( _bBidiPor )
228cdf0e10cSrcweir     {
229cdf0e10cSrcweir     }
230cdf0e10cSrcweir };
231cdf0e10cSrcweir 
232cdf0e10cSrcweir /** Function: lcl_calcLinePos
233cdf0e10cSrcweir 
234cdf0e10cSrcweir    Computes the start and end position of an underline. This function is called
235cdf0e10cSrcweir    from the DrawText-method (for underlining misspelled words or smarttag terms).
236cdf0e10cSrcweir */
237cdf0e10cSrcweir 
lcl_calcLinePos(const CalcLinePosData & rData,Point & rStart,Point & rEnd,xub_StrLen nStart,xub_StrLen nWrLen)238cdf0e10cSrcweir void lcl_calcLinePos( const CalcLinePosData &rData,
239cdf0e10cSrcweir     Point &rStart, Point &rEnd, xub_StrLen nStart, xub_StrLen nWrLen )
240cdf0e10cSrcweir {
241cdf0e10cSrcweir    long nBlank = 0;
242cdf0e10cSrcweir    const xub_StrLen nEnd = nStart + nWrLen;
243cdf0e10cSrcweir    const long nTmpSpaceAdd = rData.rInf.GetSpace() / SPACING_PRECISION_FACTOR;
244cdf0e10cSrcweir 
245cdf0e10cSrcweir    if ( nEnd < rData.nCnt
246cdf0e10cSrcweir        && CH_BLANK == rData.rInf.GetText().GetChar( rData.rInf.GetIdx() + nEnd ) )
247cdf0e10cSrcweir    {
248cdf0e10cSrcweir        if( nEnd + 1 == rData.nCnt )
249cdf0e10cSrcweir            nBlank -= nTmpSpaceAdd;
250cdf0e10cSrcweir        else
251cdf0e10cSrcweir            nBlank -= rData.nHalfSpace;
252cdf0e10cSrcweir    }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir    // determine start, end and length of wave line
255cdf0e10cSrcweir    sal_Int32 nKernStart = nStart ? rData.pKernArray[ sal_uInt16( nStart - 1 ) ] : 0;
256cdf0e10cSrcweir    sal_Int32 nKernEnd = rData.pKernArray[ sal_uInt16( nEnd - 1 ) ];
257cdf0e10cSrcweir 
258cdf0e10cSrcweir    sal_uInt16 nDir = rData.bBidiPor ? 1800 :
259cdf0e10cSrcweir        UnMapDirection( rData.rFont.GetOrientation(), rData.bSwitchH2V );
260cdf0e10cSrcweir 
261cdf0e10cSrcweir    switch ( nDir )
262cdf0e10cSrcweir    {
263cdf0e10cSrcweir    case 0 :
264cdf0e10cSrcweir        rStart.X() += nKernStart;
265cdf0e10cSrcweir        rEnd.X() = nBlank + rData.rInf.GetPos().X() + nKernEnd;
266cdf0e10cSrcweir        rEnd.Y() = rData.rInf.GetPos().Y();
267cdf0e10cSrcweir        break;
268cdf0e10cSrcweir    case 900 :
269cdf0e10cSrcweir        rStart.Y() -= nKernStart;
270cdf0e10cSrcweir        rEnd.X() = rData.rInf.GetPos().X();
271cdf0e10cSrcweir        rEnd.Y() = nBlank + rData.rInf.GetPos().Y() - nKernEnd;
272cdf0e10cSrcweir        break;
273cdf0e10cSrcweir    case 1800 :
274cdf0e10cSrcweir        rStart.X() -= nKernStart;
275cdf0e10cSrcweir        rEnd.X() = rData.rInf.GetPos().X() - nKernEnd - nBlank;
276cdf0e10cSrcweir        rEnd.Y() = rData.rInf.GetPos().Y();
277cdf0e10cSrcweir        break;
278cdf0e10cSrcweir    case 2700 :
279cdf0e10cSrcweir        rStart.Y() += nKernStart;
280cdf0e10cSrcweir        rEnd.X() = rData.rInf.GetPos().X();
281cdf0e10cSrcweir        rEnd.Y() = nBlank + rData.rInf.GetPos().Y() + nKernEnd;
282cdf0e10cSrcweir        break;
283cdf0e10cSrcweir    }
284cdf0e10cSrcweir 
285cdf0e10cSrcweir    if ( rData.bSwitchL2R )
286cdf0e10cSrcweir    {
287cdf0e10cSrcweir        rData.rInf.GetFrm()->SwitchLTRtoRTL( rStart );
288cdf0e10cSrcweir        rData.rInf.GetFrm()->SwitchLTRtoRTL( rEnd );
289cdf0e10cSrcweir    }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir    if ( rData.bSwitchH2V )
292cdf0e10cSrcweir    {
293cdf0e10cSrcweir        rData.rInf.GetFrm()->SwitchHorizontalToVertical( rStart );
294cdf0e10cSrcweir        rData.rInf.GetFrm()->SwitchHorizontalToVertical( rEnd );
295cdf0e10cSrcweir    }
296cdf0e10cSrcweir }
297cdf0e10cSrcweir 
298cdf0e10cSrcweir /*************************************************************************
299cdf0e10cSrcweir  *
300cdf0e10cSrcweir  *  sal_uInt16 SwFntObj::GetFontAscent( const OutputDevice& rOut )
301cdf0e10cSrcweir  *
302cdf0e10cSrcweir  *	Ersterstellung		AMA 7. Nov. 94
303cdf0e10cSrcweir  *	Letzte Aenderung	AMA 7. Nov. 94
304cdf0e10cSrcweir  *
305cdf0e10cSrcweir  *  Beschreibung: liefern den Ascent des Fonts auf dem
306cdf0e10cSrcweir  * 	gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
307cdf0e10cSrcweir  *  erzeugt werden.
308cdf0e10cSrcweir  *************************************************************************/
309cdf0e10cSrcweir 
GetFontAscent(const ViewShell * pSh,const OutputDevice & rOut)310cdf0e10cSrcweir sal_uInt16 SwFntObj::GetFontAscent( const ViewShell *pSh, const OutputDevice& rOut )
311cdf0e10cSrcweir {
312cdf0e10cSrcweir     sal_uInt16 nRet = 0;
313cdf0e10cSrcweir     const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
314cdf0e10cSrcweir 
315cdf0e10cSrcweir     if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
316cdf0e10cSrcweir     {
317cdf0e10cSrcweir         CreateScrFont( *pSh, rOut );
318cdf0e10cSrcweir         ASSERT( USHRT_MAX != nScrAscent, "nScrAscent is going berzerk" )
319cdf0e10cSrcweir         nRet = nScrAscent;
320cdf0e10cSrcweir 	}
321cdf0e10cSrcweir     else
322cdf0e10cSrcweir 	{
323cdf0e10cSrcweir 		if ( nPrtAscent == USHRT_MAX ) // DruckerAscent noch nicht bekannt?
324cdf0e10cSrcweir 		{
325cdf0e10cSrcweir             CreatePrtFont( rOut );
326cdf0e10cSrcweir             const Font aOldFnt( rRefDev.GetFont() );
327cdf0e10cSrcweir             ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
328cdf0e10cSrcweir             const FontMetric aOutMet( rRefDev.GetFontMetric() );
329cdf0e10cSrcweir 			nPrtAscent = (sal_uInt16) aOutMet.GetAscent();
330cdf0e10cSrcweir             ( (OutputDevice&)rRefDev).SetFont( aOldFnt );
331cdf0e10cSrcweir 		}
332cdf0e10cSrcweir 
333cdf0e10cSrcweir         nRet = nPrtAscent;
334cdf0e10cSrcweir 	}
335cdf0e10cSrcweir 
336cdf0e10cSrcweir #if !defined(MACOSX) // #i89844# extleading is below the line for Mac
337cdf0e10cSrcweir     // TODO: move extleading below the line for all platforms too
338cdf0e10cSrcweir     nRet += GetFontLeading( pSh, rRefDev );
339cdf0e10cSrcweir #endif
340cdf0e10cSrcweir 
341cdf0e10cSrcweir     ASSERT( USHRT_MAX != nRet, "GetFontAscent returned USHRT_MAX" )
342cdf0e10cSrcweir     return nRet;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir /*************************************************************************
346cdf0e10cSrcweir  *
347cdf0e10cSrcweir  *  sal_uInt16 SwFntObj::GetFontHeight( const OutputDevice* pOut )
348cdf0e10cSrcweir  *
349cdf0e10cSrcweir  *  Ersterstellung      AMA 7. Nov. 94
350cdf0e10cSrcweir  *  Letzte Aenderung    AMA 7. Nov. 94
351cdf0e10cSrcweir  *
352cdf0e10cSrcweir  *  Beschreibung: liefern die H?he des Fonts auf dem
353cdf0e10cSrcweir  *  gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
354cdf0e10cSrcweir  *  erzeugt werden.
355cdf0e10cSrcweir  *************************************************************************/
356cdf0e10cSrcweir 
GetFontHeight(const ViewShell * pSh,const OutputDevice & rOut)357cdf0e10cSrcweir sal_uInt16 SwFntObj::GetFontHeight( const ViewShell* pSh, const OutputDevice& rOut )
358cdf0e10cSrcweir {
359cdf0e10cSrcweir     sal_uInt16 nRet = 0;
360cdf0e10cSrcweir     const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
361cdf0e10cSrcweir 
362cdf0e10cSrcweir     if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
363cdf0e10cSrcweir     {
364cdf0e10cSrcweir         CreateScrFont( *pSh, rOut );
365cdf0e10cSrcweir         ASSERT( USHRT_MAX != nScrHeight, "nScrHeight is going berzerk" )
366cdf0e10cSrcweir         nRet = nScrHeight + GetFontLeading( pSh, rRefDev );
367cdf0e10cSrcweir     }
368cdf0e10cSrcweir     else
369cdf0e10cSrcweir 	{
370cdf0e10cSrcweir 		if ( nPrtHeight == USHRT_MAX ) // PrinterHeight noch nicht bekannt?
371cdf0e10cSrcweir 		{
372cdf0e10cSrcweir             CreatePrtFont( rOut );
373cdf0e10cSrcweir             const Font aOldFnt( rRefDev.GetFont() );
374cdf0e10cSrcweir             ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
375cdf0e10cSrcweir             nPrtHeight = static_cast<sal_uInt16>(rRefDev.GetTextHeight());
376cdf0e10cSrcweir 
377cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
378cdf0e10cSrcweir             // Check if vcl did not change the meading of GetTextHeight
379cdf0e10cSrcweir             const FontMetric aOutMet( rRefDev.GetFontMetric() );
380cdf0e10cSrcweir             long nTmpPrtHeight = (sal_uInt16)aOutMet.GetAscent() + aOutMet.GetDescent();
381cdf0e10cSrcweir             (void) nTmpPrtHeight;
382cdf0e10cSrcweir             // #i106098#: do not compare with == here due to rounding error
383cdf0e10cSrcweir             ASSERT( abs(nTmpPrtHeight - nPrtHeight) < 3,
384cdf0e10cSrcweir                     "GetTextHeight != Ascent + Descent" );
385cdf0e10cSrcweir #endif
386cdf0e10cSrcweir 
387cdf0e10cSrcweir             ((OutputDevice&)rRefDev).SetFont( aOldFnt );
388cdf0e10cSrcweir 		}
389cdf0e10cSrcweir 
390cdf0e10cSrcweir         nRet = nPrtHeight + GetFontLeading( pSh, rRefDev );
391cdf0e10cSrcweir 	}
392cdf0e10cSrcweir 
393cdf0e10cSrcweir     ASSERT( USHRT_MAX != nRet, "GetFontHeight returned USHRT_MAX" )
394cdf0e10cSrcweir     return nRet;
395cdf0e10cSrcweir }
396cdf0e10cSrcweir 
GetFontLeading(const ViewShell * pSh,const OutputDevice & rOut)397cdf0e10cSrcweir sal_uInt16 SwFntObj::GetFontLeading( const ViewShell *pSh, const OutputDevice& rOut )
398cdf0e10cSrcweir {
399cdf0e10cSrcweir     sal_uInt16 nRet = 0;
400cdf0e10cSrcweir 
401cdf0e10cSrcweir     if ( pSh )
402cdf0e10cSrcweir     {
403cdf0e10cSrcweir         if ( USHRT_MAX == nGuessedLeading || USHRT_MAX == nExtLeading )
404cdf0e10cSrcweir         {
405cdf0e10cSrcweir             const Font aOldFnt( rOut.GetFont() );
406cdf0e10cSrcweir             ((OutputDevice&)rOut).SetFont( *pPrtFont );
407cdf0e10cSrcweir             const FontMetric aMet( rOut.GetFontMetric() );
408cdf0e10cSrcweir             ((OutputDevice&)rOut).SetFont( aOldFnt );
409cdf0e10cSrcweir             bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
410cdf0e10cSrcweir             GuessLeading( *pSh, aMet );
411cdf0e10cSrcweir             nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
412cdf0e10cSrcweir         }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir         const IDocumentSettingAccess& rIDSA = *pSh->getIDocumentSettingAccess();
415cdf0e10cSrcweir         const bool bBrowse = ( pSh->GetWin() &&
416cdf0e10cSrcweir                                pSh->GetViewOptions()->getBrowseMode() &&
417cdf0e10cSrcweir                               !pSh->GetViewOptions()->IsPrtFormat() );
418cdf0e10cSrcweir 
419cdf0e10cSrcweir         if ( !bBrowse && rIDSA.get(IDocumentSettingAccess::ADD_EXT_LEADING) )
420cdf0e10cSrcweir             nRet = nExtLeading;
421cdf0e10cSrcweir         else
422cdf0e10cSrcweir             nRet = nGuessedLeading;
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir 
425cdf0e10cSrcweir     ASSERT( USHRT_MAX != nRet, "GetFontLeading returned USHRT_MAX" )
426cdf0e10cSrcweir     return nRet;
427cdf0e10cSrcweir }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 
430cdf0e10cSrcweir /*************************************************************************
431cdf0e10cSrcweir  *
432cdf0e10cSrcweir  *  SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
433cdf0e10cSrcweir  *
434cdf0e10cSrcweir  *	Ersterstellung		AMA 7. Nov. 94
435cdf0e10cSrcweir  *	Letzte Aenderung	AMA 7. Nov. 94
436cdf0e10cSrcweir  *
437cdf0e10cSrcweir  *  pOut is the output device, not the reference device
438cdf0e10cSrcweir  *
439cdf0e10cSrcweir  *************************************************************************/
440cdf0e10cSrcweir 
CreateScrFont(const ViewShell & rSh,const OutputDevice & rOut)441cdf0e10cSrcweir void SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir     if ( pScrFont )
444cdf0e10cSrcweir         return;
445cdf0e10cSrcweir 
446cdf0e10cSrcweir     // any changes to the output device are reset at the end of the function
447cdf0e10cSrcweir     OutputDevice* pOut = (OutputDevice*)&rOut;
448cdf0e10cSrcweir 
449cdf0e10cSrcweir     // Save old font
450cdf0e10cSrcweir     Font aOldOutFont( pOut->GetFont() );
451cdf0e10cSrcweir 
452cdf0e10cSrcweir     nScrHeight = USHRT_MAX;
453cdf0e10cSrcweir 
454cdf0e10cSrcweir     // Condition for output font / refdev font adjustment
455cdf0e10cSrcweir     OutputDevice* pPrt = &rSh.GetRefDev();
456cdf0e10cSrcweir 
457cdf0e10cSrcweir     if( !rSh.GetWin() ||
458cdf0e10cSrcweir         !rSh.GetViewOptions()->getBrowseMode() ||
459cdf0e10cSrcweir          rSh.GetViewOptions()->IsPrtFormat() )
460cdf0e10cSrcweir     {
461cdf0e10cSrcweir         // After CreatePrtFont pPrtFont is the font which is actually used
462cdf0e10cSrcweir         // by the reference device
463cdf0e10cSrcweir         CreatePrtFont( *pPrt );
464cdf0e10cSrcweir         pPrinter = pPrt;
465cdf0e10cSrcweir 
466cdf0e10cSrcweir         // save old reference device font
467cdf0e10cSrcweir         Font aOldPrtFnt( pPrt->GetFont() );
468cdf0e10cSrcweir 
469cdf0e10cSrcweir         // set the font used at the reference device at the reference device
470cdf0e10cSrcweir         // and the output device
471cdf0e10cSrcweir 		pPrt->SetFont( *pPrtFont );
472cdf0e10cSrcweir         pOut->SetFont( *pPrtFont );
473cdf0e10cSrcweir 
474cdf0e10cSrcweir         // This should be the default for pScrFont.
475cdf0e10cSrcweir         pScrFont = pPrtFont;
476cdf0e10cSrcweir 
477cdf0e10cSrcweir         FontMetric aMet = pPrt->GetFontMetric( );
478cdf0e10cSrcweir         //Don't loose "faked" properties of the logical font that don't truly
479cdf0e10cSrcweir         //exist in the physical font metrics which vcl which fake up for us
480cdf0e10cSrcweir         aMet.SetWeight(pScrFont->GetWeight());
481cdf0e10cSrcweir         aMet.SetItalic(pScrFont->GetItalic());
482cdf0e10cSrcweir 
483cdf0e10cSrcweir         bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
484cdf0e10cSrcweir 
485cdf0e10cSrcweir         if ( USHRT_MAX == nGuessedLeading )
486cdf0e10cSrcweir             GuessLeading( rSh, aMet );
487cdf0e10cSrcweir 
488cdf0e10cSrcweir         if ( USHRT_MAX == nExtLeading )
489cdf0e10cSrcweir             nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
490cdf0e10cSrcweir 
491cdf0e10cSrcweir         // reset the original reference device font
492cdf0e10cSrcweir         pPrt->SetFont( aOldPrtFnt );
493cdf0e10cSrcweir 	}
494cdf0e10cSrcweir 	else
495cdf0e10cSrcweir 	{
496cdf0e10cSrcweir 		bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
497cdf0e10cSrcweir         if ( nGuessedLeading == USHRT_MAX )
498cdf0e10cSrcweir             nGuessedLeading = 0;
499cdf0e10cSrcweir 
500cdf0e10cSrcweir         // no external leading in browse mode
501cdf0e10cSrcweir         if ( nExtLeading == USHRT_MAX )
502cdf0e10cSrcweir             nExtLeading = 0;
503cdf0e10cSrcweir 
504cdf0e10cSrcweir         pScrFont = pPrtFont;
505cdf0e10cSrcweir     }
506cdf0e10cSrcweir 
507cdf0e10cSrcweir     // Zoomfaktor ueberpruefen, z.B. wg. PrtOle2 beim Speichern
508cdf0e10cSrcweir 	{
509cdf0e10cSrcweir 		// Sollte der Zoomfaktor des OutputDevices nicht mit dem der View-
510cdf0e10cSrcweir 		// Options uebereinstimmen, so darf dieser Font nicht gecacht
511cdf0e10cSrcweir 		// werden, deshalb wird der Zoomfaktor auf einen "ungueltigen" Wert
512cdf0e10cSrcweir 		// gesetzt.
513cdf0e10cSrcweir 		long nTmp;
514cdf0e10cSrcweir 		if( pOut->GetMapMode().GetScaleX().IsValid() &&
515cdf0e10cSrcweir 			pOut->GetMapMode().GetScaleY().IsValid() &&
516cdf0e10cSrcweir 			pOut->GetMapMode().GetScaleX() == pOut->GetMapMode().GetScaleY() )
517cdf0e10cSrcweir 		{
518cdf0e10cSrcweir 			nTmp = ( 100 * pOut->GetMapMode().GetScaleX().GetNumerator() ) /
519cdf0e10cSrcweir 					 pOut->GetMapMode().GetScaleX().GetDenominator();
520cdf0e10cSrcweir 		}
521cdf0e10cSrcweir 		else
522cdf0e10cSrcweir 			nTmp = 0;
523cdf0e10cSrcweir 		if( nTmp != nZoom )
524cdf0e10cSrcweir 			nZoom = USHRT_MAX - 1;
525cdf0e10cSrcweir 	}
526cdf0e10cSrcweir 
527cdf0e10cSrcweir     nScrAscent = (sal_uInt16)pOut->GetFontMetric().GetAscent();
528cdf0e10cSrcweir     if ( USHRT_MAX == nScrHeight )
529cdf0e10cSrcweir         nScrHeight = (sal_uInt16)pOut->GetTextHeight();
530cdf0e10cSrcweir 
531cdf0e10cSrcweir     // reset original output device font
532cdf0e10cSrcweir     pOut->SetFont( aOldOutFont );
533cdf0e10cSrcweir }
534cdf0e10cSrcweir 
535cdf0e10cSrcweir 
GuessLeading(const ViewShell & rSh,const FontMetric & rMet)536cdf0e10cSrcweir void SwFntObj::GuessLeading( const ViewShell&
537cdf0e10cSrcweir #if defined(WNT) || defined(PM2)
538cdf0e10cSrcweir                              rSh
539cdf0e10cSrcweir #endif
540cdf0e10cSrcweir                              , const FontMetric& rMet )
541cdf0e10cSrcweir {
542cdf0e10cSrcweir     // If leading >= 5, this seems to be enough leading.
543cdf0e10cSrcweir     // Nothing has to be done.
544cdf0e10cSrcweir     if ( rMet.GetIntLeading() >= 5 )
545cdf0e10cSrcweir     {
546cdf0e10cSrcweir         nGuessedLeading = 0;
547cdf0e10cSrcweir         return;
548cdf0e10cSrcweir     }
549cdf0e10cSrcweir 
550cdf0e10cSrcweir #if defined(WNT) || defined(PM2)
551cdf0e10cSrcweir     OutputDevice *pWin = rSh.GetWin() ?
552cdf0e10cSrcweir                          rSh.GetWin() :
553cdf0e10cSrcweir                          GetpApp()->GetDefaultDevice();
554cdf0e10cSrcweir 	if ( pWin )
555cdf0e10cSrcweir 	{
556cdf0e10cSrcweir 		MapMode aTmpMap( MAP_TWIP );
557cdf0e10cSrcweir 		MapMode aOldMap = pWin->GetMapMode( );
558cdf0e10cSrcweir 		pWin->SetMapMode( aTmpMap );
559cdf0e10cSrcweir 		const Font aOldFnt( pWin->GetFont() );
560cdf0e10cSrcweir 		pWin->SetFont( *pPrtFont );
561cdf0e10cSrcweir 		const FontMetric aWinMet( pWin->GetFontMetric() );
562cdf0e10cSrcweir 		const sal_uInt16 nWinHeight = sal_uInt16( aWinMet.GetSize().Height() );
563cdf0e10cSrcweir 		if( pPrtFont->GetName().Search( aWinMet.GetName() ) < USHRT_MAX )
564cdf0e10cSrcweir 		{
565cdf0e10cSrcweir 			// Wenn das Leading auf dem Window auch 0 ist, dann
566cdf0e10cSrcweir 			// muss es auch so bleiben (vgl. StarMath!).
567cdf0e10cSrcweir             long nTmpLeading = (long)aWinMet.GetIntLeading();
568cdf0e10cSrcweir 			 // einen Versuch haben wir noch wg. 31003:
569cdf0e10cSrcweir 			if( nTmpLeading <= 0 )
570cdf0e10cSrcweir 			{
571cdf0e10cSrcweir 				pWin->SetFont( rMet );
572cdf0e10cSrcweir                 nTmpLeading = (long)pWin->GetFontMetric().GetIntLeading();
573cdf0e10cSrcweir 				if( nTmpLeading < 0 )
574cdf0e10cSrcweir                     nGuessedLeading = 0;
575cdf0e10cSrcweir 				else
576cdf0e10cSrcweir                     nGuessedLeading = sal_uInt16(nTmpLeading);
577cdf0e10cSrcweir 			}
578cdf0e10cSrcweir 			else
579cdf0e10cSrcweir 			{
580cdf0e10cSrcweir                 nGuessedLeading = sal_uInt16(nTmpLeading);
581cdf0e10cSrcweir 				// Manta-Hack #50153#:
582cdf0e10cSrcweir 				// Wer beim Leading luegt, luegt moeglicherweise auch beim
583cdf0e10cSrcweir 				// Ascent/Descent, deshalb wird hier ggf. der Font ein wenig
584cdf0e10cSrcweir 				// tiefergelegt, ohne dabei seine Hoehe zu aendern.
585cdf0e10cSrcweir 				long nDiff = Min( rMet.GetDescent() - aWinMet.GetDescent(),
586cdf0e10cSrcweir 					aWinMet.GetAscent() - rMet.GetAscent() - nTmpLeading );
587cdf0e10cSrcweir 				if( nDiff > 0 )
588cdf0e10cSrcweir 				{
589cdf0e10cSrcweir 					ASSERT( nPrtAscent < USHRT_MAX, "GuessLeading: PrtAscent-Fault" );
590cdf0e10cSrcweir                     if ( nPrtAscent < USHRT_MAX )
591cdf0e10cSrcweir                         nPrtAscent = nPrtAscent + (sal_uInt16)(( 2 * nDiff ) / 5);
592cdf0e10cSrcweir 				}
593cdf0e10cSrcweir 			}
594cdf0e10cSrcweir 		}
595cdf0e10cSrcweir 		else
596cdf0e10cSrcweir 		{
597cdf0e10cSrcweir 			// Wenn alle Stricke reissen, nehmen wir 15% der
598cdf0e10cSrcweir 			// Hoehe, ein von CL empirisch ermittelter Wert.
599cdf0e10cSrcweir             nGuessedLeading = (nWinHeight * 15) / 100;
600cdf0e10cSrcweir 		}
601cdf0e10cSrcweir 		pWin->SetFont( aOldFnt );
602cdf0e10cSrcweir 		pWin->SetMapMode( aOldMap );
603cdf0e10cSrcweir 	}
604cdf0e10cSrcweir 	else
605cdf0e10cSrcweir #endif
606cdf0e10cSrcweir         nGuessedLeading = 0;
607cdf0e10cSrcweir }
608cdf0e10cSrcweir 
609cdf0e10cSrcweir /*************************************************************************
610cdf0e10cSrcweir  *
611cdf0e10cSrcweir  *	void SwFntObj::SetDeviceFont( const OutputDevice *pOut ),
612cdf0e10cSrcweir  *
613cdf0e10cSrcweir  *	Ersterstellung		AMA 7. Nov. 94
614cdf0e10cSrcweir  *	Letzte Aenderung	AMA 7. Nov. 94
615cdf0e10cSrcweir  *
616cdf0e10cSrcweir  *  Beschreibung: stellt den Font am gewuenschten OutputDevice ein,
617cdf0e10cSrcweir  *  am Bildschirm muss eventuell erst den Abgleich durchgefuehrt werden.
618cdf0e10cSrcweir  *
619cdf0e10cSrcweir  *************************************************************************/
620cdf0e10cSrcweir 
SetDevFont(const ViewShell * pSh,OutputDevice & rOut)621cdf0e10cSrcweir void SwFntObj::SetDevFont( const ViewShell *pSh, OutputDevice& rOut )
622cdf0e10cSrcweir {
623cdf0e10cSrcweir     const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
624cdf0e10cSrcweir 
625cdf0e10cSrcweir     if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
626cdf0e10cSrcweir     {
627cdf0e10cSrcweir         CreateScrFont( *pSh, rOut );
628cdf0e10cSrcweir         if( !GetScrFont()->IsSameInstance( rOut.GetFont() ) )
629cdf0e10cSrcweir             rOut.SetFont( *pScrFont );
630cdf0e10cSrcweir         if( pPrinter && ( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) ) )
631cdf0e10cSrcweir             pPrinter->SetFont( *pPrtFont );
632cdf0e10cSrcweir     }
633cdf0e10cSrcweir     else
634cdf0e10cSrcweir 	{
635cdf0e10cSrcweir         CreatePrtFont( rOut );
636cdf0e10cSrcweir         if( !pPrtFont->IsSameInstance( rOut.GetFont() ) )
637cdf0e10cSrcweir             rOut.SetFont( *pPrtFont );
638cdf0e10cSrcweir 	}
639cdf0e10cSrcweir 
640cdf0e10cSrcweir     // Here, we actually do not need the leading values, but by calling
641cdf0e10cSrcweir     // GetFontLeading() we assure that the values are calculated for later use.
642cdf0e10cSrcweir     GetFontLeading( pSh, rRefDev );
643cdf0e10cSrcweir }
644cdf0e10cSrcweir 
645cdf0e10cSrcweir #define WRONG_SHOW_MIN 5
646cdf0e10cSrcweir #define WRONG_SHOW_SMALL 11
647cdf0e10cSrcweir #define WRONG_SHOW_MEDIUM 15
648cdf0e10cSrcweir 
649cdf0e10cSrcweir /*************************************************************************
650cdf0e10cSrcweir  *
651cdf0e10cSrcweir  * void SwFntObj::DrawText( ... )
652cdf0e10cSrcweir  *
653cdf0e10cSrcweir  *	Ersterstellung		AMA 16. Dez. 94
654cdf0e10cSrcweir  *	Letzte Aenderung	AMA 16. Dez. 94
655cdf0e10cSrcweir  *
656cdf0e10cSrcweir  *  Beschreibung: Textausgabe
657cdf0e10cSrcweir  * 					auf dem Bildschirm 			=> DrawTextArray
658cdf0e10cSrcweir  * 					auf dem Drucker, !Kerning 	=> DrawText
659cdf0e10cSrcweir  * 					auf dem Drucker + Kerning	=> DrawStretchText
660cdf0e10cSrcweir  *
661cdf0e10cSrcweir  *************************************************************************/
662cdf0e10cSrcweir 
lcl_WhichPunctuation(xub_Unicode cChar)663cdf0e10cSrcweir sal_uInt8 lcl_WhichPunctuation( xub_Unicode cChar )
664cdf0e10cSrcweir {
665cdf0e10cSrcweir     if ( ( cChar < 0x3001 || cChar > 0x3002 ) &&
666cdf0e10cSrcweir             ( cChar < 0x3008 || cChar > 0x3011 ) &&
667cdf0e10cSrcweir             ( cChar < 0x3014 || cChar > 0x301F ) &&
668cdf0e10cSrcweir               0xFF62 != cChar && 0xFF63 != cChar )
669cdf0e10cSrcweir         // no punctuation
670cdf0e10cSrcweir         return SwScriptInfo::NONE;
671cdf0e10cSrcweir     else if ( 0x3001 == cChar || 0x3002 == cChar ||
672cdf0e10cSrcweir               0x3009 == cChar || 0x300B == cChar ||
673cdf0e10cSrcweir               0x300D == cChar || 0x300F == cChar ||
674cdf0e10cSrcweir               0x3011 == cChar || 0x3015 == cChar ||
675cdf0e10cSrcweir               0x3017 == cChar || 0x3019 == cChar ||
676cdf0e10cSrcweir               0x301B == cChar || 0x301E == cChar ||
677cdf0e10cSrcweir               0x301F == cChar || 0xFF63 == cChar )
678cdf0e10cSrcweir         // right punctuation
679cdf0e10cSrcweir         return SwScriptInfo::SPECIAL_RIGHT;
680cdf0e10cSrcweir 
681cdf0e10cSrcweir     return SwScriptInfo::SPECIAL_LEFT;
682cdf0e10cSrcweir }
683cdf0e10cSrcweir 
lcl_IsMonoSpaceFont(const OutputDevice & rOut)684cdf0e10cSrcweir static sal_Bool lcl_IsMonoSpaceFont( const OutputDevice& rOut )
685cdf0e10cSrcweir {
686cdf0e10cSrcweir     const String aStr1( xub_Unicode( 0x3008 ) );
687cdf0e10cSrcweir     const String aStr2( xub_Unicode( 0x307C ) );
688cdf0e10cSrcweir     const long nWidth1 = rOut.GetTextWidth( aStr1 );
689cdf0e10cSrcweir     const long nWidth2 = rOut.GetTextWidth( aStr2 );
690cdf0e10cSrcweir     return nWidth1 == nWidth2;
691cdf0e10cSrcweir }
692cdf0e10cSrcweir 
693cdf0e10cSrcweir // ER 09.07.95 20:34
694cdf0e10cSrcweir // mit -Ox Optimierung stuerzt's unter win95 ab
695cdf0e10cSrcweir // JP 12.07.95: unter WNT auch (i386);       Alpha ??
696cdf0e10cSrcweir // global optimization off
697cdf0e10cSrcweir #ifdef _MSC_VER
698cdf0e10cSrcweir #pragma optimize("g",off)
699cdf0e10cSrcweir #endif
700cdf0e10cSrcweir 
701cdf0e10cSrcweir /* This helper structure (SwForbidden) contains the already marked parts of the string
702cdf0e10cSrcweir     to avoid double lines (e.g grammar + spell check error) */
703cdf0e10cSrcweir 
704cdf0e10cSrcweir typedef std::vector< std::pair< xub_StrLen, xub_StrLen > > SwForbidden;
705cdf0e10cSrcweir 
lcl_DrawLineForWrongListData(SwForbidden & rForbidden,const SwDrawTextInfo & rInf,const SwWrongList * pWList,const CalcLinePosData & rCalcLinePosData,const Size & rPrtFontSize)706cdf0e10cSrcweir static void lcl_DrawLineForWrongListData(
707cdf0e10cSrcweir     SwForbidden &rForbidden,
708cdf0e10cSrcweir     const SwDrawTextInfo    &rInf,
709cdf0e10cSrcweir     const SwWrongList       *pWList,
710cdf0e10cSrcweir     const CalcLinePosData   &rCalcLinePosData,
711cdf0e10cSrcweir     const Size              &rPrtFontSize )
712cdf0e10cSrcweir {
71346f38707SJürgen Schmidt     if (!pWList) return;
714cdf0e10cSrcweir 
715cdf0e10cSrcweir     xub_StrLen nStart = rInf.GetIdx();
716cdf0e10cSrcweir     xub_StrLen nWrLen = rInf.GetLen();
717cdf0e10cSrcweir 
718cdf0e10cSrcweir     // check if respective data is available in the current text range
71946f38707SJürgen Schmidt     if (!pWList->Check( nStart, nWrLen ))
72046f38707SJürgen Schmidt     {
72146f38707SJürgen Schmidt         return;
72246f38707SJürgen Schmidt     }
72346f38707SJürgen Schmidt 
72446f38707SJürgen Schmidt     long nHght = rInf.GetOut().LogicToPixel( rPrtFontSize ).Height();
72546f38707SJürgen Schmidt 
72646f38707SJürgen Schmidt     // Draw wavy lines for spell and grammar errors only if font is large enough.
72746f38707SJürgen Schmidt     // Lines for smart tags will always be drawn.
72846f38707SJürgen Schmidt     if (pWList != rInf.GetSmartTags() && WRONG_SHOW_MIN >= nHght)
729cdf0e10cSrcweir     {
73046f38707SJürgen Schmidt         return;
73146f38707SJürgen Schmidt     }
73246f38707SJürgen Schmidt 
73346f38707SJürgen Schmidt     SwForbidden::iterator pIter = rForbidden.begin();
73446f38707SJürgen Schmidt     if (rInf.GetOut().GetConnectMetaFile())
73546f38707SJürgen Schmidt         rInf.GetOut().Push();
73646f38707SJürgen Schmidt 
73746f38707SJürgen Schmidt     const Color aCol( rInf.GetOut().GetLineColor() );
73846f38707SJürgen Schmidt 
73946f38707SJürgen Schmidt     // iterate over all ranges stored in the respective SwWrongList
74046f38707SJürgen Schmidt     do
74146f38707SJürgen Schmidt     {
74246f38707SJürgen Schmidt         nStart = nStart - rInf.GetIdx();
74346f38707SJürgen Schmidt 
74446f38707SJürgen Schmidt         const xub_StrLen nEnd = nStart + nWrLen;
74546f38707SJürgen Schmidt         xub_StrLen nNext = nStart;
74646f38707SJürgen Schmidt         while( nNext < nEnd )
747cdf0e10cSrcweir         {
74846f38707SJürgen Schmidt             while( pIter != rForbidden.end() && pIter->second <= nNext )
74946f38707SJürgen Schmidt                 ++pIter;
750cdf0e10cSrcweir 
75146f38707SJürgen Schmidt             xub_StrLen nNextStart = nNext;
75246f38707SJürgen Schmidt             xub_StrLen nNextEnd = nEnd;
753cdf0e10cSrcweir 
75446f38707SJürgen Schmidt             if( pIter == rForbidden.end() || nNextEnd <= pIter->first )
755cdf0e10cSrcweir             {
75646f38707SJürgen Schmidt                 // No overlapping mark up found
75746f38707SJürgen Schmidt                 std::pair< xub_StrLen, xub_StrLen > aNew;
75846f38707SJürgen Schmidt                 aNew.first = nNextStart;
75946f38707SJürgen Schmidt                 aNew.second = nNextEnd;
76046f38707SJürgen Schmidt                 rForbidden.insert( pIter, aNew );
76146f38707SJürgen Schmidt                 pIter = rForbidden.begin();
76246f38707SJürgen Schmidt                 nNext = nEnd;
76346f38707SJürgen Schmidt             }
76446f38707SJürgen Schmidt             else
76546f38707SJürgen Schmidt             {
76646f38707SJürgen Schmidt                 nNext = pIter->second;
76746f38707SJürgen Schmidt                 if( nNextStart < pIter->first )
76846f38707SJürgen Schmidt                 {
76946f38707SJürgen Schmidt                     nNextEnd = pIter->first;
77046f38707SJürgen Schmidt                     pIter->first = nNextStart;
77146f38707SJürgen Schmidt                 }
77246f38707SJürgen Schmidt                 else
77346f38707SJürgen Schmidt                     continue;
77446f38707SJürgen Schmidt             }
77546f38707SJürgen Schmidt             // determine line pos
77646f38707SJürgen Schmidt             Point aStart( rInf.GetPos() );
77746f38707SJürgen Schmidt             Point aEnd;
77846f38707SJürgen Schmidt             lcl_calcLinePos( rCalcLinePosData, aStart, aEnd, nNextStart, nNextEnd - nNextStart );
77946f38707SJürgen Schmidt 
78046f38707SJürgen Schmidt 
78146f38707SJürgen Schmidt             sal_uInt16 wrongPos = pWList->GetWrongPos(nNextStart + rInf.GetIdx());
78246f38707SJürgen Schmidt 
78346f38707SJürgen Schmidt             const SwWrongArea* wrongArea = pWList->GetElement(wrongPos);
784cdf0e10cSrcweir 
78546f38707SJürgen Schmidt             if (wrongArea != 0)
78646f38707SJürgen Schmidt             {
78746f38707SJürgen Schmidt                 if (WRONGAREA_DASHED == wrongArea->mLineType)
78846f38707SJürgen Schmidt                 {
78946f38707SJürgen Schmidt                     rInf.GetOut().SetLineColor( wrongArea->mColor );
79046f38707SJürgen Schmidt 
79146f38707SJürgen Schmidt                     aStart.Y() +=30;
79246f38707SJürgen Schmidt                     aEnd.Y() +=30;
79346f38707SJürgen Schmidt 
79446f38707SJürgen Schmidt                     LineInfo aLineInfo( LINE_DASH );
79546f38707SJürgen Schmidt                     aLineInfo.SetDistance( 40 );
79646f38707SJürgen Schmidt                     aLineInfo.SetDashLen( 1 );
79746f38707SJürgen Schmidt                     aLineInfo.SetDashCount(1);
79846f38707SJürgen Schmidt 
79946f38707SJürgen Schmidt                     rInf.GetOut().DrawLine( aStart, aEnd, aLineInfo );
80046f38707SJürgen Schmidt                 }
80146f38707SJürgen Schmidt                 else if (WRONGAREA_WAVE == wrongArea->mLineType)
802cdf0e10cSrcweir                 {
80346f38707SJürgen Schmidt                     rInf.GetOut().SetLineColor( wrongArea->mColor );
80446f38707SJürgen Schmidt 
80546f38707SJürgen Schmidt                     // get wavy line type to use
80646f38707SJürgen Schmidt                     sal_uInt16 nWave =
80746f38707SJürgen Schmidt                         WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
80846f38707SJürgen Schmidt                         ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL : WAVE_FLAT );
80946f38707SJürgen Schmidt 
81046f38707SJürgen Schmidt                     rInf.GetOut().DrawWaveLine( aStart, aEnd, nWave );
811cdf0e10cSrcweir                 }
81246f38707SJürgen Schmidt                 else if (WRONGAREA_WAVE_NORMAL == wrongArea->mLineType)
81346f38707SJürgen Schmidt                 {
81446f38707SJürgen Schmidt                     rInf.GetOut().SetLineColor( wrongArea->mColor );
815cdf0e10cSrcweir 
81646f38707SJürgen Schmidt                     rInf.GetOut().DrawWaveLine( aStart, aEnd, WAVE_NORMAL);
81746f38707SJürgen Schmidt                 }
81846f38707SJürgen Schmidt 
81946f38707SJürgen Schmidt                 else if (WRONGAREA_WAVE_SMALL == wrongArea->mLineType)
82046f38707SJürgen Schmidt                 {
82146f38707SJürgen Schmidt                     rInf.GetOut().SetLineColor( wrongArea->mColor );
822cdf0e10cSrcweir 
82346f38707SJürgen Schmidt                     rInf.GetOut().DrawWaveLine( aStart, aEnd, WAVE_SMALL);
82446f38707SJürgen Schmidt                 }
82546f38707SJürgen Schmidt                 else if (WRONGAREA_WAVE_FLAT == wrongArea->mLineType)
82646f38707SJürgen Schmidt                 {
82746f38707SJürgen Schmidt                     rInf.GetOut().SetLineColor( wrongArea->mColor );
828cdf0e10cSrcweir 
82946f38707SJürgen Schmidt                     rInf.GetOut().DrawWaveLine( aStart, aEnd, WAVE_FLAT);
83046f38707SJürgen Schmidt                 }
83146f38707SJürgen Schmidt             }
832cdf0e10cSrcweir         }
83346f38707SJürgen Schmidt 
83446f38707SJürgen Schmidt         nStart = nEnd + rInf.GetIdx();
83546f38707SJürgen Schmidt         nWrLen = rInf.GetIdx() + rInf.GetLen() - nStart;
836cdf0e10cSrcweir     }
83746f38707SJürgen Schmidt     while (nWrLen && pWList->Check( nStart, nWrLen ));
83846f38707SJürgen Schmidt 
83946f38707SJürgen Schmidt     rInf.GetOut().SetLineColor( aCol );
84046f38707SJürgen Schmidt 
84146f38707SJürgen Schmidt     if (rInf.GetOut().GetConnectMetaFile())
84246f38707SJürgen Schmidt         rInf.GetOut().Pop();
843cdf0e10cSrcweir }
844cdf0e10cSrcweir 
845cdf0e10cSrcweir 
DrawText(SwDrawTextInfo & rInf)846cdf0e10cSrcweir void SwFntObj::DrawText( SwDrawTextInfo &rInf )
847cdf0e10cSrcweir {
848cdf0e10cSrcweir     ASSERT( rInf.GetShell(), "SwFntObj::DrawText without shell" )
849cdf0e10cSrcweir 
850cdf0e10cSrcweir     OutputDevice& rRefDev = rInf.GetShell()->GetRefDev();
851cdf0e10cSrcweir     OutputDevice* pWin = rInf.GetShell()->GetWin();
852cdf0e10cSrcweir 
853cdf0e10cSrcweir     // true if pOut is the printer and the printer has been used for formatting
854cdf0e10cSrcweir     const sal_Bool bPrt = OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() &&
855cdf0e10cSrcweir                       OUTDEV_PRINTER == rRefDev.GetOutDevType();
856cdf0e10cSrcweir     const sal_Bool bBrowse = ( pWin &&
857cdf0e10cSrcweir                            rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
858cdf0e10cSrcweir                           !rInf.GetShell()->GetViewOptions()->IsPrtFormat() &&
859cdf0e10cSrcweir                           !rInf.GetBullet() &&
860cdf0e10cSrcweir                            ( rInf.GetSpace() || !rInf.GetKern() ) &&
861cdf0e10cSrcweir                           !rInf.GetWrong() &&
862cdf0e10cSrcweir                           !rInf.GetGrammarCheck() &&
863cdf0e10cSrcweir                           !rInf.GetSmartTags() &&
864cdf0e10cSrcweir                           !rInf.GetGreyWave() );
865cdf0e10cSrcweir 
866cdf0e10cSrcweir     // bDirectPrint indicates that we can enter the branch which calls
867cdf0e10cSrcweir     // the DrawText functions instead of calling the DrawTextArray functions
868cdf0e10cSrcweir     const sal_Bool bDirectPrint = bPrt || bBrowse;
869cdf0e10cSrcweir 
870cdf0e10cSrcweir     // Condition for output font / refdev font adjustment
871cdf0e10cSrcweir     const sal_Bool bUseScrFont =
872cdf0e10cSrcweir         lcl_IsFontAdjustNecessary( rInf.GetOut(), rRefDev );
873cdf0e10cSrcweir 
874cdf0e10cSrcweir     Font* pTmpFont = bUseScrFont ? pScrFont : pPrtFont;
875cdf0e10cSrcweir 
876cdf0e10cSrcweir     //
877cdf0e10cSrcweir     //  bDirectPrint and bUseScrFont should have these values:
878cdf0e10cSrcweir     //
879cdf0e10cSrcweir     //  Outdev / RefDef  | Printer | VirtPrinter | Window
880cdf0e10cSrcweir     // ----------------------------------------------------
881cdf0e10cSrcweir     //  Printer          | 1 - 0   | 0 - 1       | -
882cdf0e10cSrcweir     // ----------------------------------------------------
883cdf0e10cSrcweir     //  VirtPrinter/PDF  | 0 - 1   | 0 - 1       | -
884cdf0e10cSrcweir     // ----------------------------------------------------
885cdf0e10cSrcweir     //  Window/VirtWindow| 0 - 1   | 0 - 1       | 1 - 0
886cdf0e10cSrcweir     //
887cdf0e10cSrcweir     // Exception: During painting of a Writer OLE object, we do not have
888cdf0e10cSrcweir     // a window. Therefore bUseSrcFont is always 0 in this case.
889cdf0e10cSrcweir     //
890cdf0e10cSrcweir 
891cdf0e10cSrcweir #ifdef DBG_UTIL
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     const sal_Bool bNoAdjust = bPrt ||
894cdf0e10cSrcweir             (  pWin &&
895cdf0e10cSrcweir                rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
896cdf0e10cSrcweir               !rInf.GetShell()->GetViewOptions()->IsPrtFormat() );
897cdf0e10cSrcweir 
898cdf0e10cSrcweir     if ( OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() )
899cdf0e10cSrcweir     {
900cdf0e10cSrcweir         // Printer output
901cdf0e10cSrcweir         if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
902cdf0e10cSrcweir         {
903cdf0e10cSrcweir             ASSERT( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" )
904cdf0e10cSrcweir         }
905cdf0e10cSrcweir         else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
906cdf0e10cSrcweir         {
907cdf0e10cSrcweir             ASSERT( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" )
908cdf0e10cSrcweir         }
909cdf0e10cSrcweir         else
910cdf0e10cSrcweir         {
911cdf0e10cSrcweir             ASSERT( sal_False, "Outdev Check failed" )
912cdf0e10cSrcweir         }
913cdf0e10cSrcweir     }
914cdf0e10cSrcweir     else if ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && ! pWin )
915cdf0e10cSrcweir     {
916cdf0e10cSrcweir         // PDF export
917cdf0e10cSrcweir         if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
918cdf0e10cSrcweir         {
919cdf0e10cSrcweir             ASSERT( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" )
920cdf0e10cSrcweir         }
921cdf0e10cSrcweir         else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
922cdf0e10cSrcweir         {
923cdf0e10cSrcweir             ASSERT( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" )
924cdf0e10cSrcweir         }
925cdf0e10cSrcweir         else
926cdf0e10cSrcweir         {
927cdf0e10cSrcweir             ASSERT( sal_False, "Outdev Check failed" )
928cdf0e10cSrcweir         }
929cdf0e10cSrcweir     }
930cdf0e10cSrcweir     else if ( OUTDEV_WINDOW == rInf.GetOut().GetOutDevType() ||
931cdf0e10cSrcweir                ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && pWin ) )
932cdf0e10cSrcweir     {
933cdf0e10cSrcweir         // Window or virtual window
934cdf0e10cSrcweir         if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
935cdf0e10cSrcweir         {
936cdf0e10cSrcweir             ASSERT( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" )
937cdf0e10cSrcweir         }
938cdf0e10cSrcweir         else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
939cdf0e10cSrcweir         {
940cdf0e10cSrcweir             ASSERT( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" )
941cdf0e10cSrcweir         }
942cdf0e10cSrcweir         else if ( OUTDEV_WINDOW == rRefDev.GetOutDevType() )
943cdf0e10cSrcweir         {
944cdf0e10cSrcweir             ASSERT( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" )
945cdf0e10cSrcweir         }
946cdf0e10cSrcweir         else
947cdf0e10cSrcweir         {
948cdf0e10cSrcweir             ASSERT( sal_False, "Outdev Check failed" )
949cdf0e10cSrcweir         }
950cdf0e10cSrcweir     }
951cdf0e10cSrcweir     else
952cdf0e10cSrcweir     {
953cdf0e10cSrcweir             ASSERT( sal_False, "Outdev Check failed" )
954cdf0e10cSrcweir     }
955cdf0e10cSrcweir 
956cdf0e10cSrcweir #endif
957cdf0e10cSrcweir 
958cdf0e10cSrcweir     // robust: better use the printer font instead of using no font at all
959cdf0e10cSrcweir     ASSERT( pTmpFont, "No screen or printer font?" );
960cdf0e10cSrcweir     if ( ! pTmpFont )
961cdf0e10cSrcweir         pTmpFont = pPrtFont;
962cdf0e10cSrcweir 
963cdf0e10cSrcweir     // HACK: UNDERLINE_WAVE darf nicht mehr missbraucht werden, daher
964cdf0e10cSrcweir     // wird die graue Wellenlinie des ExtendedAttributSets zunaechst
965cdf0e10cSrcweir     // in der Fontfarbe erscheinen.
966cdf0e10cSrcweir 
967cdf0e10cSrcweir     const sal_Bool bSwitchH2V = rInf.GetFrm() && rInf.GetFrm()->IsVertical();
968cdf0e10cSrcweir     const sal_Bool bSwitchL2R = rInf.GetFrm() && rInf.GetFrm()->IsRightToLeft() &&
969cdf0e10cSrcweir                             ! rInf.IsIgnoreFrmRTL();
970cdf0e10cSrcweir     const sal_uLong nMode = rInf.GetOut().GetLayoutMode();
971cdf0e10cSrcweir     const sal_Bool bBidiPor = ( bSwitchL2R !=
972cdf0e10cSrcweir                             ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
973cdf0e10cSrcweir 
974cdf0e10cSrcweir     // be sure to have the correct layout mode at the printer
975cdf0e10cSrcweir     if ( pPrinter )
976cdf0e10cSrcweir     {
977cdf0e10cSrcweir         pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
978cdf0e10cSrcweir         pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
979cdf0e10cSrcweir     }
980cdf0e10cSrcweir 
981cdf0e10cSrcweir     Point aPos( rInf.GetPos() );
982cdf0e10cSrcweir     if( !bPrt )
983cdf0e10cSrcweir     {
984cdf0e10cSrcweir         if( rInf.GetpOut() != pPixOut || rInf.GetOut().GetMapMode() != *pPixMap )
985cdf0e10cSrcweir         {
986cdf0e10cSrcweir             *pPixMap = rInf.GetOut().GetMapMode();
987cdf0e10cSrcweir             pPixOut = rInf.GetpOut();
988cdf0e10cSrcweir             Size aTmp( 1, 1 );
989cdf0e10cSrcweir             nPixWidth = rInf.GetOut().PixelToLogic( aTmp ).Width();
990cdf0e10cSrcweir         }
991cdf0e10cSrcweir 
992cdf0e10cSrcweir         aPos.X() += rInf.GetFrm()->IsRightToLeft() ? 0 : nPixWidth;
993cdf0e10cSrcweir     }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir     Color aOldColor( pTmpFont->GetColor() );
996cdf0e10cSrcweir     sal_Bool bChgColor = rInf.ApplyAutoColor( pTmpFont );
997cdf0e10cSrcweir     if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
998cdf0e10cSrcweir         rInf.GetOut().SetFont( *pTmpFont );
999cdf0e10cSrcweir     if ( bChgColor )
1000cdf0e10cSrcweir         pTmpFont->SetColor( aOldColor );
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir     if ( STRING_LEN == rInf.GetLen() )
1003cdf0e10cSrcweir         rInf.SetLen( rInf.GetText().Len() );
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir     //
1007cdf0e10cSrcweir     // ASIAN LINE AND CHARACTER GRID MODE START: snap to characters
1008cdf0e10cSrcweir     //
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir     if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
1011cdf0e10cSrcweir          SW_CJK == rInf.GetFont()->GetActual() )
1012cdf0e10cSrcweir     {
1013cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
1014cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars())
1015cdf0e10cSrcweir         {
1016cdf0e10cSrcweir             //for textgrid refactor
1017cdf0e10cSrcweir             //const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
1018cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1019cdf0e10cSrcweir             const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
1020cdf0e10cSrcweir             sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir             if ( pPrinter )
1023cdf0e10cSrcweir                 pPrinter->GetTextArray( rInf.GetText(), pKernArray,
1024cdf0e10cSrcweir                                         rInf.GetIdx(), rInf.GetLen() );
1025cdf0e10cSrcweir             else
1026cdf0e10cSrcweir                 rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1027cdf0e10cSrcweir                                             rInf.GetIdx(), rInf.GetLen() );
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir             long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir             const sal_uLong i = nWidthPerChar ?
1032cdf0e10cSrcweir                                 ( nWidthPerChar - 1 ) / nGridWidth + 1:
1033cdf0e10cSrcweir                                 1;
1034cdf0e10cSrcweir 
1035cdf0e10cSrcweir             nWidthPerChar = i * nGridWidth;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir             // position of first character, we take the printer position
1038cdf0e10cSrcweir             long nCharWidth = pKernArray[ 0 ];
1039cdf0e10cSrcweir             sal_uLong nHalfWidth = nWidthPerChar / 2;
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir             long nNextFix;
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir             // punctuation characters are not centered
1044cdf0e10cSrcweir             xub_Unicode cChar = rInf.GetText().GetChar( rInf.GetIdx() );
1045cdf0e10cSrcweir             sal_uInt8 nType = lcl_WhichPunctuation( cChar );
1046cdf0e10cSrcweir             switch ( nType )
1047cdf0e10cSrcweir             {
1048cdf0e10cSrcweir             case SwScriptInfo::NONE :
1049cdf0e10cSrcweir                 aPos.X() += ( nWidthPerChar - nCharWidth ) / 2;
1050cdf0e10cSrcweir                 nNextFix = nCharWidth / 2;
1051cdf0e10cSrcweir                 break;
1052cdf0e10cSrcweir             case SwScriptInfo::SPECIAL_RIGHT :
1053cdf0e10cSrcweir                 nNextFix = nHalfWidth;
1054cdf0e10cSrcweir                 break;
1055cdf0e10cSrcweir             default:
1056cdf0e10cSrcweir                 aPos.X() += nWidthPerChar - nCharWidth;
1057cdf0e10cSrcweir                 nNextFix = nCharWidth - nHalfWidth;
1058cdf0e10cSrcweir             }
1059cdf0e10cSrcweir 
1060cdf0e10cSrcweir             // calculate offsets
1061cdf0e10cSrcweir             for ( xub_StrLen j = 1; j < rInf.GetLen(); ++j )
1062cdf0e10cSrcweir             {
1063cdf0e10cSrcweir                 long nScr = pKernArray[ j ] - pKernArray[ j - 1 ];
1064cdf0e10cSrcweir                 nNextFix += nWidthPerChar;
1065cdf0e10cSrcweir 
1066cdf0e10cSrcweir                 // punctuation characters are not centered
1067cdf0e10cSrcweir                 cChar = rInf.GetText().GetChar( rInf.GetIdx() + j );
1068cdf0e10cSrcweir                 nType = lcl_WhichPunctuation( cChar );
1069cdf0e10cSrcweir                 switch ( nType )
1070cdf0e10cSrcweir                 {
1071cdf0e10cSrcweir                 case SwScriptInfo::NONE :
1072cdf0e10cSrcweir                     pKernArray[ j - 1 ] = nNextFix - ( nScr / 2 );
1073cdf0e10cSrcweir                     break;
1074cdf0e10cSrcweir                 case SwScriptInfo::SPECIAL_RIGHT :
1075cdf0e10cSrcweir                     pKernArray[ j - 1 ] = nNextFix - nHalfWidth;
1076cdf0e10cSrcweir                     break;
1077cdf0e10cSrcweir                 default:
1078cdf0e10cSrcweir                     pKernArray[ j - 1 ] = nNextFix + nHalfWidth - nScr;
1079cdf0e10cSrcweir                 }
1080cdf0e10cSrcweir             }
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir             // the layout engine requires the total width of the output
1083cdf0e10cSrcweir             pKernArray[ rInf.GetLen() - 1 ] = rInf.GetWidth() -
1084cdf0e10cSrcweir                                               aPos.X() + rInf.GetPos().X() ;
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir             if ( bSwitchH2V )
1087cdf0e10cSrcweir                 rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir             rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1090cdf0e10cSrcweir                 pKernArray, rInf.GetIdx(), rInf.GetLen() );
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir             delete[] pKernArray;
1093cdf0e10cSrcweir             return;
1094cdf0e10cSrcweir         }
1095cdf0e10cSrcweir     }
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir     // For text grid refactor
1098cdf0e10cSrcweir     // ASIAN LINE AND CHARACTER GRID MODE START: not snap to characters
1099cdf0e10cSrcweir     //
1100cdf0e10cSrcweir     if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
1101cdf0e10cSrcweir          SW_CJK == rInf.GetFont()->GetActual() )
1102cdf0e10cSrcweir     {
1103cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
1106cdf0e10cSrcweir         {
1107cdf0e10cSrcweir             const sal_uInt16  nDefaultFontHeight = GetDefaultFontHeight( rInf );
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1110cdf0e10cSrcweir             long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
1111cdf0e10cSrcweir             if( SW_LATIN == rInf.GetFont()->GetActual() )
1112cdf0e10cSrcweir                 nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
1113cdf0e10cSrcweir             else
1114cdf0e10cSrcweir                 nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir             sal_Int32*  pKernArray = new sal_Int32[rInf.GetLen()];
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir             if ( pPrinter )
1119cdf0e10cSrcweir                 pPrinter->GetTextArray( rInf.GetText(), pKernArray,
1120cdf0e10cSrcweir                 rInf.GetIdx(), rInf.GetLen() );
1121cdf0e10cSrcweir             else
1122cdf0e10cSrcweir                 rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1123cdf0e10cSrcweir                 rInf.GetIdx(), rInf.GetLen() );
1124cdf0e10cSrcweir             if ( bSwitchH2V )
1125cdf0e10cSrcweir                 rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1126cdf0e10cSrcweir             if ( rInf.GetSpace() || rInf.GetKanaComp())
1127cdf0e10cSrcweir             {
1128cdf0e10cSrcweir                 long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1129cdf0e10cSrcweir                 sal_Bool bSpecialJust = sal_False;
1130cdf0e10cSrcweir                 if ( rInf.GetFont() && rInf.GetLen() )
1131cdf0e10cSrcweir                 {
1132cdf0e10cSrcweir                     const SwScriptInfo* pSI = rInf.GetScriptInfo();
1133cdf0e10cSrcweir                     const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1134cdf0e10cSrcweir                     ///Kana Compression
1135cdf0e10cSrcweir                     if( SW_CJK == nActual && rInf.GetKanaComp() &&
1136cdf0e10cSrcweir                         pSI && pSI->CountCompChg() &&
1137cdf0e10cSrcweir                         lcl_IsMonoSpaceFont( *(rInf.GetpOut()) ) )
1138cdf0e10cSrcweir                     {
1139cdf0e10cSrcweir                         pSI->Compress( pKernArray,rInf.GetIdx(), rInf.GetLen(),
1140cdf0e10cSrcweir                             rInf.GetKanaComp(), (sal_uInt16)aFont.GetSize().Height(),&aPos );
1141cdf0e10cSrcweir                         bSpecialJust = sal_True;
1142cdf0e10cSrcweir                     }
1143cdf0e10cSrcweir                     ///Asian Justification
1144cdf0e10cSrcweir                     if ( ( SW_CJK == nActual || SW_LATIN == nActual ) && nSpaceAdd )
1145cdf0e10cSrcweir                     {
1146cdf0e10cSrcweir                         LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1147cdf0e10cSrcweir                         if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang)
1148cdf0e10cSrcweir                         {
1149cdf0e10cSrcweir                             long nSpaceSum = nSpaceAdd;
1150cdf0e10cSrcweir                             for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1151cdf0e10cSrcweir                             {
1152cdf0e10cSrcweir                                 pKernArray[ nI ] += nSpaceSum;
1153cdf0e10cSrcweir                                 nSpaceSum += nSpaceAdd;
1154cdf0e10cSrcweir                             }
1155cdf0e10cSrcweir                             bSpecialJust = sal_True;
1156cdf0e10cSrcweir                             nSpaceAdd = 0;
1157cdf0e10cSrcweir                         }
1158cdf0e10cSrcweir                     }
1159cdf0e10cSrcweir                     long nGridAddSum = nGridWidthAdd;
1160cdf0e10cSrcweir                     for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd )
1161cdf0e10cSrcweir                     {
1162cdf0e10cSrcweir                         pKernArray[i] += nGridAddSum;
1163cdf0e10cSrcweir                     }
1164cdf0e10cSrcweir                     long nKernSum = rInf.GetKern();
1165cdf0e10cSrcweir                     if ( bSpecialJust || rInf.GetKern() )
1166cdf0e10cSrcweir                     {
1167cdf0e10cSrcweir                         for( xub_StrLen i = 0; i < rInf.GetLen(); i++, nKernSum += rInf.GetKern() )
1168cdf0e10cSrcweir                         {
1169cdf0e10cSrcweir                             if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
1170cdf0e10cSrcweir                                 nKernSum += nSpaceAdd;
1171cdf0e10cSrcweir                             pKernArray[i] += nKernSum;
1172cdf0e10cSrcweir                         }
1173cdf0e10cSrcweir                         ///With through/uderstr. Grouped style requires a blank at the end
1174cdf0e10cSrcweir                         ///of a text edition special measures:
1175cdf0e10cSrcweir                         if( bPaintBlank && rInf.GetLen() && (CH_BLANK ==
1176cdf0e10cSrcweir                             rInf.GetText().GetChar( rInf.GetIdx() + rInf.GetLen() - 1) ) )
1177cdf0e10cSrcweir                         {
1178cdf0e10cSrcweir                             ///If it concerns a singular, underlined space acts,
1179cdf0e10cSrcweir                             ///we must spend two:
1180cdf0e10cSrcweir                             if( 1 == rInf.GetLen() )
1181cdf0e10cSrcweir                             {
1182cdf0e10cSrcweir                                 pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
1183cdf0e10cSrcweir                                 rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1184cdf0e10cSrcweir                                     pKernArray, rInf.GetIdx(), 1 );
1185cdf0e10cSrcweir                             }
1186cdf0e10cSrcweir                             else
1187cdf0e10cSrcweir                             {
1188cdf0e10cSrcweir                                 pKernArray[ rInf.GetLen() - 2] += nSpaceAdd;
1189cdf0e10cSrcweir                                 rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1190cdf0e10cSrcweir                                     pKernArray, rInf.GetIdx(), rInf.GetLen() );
1191cdf0e10cSrcweir                             }
1192cdf0e10cSrcweir                         }
1193cdf0e10cSrcweir                         else
1194cdf0e10cSrcweir                         {
1195cdf0e10cSrcweir                             rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1196cdf0e10cSrcweir                                 pKernArray, rInf.GetIdx(), rInf.GetLen() );
1197cdf0e10cSrcweir                         }
1198cdf0e10cSrcweir                     }
1199cdf0e10cSrcweir                     else
1200cdf0e10cSrcweir                     {
1201cdf0e10cSrcweir                         Point aTmpPos( aPos );
1202cdf0e10cSrcweir                         xub_StrLen i;
1203cdf0e10cSrcweir                         xub_StrLen j = 0;
1204cdf0e10cSrcweir                         long nSpaceSum = 0;
1205cdf0e10cSrcweir                         for( i = 0; i < rInf.GetLen(); i++ )
1206cdf0e10cSrcweir                         {
1207cdf0e10cSrcweir                             if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx() + i) )
1208cdf0e10cSrcweir                             {
1209cdf0e10cSrcweir                                 nSpaceSum += nSpaceAdd;
1210cdf0e10cSrcweir                                 if( j < i)
1211cdf0e10cSrcweir                                     rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1212cdf0e10cSrcweir                                     rInf.GetIdx() + j, i - j );
1213cdf0e10cSrcweir                                 j = i + 1;
1214cdf0e10cSrcweir                                 pKernArray[i] = pKernArray[i] + nSpaceSum;
1215cdf0e10cSrcweir                                 aTmpPos.X() = aPos.X() + pKernArray[ i ] + nKernSum;
1216cdf0e10cSrcweir                             }
1217cdf0e10cSrcweir                         }
1218cdf0e10cSrcweir                         if( j < i )
1219cdf0e10cSrcweir                             rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1220cdf0e10cSrcweir                             rInf.GetIdx() +j , i - j );
1221cdf0e10cSrcweir                     }
1222cdf0e10cSrcweir                 }
1223cdf0e10cSrcweir             }
1224cdf0e10cSrcweir             else
1225cdf0e10cSrcweir             {
1226cdf0e10cSrcweir                 //long nKernAdd = rInf.GetKern();
1227cdf0e10cSrcweir 		long nKernAdd = 0;
1228cdf0e10cSrcweir                 long nGridAddSum = nGridWidthAdd + nKernAdd;
1229cdf0e10cSrcweir                 for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd + nKernAdd )
1230cdf0e10cSrcweir                 {
1231cdf0e10cSrcweir                     pKernArray[i] += nGridAddSum;
1232cdf0e10cSrcweir                 }
1233cdf0e10cSrcweir                 rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1234cdf0e10cSrcweir                     pKernArray, rInf.GetIdx(), rInf.GetLen() );
1235cdf0e10cSrcweir             }
1236cdf0e10cSrcweir             delete[] pKernArray;
1237cdf0e10cSrcweir             return;
1238cdf0e10cSrcweir         }
1239cdf0e10cSrcweir     }
1240cdf0e10cSrcweir 
1241cdf0e10cSrcweir     //
1242cdf0e10cSrcweir     // DIRECT PAINTING WITHOUT SCREEN ADJUSTMENT
1243cdf0e10cSrcweir     //
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir     if ( bDirectPrint )
1246cdf0e10cSrcweir     {
1247cdf0e10cSrcweir         const Fraction aTmp( 1, 1 );
1248cdf0e10cSrcweir         sal_Bool bStretch = rInf.GetWidth() && ( rInf.GetLen() > 1 ) && bPrt
1249cdf0e10cSrcweir                         && ( aTmp != rInf.GetOut().GetMapMode().GetScaleX() );
1250cdf0e10cSrcweir 
1251cdf0e10cSrcweir         if ( bSwitchL2R )
1252cdf0e10cSrcweir             rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir         if ( bSwitchH2V )
1255cdf0e10cSrcweir             rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir         // In the good old days we used to have a simple DrawText if the
1258cdf0e10cSrcweir         // output device is the printer. Now we need a DrawTextArray if
1259cdf0e10cSrcweir         // 1. KanaCompression is enabled
1260cdf0e10cSrcweir         // 2. Justified alignment
1261cdf0e10cSrcweir         // Simple kerning is handled by DrawStretchText
1262cdf0e10cSrcweir         if( rInf.GetSpace() || rInf.GetKanaComp() )
1263cdf0e10cSrcweir         {
1264cdf0e10cSrcweir             sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
1265cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1266cdf0e10cSrcweir                                        rInf.GetIdx(), rInf.GetLen() );
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir             if( bStretch )
1269cdf0e10cSrcweir             {
1270cdf0e10cSrcweir                 xub_StrLen nZwi = rInf.GetLen() - 1;
1271cdf0e10cSrcweir                 long nDiff = rInf.GetWidth() - pKernArray[ nZwi ]
1272cdf0e10cSrcweir                              - rInf.GetLen() * rInf.GetKern();
1273cdf0e10cSrcweir                 long nRest = nDiff % nZwi;
1274cdf0e10cSrcweir                 long nAdd;
1275cdf0e10cSrcweir                 if( nRest < 0 )
1276cdf0e10cSrcweir                 {
1277cdf0e10cSrcweir                     nAdd = -1;
1278cdf0e10cSrcweir                     nRest += nZwi;
1279cdf0e10cSrcweir                 }
1280cdf0e10cSrcweir                 else
1281cdf0e10cSrcweir                 {
1282cdf0e10cSrcweir                     nAdd = +1;
1283cdf0e10cSrcweir                     nRest = nZwi - nRest;
1284cdf0e10cSrcweir                 }
1285cdf0e10cSrcweir                 nDiff /= nZwi;
1286cdf0e10cSrcweir                 long nSum = nDiff;
1287cdf0e10cSrcweir                 for( xub_StrLen i = 0; i < nZwi; )
1288cdf0e10cSrcweir                 {
1289cdf0e10cSrcweir                     pKernArray[ i ] += nSum;
1290cdf0e10cSrcweir                     if( ++i == nRest )
1291cdf0e10cSrcweir                         nDiff += nAdd;
1292cdf0e10cSrcweir                     nSum += nDiff;
1293cdf0e10cSrcweir                 }
1294cdf0e10cSrcweir             }
1295cdf0e10cSrcweir 
1296cdf0e10cSrcweir             //
1297cdf0e10cSrcweir             // Modify Array for special justifications
1298cdf0e10cSrcweir             //
1299cdf0e10cSrcweir             long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1300cdf0e10cSrcweir             sal_Bool bSpecialJust = sal_False;
1301cdf0e10cSrcweir 
1302cdf0e10cSrcweir             if ( rInf.GetFont() && rInf.GetLen() )
1303cdf0e10cSrcweir             {
1304cdf0e10cSrcweir                 const SwScriptInfo* pSI = rInf.GetScriptInfo();
1305cdf0e10cSrcweir                 const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1306cdf0e10cSrcweir 
1307cdf0e10cSrcweir                 // Kana Compression
1308cdf0e10cSrcweir                 if ( SW_CJK == nActual && rInf.GetKanaComp() &&
1309cdf0e10cSrcweir                      pSI && pSI->CountCompChg() &&
1310cdf0e10cSrcweir                      lcl_IsMonoSpaceFont( rInf.GetOut() ) )
1311cdf0e10cSrcweir                 {
1312cdf0e10cSrcweir                     pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
1313cdf0e10cSrcweir                                    rInf.GetKanaComp(),
1314cdf0e10cSrcweir                                    (sal_uInt16)aFont.GetSize().Height(), &aPos );
1315cdf0e10cSrcweir                     bSpecialJust = sal_True;
1316cdf0e10cSrcweir                 }
1317cdf0e10cSrcweir 
1318cdf0e10cSrcweir                 // Asian Justification
1319cdf0e10cSrcweir                 if ( SW_CJK == nActual && nSpaceAdd )
1320cdf0e10cSrcweir                 {
1321cdf0e10cSrcweir                     LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir                     if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
1324cdf0e10cSrcweir                     {
1325cdf0e10cSrcweir                         long nSpaceSum = nSpaceAdd;
1326cdf0e10cSrcweir                         for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1327cdf0e10cSrcweir                         {
1328cdf0e10cSrcweir                             pKernArray[ nI ] += nSpaceSum;
1329cdf0e10cSrcweir                             nSpaceSum += nSpaceAdd;
1330cdf0e10cSrcweir                         }
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir                         bSpecialJust = sal_True;
1333cdf0e10cSrcweir                         nSpaceAdd = 0;
1334cdf0e10cSrcweir                     }
1335cdf0e10cSrcweir                 }
1336cdf0e10cSrcweir 
1337cdf0e10cSrcweir                 // Kashida Justification
1338cdf0e10cSrcweir                 if ( SW_CTL == nActual && nSpaceAdd )
1339cdf0e10cSrcweir                 {
1340cdf0e10cSrcweir                     if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
1341cdf0e10cSrcweir                     {
1342cdf0e10cSrcweir                         if ( pSI && pSI->CountKashida() &&
1343cdf0e10cSrcweir                             pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
1344cdf0e10cSrcweir                                                  rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
1345cdf0e10cSrcweir                         {
1346cdf0e10cSrcweir                             bSpecialJust = sal_True;
1347cdf0e10cSrcweir                             nSpaceAdd = 0;
1348cdf0e10cSrcweir                         }
1349cdf0e10cSrcweir                     }
1350cdf0e10cSrcweir                 }
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir                 // Thai Justification
1353cdf0e10cSrcweir                 if ( SW_CTL == nActual && nSpaceAdd )
1354cdf0e10cSrcweir                 {
1355cdf0e10cSrcweir                     LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
1356cdf0e10cSrcweir 
1357cdf0e10cSrcweir                     if ( LANGUAGE_THAI == aLang )
1358cdf0e10cSrcweir                     {
1359cdf0e10cSrcweir                         // Use rInf.GetSpace() because it has more precision than
1360cdf0e10cSrcweir                         // nSpaceAdd:
1361cdf0e10cSrcweir                         SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
1362cdf0e10cSrcweir                                                    rInf.GetIdx(), rInf.GetLen(),
1363cdf0e10cSrcweir                                                    rInf.GetNumberOfBlanks(),
1364cdf0e10cSrcweir                                                    rInf.GetSpace() );
1365cdf0e10cSrcweir 
1366cdf0e10cSrcweir                         // adding space to blanks is already done
1367cdf0e10cSrcweir                         bSpecialJust = sal_True;
1368cdf0e10cSrcweir                         nSpaceAdd = 0;
1369cdf0e10cSrcweir                     }
1370cdf0e10cSrcweir                 }
1371cdf0e10cSrcweir             }
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir             long nKernSum = rInf.GetKern();
1374cdf0e10cSrcweir 
1375cdf0e10cSrcweir             if ( bStretch || bPaintBlank || rInf.GetKern() || bSpecialJust )
1376cdf0e10cSrcweir             {
1377cdf0e10cSrcweir                 for( xub_StrLen i = 0; i < rInf.GetLen(); i++,
1378cdf0e10cSrcweir                      nKernSum += rInf.GetKern() )
1379cdf0e10cSrcweir                 {
1380cdf0e10cSrcweir                     if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
1381cdf0e10cSrcweir                         nKernSum += nSpaceAdd;
1382cdf0e10cSrcweir                     pKernArray[i] += nKernSum;
1383cdf0e10cSrcweir                 }
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir 				// Bei durch/unterstr. Blocksatz erfordert ein Blank am Ende
1386cdf0e10cSrcweir 				// einer Textausgabe besondere Massnahmen:
1387cdf0e10cSrcweir 				if( bPaintBlank && rInf.GetLen() && ( CH_BLANK ==
1388cdf0e10cSrcweir 					rInf.GetText().GetChar( rInf.GetIdx()+rInf.GetLen()-1 ) ) )
1389cdf0e10cSrcweir 				{
1390cdf0e10cSrcweir 					// Wenn es sich um ein singulaeres, unterstrichenes Space
1391cdf0e10cSrcweir 					// handelt, muessen wir zwei ausgeben:
1392cdf0e10cSrcweir 					if( 1 == rInf.GetLen() )
1393cdf0e10cSrcweir 					{
1394cdf0e10cSrcweir                			pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir 						rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1397cdf0e10cSrcweir 					                                 pKernArray, rInf.GetIdx(), 1 );
1398cdf0e10cSrcweir 					}
1399cdf0e10cSrcweir 					else
1400cdf0e10cSrcweir 					{
1401cdf0e10cSrcweir                         pKernArray[ rInf.GetLen() - 2 ] += nSpaceAdd;
1402cdf0e10cSrcweir                         rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1403cdf0e10cSrcweir                             pKernArray, rInf.GetIdx(), rInf.GetLen() );
1404cdf0e10cSrcweir                     }
1405cdf0e10cSrcweir                 }
1406cdf0e10cSrcweir                 else
1407cdf0e10cSrcweir                     rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1408cdf0e10cSrcweir                                                  pKernArray, rInf.GetIdx(), rInf.GetLen() );
1409cdf0e10cSrcweir             }
1410cdf0e10cSrcweir             else
1411cdf0e10cSrcweir             {
1412cdf0e10cSrcweir                 Point aTmpPos( aPos );
1413cdf0e10cSrcweir                 xub_StrLen j = 0;
1414cdf0e10cSrcweir                 xub_StrLen i;
1415cdf0e10cSrcweir                 for( i = 0; i < rInf.GetLen(); i++ )
1416cdf0e10cSrcweir                 {
1417cdf0e10cSrcweir                     if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx()+i ) )
1418cdf0e10cSrcweir                     {
1419cdf0e10cSrcweir                         nKernSum += nSpaceAdd;
1420cdf0e10cSrcweir                         if( j < i )
1421cdf0e10cSrcweir                         rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1422cdf0e10cSrcweir                                                 rInf.GetIdx() + j, i - j );
1423cdf0e10cSrcweir                         j = i + 1;
1424cdf0e10cSrcweir                         SwTwips nAdd = pKernArray[ i ] + nKernSum;
1425cdf0e10cSrcweir                         if ( ( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ) == nMode )
1426cdf0e10cSrcweir                             nAdd *= -1;
1427cdf0e10cSrcweir                         aTmpPos.X() = aPos.X() + nAdd;
1428cdf0e10cSrcweir                     }
1429cdf0e10cSrcweir                 }
1430cdf0e10cSrcweir                 if( j < i )
1431cdf0e10cSrcweir                     rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1432cdf0e10cSrcweir                                             rInf.GetIdx() + j, i - j );
1433cdf0e10cSrcweir             }
1434cdf0e10cSrcweir             delete[] pKernArray;
1435cdf0e10cSrcweir         }
1436cdf0e10cSrcweir         else if( bStretch )
1437cdf0e10cSrcweir         {
1438cdf0e10cSrcweir             long nTmpWidth = rInf.GetWidth();
1439cdf0e10cSrcweir             if( rInf.GetKern() && rInf.GetLen() && nTmpWidth > rInf.GetKern() )
1440cdf0e10cSrcweir                 nTmpWidth -= rInf.GetKern();
1441cdf0e10cSrcweir             rInf.GetOut().DrawStretchText( aPos, nTmpWidth,
1442cdf0e10cSrcweir                                            rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
1443cdf0e10cSrcweir         }
1444cdf0e10cSrcweir         else if( rInf.GetKern() )
1445cdf0e10cSrcweir         {
1446cdf0e10cSrcweir             const long nTmpWidth = GetTextSize( rInf ).Width();
1447cdf0e10cSrcweir 
1448cdf0e10cSrcweir             const Color aSaveColor( pTmpFont->GetColor() );
1449cdf0e10cSrcweir             const sal_Bool bColorChanged = rInf.ApplyAutoColor( pTmpFont );
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir             if( bColorChanged )
1452cdf0e10cSrcweir             {
1453cdf0e10cSrcweir                 if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
1454cdf0e10cSrcweir                     rInf.GetOut().SetFont( *pTmpFont );
1455cdf0e10cSrcweir                 pTmpFont->SetColor( aSaveColor );
1456cdf0e10cSrcweir             }
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir             rInf.GetOut().DrawStretchText( aPos, (sal_uInt16)nTmpWidth,
1459cdf0e10cSrcweir                                            rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
1460cdf0e10cSrcweir         }
1461cdf0e10cSrcweir         else
1462cdf0e10cSrcweir             rInf.GetOut().DrawText( aPos, rInf.GetText(),
1463cdf0e10cSrcweir                                     rInf.GetIdx(), rInf.GetLen() );
1464cdf0e10cSrcweir     }
1465cdf0e10cSrcweir 
1466cdf0e10cSrcweir     //
1467cdf0e10cSrcweir     // PAINTING WITH FORMATTING DEVICE/SCREEN ADJUSTMENT
1468cdf0e10cSrcweir     //
1469cdf0e10cSrcweir 
1470cdf0e10cSrcweir     else
1471cdf0e10cSrcweir     {
1472cdf0e10cSrcweir         const String* pStr = &rInf.GetText();
1473cdf0e10cSrcweir         String aStr( aEmptyStr );
1474cdf0e10cSrcweir         sal_Bool bBullet = rInf.GetBullet();
1475cdf0e10cSrcweir         if( bSymbol )
1476cdf0e10cSrcweir             bBullet = sal_False;
1477cdf0e10cSrcweir         sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
1478cdf0e10cSrcweir         CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
1479cdf0e10cSrcweir         long nScrPos;
1480cdf0e10cSrcweir 
1481cdf0e10cSrcweir         // get screen array
1482cdf0e10cSrcweir         sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
1483cdf0e10cSrcweir         rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
1484cdf0e10cSrcweir                                     rInf.GetIdx(), rInf.GetLen() );
1485cdf0e10cSrcweir 
1486cdf0e10cSrcweir         // OLE: no printer available
1487cdf0e10cSrcweir         // ASSERT( pPrinter, "DrawText needs pPrinter" )
1488cdf0e10cSrcweir         if ( pPrinter )
1489cdf0e10cSrcweir         {
1490cdf0e10cSrcweir             // pTmpFont has already been set as current font for rInf.GetOut()
1491cdf0e10cSrcweir             if ( pPrinter != rInf.GetpOut() || pTmpFont != pPrtFont )
1492cdf0e10cSrcweir             {
1493cdf0e10cSrcweir                 if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1494cdf0e10cSrcweir                     pPrinter->SetFont( *pPrtFont );
1495cdf0e10cSrcweir             }
1496cdf0e10cSrcweir             pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),
1497cdf0e10cSrcweir                                     rInf.GetLen() );
1498cdf0e10cSrcweir         }
1499cdf0e10cSrcweir         else
1500cdf0e10cSrcweir         {
1501cdf0e10cSrcweir //            sal_Bool bRestore = sal_False;
1502cdf0e10cSrcweir //            MapMode aOld( rInf.GetOut().GetMapMode() );
1503cdf0e10cSrcweir //                if( rInf.GetZoom().GetNumerator() &&
1504cdf0e10cSrcweir //                        rInf.GetZoom() != aOld.GetScaleX() )
1505cdf0e10cSrcweir //                {
1506cdf0e10cSrcweir //                        MapMode aNew( aOld );
1507cdf0e10cSrcweir //                        aNew.SetScaleX( rInf.GetZoom() );
1508cdf0e10cSrcweir //                        aNew.SetScaleY( rInf.GetZoom() );
1509cdf0e10cSrcweir //                        rInf.GetOut().SetMapMode( aNew );
1510cdf0e10cSrcweir //                        bRestore = sal_True;
1511cdf0e10cSrcweir //                }
1512cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1513cdf0e10cSrcweir                                         rInf.GetIdx(), rInf.GetLen() );
1514cdf0e10cSrcweir //            if( bRestore )
1515cdf0e10cSrcweir //                rInf.GetOut().SetMapMode( aOld );
1516cdf0e10cSrcweir         }
1517cdf0e10cSrcweir 
1518cdf0e10cSrcweir         //
1519cdf0e10cSrcweir         // Modify Printer and ScreenArrays for special justifications
1520cdf0e10cSrcweir         //
1521cdf0e10cSrcweir         long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1522cdf0e10cSrcweir         bool bNoHalfSpace = false;
1523cdf0e10cSrcweir 
1524cdf0e10cSrcweir         if ( rInf.GetFont() && rInf.GetLen() )
1525cdf0e10cSrcweir         {
1526cdf0e10cSrcweir             const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1527cdf0e10cSrcweir             const SwScriptInfo* pSI = rInf.GetScriptInfo();
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir             // Kana Compression
1530cdf0e10cSrcweir             if ( SW_CJK == nActual && rInf.GetKanaComp() &&
1531cdf0e10cSrcweir                  pSI && pSI->CountCompChg() &&
1532cdf0e10cSrcweir                  lcl_IsMonoSpaceFont( rInf.GetOut() ) )
1533cdf0e10cSrcweir             {
1534cdf0e10cSrcweir                 Point aTmpPos( aPos );
1535cdf0e10cSrcweir                 pSI->Compress( pScrArray, rInf.GetIdx(), rInf.GetLen(),
1536cdf0e10cSrcweir                                rInf.GetKanaComp(),
1537cdf0e10cSrcweir                                (sal_uInt16)aFont.GetSize().Height(), &aTmpPos );
1538cdf0e10cSrcweir                 pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
1539cdf0e10cSrcweir                                rInf.GetKanaComp(),
1540cdf0e10cSrcweir                                (sal_uInt16)aFont.GetSize().Height(), &aPos );
1541cdf0e10cSrcweir             }
1542cdf0e10cSrcweir 
1543cdf0e10cSrcweir             // Asian Justification
1544cdf0e10cSrcweir             if ( SW_CJK == nActual && nSpaceAdd )
1545cdf0e10cSrcweir             {
1546cdf0e10cSrcweir                 LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1547cdf0e10cSrcweir 
1548cdf0e10cSrcweir                 if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
1549cdf0e10cSrcweir                 {
1550cdf0e10cSrcweir                     long nSpaceSum = nSpaceAdd;
1551cdf0e10cSrcweir                     for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1552cdf0e10cSrcweir                     {
1553cdf0e10cSrcweir                         pKernArray[ nI ] += nSpaceSum;
1554cdf0e10cSrcweir                         pScrArray[ nI ] += nSpaceSum;
1555cdf0e10cSrcweir                         nSpaceSum += nSpaceAdd;
1556cdf0e10cSrcweir                     }
1557cdf0e10cSrcweir 
1558cdf0e10cSrcweir                     nSpaceAdd = 0;
1559cdf0e10cSrcweir                 }
1560cdf0e10cSrcweir             }
1561cdf0e10cSrcweir 
1562cdf0e10cSrcweir             // Kashida Justification
1563cdf0e10cSrcweir             if ( SW_CTL == nActual && nSpaceAdd )
1564cdf0e10cSrcweir             {
1565cdf0e10cSrcweir                 if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
1566cdf0e10cSrcweir                 {
1567cdf0e10cSrcweir                     if ( pSI && pSI->CountKashida() &&
1568cdf0e10cSrcweir                          pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
1569cdf0e10cSrcweir                                               rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
1570cdf0e10cSrcweir                         nSpaceAdd = 0;
1571cdf0e10cSrcweir                     else
1572cdf0e10cSrcweir                         bNoHalfSpace = true;
1573cdf0e10cSrcweir                 }
1574cdf0e10cSrcweir             }
1575cdf0e10cSrcweir 
1576cdf0e10cSrcweir             // Thai Justification
1577cdf0e10cSrcweir             if ( SW_CTL == nActual && nSpaceAdd )
1578cdf0e10cSrcweir             {
1579cdf0e10cSrcweir                 LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
1580cdf0e10cSrcweir 
1581cdf0e10cSrcweir                 if ( LANGUAGE_THAI == aLang )
1582cdf0e10cSrcweir                 {
1583cdf0e10cSrcweir                     SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray,
1584cdf0e10cSrcweir                                                pScrArray, rInf.GetIdx(),
1585cdf0e10cSrcweir                                                rInf.GetLen(),
1586cdf0e10cSrcweir                                                rInf.GetNumberOfBlanks(),
1587cdf0e10cSrcweir                                                rInf.GetSpace() );
1588cdf0e10cSrcweir 
1589cdf0e10cSrcweir                     // adding space to blanks is already done
1590cdf0e10cSrcweir                     nSpaceAdd = 0;
1591cdf0e10cSrcweir                 }
1592cdf0e10cSrcweir             }
1593cdf0e10cSrcweir         }
1594cdf0e10cSrcweir 
1595cdf0e10cSrcweir         nScrPos = pScrArray[ 0 ];
1596cdf0e10cSrcweir 
1597cdf0e10cSrcweir         if( bBullet )
1598cdf0e10cSrcweir         {
1599cdf0e10cSrcweir             // !!! HACK !!!
1600cdf0e10cSrcweir             // The Arabic layout engine requires some context of the string
1601cdf0e10cSrcweir             // which should be painted.
1602cdf0e10cSrcweir             xub_StrLen nCopyStart = rInf.GetIdx();
1603cdf0e10cSrcweir             if ( nCopyStart )
1604cdf0e10cSrcweir                 --nCopyStart;
1605cdf0e10cSrcweir 
1606cdf0e10cSrcweir             xub_StrLen nCopyLen = rInf.GetLen();
1607cdf0e10cSrcweir             if ( nCopyStart + nCopyLen < rInf.GetText().Len() )
1608cdf0e10cSrcweir                 ++nCopyLen;
1609cdf0e10cSrcweir 
1610cdf0e10cSrcweir             aStr = rInf.GetText().Copy( nCopyStart, nCopyLen );
1611cdf0e10cSrcweir             pStr = &aStr;
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir             for( xub_StrLen i = 0; i < aStr.Len(); ++i )
1614cdf0e10cSrcweir                 if( CH_BLANK == aStr.GetChar( i ) )
1615cdf0e10cSrcweir                     aStr.SetChar( i, CH_BULLET );
1616cdf0e10cSrcweir         }
1617cdf0e10cSrcweir 
1618cdf0e10cSrcweir 		xub_StrLen nCnt = rInf.GetText().Len();
1619cdf0e10cSrcweir 		if ( nCnt < rInf.GetIdx() )
1620cdf0e10cSrcweir 			nCnt = 0;
1621cdf0e10cSrcweir 		else
1622cdf0e10cSrcweir 			nCnt = nCnt - rInf.GetIdx();
1623cdf0e10cSrcweir 		nCnt = Min( nCnt, rInf.GetLen() );
1624cdf0e10cSrcweir 		long nKernSum = rInf.GetKern();
1625cdf0e10cSrcweir 		xub_Unicode cChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
1626cdf0e10cSrcweir 
1627cdf0e10cSrcweir 		// Wenn es sich um ein singulaeres, unterstrichenes Space
1628cdf0e10cSrcweir 		// im Blocksatz handelt, muessen wir zwei ausgeben:
1629cdf0e10cSrcweir 		if ( ( nCnt == 1 ) && rInf.GetSpace() && ( cChPrev == CH_BLANK ) )
1630cdf0e10cSrcweir 		{
1631cdf0e10cSrcweir             pKernArray[0] = rInf.GetWidth() +
1632cdf0e10cSrcweir                             rInf.GetKern() +
1633cdf0e10cSrcweir                           ( rInf.GetSpace() / SPACING_PRECISION_FACTOR );
1634cdf0e10cSrcweir 
1635cdf0e10cSrcweir             if ( bSwitchL2R )
1636cdf0e10cSrcweir                 rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1637cdf0e10cSrcweir 
1638cdf0e10cSrcweir             if ( bSwitchH2V )
1639cdf0e10cSrcweir                 rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir             rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1642cdf0e10cSrcweir                                          pKernArray, rInf.GetIdx(), 1 );
1643cdf0e10cSrcweir 			if( bBullet )
1644cdf0e10cSrcweir 				rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray,
1645cdf0e10cSrcweir                                              rInf.GetIdx() ? 1 : 0, 1 );
1646cdf0e10cSrcweir         }
1647cdf0e10cSrcweir         else
1648cdf0e10cSrcweir         {
1649cdf0e10cSrcweir             xub_Unicode nCh;
1650cdf0e10cSrcweir 
1651cdf0e10cSrcweir             // Bei Pairkerning waechst der Printereinfluss auf die Positionierung
1652cdf0e10cSrcweir             sal_uInt16 nMul = 3;
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir             if ( pPrtFont->GetKerning() )
1655cdf0e10cSrcweir                 nMul = 1;
1656cdf0e10cSrcweir 
1657cdf0e10cSrcweir             const sal_uInt16 nDiv = nMul+1;
1658cdf0e10cSrcweir 
1659cdf0e10cSrcweir             // In nSpaceSum wird der durch Blocksatz auf die Spaces verteilte
1660cdf0e10cSrcweir             // Zwischenraum aufsummiert.
1661cdf0e10cSrcweir             // Die Spaces selbst werden im Normalfall in der Mitte des
1662cdf0e10cSrcweir             // Zwischenraums positioniert, deshalb die nSpace/2-Mimik.
1663cdf0e10cSrcweir             // Bei wortweiser Unterstreichung muessen sie am Anfang des
1664cdf0e10cSrcweir             // Zwischenraums stehen, damit dieser nicht unterstrichen wird.
1665cdf0e10cSrcweir             // Ein Space am Anfang oder am Ende des Textes muss allerdings
1666cdf0e10cSrcweir             // vor bzw. hinter den kompletten Zwischenraum gesetzt werden,
1667cdf0e10cSrcweir             // sonst wuerde das Durch-/Unterstreichen Luecken aufweisen.
1668cdf0e10cSrcweir             long nSpaceSum = 0;
1669cdf0e10cSrcweir             // in word line mode and for Arabic, we disable the half space trick:
1670cdf0e10cSrcweir             const long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2;
1671cdf0e10cSrcweir             const long nOtherHalf = nSpaceAdd - nHalfSpace;
1672cdf0e10cSrcweir             if ( nSpaceAdd && ( cChPrev == CH_BLANK ) )
1673cdf0e10cSrcweir                 nSpaceSum = nHalfSpace;
1674cdf0e10cSrcweir             for ( xub_StrLen i=1; i<nCnt; ++i,nKernSum += rInf.GetKern() )
1675cdf0e10cSrcweir             {
1676cdf0e10cSrcweir                 nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
1677cdf0e10cSrcweir 
1678cdf0e10cSrcweir                 ASSERT( pScrArray, "Where is the screen array?" )
1679cdf0e10cSrcweir                 long nScr;
1680cdf0e10cSrcweir                 nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
1681cdf0e10cSrcweir 
1682cdf0e10cSrcweir                 // Wenn vor uns ein (Ex-)SPACE ist, positionieren wir uns optimal,
1683cdf0e10cSrcweir                 // d.h. unseren rechten Rand auf die 100% Druckerposition,
1684cdf0e10cSrcweir                 // sind wir sogar selbst ein Ex-SPACE, so positionieren wir uns
1685cdf0e10cSrcweir                 // linksbuendig zur Druckerposition.
1686cdf0e10cSrcweir                 if ( nCh == CH_BLANK )
1687cdf0e10cSrcweir                 {
1688cdf0e10cSrcweir #ifdef FONT_TEST_DEBUG
1689cdf0e10cSrcweir                     lcl_Pos( 3, nScrPos, nScr, pKernArray[i-1], pKernArray[i] );
1690cdf0e10cSrcweir #else
1691cdf0e10cSrcweir                     nScrPos = pKernArray[i-1] + nScr;
1692cdf0e10cSrcweir #endif
1693cdf0e10cSrcweir                     if ( cChPrev == CH_BLANK )
1694cdf0e10cSrcweir                         nSpaceSum += nOtherHalf;
1695cdf0e10cSrcweir                     if ( i + 1 == nCnt )
1696cdf0e10cSrcweir                         nSpaceSum += nSpaceAdd;
1697cdf0e10cSrcweir                     else
1698cdf0e10cSrcweir                         nSpaceSum += nHalfSpace;
1699cdf0e10cSrcweir                 }
1700cdf0e10cSrcweir                 else
1701cdf0e10cSrcweir                 {
1702cdf0e10cSrcweir                     if ( cChPrev == CH_BLANK )
1703cdf0e10cSrcweir                     {
1704cdf0e10cSrcweir #ifdef FONT_TEST_DEBUG
1705cdf0e10cSrcweir                         lcl_Pos( 6, nScrPos, nScr, pKernArray[i-1], pKernArray[i] );
1706cdf0e10cSrcweir #else
1707cdf0e10cSrcweir                         nScrPos = pKernArray[i-1] + nScr;
1708cdf0e10cSrcweir #endif
1709cdf0e10cSrcweir                         // kein Pixel geht verloren:
1710cdf0e10cSrcweir                         nSpaceSum += nOtherHalf;
1711cdf0e10cSrcweir                     }
1712cdf0e10cSrcweir                     else if ( cChPrev == '-' )
1713cdf0e10cSrcweir #ifdef FONT_TEST_DEBUG
1714cdf0e10cSrcweir                         lcl_Pos( 6, nScrPos, nScr, pKernArray[i-1], pKernArray[i] );
1715cdf0e10cSrcweir #else
1716cdf0e10cSrcweir                         nScrPos = pKernArray[i-1] + nScr;
1717cdf0e10cSrcweir #endif
1718cdf0e10cSrcweir                     else
1719cdf0e10cSrcweir                     {
1720cdf0e10cSrcweir #ifdef FONT_TEST_DEBUG
1721cdf0e10cSrcweir                         lcl_Pos( 0, nScrPos, nScr, pKernArray[i-1], pKernArray[i] );
1722cdf0e10cSrcweir #else
1723cdf0e10cSrcweir                         nScrPos += nScr;
1724cdf0e10cSrcweir                         nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
1725cdf0e10cSrcweir #endif
1726cdf0e10cSrcweir                     }
1727cdf0e10cSrcweir                 }
1728cdf0e10cSrcweir                 cChPrev = nCh;
1729cdf0e10cSrcweir                 pKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum;
1730cdf0e10cSrcweir                 // In word line mode and for Arabic, we disabled the half space trick. If a portion
1731cdf0e10cSrcweir                 // ends with a blank, the full nSpaceAdd value has been added to the character in
1732cdf0e10cSrcweir                 // front of the blank. This leads to painting artifacts, therefore we remove the
1733cdf0e10cSrcweir                 // nSpaceAdd value again:
1734cdf0e10cSrcweir 				if ( (bNoHalfSpace || pPrtFont->IsWordLineMode()) && i+1 == nCnt && nCh == CH_BLANK )
1735cdf0e10cSrcweir 					pKernArray[i-1] = pKernArray[i-1] - nSpaceAdd;
1736cdf0e10cSrcweir             }
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir             // the layout engine requires the total width of the output
1739cdf0e10cSrcweir             pKernArray[ rInf.GetLen() - 1 ] += nKernSum + nSpaceSum;
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir             if( rInf.GetGreyWave() )
1742cdf0e10cSrcweir             {
1743cdf0e10cSrcweir                 if( rInf.GetLen() )
1744cdf0e10cSrcweir                 {
1745cdf0e10cSrcweir                     long nHght = rInf.GetOut().LogicToPixel(
1746cdf0e10cSrcweir                                     pPrtFont->GetSize() ).Height();
1747cdf0e10cSrcweir                     if( WRONG_SHOW_MIN < nHght )
1748cdf0e10cSrcweir                     {
1749cdf0e10cSrcweir                         if ( rInf.GetOut().GetConnectMetaFile() )
1750cdf0e10cSrcweir                             rInf.GetOut().Push();
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir                         sal_uInt16 nWave =
1753cdf0e10cSrcweir                             WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
1754cdf0e10cSrcweir                             ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL :
1755cdf0e10cSrcweir                             WAVE_FLAT );
1756cdf0e10cSrcweir                         Color aCol( rInf.GetOut().GetLineColor() );
1757cdf0e10cSrcweir                         sal_Bool bColSave = aCol != *pWaveCol;
1758cdf0e10cSrcweir                         if ( bColSave )
1759cdf0e10cSrcweir                             rInf.GetOut().SetLineColor( *pWaveCol );
1760cdf0e10cSrcweir 
1761cdf0e10cSrcweir                         Point aEnd;
1762cdf0e10cSrcweir                         long nKernVal = pKernArray[ sal_uInt16( rInf.GetLen() - 1 ) ];
1763cdf0e10cSrcweir 
1764cdf0e10cSrcweir                         sal_uInt16 nDir = bBidiPor ?
1765cdf0e10cSrcweir                                         1800 :
1766cdf0e10cSrcweir                                         UnMapDirection(
1767cdf0e10cSrcweir                                             GetFont()->GetOrientation(),
1768cdf0e10cSrcweir                                             bSwitchH2V );
1769cdf0e10cSrcweir 
1770cdf0e10cSrcweir                         switch ( nDir )
1771cdf0e10cSrcweir                         {
1772cdf0e10cSrcweir                         case 0 :
1773cdf0e10cSrcweir                             aEnd.X() = rInf.GetPos().X() + nKernVal;
1774cdf0e10cSrcweir                             aEnd.Y() = rInf.GetPos().Y();
1775cdf0e10cSrcweir                             break;
1776cdf0e10cSrcweir                         case 900 :
1777cdf0e10cSrcweir                             aEnd.X() = rInf.GetPos().X();
1778cdf0e10cSrcweir                             aEnd.Y() = rInf.GetPos().Y() - nKernVal;
1779cdf0e10cSrcweir                             break;
1780cdf0e10cSrcweir                         case 1800 :
1781cdf0e10cSrcweir                             aEnd.X() = rInf.GetPos().X() - nKernVal;
1782cdf0e10cSrcweir                             aEnd.Y() = rInf.GetPos().Y();
1783cdf0e10cSrcweir                             break;
1784cdf0e10cSrcweir                         case 2700 :
1785cdf0e10cSrcweir                             aEnd.X() = rInf.GetPos().X();
1786cdf0e10cSrcweir                             aEnd.Y() = rInf.GetPos().Y() + nKernVal;
1787cdf0e10cSrcweir                             break;
1788cdf0e10cSrcweir                         }
1789cdf0e10cSrcweir 
1790cdf0e10cSrcweir                         Point aCurrPos( rInf.GetPos() );
1791cdf0e10cSrcweir 
1792cdf0e10cSrcweir                         if ( bSwitchL2R )
1793cdf0e10cSrcweir                         {
1794cdf0e10cSrcweir                             rInf.GetFrm()->SwitchLTRtoRTL( aCurrPos );
1795cdf0e10cSrcweir                             rInf.GetFrm()->SwitchLTRtoRTL( aEnd );
1796cdf0e10cSrcweir                         }
1797cdf0e10cSrcweir 
1798cdf0e10cSrcweir                         if ( bSwitchH2V )
1799cdf0e10cSrcweir                         {
1800cdf0e10cSrcweir                             rInf.GetFrm()->SwitchHorizontalToVertical( aCurrPos );
1801cdf0e10cSrcweir                             rInf.GetFrm()->SwitchHorizontalToVertical( aEnd );
1802cdf0e10cSrcweir                         }
1803cdf0e10cSrcweir                         rInf.GetOut().DrawWaveLine( aCurrPos, aEnd, nWave );
1804cdf0e10cSrcweir 
1805cdf0e10cSrcweir                         if ( bColSave )
1806cdf0e10cSrcweir                             rInf.GetOut().SetLineColor( aCol );
1807cdf0e10cSrcweir 
1808cdf0e10cSrcweir                         if ( rInf.GetOut().GetConnectMetaFile() )
1809cdf0e10cSrcweir                             rInf.GetOut().Pop();
1810cdf0e10cSrcweir                     }
1811cdf0e10cSrcweir                 }
1812cdf0e10cSrcweir             }
1813cdf0e10cSrcweir             else if( !bSymbol && rInf.GetLen() )
1814cdf0e10cSrcweir             {
1815cdf0e10cSrcweir 				// anything to do?
1816cdf0e10cSrcweir 				if (rInf.GetWrong() || rInf.GetGrammarCheck() || rInf.GetSmartTags())
1817cdf0e10cSrcweir 				{
1818cdf0e10cSrcweir 					CalcLinePosData aCalcLinePosData(rInf, *GetFont(),
1819cdf0e10cSrcweir 							nCnt, bSwitchH2V, bSwitchL2R,
1820cdf0e10cSrcweir 							nHalfSpace, pKernArray, bBidiPor);
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir                     SwForbidden aForbidden;
1823cdf0e10cSrcweir 					// draw line for smart tag data
1824cdf0e10cSrcweir 					lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetSmartTags(), aCalcLinePosData, Size() );
1825cdf0e10cSrcweir                     // draw wave line for spell check errors
1826cdf0e10cSrcweir                     // draw them BEFORE the grammar check lines to 'override' the latter in case of conflict.
1827cdf0e10cSrcweir                     // reason: some grammar errors can only be found if spelling errors are fixed,
1828cdf0e10cSrcweir                     // therefore we don't want the user to miss a spelling error.
1829cdf0e10cSrcweir                     lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetWrong(), aCalcLinePosData, pPrtFont->GetSize() );
1830cdf0e10cSrcweir 					// draw wave line for grammar check errors
1831cdf0e10cSrcweir 					lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetGrammarCheck(), aCalcLinePosData, pPrtFont->GetSize() );
1832cdf0e10cSrcweir 				}
1833cdf0e10cSrcweir             }
1834cdf0e10cSrcweir 
1835cdf0e10cSrcweir             xub_StrLen nOffs = 0;
1836cdf0e10cSrcweir             xub_StrLen nLen = rInf.GetLen();
1837cdf0e10cSrcweir #ifdef COMING_SOON
1838cdf0e10cSrcweir             if( aPos.X() < rInf.GetLeft() )
1839cdf0e10cSrcweir             {
1840cdf0e10cSrcweir                 while( nOffs < nLen &&
1841cdf0e10cSrcweir                     aPos.X() + pKernArray[ nOffs ] < rInf.GetLeft() )
1842cdf0e10cSrcweir                     ++nOffs;
1843cdf0e10cSrcweir                 if( nOffs < nLen )
1844cdf0e10cSrcweir                 {
1845cdf0e10cSrcweir                     --nLen;
1846cdf0e10cSrcweir                     while( nLen > nOffs &&
1847cdf0e10cSrcweir                         aPos.X() + pKernArray[ nLen ] > rInf.GetRight() )
1848cdf0e10cSrcweir                         --nLen;
1849cdf0e10cSrcweir                     ++nLen;
1850cdf0e10cSrcweir                     if( nOffs )
1851cdf0e10cSrcweir                         --nOffs;
1852cdf0e10cSrcweir                 }
1853cdf0e10cSrcweir                 if( nOffs )
1854cdf0e10cSrcweir                 {
1855cdf0e10cSrcweir                     long nDiff = pKernArray[ nOffs - 1 ];
1856cdf0e10cSrcweir                     aPos.X() += nDiff;
1857cdf0e10cSrcweir                     for( xub_StrLen nX = nOffs; nX < nLen; ++nX )
1858cdf0e10cSrcweir                         pKernArray[ nX ] -= nDiff;
1859cdf0e10cSrcweir                 }
1860cdf0e10cSrcweir             }
1861cdf0e10cSrcweir #endif
1862cdf0e10cSrcweir             if( nOffs < nLen )
1863cdf0e10cSrcweir             {
1864cdf0e10cSrcweir                 // If we paint bullets instead of spaces, we use a copy of
1865cdf0e10cSrcweir                 // the paragraph string. For the layout engine, the copy
1866cdf0e10cSrcweir                 // of the string has to be an environment of the range which
1867cdf0e10cSrcweir                 // is painted
1868cdf0e10cSrcweir                 xub_StrLen nTmpIdx = bBullet ?
1869cdf0e10cSrcweir                                               ( rInf.GetIdx() ? 1 : 0 ) :
1870cdf0e10cSrcweir                                               rInf.GetIdx();
1871cdf0e10cSrcweir 
1872cdf0e10cSrcweir                 if ( bSwitchL2R )
1873cdf0e10cSrcweir                     rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1874cdf0e10cSrcweir 
1875cdf0e10cSrcweir                 if ( bSwitchH2V )
1876cdf0e10cSrcweir                     rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1877cdf0e10cSrcweir 
1878cdf0e10cSrcweir                 rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
1879cdf0e10cSrcweir                                              nTmpIdx + nOffs , nLen - nOffs );
1880cdf0e10cSrcweir             }
1881cdf0e10cSrcweir         }
1882cdf0e10cSrcweir         delete[] pScrArray;
1883cdf0e10cSrcweir         delete[] pKernArray;
1884cdf0e10cSrcweir     }
1885cdf0e10cSrcweir }
1886cdf0e10cSrcweir 
1887cdf0e10cSrcweir 
1888cdf0e10cSrcweir // Optimierung war fuer DrawText() ausgeschaltet
1889cdf0e10cSrcweir #ifdef _MSC_VER
1890cdf0e10cSrcweir #pragma optimize("",on)
1891cdf0e10cSrcweir #endif
1892cdf0e10cSrcweir 
1893cdf0e10cSrcweir 
1894cdf0e10cSrcweir /*************************************************************************
1895cdf0e10cSrcweir  *
1896cdf0e10cSrcweir  *	Size SwFntObj::GetTextSize( const OutputDevice *pOut, const String &rTxt,
1897cdf0e10cSrcweir  *			 const sal_uInt16 nIdx, const sal_uInt16 nLen, const short nKern = 0 );
1898cdf0e10cSrcweir  *
1899cdf0e10cSrcweir  *	Ersterstellung		AMA 16. Dez. 94
1900cdf0e10cSrcweir  *	Letzte Aenderung	AMA 16. Dez. 94
1901cdf0e10cSrcweir  *
1902cdf0e10cSrcweir  *  Beschreibung: ermittelt die TextSize (des Druckers)
1903cdf0e10cSrcweir  *
1904cdf0e10cSrcweir  *************************************************************************/
1905cdf0e10cSrcweir 
GetTextSize(SwDrawTextInfo & rInf)1906cdf0e10cSrcweir Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
1907cdf0e10cSrcweir {
1908cdf0e10cSrcweir 	Size aTxtSize;
1909cdf0e10cSrcweir 	const xub_StrLen nLn = ( STRING_LEN != rInf.GetLen() ) ? rInf.GetLen() :
1910cdf0e10cSrcweir 						   rInf.GetText().Len();
1911cdf0e10cSrcweir 
1912cdf0e10cSrcweir     // be sure to have the correct layout mode at the printer
1913cdf0e10cSrcweir     if ( pPrinter )
1914cdf0e10cSrcweir     {
1915cdf0e10cSrcweir         pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
1916cdf0e10cSrcweir         pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
1917cdf0e10cSrcweir     }
1918cdf0e10cSrcweir 
1919cdf0e10cSrcweir     if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
1920cdf0e10cSrcweir          SW_CJK == rInf.GetFont()->GetActual() )
1921cdf0e10cSrcweir     {
1922cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
1923cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
1924cdf0e10cSrcweir         {
1925cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1926cdf0e10cSrcweir             const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
1927cdf0e10cSrcweir 
1928cdf0e10cSrcweir             OutputDevice* pOutDev;
1929cdf0e10cSrcweir 
1930cdf0e10cSrcweir             if ( pPrinter )
1931cdf0e10cSrcweir             {
1932cdf0e10cSrcweir                 if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1933cdf0e10cSrcweir                     pPrinter->SetFont(*pPrtFont);
1934cdf0e10cSrcweir                 pOutDev = pPrinter;
1935cdf0e10cSrcweir             }
1936cdf0e10cSrcweir             else
1937cdf0e10cSrcweir                 pOutDev = rInf.GetpOut();
1938cdf0e10cSrcweir 
1939cdf0e10cSrcweir             aTxtSize.Width() =
1940cdf0e10cSrcweir                     pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
1941cdf0e10cSrcweir 
1942cdf0e10cSrcweir             ASSERT( !rInf.GetShell() ||
1943cdf0e10cSrcweir                     ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
1944cdf0e10cSrcweir                 "Leading values should be already calculated" )
1945cdf0e10cSrcweir             aTxtSize.Height() = pOutDev->GetTextHeight() +
1946cdf0e10cSrcweir                                 GetFontLeading( rInf.GetShell(), rInf.GetOut() );
1947cdf0e10cSrcweir 
1948cdf0e10cSrcweir             long nWidthPerChar = aTxtSize.Width() / nLn;
1949cdf0e10cSrcweir 
1950cdf0e10cSrcweir             const sal_uLong i = nWidthPerChar ?
1951cdf0e10cSrcweir                             ( nWidthPerChar - 1 ) / nGridWidth + 1:
1952cdf0e10cSrcweir                             1;
1953cdf0e10cSrcweir 
1954cdf0e10cSrcweir             aTxtSize.Width() = i * nGridWidth * nLn;
1955cdf0e10cSrcweir             rInf.SetKanaDiff( 0 );
1956cdf0e10cSrcweir             return aTxtSize;
1957cdf0e10cSrcweir         }
1958cdf0e10cSrcweir     }
1959cdf0e10cSrcweir 
1960cdf0e10cSrcweir     //for textgrid refactor
1961cdf0e10cSrcweir     if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
1962cdf0e10cSrcweir          SW_CJK == rInf.GetFont()->GetActual() )
1963cdf0e10cSrcweir     {
1964cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
1965cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
1966cdf0e10cSrcweir         {
1967cdf0e10cSrcweir             const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
1968cdf0e10cSrcweir 
1969cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1970cdf0e10cSrcweir             long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
1971cdf0e10cSrcweir             if( SW_LATIN == rInf.GetFont()->GetActual() )
1972cdf0e10cSrcweir                 nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
1973cdf0e10cSrcweir             else
1974cdf0e10cSrcweir                 nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
1975cdf0e10cSrcweir             OutputDevice* pOutDev;
1976cdf0e10cSrcweir             if ( pPrinter )
1977cdf0e10cSrcweir             {
1978cdf0e10cSrcweir                 if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1979cdf0e10cSrcweir                     pPrinter->SetFont(*pPrtFont);
1980cdf0e10cSrcweir                 pOutDev = pPrinter;
1981cdf0e10cSrcweir             }
1982cdf0e10cSrcweir             else
1983cdf0e10cSrcweir                 pOutDev = rInf.GetpOut();
1984cdf0e10cSrcweir             aTxtSize.Width() = pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
1985cdf0e10cSrcweir             aTxtSize.Height() = pOutDev->GetTextHeight() +
1986cdf0e10cSrcweir                                 GetFontLeading( rInf.GetShell(), rInf.GetOut() );
1987cdf0e10cSrcweir             aTxtSize.Width() += (nLn) * long( nGridWidthAdd );
1988cdf0e10cSrcweir             //if ( rInf.GetKern() && nLn )
1989cdf0e10cSrcweir             //    aTxtSize.Width() += ( nLn ) * long( rInf.GetKern() );
1990cdf0e10cSrcweir 
1991cdf0e10cSrcweir             rInf.SetKanaDiff( 0 );
1992cdf0e10cSrcweir             return aTxtSize;
1993cdf0e10cSrcweir         }
1994cdf0e10cSrcweir     }
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir     const sal_Bool bCompress = rInf.GetKanaComp() && nLn &&
1997cdf0e10cSrcweir                            rInf.GetFont() &&
1998cdf0e10cSrcweir                            SW_CJK == rInf.GetFont()->GetActual() &&
1999cdf0e10cSrcweir                            rInf.GetScriptInfo() &&
2000cdf0e10cSrcweir                            rInf.GetScriptInfo()->CountCompChg() &&
2001cdf0e10cSrcweir                            lcl_IsMonoSpaceFont( rInf.GetOut() );
2002cdf0e10cSrcweir 
2003cdf0e10cSrcweir 	ASSERT(	!bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
2004cdf0e10cSrcweir 			CountCompChg()), "Compression without info" );
2005cdf0e10cSrcweir 
2006cdf0e10cSrcweir     // This is the part used e.g., for cursor travelling
2007cdf0e10cSrcweir     // See condition for DrawText or DrawTextArray (bDirectPrint)
2008cdf0e10cSrcweir     if ( pPrinter && pPrinter != rInf.GetpOut() )
2009cdf0e10cSrcweir 	{
2010cdf0e10cSrcweir 		if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
2011cdf0e10cSrcweir 			pPrinter->SetFont(*pPrtFont);
2012cdf0e10cSrcweir 		aTxtSize.Width() = pPrinter->GetTextWidth( rInf.GetText(),
2013cdf0e10cSrcweir                                                    rInf.GetIdx(), nLn );
2014cdf0e10cSrcweir 		aTxtSize.Height() = pPrinter->GetTextHeight();
2015cdf0e10cSrcweir 		sal_Int32 *pKernArray = new sal_Int32[nLn];
2016cdf0e10cSrcweir         CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
2017cdf0e10cSrcweir         if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
2018cdf0e10cSrcweir             rInf.GetOut().SetFont( *pScrFont );
2019cdf0e10cSrcweir 		long nScrPos;
2020cdf0e10cSrcweir 
2021cdf0e10cSrcweir         pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),nLn );
2022cdf0e10cSrcweir 		if( bCompress )
2023cdf0e10cSrcweir             rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
2024cdf0e10cSrcweir             	rInf.GetIdx(), nLn, rInf.GetKanaComp(),
2025cdf0e10cSrcweir 				(sal_uInt16)aFont.GetSize().Height() ) );
2026cdf0e10cSrcweir 		else
2027cdf0e10cSrcweir 			rInf.SetKanaDiff( 0 );
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir         if ( rInf.GetKanaDiff() )
2030cdf0e10cSrcweir             nScrPos = pKernArray[ nLn - 1 ];
2031cdf0e10cSrcweir         else
2032cdf0e10cSrcweir         {
2033cdf0e10cSrcweir             sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
2034cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
2035cdf0e10cSrcweir                                         rInf.GetIdx(), rInf.GetLen() );
2036cdf0e10cSrcweir             nScrPos = pScrArray[ 0 ];
2037cdf0e10cSrcweir             xub_StrLen nCnt = rInf.GetText().Len();
2038cdf0e10cSrcweir             if ( nCnt < rInf.GetIdx() )
2039cdf0e10cSrcweir                 nCnt=0;
2040cdf0e10cSrcweir             else
2041cdf0e10cSrcweir                 nCnt = nCnt - rInf.GetIdx();
2042cdf0e10cSrcweir             nCnt = Min (nCnt, nLn);
2043cdf0e10cSrcweir             xub_Unicode nChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
2044cdf0e10cSrcweir 
2045cdf0e10cSrcweir             xub_Unicode nCh;
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir             // Bei Pairkerning waechst der Printereinfluss auf die Positionierung
2048cdf0e10cSrcweir             sal_uInt16 nMul = 3;
2049cdf0e10cSrcweir             if ( pPrtFont->GetKerning() )
2050cdf0e10cSrcweir                 nMul = 1;
2051cdf0e10cSrcweir             const sal_uInt16 nDiv = nMul+1;
2052cdf0e10cSrcweir             for( xub_StrLen i=1; i<nCnt; i++ )
2053cdf0e10cSrcweir             {
2054cdf0e10cSrcweir                 nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
2055cdf0e10cSrcweir                 long nScr;
2056cdf0e10cSrcweir                 nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
2057cdf0e10cSrcweir                 if ( nCh == CH_BLANK )
2058cdf0e10cSrcweir                     nScrPos = pKernArray[i-1]+nScr;
2059cdf0e10cSrcweir                 else
2060cdf0e10cSrcweir                 {
2061cdf0e10cSrcweir                     if ( nChPrev == CH_BLANK || nChPrev == '-' )
2062cdf0e10cSrcweir                         nScrPos = pKernArray[i-1]+nScr;
2063cdf0e10cSrcweir                     else
2064cdf0e10cSrcweir                     {
2065cdf0e10cSrcweir                         nScrPos += nScr;
2066cdf0e10cSrcweir                         nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
2067cdf0e10cSrcweir                     }
2068cdf0e10cSrcweir                 }
2069cdf0e10cSrcweir                 nChPrev = nCh;
2070cdf0e10cSrcweir                 pKernArray[i-1] = nScrPos - nScr;
2071cdf0e10cSrcweir             }
2072cdf0e10cSrcweir             delete[] pScrArray;
2073cdf0e10cSrcweir         }
2074cdf0e10cSrcweir 
2075cdf0e10cSrcweir         delete[] pKernArray;
2076cdf0e10cSrcweir 		aTxtSize.Width() = nScrPos;
2077cdf0e10cSrcweir 	}
2078cdf0e10cSrcweir 	else
2079cdf0e10cSrcweir 	{
2080cdf0e10cSrcweir         if( !pPrtFont->IsSameInstance( rInf.GetOut().GetFont() ) )
2081cdf0e10cSrcweir             rInf.GetOut().SetFont( *pPrtFont );
2082cdf0e10cSrcweir 		if( bCompress )
2083cdf0e10cSrcweir 		{
2084cdf0e10cSrcweir 			sal_Int32 *pKernArray = new sal_Int32[nLn];
2085cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2086cdf0e10cSrcweir                                         rInf.GetIdx(), nLn );
2087cdf0e10cSrcweir             rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
2088cdf0e10cSrcweir             	rInf.GetIdx(), nLn, rInf.GetKanaComp(),
2089cdf0e10cSrcweir 				(sal_uInt16) aFont.GetSize().Height() ) );
2090cdf0e10cSrcweir 			aTxtSize.Width() = pKernArray[ nLn - 1 ];
2091cdf0e10cSrcweir 			delete[] pKernArray;
2092cdf0e10cSrcweir 		}
2093cdf0e10cSrcweir 		else
2094cdf0e10cSrcweir 		{
2095cdf0e10cSrcweir             aTxtSize.Width() = rInf.GetOut().GetTextWidth( rInf.GetText(),
2096cdf0e10cSrcweir                                                            rInf.GetIdx(), nLn );
2097cdf0e10cSrcweir 			rInf.SetKanaDiff( 0 );
2098cdf0e10cSrcweir 		}
2099cdf0e10cSrcweir 
2100cdf0e10cSrcweir         aTxtSize.Height() = rInf.GetOut().GetTextHeight();
2101cdf0e10cSrcweir 	}
2102cdf0e10cSrcweir 
2103cdf0e10cSrcweir 	if ( rInf.GetKern() && nLn )
2104cdf0e10cSrcweir 		aTxtSize.Width() += ( nLn - 1 ) * long( rInf.GetKern() );
2105cdf0e10cSrcweir 
2106cdf0e10cSrcweir     ASSERT( !rInf.GetShell() ||
2107cdf0e10cSrcweir             ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
2108cdf0e10cSrcweir               "Leading values should be already calculated" )
2109cdf0e10cSrcweir     aTxtSize.Height() += GetFontLeading( rInf.GetShell(), rInf.GetOut() );
2110cdf0e10cSrcweir 	return aTxtSize;
2111cdf0e10cSrcweir }
2112cdf0e10cSrcweir 
2113cdf0e10cSrcweir 
GetCrsrOfst(SwDrawTextInfo & rInf)2114cdf0e10cSrcweir xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
2115cdf0e10cSrcweir {
2116cdf0e10cSrcweir     long nSpaceAdd =       rInf.GetSpace() / SPACING_PRECISION_FACTOR;
2117cdf0e10cSrcweir     const long nSperren = -rInf.GetSperren() / SPACING_PRECISION_FACTOR;
2118cdf0e10cSrcweir     long nKern = rInf.GetKern();
2119cdf0e10cSrcweir 
2120cdf0e10cSrcweir     if( 0 != nSperren )
2121cdf0e10cSrcweir         nKern -= nSperren;
2122cdf0e10cSrcweir 
2123cdf0e10cSrcweir     sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
2124cdf0e10cSrcweir 
2125cdf0e10cSrcweir     // be sure to have the correct layout mode at the printer
2126cdf0e10cSrcweir     if ( pPrinter )
2127cdf0e10cSrcweir     {
2128cdf0e10cSrcweir         pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
2129cdf0e10cSrcweir         pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
2130cdf0e10cSrcweir         pPrinter->GetTextArray( rInf.GetText(), pKernArray,
2131cdf0e10cSrcweir                                 rInf.GetIdx(), rInf.GetLen() );
2132cdf0e10cSrcweir     }
2133cdf0e10cSrcweir 	else
2134cdf0e10cSrcweir         rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2135cdf0e10cSrcweir                                     rInf.GetIdx(), rInf.GetLen() );
2136cdf0e10cSrcweir 
2137cdf0e10cSrcweir     const SwScriptInfo* pSI = rInf.GetScriptInfo();
2138cdf0e10cSrcweir     if ( rInf.GetFont() && rInf.GetLen() )
2139cdf0e10cSrcweir     {
2140cdf0e10cSrcweir         const sal_uInt8 nActual = rInf.GetFont()->GetActual();
2141cdf0e10cSrcweir 
2142cdf0e10cSrcweir         // Kana Compression
2143cdf0e10cSrcweir         if ( SW_CJK == nActual && rInf.GetKanaComp() &&
2144cdf0e10cSrcweir              pSI && pSI->CountCompChg() &&
2145cdf0e10cSrcweir              lcl_IsMonoSpaceFont( rInf.GetOut() ) )
2146cdf0e10cSrcweir         {
2147cdf0e10cSrcweir             pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
2148cdf0e10cSrcweir                            rInf.GetKanaComp(),
2149cdf0e10cSrcweir                            (sal_uInt16) aFont.GetSize().Height() );
2150cdf0e10cSrcweir         }
2151cdf0e10cSrcweir 
2152cdf0e10cSrcweir         // Asian Justification
2153cdf0e10cSrcweir         if ( SW_CJK == rInf.GetFont()->GetActual() )
2154cdf0e10cSrcweir         {
2155cdf0e10cSrcweir             LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
2156cdf0e10cSrcweir 
2157cdf0e10cSrcweir             if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
2158cdf0e10cSrcweir             {
2159cdf0e10cSrcweir                 long nSpaceSum = nSpaceAdd;
2160cdf0e10cSrcweir                 for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
2161cdf0e10cSrcweir                 {
2162cdf0e10cSrcweir                     pKernArray[ nI ] += nSpaceSum;
2163cdf0e10cSrcweir                     nSpaceSum += nSpaceAdd;
2164cdf0e10cSrcweir                 }
2165cdf0e10cSrcweir 
2166cdf0e10cSrcweir                 nSpaceAdd = 0;
2167cdf0e10cSrcweir             }
2168cdf0e10cSrcweir 
2169cdf0e10cSrcweir         }
2170cdf0e10cSrcweir 
2171cdf0e10cSrcweir         // Kashida Justification
2172cdf0e10cSrcweir         if ( SW_CTL == nActual && rInf.GetSpace() )
2173cdf0e10cSrcweir         {
2174cdf0e10cSrcweir             if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
2175cdf0e10cSrcweir             {
2176cdf0e10cSrcweir                 if ( pSI && pSI->CountKashida() &&
2177cdf0e10cSrcweir                     pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
2178cdf0e10cSrcweir                                          nSpaceAdd ) != STRING_LEN )
2179cdf0e10cSrcweir                     nSpaceAdd = 0;
2180cdf0e10cSrcweir             }
2181cdf0e10cSrcweir         }
2182cdf0e10cSrcweir 
2183cdf0e10cSrcweir         // Thai Justification
2184cdf0e10cSrcweir         if ( SW_CTL == nActual && nSpaceAdd )
2185cdf0e10cSrcweir         {
2186cdf0e10cSrcweir             LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
2187cdf0e10cSrcweir 
2188cdf0e10cSrcweir             if ( LANGUAGE_THAI == aLang )
2189cdf0e10cSrcweir             {
2190cdf0e10cSrcweir                 SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
2191cdf0e10cSrcweir                                            rInf.GetIdx(), rInf.GetLen(),
2192cdf0e10cSrcweir                                            rInf.GetNumberOfBlanks(),
2193cdf0e10cSrcweir                                            rInf.GetSpace() );
2194cdf0e10cSrcweir 
2195cdf0e10cSrcweir                 // adding space to blanks is already done
2196cdf0e10cSrcweir                 nSpaceAdd = 0;
2197cdf0e10cSrcweir             }
2198cdf0e10cSrcweir         }
2199cdf0e10cSrcweir     }
2200cdf0e10cSrcweir 
2201cdf0e10cSrcweir 	long nLeft = 0;
2202cdf0e10cSrcweir 	long nRight = 0;
2203cdf0e10cSrcweir 	xub_StrLen nCnt = 0;
2204cdf0e10cSrcweir     long nSpaceSum = 0;
2205cdf0e10cSrcweir 	long nKernSum = 0;
2206cdf0e10cSrcweir 
2207cdf0e10cSrcweir     if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
2208cdf0e10cSrcweir          rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2209cdf0e10cSrcweir     {
2210cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
2211cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
2212cdf0e10cSrcweir         {
2213cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2214cdf0e10cSrcweir             const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
2215cdf0e10cSrcweir 
2216cdf0e10cSrcweir             long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
2217cdf0e10cSrcweir 
2218cdf0e10cSrcweir             sal_uLong i = nWidthPerChar ?
2219cdf0e10cSrcweir                       ( nWidthPerChar - 1 ) / nGridWidth + 1:
2220cdf0e10cSrcweir                       1;
2221cdf0e10cSrcweir 
2222cdf0e10cSrcweir             nWidthPerChar = i * nGridWidth;
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir             nCnt = (sal_uInt16)(rInf.GetOfst() / nWidthPerChar);
2225cdf0e10cSrcweir             if ( 2 * ( rInf.GetOfst() - nCnt * nWidthPerChar ) > nWidthPerChar )
2226cdf0e10cSrcweir                 ++nCnt;
2227cdf0e10cSrcweir 
2228cdf0e10cSrcweir             delete[] pKernArray;
2229cdf0e10cSrcweir             return nCnt;
2230cdf0e10cSrcweir         }
2231cdf0e10cSrcweir     }
2232cdf0e10cSrcweir 
2233cdf0e10cSrcweir     //for textgrid refactor
2234cdf0e10cSrcweir     if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
2235cdf0e10cSrcweir          rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2236cdf0e10cSrcweir     {
2237cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
2238cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
2239cdf0e10cSrcweir         {
2240cdf0e10cSrcweir 
2241cdf0e10cSrcweir             const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
2242cdf0e10cSrcweir 
2243cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2244cdf0e10cSrcweir             long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
2245cdf0e10cSrcweir             if( SW_LATIN == rInf.GetFont()->GetActual() )
2246cdf0e10cSrcweir                 nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
2247cdf0e10cSrcweir             else
2248cdf0e10cSrcweir                 nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
2249cdf0e10cSrcweir 
2250cdf0e10cSrcweir             for(xub_StrLen j = 0; j < rInf.GetLen(); j++)
2251cdf0e10cSrcweir             {
2252cdf0e10cSrcweir                 long nScr = pKernArray[ j ] + ( nSpaceAdd + nGridWidthAdd  ) * ( j + 1 );
2253cdf0e10cSrcweir                 if( nScr >= rInf.GetOfst())
2254cdf0e10cSrcweir                 {
2255cdf0e10cSrcweir                     nCnt = j;
2256cdf0e10cSrcweir                     break;
2257cdf0e10cSrcweir                 }
2258cdf0e10cSrcweir             }
2259cdf0e10cSrcweir             delete[] pKernArray;
2260cdf0e10cSrcweir             return nCnt;
2261cdf0e10cSrcweir         }
2262cdf0e10cSrcweir     }
2263cdf0e10cSrcweir 
2264cdf0e10cSrcweir     sal_uInt16 nItrMode = i18n::CharacterIteratorMode::SKIPCELL;
2265cdf0e10cSrcweir     sal_Int32 nDone = 0;
2266cdf0e10cSrcweir     LanguageType aLang = LANGUAGE_NONE;
2267cdf0e10cSrcweir     bool bSkipCharacterCells = false;
2268cdf0e10cSrcweir     xub_StrLen nIdx = rInf.GetIdx();
2269cdf0e10cSrcweir     xub_StrLen nLastIdx = nIdx;
2270cdf0e10cSrcweir     const xub_StrLen nEnd = rInf.GetIdx() + rInf.GetLen();
2271cdf0e10cSrcweir 
2272cdf0e10cSrcweir     // --> OD 2009-12-29 #i105901#
2273cdf0e10cSrcweir     // skip character cells for all script types
2274cdf0e10cSrcweir     if ( pBreakIt->GetBreakIter().is() )
2275cdf0e10cSrcweir     // <--
2276cdf0e10cSrcweir     {
2277cdf0e10cSrcweir         aLang = rInf.GetFont()->GetLanguage();
2278cdf0e10cSrcweir         bSkipCharacterCells = true;
2279cdf0e10cSrcweir     }
2280cdf0e10cSrcweir 
2281cdf0e10cSrcweir     while ( ( nRight < long( rInf.GetOfst() ) ) && ( nIdx < nEnd ) )
2282cdf0e10cSrcweir 	{
2283cdf0e10cSrcweir         if ( nSpaceAdd && CH_BLANK == rInf.GetText().GetChar( nIdx ) )
2284cdf0e10cSrcweir             nSpaceSum += nSpaceAdd;
2285cdf0e10cSrcweir 
2286cdf0e10cSrcweir         // go to next character (cell).
2287cdf0e10cSrcweir         nLastIdx = nIdx;
2288cdf0e10cSrcweir 
2289cdf0e10cSrcweir         if ( bSkipCharacterCells )
2290cdf0e10cSrcweir         {
2291cdf0e10cSrcweir             nIdx = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rInf.GetText(),
2292cdf0e10cSrcweir                         nIdx, pBreakIt->GetLocale( aLang ), nItrMode, 1, nDone );
2293cdf0e10cSrcweir             if ( nIdx <= nLastIdx )
2294cdf0e10cSrcweir                 break;
2295cdf0e10cSrcweir         }
2296cdf0e10cSrcweir         else
2297cdf0e10cSrcweir             ++nIdx;
2298cdf0e10cSrcweir 
2299cdf0e10cSrcweir 		nLeft = nRight;
2300cdf0e10cSrcweir         nRight = pKernArray[ nIdx - rInf.GetIdx() - 1 ] + nKernSum + nSpaceSum;
2301cdf0e10cSrcweir 
2302cdf0e10cSrcweir         nKernSum += nKern;
2303cdf0e10cSrcweir 	}
2304cdf0e10cSrcweir 
2305cdf0e10cSrcweir     // step back if position is before the middle of the character
2306cdf0e10cSrcweir     // or if we do not want to go to the next character
2307cdf0e10cSrcweir     if ( nIdx > rInf.GetIdx() &&
2308cdf0e10cSrcweir          ( rInf.IsPosMatchesBounds() ||
2309cdf0e10cSrcweir            ( ( nRight > long( rInf.GetOfst() ) ) &&
2310cdf0e10cSrcweir              ( nRight - rInf.GetOfst() > rInf.GetOfst() - nLeft ) ) ) )
2311cdf0e10cSrcweir         nCnt = nLastIdx - rInf.GetIdx(); // first half
2312cdf0e10cSrcweir     else
2313cdf0e10cSrcweir         nCnt = nIdx - rInf.GetIdx(); // second half
2314cdf0e10cSrcweir 
2315cdf0e10cSrcweir     if ( pSI )
2316cdf0e10cSrcweir         rInf.SetCursorBidiLevel( pSI->DirType( nLastIdx ) );
2317cdf0e10cSrcweir 
2318cdf0e10cSrcweir 	delete[] pKernArray;
2319cdf0e10cSrcweir 	return nCnt;
2320cdf0e10cSrcweir }
2321cdf0e10cSrcweir 
2322cdf0e10cSrcweir 
2323cdf0e10cSrcweir /*************************************************************************
2324cdf0e10cSrcweir |*
2325cdf0e10cSrcweir |*	SwFntAccess::SwFntAccess()
2326cdf0e10cSrcweir |*
2327cdf0e10cSrcweir |*	Ersterstellung		AMA 9. Nov. 94
2328cdf0e10cSrcweir |*	Letzte Aenderung	AMA 9. Nov. 94
2329cdf0e10cSrcweir |*
2330cdf0e10cSrcweir |*************************************************************************/
2331cdf0e10cSrcweir 
SwFntAccess(const void * & rMagic,sal_uInt16 & rIndex,const void * pOwn,ViewShell * pSh,sal_Bool bCheck)2332cdf0e10cSrcweir SwFntAccess::SwFntAccess( const void* &rMagic,
2333cdf0e10cSrcweir                 sal_uInt16 &rIndex, const void *pOwn, ViewShell *pSh,
2334cdf0e10cSrcweir 				sal_Bool bCheck ) :
2335cdf0e10cSrcweir   SwCacheAccess( *pFntCache, rMagic, rIndex ),
2336cdf0e10cSrcweir   pShell( pSh )
2337cdf0e10cSrcweir {
2338cdf0e10cSrcweir 	// Der benutzte CTor von SwCacheAccess sucht anhand rMagic+rIndex im Cache
2339cdf0e10cSrcweir 	if ( IsAvail() )
2340cdf0e10cSrcweir 	{
2341cdf0e10cSrcweir 		// Der schnellste Fall: ein bekannter Font ( rMagic ),
2342cdf0e10cSrcweir 		// bei dem Drucker und Zoom nicht ueberprueft werden brauchen.
2343cdf0e10cSrcweir 		if ( !bCheck )
2344cdf0e10cSrcweir 			return;
2345cdf0e10cSrcweir 
2346cdf0e10cSrcweir 		// Hier ist zwar der Font bekannt, muss aber noch ueberprueft werden.
2347cdf0e10cSrcweir 
2348cdf0e10cSrcweir 	}
2349cdf0e10cSrcweir 	else
2350cdf0e10cSrcweir 		// Hier ist der Font nicht bekannt, muss also gesucht werden.
2351cdf0e10cSrcweir 		bCheck = sal_False;
2352cdf0e10cSrcweir 
2353cdf0e10cSrcweir 
2354cdf0e10cSrcweir     {
2355cdf0e10cSrcweir         OutputDevice* pOut = 0;
2356cdf0e10cSrcweir 		sal_uInt16 nZoom = USHRT_MAX;
2357cdf0e10cSrcweir 
2358cdf0e10cSrcweir         // Get the reference device
2359cdf0e10cSrcweir         if ( pSh )
2360cdf0e10cSrcweir         {
2361cdf0e10cSrcweir             pOut = &pSh->GetRefDev();
2362cdf0e10cSrcweir             nZoom = pSh->GetViewOptions()->GetZoom();
2363cdf0e10cSrcweir         }
2364cdf0e10cSrcweir 
2365cdf0e10cSrcweir 		SwFntObj *pFntObj;
2366cdf0e10cSrcweir 		if ( bCheck )
2367cdf0e10cSrcweir 		{
2368cdf0e10cSrcweir             pFntObj = Get();
2369cdf0e10cSrcweir 			if ( ( pFntObj->GetZoom( ) == nZoom ) &&
2370cdf0e10cSrcweir 				 ( pFntObj->pPrinter == pOut ) &&
2371cdf0e10cSrcweir 				   pFntObj->GetPropWidth() ==
2372cdf0e10cSrcweir                         ((SwSubFont*)pOwn)->GetPropWidth() )
2373cdf0e10cSrcweir 				return; // Die Ueberpruefung ergab: Drucker+Zoom okay.
2374cdf0e10cSrcweir 			pFntObj->Unlock( ); // Vergiss dies Objekt, es wurde leider
2375cdf0e10cSrcweir 			pObj = NULL;	 	// eine Drucker/Zoomaenderung festgestellt.
2376cdf0e10cSrcweir 		}
2377cdf0e10cSrcweir 
2378cdf0e10cSrcweir         // Search by font comparison, quite expensive!
2379cdf0e10cSrcweir         // Look for same font and same printer
2380cdf0e10cSrcweir         pFntObj = pFntCache->First();
2381cdf0e10cSrcweir         while ( pFntObj && !( pFntObj->aFont == *(Font *)pOwn &&
2382cdf0e10cSrcweir                               pFntObj->GetZoom() == nZoom &&
2383cdf0e10cSrcweir                               pFntObj->GetPropWidth() ==
2384cdf0e10cSrcweir                               ((SwSubFont*)pOwn)->GetPropWidth() &&
2385cdf0e10cSrcweir                               ( !pFntObj->pPrinter || pFntObj->pPrinter == pOut ) ) )
2386cdf0e10cSrcweir 			pFntObj = pFntCache->Next( pFntObj );
2387cdf0e10cSrcweir 
2388cdf0e10cSrcweir 		if( pFntObj && pFntObj->pPrinter != pOut )
2389cdf0e10cSrcweir 		{
2390cdf0e10cSrcweir 			// Wir haben zwar einen ohne Drucker gefunden, mal sehen, ob es
2391cdf0e10cSrcweir 			// auch noch einen mit identischem Drucker gibt.
2392cdf0e10cSrcweir 			SwFntObj *pTmpObj = pFntObj;
2393cdf0e10cSrcweir             while( pTmpObj && !( pTmpObj->aFont == *(Font *)pOwn &&
2394cdf0e10cSrcweir 				   pTmpObj->GetZoom()==nZoom && pTmpObj->pPrinter==pOut &&
2395cdf0e10cSrcweir 				   pTmpObj->GetPropWidth() ==
2396cdf0e10cSrcweir                         ((SwSubFont*)pOwn)->GetPropWidth() ) )
2397cdf0e10cSrcweir 				pTmpObj = pFntCache->Next( pTmpObj );
2398cdf0e10cSrcweir 			if( pTmpObj )
2399cdf0e10cSrcweir 				pFntObj = pTmpObj;
2400cdf0e10cSrcweir 		}
2401cdf0e10cSrcweir 
2402cdf0e10cSrcweir         if ( !pFntObj ) // Font has not been found, create one
2403cdf0e10cSrcweir 		{
2404cdf0e10cSrcweir 			// Das Objekt muss neu angelegt werden, deshalb muss der Owner ein
2405cdf0e10cSrcweir 			// SwFont sein, spaeter wird als Owner die "MagicNumber" gehalten.
2406cdf0e10cSrcweir             SwCacheAccess::pOwner = pOwn;
2407cdf0e10cSrcweir 			pFntObj = Get(); // hier wird via NewObj() angelegt und gelockt.
2408cdf0e10cSrcweir 			ASSERT(pFntObj, "No Font, no Fun.");
2409cdf0e10cSrcweir 		}
2410cdf0e10cSrcweir         else  // Font has been found, so we lock it.
2411cdf0e10cSrcweir 		{
2412cdf0e10cSrcweir 			pFntObj->Lock();
2413cdf0e10cSrcweir 			if( pFntObj->pPrinter != pOut ) // Falls bis dato kein Drucker bekannt
2414cdf0e10cSrcweir 			{
2415cdf0e10cSrcweir 				ASSERT( !pFntObj->pPrinter, "SwFntAccess: Printer Changed" );
2416cdf0e10cSrcweir                 pFntObj->CreatePrtFont( *pOut );
2417cdf0e10cSrcweir 				pFntObj->pPrinter = pOut;
2418cdf0e10cSrcweir 				pFntObj->pScrFont = NULL;
2419cdf0e10cSrcweir                 pFntObj->nGuessedLeading = USHRT_MAX;
2420cdf0e10cSrcweir                 pFntObj->nExtLeading = USHRT_MAX;
2421cdf0e10cSrcweir 				pFntObj->nPrtAscent = USHRT_MAX;
2422cdf0e10cSrcweir 				pFntObj->nPrtHeight = USHRT_MAX;
2423cdf0e10cSrcweir 			}
2424cdf0e10cSrcweir 			pObj = pFntObj;
2425cdf0e10cSrcweir 		}
2426cdf0e10cSrcweir 
2427cdf0e10cSrcweir 		// egal, ob neu oder gefunden, ab jetzt ist der Owner vom Objekt eine
2428cdf0e10cSrcweir 		// MagicNumber und wird auch dem aufrufenden SwFont bekanntgegeben,
2429cdf0e10cSrcweir 		// ebenso der Index fuer spaetere direkte Zugriffe
2430cdf0e10cSrcweir 		rMagic = pFntObj->GetOwner();
2431cdf0e10cSrcweir 		SwCacheAccess::pOwner = rMagic;
2432cdf0e10cSrcweir 		rIndex = pFntObj->GetCachePos();
2433cdf0e10cSrcweir 	}
2434cdf0e10cSrcweir }
2435cdf0e10cSrcweir 
NewObj()2436cdf0e10cSrcweir SwCacheObj *SwFntAccess::NewObj( )
2437cdf0e10cSrcweir {
2438cdf0e10cSrcweir 	// Ein neuer Font, eine neue "MagicNumber".
2439cdf0e10cSrcweir 	return new SwFntObj( *(SwSubFont *)pOwner, ++pMagicNo, pShell );
2440cdf0e10cSrcweir }
2441cdf0e10cSrcweir 
2442cdf0e10cSrcweir extern xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt,
2443cdf0e10cSrcweir                                    const XubString& rOrigString,
2444cdf0e10cSrcweir                                    xub_StrLen nOfst,
2445cdf0e10cSrcweir                                    xub_StrLen nLen,
2446cdf0e10cSrcweir                                    xub_StrLen nIdx );
2447cdf0e10cSrcweir 
GetTxtBreak(SwDrawTextInfo & rInf,long nTextWidth)2448cdf0e10cSrcweir xub_StrLen SwFont::GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth )
2449cdf0e10cSrcweir {
2450cdf0e10cSrcweir     ChgFnt( rInf.GetShell(), rInf.GetOut() );
2451cdf0e10cSrcweir 
2452cdf0e10cSrcweir     const sal_Bool bCompress = rInf.GetKanaComp() && rInf.GetLen() &&
2453cdf0e10cSrcweir                            SW_CJK == GetActual() &&
2454cdf0e10cSrcweir                            rInf.GetScriptInfo() &&
2455cdf0e10cSrcweir                            rInf.GetScriptInfo()->CountCompChg() &&
2456cdf0e10cSrcweir                            lcl_IsMonoSpaceFont( rInf.GetOut() );
2457cdf0e10cSrcweir 
2458cdf0e10cSrcweir     ASSERT( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
2459cdf0e10cSrcweir             CountCompChg()), "Compression without info" );
2460cdf0e10cSrcweir 
2461cdf0e10cSrcweir 	sal_uInt16 nTxtBreak = 0;
2462cdf0e10cSrcweir 	long nKern = 0;
2463cdf0e10cSrcweir 
2464cdf0e10cSrcweir 	sal_uInt16 nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
2465cdf0e10cSrcweir 											   : rInf.GetLen() );
2466cdf0e10cSrcweir 
2467cdf0e10cSrcweir     if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() &&
2468cdf0e10cSrcweir          rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2469cdf0e10cSrcweir     {
2470cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
2471cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
2472cdf0e10cSrcweir         {
2473cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2474cdf0e10cSrcweir             const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
2475cdf0e10cSrcweir 
2476cdf0e10cSrcweir             sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
2477cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2478cdf0e10cSrcweir                                         rInf.GetIdx(), rInf.GetLen() );
2479cdf0e10cSrcweir 
2480cdf0e10cSrcweir             long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
2481cdf0e10cSrcweir 
2482cdf0e10cSrcweir             const sal_uLong i = nWidthPerChar ?
2483cdf0e10cSrcweir                             ( nWidthPerChar - 1 ) / nGridWidth + 1:
2484cdf0e10cSrcweir                             1;
2485cdf0e10cSrcweir 
2486cdf0e10cSrcweir             nWidthPerChar = i * nGridWidth;
2487cdf0e10cSrcweir             long nCurrPos = nWidthPerChar;
2488cdf0e10cSrcweir 
2489cdf0e10cSrcweir             while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos )
2490cdf0e10cSrcweir             {
2491cdf0e10cSrcweir                 nCurrPos += nWidthPerChar;
2492cdf0e10cSrcweir                 ++nTxtBreak;
2493cdf0e10cSrcweir             }
2494cdf0e10cSrcweir 
2495cdf0e10cSrcweir             delete[] pKernArray;
2496cdf0e10cSrcweir             return nTxtBreak + rInf.GetIdx();
2497cdf0e10cSrcweir         }
2498cdf0e10cSrcweir     }
2499cdf0e10cSrcweir 
2500cdf0e10cSrcweir     //for text grid enhancement
2501cdf0e10cSrcweir     if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
2502cdf0e10cSrcweir          SW_CJK == rInf.GetFont()->GetActual() )
2503cdf0e10cSrcweir     {
2504cdf0e10cSrcweir         GETGRID( rInf.GetFrm()->FindPageFrm() )
2505cdf0e10cSrcweir         if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
2506cdf0e10cSrcweir         {
2507cdf0e10cSrcweir             const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
2508cdf0e10cSrcweir 
2509cdf0e10cSrcweir 			const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2510cdf0e10cSrcweir             long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
2511cdf0e10cSrcweir             if( SW_LATIN == rInf.GetFont()->GetActual() )
2512cdf0e10cSrcweir                 nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2 ;
2513cdf0e10cSrcweir             else
2514cdf0e10cSrcweir                 nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
2515cdf0e10cSrcweir 
2516cdf0e10cSrcweir             sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
2517cdf0e10cSrcweir             rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2518cdf0e10cSrcweir                                             rInf.GetIdx(), rInf.GetLen() );
2519cdf0e10cSrcweir             long nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd;
2520cdf0e10cSrcweir             while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos)
2521cdf0e10cSrcweir             {
2522cdf0e10cSrcweir                 nTxtBreak++;
2523cdf0e10cSrcweir                 nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd * ( nTxtBreak + 1 );
2524cdf0e10cSrcweir             }
2525cdf0e10cSrcweir             delete[] pKernArray;
2526cdf0e10cSrcweir             return nTxtBreak + rInf.GetIdx();
2527cdf0e10cSrcweir         }
2528cdf0e10cSrcweir     }
2529cdf0e10cSrcweir 
2530cdf0e10cSrcweir     if( aSub[nActual].IsCapital() && nLn )
2531cdf0e10cSrcweir 		nTxtBreak = GetCapitalBreak( rInf.GetShell(), rInf.GetpOut(),
2532cdf0e10cSrcweir 		rInf.GetScriptInfo(), rInf.GetText(), nTextWidth,0, rInf.GetIdx(),nLn );
2533cdf0e10cSrcweir 	else
2534cdf0e10cSrcweir 	{
2535cdf0e10cSrcweir 		nKern = CheckKerning();
2536cdf0e10cSrcweir 
2537cdf0e10cSrcweir         const XubString* pTmpText;
2538cdf0e10cSrcweir         XubString aTmpText;
2539cdf0e10cSrcweir         xub_StrLen nTmpIdx;
2540cdf0e10cSrcweir         xub_StrLen nTmpLen;
2541cdf0e10cSrcweir         bool bTextReplaced = false;
2542cdf0e10cSrcweir 
2543cdf0e10cSrcweir         if ( !aSub[nActual].IsCaseMap() )
2544cdf0e10cSrcweir         {
2545cdf0e10cSrcweir             pTmpText = &rInf.GetText();
2546cdf0e10cSrcweir             nTmpIdx = rInf.GetIdx();
2547cdf0e10cSrcweir             nTmpLen = nLn;
2548cdf0e10cSrcweir         }
2549cdf0e10cSrcweir         else
2550cdf0e10cSrcweir         {
2551cdf0e10cSrcweir 			const XubString aSnippet( rInf.GetText(), rInf.GetIdx(), nLn );
2552cdf0e10cSrcweir             aTmpText = aSub[nActual].CalcCaseMap( aSnippet );
2553cdf0e10cSrcweir             const bool bTitle = SVX_CASEMAP_TITEL == aSub[nActual].GetCaseMap() &&
2554cdf0e10cSrcweir                                 pBreakIt->GetBreakIter().is();
2555cdf0e10cSrcweir 
2556cdf0e10cSrcweir             // Uaaaaahhhh!!! In title case mode, we would get wrong results
2557cdf0e10cSrcweir             if ( bTitle && nLn )
2558cdf0e10cSrcweir             {
2559cdf0e10cSrcweir                 // check if rInf.GetIdx() is begin of word
2560cdf0e10cSrcweir                 if ( !pBreakIt->GetBreakIter()->isBeginWord(
2561cdf0e10cSrcweir                      rInf.GetText(), rInf.GetIdx(),
2562cdf0e10cSrcweir                      pBreakIt->GetLocale( aSub[nActual].GetLanguage() ),
2563cdf0e10cSrcweir                      i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
2564cdf0e10cSrcweir                 {
2565cdf0e10cSrcweir                     // In this case, the beginning of aTmpText is wrong.
2566cdf0e10cSrcweir                     XubString aSnippetTmp( aSnippet, 0, 1 );
2567cdf0e10cSrcweir                     aSnippetTmp = aSub[nActual].CalcCaseMap( aSnippetTmp );
2568cdf0e10cSrcweir                     aTmpText.Erase( 0, aSnippetTmp.Len() );
2569cdf0e10cSrcweir                     aTmpText.Insert( aSnippet.GetChar( 0 ), 0 );
2570cdf0e10cSrcweir                 }
2571cdf0e10cSrcweir             }
2572cdf0e10cSrcweir 
2573cdf0e10cSrcweir             pTmpText = &aTmpText;
2574cdf0e10cSrcweir             nTmpIdx = 0;
2575cdf0e10cSrcweir             nTmpLen = aTmpText.Len();
2576cdf0e10cSrcweir             bTextReplaced = true;
2577cdf0e10cSrcweir         }
2578cdf0e10cSrcweir 
2579cdf0e10cSrcweir        	if( rInf.GetHyphPos() )
2580cdf0e10cSrcweir             nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
2581cdf0e10cSrcweir                                                     '-', *rInf.GetHyphPos(),
2582cdf0e10cSrcweir                                                      nTmpIdx, nTmpLen, nKern );
2583cdf0e10cSrcweir         else
2584cdf0e10cSrcweir             nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
2585cdf0e10cSrcweir                                                     nTmpIdx, nTmpLen, nKern );
2586cdf0e10cSrcweir 
2587cdf0e10cSrcweir         if ( bTextReplaced && STRING_LEN != nTxtBreak )
2588cdf0e10cSrcweir         {
2589cdf0e10cSrcweir             if ( nTmpLen != nLn )
2590cdf0e10cSrcweir                 nTxtBreak = lcl_CalcCaseMap( *this, rInf.GetText(),
2591cdf0e10cSrcweir                                              rInf.GetIdx(), nLn, nTxtBreak );
2592cdf0e10cSrcweir             else
2593cdf0e10cSrcweir                 nTxtBreak = nTxtBreak + rInf.GetIdx();
2594cdf0e10cSrcweir         }
2595cdf0e10cSrcweir 	}
2596cdf0e10cSrcweir 
2597cdf0e10cSrcweir     if ( ! bCompress )
2598cdf0e10cSrcweir         return nTxtBreak;
2599cdf0e10cSrcweir 
2600cdf0e10cSrcweir     nTxtBreak = nTxtBreak - rInf.GetIdx();
2601cdf0e10cSrcweir 
2602cdf0e10cSrcweir     if( nTxtBreak < nLn )
2603cdf0e10cSrcweir 	{
2604cdf0e10cSrcweir         if( !nTxtBreak && nLn )
2605cdf0e10cSrcweir 			nLn = 1;
2606cdf0e10cSrcweir 		else if( nLn > 2 * nTxtBreak )
2607cdf0e10cSrcweir 			nLn = 2 * nTxtBreak;
2608cdf0e10cSrcweir 		sal_Int32 *pKernArray = new sal_Int32[ nLn ];
2609cdf0e10cSrcweir 		rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2610cdf0e10cSrcweir 									rInf.GetIdx(), nLn );
2611cdf0e10cSrcweir         if( rInf.GetScriptInfo()->Compress( pKernArray, rInf.GetIdx(), nLn,
2612cdf0e10cSrcweir                             rInf.GetKanaComp(), (sal_uInt16)GetHeight( nActual ) ) )
2613cdf0e10cSrcweir 		{
2614cdf0e10cSrcweir 			long nKernAdd = nKern;
2615cdf0e10cSrcweir 			xub_StrLen nTmpBreak = nTxtBreak;
2616cdf0e10cSrcweir 			if( nKern && nTxtBreak )
2617cdf0e10cSrcweir 				nKern *= nTxtBreak - 1;
2618cdf0e10cSrcweir 			while( nTxtBreak<nLn && nTextWidth >= pKernArray[nTxtBreak] +nKern )
2619cdf0e10cSrcweir 			{
2620cdf0e10cSrcweir 				nKern += nKernAdd;
2621cdf0e10cSrcweir 				++nTxtBreak;
2622cdf0e10cSrcweir 			}
2623cdf0e10cSrcweir 			if( rInf.GetHyphPos() )
2624cdf0e10cSrcweir 				*rInf.GetHyphPos() += nTxtBreak - nTmpBreak; // It's not perfect
2625cdf0e10cSrcweir 		}
2626cdf0e10cSrcweir 		delete[] pKernArray;
2627cdf0e10cSrcweir     }
2628cdf0e10cSrcweir     nTxtBreak = nTxtBreak + rInf.GetIdx();
2629cdf0e10cSrcweir 
2630cdf0e10cSrcweir     return nTxtBreak;
2631cdf0e10cSrcweir }
2632cdf0e10cSrcweir 
2633cdf0e10cSrcweir extern Color aGlobalRetoucheColor;
2634cdf0e10cSrcweir 
ApplyAutoColor(Font * pFont)2635cdf0e10cSrcweir sal_Bool SwDrawTextInfo::ApplyAutoColor( Font* pFont )
2636cdf0e10cSrcweir {
2637cdf0e10cSrcweir     const Font& rFnt = pFont ? *pFont : GetOut().GetFont();
2638cdf0e10cSrcweir     sal_Bool bPrt = GetShell() && ! GetShell()->GetWin();
2639cdf0e10cSrcweir     ColorData nNewColor = COL_BLACK;
2640cdf0e10cSrcweir     sal_Bool bChgFntColor = sal_False;
2641cdf0e10cSrcweir     sal_Bool bChgLineColor = sal_False;
2642cdf0e10cSrcweir 
2643cdf0e10cSrcweir     if( bPrt && GetShell() && GetShell()->GetViewOptions()->IsBlackFont() )
2644cdf0e10cSrcweir 	{
2645cdf0e10cSrcweir         if ( COL_BLACK != rFnt.GetColor().GetColor() )
2646cdf0e10cSrcweir             bChgFntColor = sal_True;
2647cdf0e10cSrcweir 
2648cdf0e10cSrcweir         if ( (COL_BLACK != GetOut().GetLineColor().GetColor()) ||
2649cdf0e10cSrcweir              (COL_BLACK != GetOut().GetOverlineColor().GetColor()) )
2650cdf0e10cSrcweir             bChgLineColor = sal_True;
2651cdf0e10cSrcweir 	}
2652cdf0e10cSrcweir     else
2653cdf0e10cSrcweir     {
2654cdf0e10cSrcweir         // FontColor has to be changed if:
2655cdf0e10cSrcweir         // 1. FontColor = AUTO or 2. IsAlwaysAutoColor is set
2656cdf0e10cSrcweir         // LineColor has to be changed if:
2657cdf0e10cSrcweir         // 1. IsAlwaysAutoColor is set
2658cdf0e10cSrcweir 
2659cdf0e10cSrcweir         bChgLineColor = ! bPrt && GetShell() &&
2660cdf0e10cSrcweir                 GetShell()->GetAccessibilityOptions()->IsAlwaysAutoColor();
2661cdf0e10cSrcweir 
2662cdf0e10cSrcweir         bChgFntColor = COL_AUTO == rFnt.GetColor().GetColor() || bChgLineColor;
2663cdf0e10cSrcweir 
2664cdf0e10cSrcweir         if ( bChgFntColor )
2665cdf0e10cSrcweir         {
2666cdf0e10cSrcweir             // check if current background has a user defined setting
2667cdf0e10cSrcweir             const Color* pCol = GetFont() ? GetFont()->GetBackColor() : NULL;
2668cdf0e10cSrcweir             if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
2669cdf0e10cSrcweir             {
2670cdf0e10cSrcweir                 const SvxBrushItem* pItem;
2671cdf0e10cSrcweir                 SwRect aOrigBackRect;
2672cdf0e10cSrcweir 
267364b14621SArmin Le Grand                 //UUUU
2674*56b35d86SArmin Le Grand                 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
267564b14621SArmin Le Grand 
2676cdf0e10cSrcweir                 /// OD 21.08.2002
2677cdf0e10cSrcweir                 ///     consider, that [GetBackgroundBrush(...)] can set <pCol>
2678cdf0e10cSrcweir                 ///     - see implementation in /core/layout/paintfrm.cxx
2679cdf0e10cSrcweir                 /// OD 21.08.2002 #99657#
2680cdf0e10cSrcweir                 ///     There is a user defined setting for the background, if there
2681cdf0e10cSrcweir                 ///     is a background brush and its color is *not* "no fill"/"auto fill".
268264b14621SArmin Le Grand                 if( GetFrm()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, sal_False ) )
2683cdf0e10cSrcweir                 {
2684cdf0e10cSrcweir                     if ( !pCol )
2685cdf0e10cSrcweir                     {
2686cdf0e10cSrcweir                         pCol = &pItem->GetColor();
2687cdf0e10cSrcweir                     }
2688cdf0e10cSrcweir 
2689cdf0e10cSrcweir                     /// OD 30.08.2002 #99657#
2690cdf0e10cSrcweir                     /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
2691cdf0e10cSrcweir                     if ( pCol->GetColor() == COL_TRANSPARENT)
2692cdf0e10cSrcweir                         pCol = NULL;
2693cdf0e10cSrcweir                 }
2694cdf0e10cSrcweir                 else
2695cdf0e10cSrcweir                     pCol = NULL;
2696cdf0e10cSrcweir             }
2697cdf0e10cSrcweir 
2698cdf0e10cSrcweir             // no user defined color at paragraph or font background
2699cdf0e10cSrcweir             if ( ! pCol )
2700cdf0e10cSrcweir                 pCol = &aGlobalRetoucheColor;
2701cdf0e10cSrcweir 
2702cdf0e10cSrcweir             if( GetShell() && GetShell()->GetWin() )
2703cdf0e10cSrcweir             {
270486e1cf34SPedro Giffuni                 // here we determine the preferred window text color for painting
2705cdf0e10cSrcweir                 const SwViewOption* pViewOption = GetShell()->GetViewOptions();
2706cdf0e10cSrcweir                 if(pViewOption->IsPagePreview() &&
2707cdf0e10cSrcweir                         !SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews())
2708cdf0e10cSrcweir                     nNewColor = COL_BLACK;
2709cdf0e10cSrcweir                 else
271086e1cf34SPedro Giffuni                     // we take the font color from the appearance page
2711cdf0e10cSrcweir                     nNewColor = SwViewOption::GetFontColor().GetColor();
2712cdf0e10cSrcweir             }
2713cdf0e10cSrcweir 
2714cdf0e10cSrcweir             // change painting color depending of dark/bright background
2715cdf0e10cSrcweir             Color aTmpColor( nNewColor );
2716cdf0e10cSrcweir             if ( pCol->IsDark() && aTmpColor.IsDark() )
2717cdf0e10cSrcweir                 nNewColor = COL_WHITE;
2718cdf0e10cSrcweir             else if ( pCol->IsBright() && aTmpColor.IsBright() )
2719cdf0e10cSrcweir                 nNewColor = COL_BLACK;
2720cdf0e10cSrcweir         }
2721cdf0e10cSrcweir     }
2722cdf0e10cSrcweir 
2723cdf0e10cSrcweir     if ( bChgFntColor || bChgLineColor )
2724cdf0e10cSrcweir     {
2725cdf0e10cSrcweir         Color aNewColor( nNewColor );
2726cdf0e10cSrcweir 
2727cdf0e10cSrcweir         if ( bChgFntColor )
2728cdf0e10cSrcweir         {
2729cdf0e10cSrcweir             if ( pFont && aNewColor != pFont->GetColor() )
2730cdf0e10cSrcweir             {
2731cdf0e10cSrcweir                 // only set the new color at the font passed as argument
2732cdf0e10cSrcweir                 pFont->SetColor( aNewColor );
2733cdf0e10cSrcweir             }
2734cdf0e10cSrcweir             else if ( aNewColor != GetOut().GetFont().GetColor() )
2735cdf0e10cSrcweir             {
2736cdf0e10cSrcweir                 // set new font with new color at output device
2737cdf0e10cSrcweir                 Font aFont( rFnt );
2738cdf0e10cSrcweir                 aFont.SetColor( aNewColor );
2739cdf0e10cSrcweir                 GetOut().SetFont( aFont );
2740cdf0e10cSrcweir             }
2741cdf0e10cSrcweir         }
2742cdf0e10cSrcweir 
2743cdf0e10cSrcweir         // the underline and overline colors have to be set separately
2744cdf0e10cSrcweir         if ( bChgLineColor )
2745cdf0e10cSrcweir         {
2746cdf0e10cSrcweir             // get current font color or color set at output device
2747cdf0e10cSrcweir             aNewColor = pFont ? pFont->GetColor() : GetOut().GetFont().GetColor();
2748cdf0e10cSrcweir             if ( aNewColor != GetOut().GetLineColor() )
2749cdf0e10cSrcweir                 GetOut().SetLineColor( aNewColor );
2750cdf0e10cSrcweir             if ( aNewColor != GetOut().GetOverlineColor() )
2751cdf0e10cSrcweir                 GetOut().SetOverlineColor( aNewColor );
2752cdf0e10cSrcweir         }
2753cdf0e10cSrcweir 
2754cdf0e10cSrcweir         return sal_True;
2755cdf0e10cSrcweir 	}
2756cdf0e10cSrcweir 
2757cdf0e10cSrcweir     return sal_False;
2758cdf0e10cSrcweir }
2759cdf0e10cSrcweir 
2760