Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <i18npool/mslangid.hxx>
30 : : #include <vcl/outdev.hxx>
31 : : #include <vcl/print.hxx>
32 : : #include <vcl/lineinfo.hxx>
33 : : #include <vcl/metric.hxx>
34 : : #include <vcl/window.hxx>
35 : : #include <vcl/svapp.hxx>
36 : : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
37 : : #include <com/sun/star/i18n/WordType.hpp>
38 : : #include <breakit.hxx>
39 : : #include <viewsh.hxx>
40 : : #include <viewopt.hxx>
41 : : #include <fntcache.hxx>
42 : : #include <IDocumentSettingAccess.hxx>
43 : : #include <swfont.hxx> // CH_BLANK + CH_BULLET
44 : : #include <wrong.hxx>
45 : : #include "dbg_lay.hxx"
46 : : #include <txtfrm.hxx> // SwTxtFrm
47 : : #include <pagefrm.hxx>
48 : : #include <pagedesc.hxx> // SwPageDesc
49 : : #include <tgrditem.hxx>
50 : : #include <scriptinfo.hxx>
51 : : #include <editeng/brshitem.hxx>
52 : : #include <tools/shl.hxx>
53 : : #include <swmodule.hxx>
54 : : #include <accessibilityoptions.hxx>
55 : : #include <svtools/accessibilityoptions.hxx>
56 : : #include <doc.hxx>
57 : : #include <editeng/fhgtitem.hxx>
58 : : #include <docsh.hxx>
59 : : #include <poolfmt.hrc>
60 : :
61 : : using namespace ::com::sun::star;
62 : :
63 : : // global variables declared in fntcache.hxx
64 : : // FontCache is created in txtinit.cxx _TextInit and deleted in _TextFinit
65 : : SwFntCache *pFntCache = NULL;
66 : : // last Font set by ChgFntCache
67 : : SwFntObj *pLastFont = NULL;
68 : : // "MagicNumber" used to identify Fonts
69 : : sal_uInt8* pMagicNo = NULL;
70 : :
71 : : Color *pWaveCol = 0;
72 : :
73 : : long SwFntObj::nPixWidth;
74 : : MapMode* SwFntObj::pPixMap = NULL;
75 : : OutputDevice* SwFntObj::pPixOut = NULL;
76 : :
77 : : extern sal_uInt16 UnMapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat );
78 : 0 : sal_uInt16 GetDefaultFontHeight( SwDrawTextInfo &rInf )
79 : : {
80 : 0 : SwDocShell* pDocShell = rInf.GetShell()->GetDoc()->GetDocShell();
81 [ # # ]: 0 : SfxStyleSheetBasePool* pBasePool = pDocShell->GetStyleSheetPool();
82 : :
83 [ # # ]: 0 : String aString(SW_RES(STR_POOLCOLL_STANDARD));
84 : :
85 [ # # ]: 0 : SfxStyleSheetBase* pStyle = pBasePool->Find( aString, (SfxStyleFamily)SFX_STYLE_FAMILY_PARA );
86 [ # # ]: 0 : SfxItemSet& aTmpSet = pStyle->GetItemSet();
87 [ # # ]: 0 : SvxFontHeightItem &aDefaultFontItem = (SvxFontHeightItem&)aTmpSet.Get(RES_CHRATR_CJK_FONTSIZE);
88 [ # # ]: 0 : return (sal_uInt16)aDefaultFontItem.GetHeight();
89 : : }
90 : :
91 : :
92 : :
93 : : /*************************************************************************
94 : : |*
95 : : |* SwFntCache::Flush()
96 : : |*
97 : : |*************************************************************************/
98 : :
99 : 1363 : void SwFntCache::Flush( )
100 : : {
101 [ + + ]: 1363 : if ( pLastFont )
102 : : {
103 : 1288 : pLastFont->Unlock();
104 : 1288 : pLastFont = NULL;
105 : : }
106 : 1363 : SwCache::Flush( );
107 : 1363 : }
108 : :
109 : : /*************************************************************************
110 : : |*
111 : : |* SwFntObj::SwFntObj(), ~SwFntObj()
112 : : |*
113 : : |*************************************************************************/
114 : :
115 : 2288 : SwFntObj::SwFntObj( const SwSubFont &rFont, const void *pOwn, ViewShell *pSh ) :
116 : : SwCacheObj( (void*)pOwn ),
117 : : aFont( rFont ),
118 : : pScrFont( NULL ),
119 : : pPrtFont( &aFont ),
120 : : pPrinter( NULL ),
121 [ + - ]: 2288 : nPropWidth( rFont.GetPropWidth() )
122 : : {
123 [ + + ]: 2288 : nZoom = pSh ? pSh->GetViewOptions()->GetZoom() : USHRT_MAX;
124 : 2288 : nGuessedLeading = USHRT_MAX;
125 : 2288 : nExtLeading = USHRT_MAX;
126 : 2288 : nPrtAscent = USHRT_MAX;
127 : 2288 : nPrtHeight = USHRT_MAX;
128 [ + - ]: 2288 : bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
129 [ + - ]: 2288 : bPaintBlank = ( UNDERLINE_NONE != aFont.GetUnderline()
130 [ + - ]: 1970 : || UNDERLINE_NONE != aFont.GetOverline()
131 [ + - ]: 1970 : || STRIKEOUT_NONE != aFont.GetStrikeout() )
132 [ + + ][ + - ]: 6228 : && !aFont.IsWordLineMode();
[ + + ][ + - ]
[ + + ]
133 [ + - ]: 2288 : aFont.SetLanguage(rFont.GetLanguage());
134 : 2288 : }
135 : :
136 [ + - ]: 2288 : SwFntObj::~SwFntObj()
137 : : {
138 [ + + ]: 2288 : if ( pScrFont != pPrtFont )
139 [ - + ][ # # ]: 1510 : delete pScrFont;
140 [ + + ]: 2288 : if ( pPrtFont != &aFont )
141 [ + - ][ + - ]: 140 : delete pPrtFont;
142 [ - + ]: 4576 : }
143 : :
144 : 281705 : void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
145 : : {
146 [ + + ][ + + ]: 281705 : if ( nPropWidth != 100 && pPrinter != &rPrt )
147 : : {
148 [ + - ]: 464 : if( pScrFont != pPrtFont )
149 [ - + ][ # # ]: 464 : delete pScrFont;
150 [ + + ]: 464 : if( pPrtFont != &aFont )
151 [ + - ][ + - ]: 324 : delete pPrtFont;
152 : :
153 [ + - ]: 464 : const Font aOldFnt( rPrt.GetFont() );
154 [ + - ]: 464 : ((OutputDevice&)rPrt).SetFont( aFont );
155 [ + - ]: 464 : const FontMetric aWinMet( rPrt.GetFontMetric() );
156 [ + - ]: 464 : ((OutputDevice&)rPrt).SetFont( aOldFnt );
157 [ + - ]: 464 : long nWidth = ( aWinMet.GetSize().Width() * nPropWidth ) / 100;
158 : :
159 [ - + ]: 464 : if( !nWidth )
160 : 0 : ++nWidth;
161 [ + - ][ + - ]: 464 : pPrtFont = new Font( aFont );
162 [ + - ][ + - ]: 464 : pPrtFont->SetSize( Size( nWidth, aFont.GetSize().Height() ) );
163 [ + - ][ + - ]: 464 : pScrFont = NULL;
164 : : }
165 : 281705 : }
166 : :
167 : : /*************************************************************************
168 : : *
169 : : * bool lcl_IsFontAdjustNecessary( rOutDev, rRefDev )
170 : : *
171 : : * returns whether we have to adjust the output font to resemble
172 : : * the formatting font
173 : : *
174 : : * _Not_ necessary if
175 : : *
176 : : * 1. RefDef == OutDev (text formatting, online layout...)
177 : : * 2. PDF export from online layout
178 : : * 3. Prospect/PagePreview pringing
179 : : *
180 : : *************************************************************************/
181 : :
182 : 577428 : bool lcl_IsFontAdjustNecessary( const OutputDevice& rOutDev,
183 : : const OutputDevice& rRefDev )
184 : : {
185 : : return &rRefDev != &rOutDev &&
186 : 62887 : OUTDEV_WINDOW != rRefDev.GetOutDevType() &&
187 : 62772 : ( OUTDEV_PRINTER != rRefDev.GetOutDevType() ||
188 [ + + + + : 703087 : OUTDEV_PRINTER != rOutDev.GetOutDevType() );
+ + ][ + - ]
189 : : }
190 : :
191 : : struct CalcLinePosData
192 : : {
193 : : SwDrawTextInfo& rInf;
194 : : Font& rFont;
195 : : xub_StrLen nCnt;
196 : : const sal_Bool bSwitchH2V;
197 : : const sal_Bool bSwitchL2R;
198 : : long nHalfSpace;
199 : : sal_Int32* pKernArray;
200 : : const sal_Bool bBidiPor;
201 : :
202 : 22705 : CalcLinePosData( SwDrawTextInfo& _rInf, Font& _rFont,
203 : : xub_StrLen _nCnt, const sal_Bool _bSwitchH2V, const sal_Bool _bSwitchL2R,
204 : : long _nHalfSpace, sal_Int32* _pKernArray, const sal_Bool _bBidiPor) :
205 : : rInf( _rInf ),
206 : : rFont( _rFont ),
207 : : nCnt( _nCnt ),
208 : : bSwitchH2V( _bSwitchH2V ),
209 : : bSwitchL2R( _bSwitchL2R ),
210 : : nHalfSpace( _nHalfSpace ),
211 : : pKernArray( _pKernArray ),
212 : 22705 : bBidiPor( _bBidiPor )
213 : : {
214 : 22705 : }
215 : : };
216 : :
217 : : /** Function: lcl_calcLinePos
218 : :
219 : : Computes the start and end position of an underline. This function is called
220 : : from the DrawText-method (for underlining misspelled words or smarttag terms).
221 : : */
222 : :
223 : 3463 : void lcl_calcLinePos( const CalcLinePosData &rData,
224 : : Point &rStart, Point &rEnd, xub_StrLen nStart, xub_StrLen nWrLen )
225 : : {
226 : 3463 : long nBlank = 0;
227 : 3463 : const xub_StrLen nEnd = nStart + nWrLen;
228 : 3463 : const long nTmpSpaceAdd = rData.rInf.GetSpace() / SPACING_PRECISION_FACTOR;
229 : :
230 [ + + ]: 5746 : if ( nEnd < rData.nCnt
[ + + + + ]
231 : 2283 : && CH_BLANK == rData.rInf.GetText().GetChar( rData.rInf.GetIdx() + nEnd ) )
232 : : {
233 [ + + ]: 1464 : if( nEnd + 1 == rData.nCnt )
234 : 78 : nBlank -= nTmpSpaceAdd;
235 : : else
236 : 1386 : nBlank -= rData.nHalfSpace;
237 : : }
238 : :
239 : : // determine start, end and length of wave line
240 [ + + ]: 3463 : sal_Int32 nKernStart = nStart ? rData.pKernArray[ sal_uInt16( nStart - 1 ) ] : 0;
241 : 3463 : sal_Int32 nKernEnd = rData.pKernArray[ sal_uInt16( nEnd - 1 ) ];
242 : :
243 : : sal_uInt16 nDir = rData.bBidiPor ? 1800 :
244 [ + - ]: 3463 : UnMapDirection( rData.rFont.GetOrientation(), rData.bSwitchH2V );
245 : :
246 [ + - - - : 3463 : switch ( nDir )
- ]
247 : : {
248 : : case 0 :
249 : 3463 : rStart.X() += nKernStart;
250 : 3463 : rEnd.X() = nBlank + rData.rInf.GetPos().X() + nKernEnd;
251 : 3463 : rEnd.Y() = rData.rInf.GetPos().Y();
252 : 3463 : break;
253 : : case 900 :
254 : 0 : rStart.Y() -= nKernStart;
255 : 0 : rEnd.X() = rData.rInf.GetPos().X();
256 : 0 : rEnd.Y() = nBlank + rData.rInf.GetPos().Y() - nKernEnd;
257 : 0 : break;
258 : : case 1800 :
259 : 0 : rStart.X() -= nKernStart;
260 : 0 : rEnd.X() = rData.rInf.GetPos().X() - nKernEnd - nBlank;
261 : 0 : rEnd.Y() = rData.rInf.GetPos().Y();
262 : 0 : break;
263 : : case 2700 :
264 : 0 : rStart.Y() += nKernStart;
265 : 0 : rEnd.X() = rData.rInf.GetPos().X();
266 : 0 : rEnd.Y() = nBlank + rData.rInf.GetPos().Y() + nKernEnd;
267 : 0 : break;
268 : : }
269 : :
270 [ - + ]: 3463 : if ( rData.bSwitchL2R )
271 : : {
272 : 0 : rData.rInf.GetFrm()->SwitchLTRtoRTL( rStart );
273 : 0 : rData.rInf.GetFrm()->SwitchLTRtoRTL( rEnd );
274 : : }
275 : :
276 [ - + ]: 3463 : if ( rData.bSwitchH2V )
277 : : {
278 : 0 : rData.rInf.GetFrm()->SwitchHorizontalToVertical( rStart );
279 : 0 : rData.rInf.GetFrm()->SwitchHorizontalToVertical( rEnd );
280 : : }
281 : 3463 : }
282 : :
283 : : /*************************************************************************
284 : : *
285 : : * sal_uInt16 SwFntObj::GetFontAscent( const OutputDevice& rOut )
286 : : *
287 : : * Returns the Ascent of the Font on the given output device;
288 : : * it may be necessary to create the screen font first.
289 : : *************************************************************************/
290 : :
291 : 118601 : sal_uInt16 SwFntObj::GetFontAscent( const ViewShell *pSh, const OutputDevice& rOut )
292 : : {
293 : 118601 : sal_uInt16 nRet = 0;
294 [ + - ]: 118601 : const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
295 : :
296 [ + - ][ + + ]: 118601 : if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
[ + + ]
297 : : {
298 : 1343 : CreateScrFont( *pSh, rOut );
299 : : OSL_ENSURE( USHRT_MAX != nScrAscent, "nScrAscent is going berzerk" );
300 : 1343 : nRet = nScrAscent;
301 : : }
302 : : else
303 : : {
304 [ + + ]: 117258 : if (nPrtAscent == USHRT_MAX) // printer ascent unknown?
305 : : {
306 [ + - ]: 2167 : CreatePrtFont( rOut );
307 [ + - ]: 2167 : const Font aOldFnt( rRefDev.GetFont() );
308 [ + - ]: 2167 : ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
309 [ + - ]: 2167 : const FontMetric aOutMet( rRefDev.GetFontMetric() );
310 [ + - ]: 2167 : nPrtAscent = (sal_uInt16) aOutMet.GetAscent();
311 [ + - ][ + - ]: 2167 : ( (OutputDevice&)rRefDev).SetFont( aOldFnt );
[ + - ]
312 : : }
313 : :
314 : 117258 : nRet = nPrtAscent;
315 : : }
316 : :
317 : : #if !defined(MACOSX) // #i89844# extleading is below the line for Mac
318 : : // TODO: move extleading below the line for all platforms too
319 : 118601 : nRet += GetFontLeading( pSh, rRefDev );
320 : : #endif
321 : :
322 : : OSL_ENSURE( USHRT_MAX != nRet, "GetFontAscent returned USHRT_MAX" );
323 : 118601 : return nRet;
324 : : }
325 : :
326 : : /*************************************************************************
327 : : *
328 : : * sal_uInt16 SwFntObj::GetFontHeight( const OutputDevice* pOut )
329 : : *
330 : : * Returns the height of the Font on the given output device;
331 : : * it may be necessary to create the screen font first.
332 : : *************************************************************************/
333 : :
334 : 124616 : sal_uInt16 SwFntObj::GetFontHeight( const ViewShell* pSh, const OutputDevice& rOut )
335 : : {
336 : 124616 : sal_uInt16 nRet = 0;
337 [ + - ]: 124616 : const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
338 : :
339 [ + - ][ + + ]: 124616 : if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
[ + + ]
340 : : {
341 : 1178 : CreateScrFont( *pSh, rOut );
342 : : OSL_ENSURE( USHRT_MAX != nScrHeight, "nScrHeight is going berzerk" );
343 : 1178 : nRet = nScrHeight + GetFontLeading( pSh, rRefDev );
344 : : }
345 : : else
346 : : {
347 [ + + ]: 123438 : if (nPrtHeight == USHRT_MAX) // printer height unknown?
348 : : {
349 [ + - ]: 2690 : CreatePrtFont( rOut );
350 [ + - ]: 2690 : const Font aOldFnt( rRefDev.GetFont() );
351 [ + - ]: 2690 : ((OutputDevice&)rRefDev).SetFont( *pPrtFont );
352 [ + - ]: 2690 : nPrtHeight = static_cast<sal_uInt16>(rRefDev.GetTextHeight());
353 : :
354 : : #if OSL_DEBUG_LEVEL > 0
355 : : // Check if vcl did not change the meading of GetTextHeight
356 : : const FontMetric aOutMet( rRefDev.GetFontMetric() );
357 : : long nTmpPrtHeight = (sal_uInt16)aOutMet.GetAscent() + aOutMet.GetDescent();
358 : : (void) nTmpPrtHeight;
359 : : // #i106098#: do not compare with == here due to rounding error
360 : : OSL_ENSURE( abs(nTmpPrtHeight - nPrtHeight) < 3,
361 : : "GetTextHeight != Ascent + Descent" );
362 : : #endif
363 : :
364 [ + - ][ + - ]: 2690 : ((OutputDevice&)rRefDev).SetFont( aOldFnt );
365 : : }
366 : :
367 : 123438 : nRet = nPrtHeight + GetFontLeading( pSh, rRefDev );
368 : : }
369 : :
370 : : OSL_ENSURE( USHRT_MAX != nRet, "GetFontHeight returned USHRT_MAX" );
371 : 124616 : return nRet;
372 : : }
373 : :
374 : 605640 : sal_uInt16 SwFntObj::GetFontLeading( const ViewShell *pSh, const OutputDevice& rOut )
375 : : {
376 : 605640 : sal_uInt16 nRet = 0;
377 : :
378 [ + + ]: 605640 : if ( pSh )
379 : : {
380 [ + + ][ - + ]: 605562 : if ( USHRT_MAX == nGuessedLeading || USHRT_MAX == nExtLeading )
381 : : {
382 [ + - ]: 2693 : SolarMutexGuard aGuard;
383 : :
384 [ + - ]: 2693 : const Font aOldFnt( rOut.GetFont() );
385 [ + - ]: 2693 : ((OutputDevice&)rOut).SetFont( *pPrtFont );
386 [ + - ]: 2693 : const FontMetric aMet( rOut.GetFontMetric() );
387 [ + - ]: 2693 : ((OutputDevice&)rOut).SetFont( aOldFnt );
388 [ + - ]: 2693 : bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
389 [ + - ]: 2693 : GuessLeading( *pSh, aMet );
390 [ + - ][ + - ]: 2693 : nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
[ + - ][ + - ]
391 : : }
392 : :
393 : 605562 : const IDocumentSettingAccess& rIDSA = *pSh->getIDocumentSettingAccess();
394 : 605562 : const bool bBrowse = ( pSh->GetWin() &&
395 : 604958 : pSh->GetViewOptions()->getBrowseMode() &&
396 [ + - ]: 1210520 : !pSh->GetViewOptions()->IsPrtFormat() );
[ + + + + ]
397 : :
398 [ + + ][ + + ]: 605562 : if ( !bBrowse && rIDSA.get(IDocumentSettingAccess::ADD_EXT_LEADING) )
[ + + ]
399 : 605216 : nRet = nExtLeading;
400 : : else
401 : 346 : nRet = nGuessedLeading;
402 : : }
403 : :
404 : : OSL_ENSURE( USHRT_MAX != nRet, "GetFontLeading returned USHRT_MAX" );
405 : 605640 : return nRet;
406 : : }
407 : :
408 : :
409 : : /*************************************************************************
410 : : *
411 : : * SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
412 : : *
413 : : * pOut is the output device, not the reference device
414 : : *
415 : : *************************************************************************/
416 : :
417 : 64036 : void SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
418 : : {
419 [ + + ]: 64036 : if ( pScrFont )
420 : 64036 : return;
421 : :
422 : : // any changes to the output device are reset at the end of the function
423 : 778 : OutputDevice* pOut = (OutputDevice*)&rOut;
424 : :
425 : : // Save old font
426 [ + - ]: 778 : Font aOldOutFont( pOut->GetFont() );
427 : :
428 : 778 : nScrHeight = USHRT_MAX;
429 : :
430 : : // Condition for output font / refdev font adjustment
431 [ + - ]: 778 : OutputDevice* pPrt = &rSh.GetRefDev();
432 : :
433 [ + + - + : 1541 : if( !rSh.GetWin() ||
# # ][ + - ]
434 : 763 : !rSh.GetViewOptions()->getBrowseMode() ||
435 : 0 : rSh.GetViewOptions()->IsPrtFormat() )
436 : : {
437 : : // After CreatePrtFont pPrtFont is the font which is actually used
438 : : // by the reference device
439 [ + - ]: 778 : CreatePrtFont( *pPrt );
440 : 778 : pPrinter = pPrt;
441 : :
442 : : // save old reference device font
443 [ + - ]: 778 : Font aOldPrtFnt( pPrt->GetFont() );
444 : :
445 : : // set the font used at the reference device at the reference device
446 : : // and the output device
447 [ + - ]: 778 : pPrt->SetFont( *pPrtFont );
448 [ + - ]: 778 : pOut->SetFont( *pPrtFont );
449 : :
450 : : // This should be the default for pScrFont.
451 : 778 : pScrFont = pPrtFont;
452 : :
453 [ + - ]: 778 : FontMetric aMet = pPrt->GetFontMetric( );
454 : : //Don't loose "faked" properties of the logical font that don't truly
455 : : //exist in the physical font metrics which vcl which fake up for us
456 [ + - ][ + - ]: 778 : aMet.SetWeight(pScrFont->GetWeight());
457 [ + - ][ + - ]: 778 : aMet.SetItalic(pScrFont->GetItalic());
458 : :
459 [ + - ]: 778 : bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
460 : :
461 [ + + ]: 778 : if ( USHRT_MAX == nGuessedLeading )
462 [ + - ]: 92 : GuessLeading( rSh, aMet );
463 : :
464 [ + + ]: 778 : if ( USHRT_MAX == nExtLeading )
465 [ + - ]: 92 : nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
466 : :
467 : : // reset the original reference device font
468 [ + - ][ + - ]: 778 : pPrt->SetFont( aOldPrtFnt );
[ + - ]
469 : : }
470 : : else
471 : : {
472 [ # # ]: 0 : bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
473 [ # # ]: 0 : if ( nGuessedLeading == USHRT_MAX )
474 : 0 : nGuessedLeading = 0;
475 : :
476 : : // no external leading in browse mode
477 [ # # ]: 0 : if ( nExtLeading == USHRT_MAX )
478 : 0 : nExtLeading = 0;
479 : :
480 : 0 : pScrFont = pPrtFont;
481 : : }
482 : :
483 : : // check zoom factor, e.g. because of PrtOle2 during export
484 : : {
485 : : // In case the zoom factor of the output device differs from the
486 : : // one in the ViewOptions, this Font must not be cached,
487 : : // hence set zoom factor to an invalid value
488 : : long nTmp;
489 [ + - ][ + - ]: 2334 : if( pOut->GetMapMode().GetScaleX().IsValid() &&
[ + - ][ + - ]
[ + - ]
490 [ + - ]: 778 : pOut->GetMapMode().GetScaleY().IsValid() &&
491 [ + - ]: 778 : pOut->GetMapMode().GetScaleX() == pOut->GetMapMode().GetScaleY() )
492 : : {
493 : 778 : nTmp = ( 100 * pOut->GetMapMode().GetScaleX().GetNumerator() ) /
494 : 778 : pOut->GetMapMode().GetScaleX().GetDenominator();
495 : : }
496 : : else
497 : 0 : nTmp = 0;
498 [ - + ]: 778 : if( nTmp != nZoom )
499 : 0 : nZoom = USHRT_MAX - 1;
500 : : }
501 : :
502 [ + - ][ + - ]: 778 : nScrAscent = (sal_uInt16)pOut->GetFontMetric().GetAscent();
[ + - ]
503 [ + - ]: 778 : if ( USHRT_MAX == nScrHeight )
504 [ + - ]: 778 : nScrHeight = (sal_uInt16)pOut->GetTextHeight();
505 : :
506 : : // reset original output device font
507 [ + - ][ + - ]: 64036 : pOut->SetFont( aOldOutFont );
508 : : }
509 : :
510 : :
511 : 2785 : void SwFntObj::GuessLeading( const ViewShell&
512 : : #if defined(WNT)
513 : : rSh
514 : : #endif
515 : : , const FontMetric& rMet )
516 : : {
517 : : // If leading >= 5, this seems to be enough leading.
518 : : // Nothing has to be done.
519 [ + + ]: 2785 : if ( rMet.GetIntLeading() >= 5 )
520 : : {
521 : 2740 : nGuessedLeading = 0;
522 : 2785 : return;
523 : : }
524 : :
525 : : #if defined(WNT)
526 : : OutputDevice *pWin = rSh.GetWin() ?
527 : : rSh.GetWin() :
528 : : GetpApp()->GetDefaultDevice();
529 : : if ( pWin )
530 : : {
531 : : MapMode aTmpMap( MAP_TWIP );
532 : : MapMode aOldMap = pWin->GetMapMode( );
533 : : pWin->SetMapMode( aTmpMap );
534 : : const Font aOldFnt( pWin->GetFont() );
535 : : pWin->SetFont( *pPrtFont );
536 : : const FontMetric aWinMet( pWin->GetFontMetric() );
537 : : const sal_uInt16 nWinHeight = sal_uInt16( aWinMet.GetSize().Height() );
538 : : if( pPrtFont->GetName().Search( aWinMet.GetName() ) < USHRT_MAX )
539 : : {
540 : : // If the Leading on the Window is also 0, then it has to stay
541 : : // that way (see also StarMath).
542 : : long nTmpLeading = (long)aWinMet.GetIntLeading();
543 : : if( nTmpLeading <= 0 )
544 : : {
545 : : pWin->SetFont( rMet );
546 : : nTmpLeading = (long)pWin->GetFontMetric().GetIntLeading();
547 : : if( nTmpLeading < 0 )
548 : : nGuessedLeading = 0;
549 : : else
550 : : nGuessedLeading = sal_uInt16(nTmpLeading);
551 : : }
552 : : else
553 : : {
554 : : nGuessedLeading = sal_uInt16(nTmpLeading);
555 : : // Manta-Hack #50153#:
556 : : // Wer beim Leading luegt, luegt moeglicherweise auch beim
557 : : // Ascent/Descent, deshalb wird hier ggf. der Font ein wenig
558 : : // tiefergelegt, ohne dabei seine Hoehe zu aendern.
559 : : // (above original comment preserved for cultural reasons)
560 : : // Those who lie about their Leading, may lie about their
561 : : // Ascent/Descent as well, hence the Font will be lowered a
562 : : // litte without changing its height.
563 : : long nDiff = Min( rMet.GetDescent() - aWinMet.GetDescent(),
564 : : aWinMet.GetAscent() - rMet.GetAscent() - nTmpLeading );
565 : : if( nDiff > 0 )
566 : : {
567 : : OSL_ENSURE( nPrtAscent < USHRT_MAX, "GuessLeading: PrtAscent-Fault" );
568 : : if ( nPrtAscent < USHRT_MAX )
569 : : nPrtAscent = nPrtAscent + (sal_uInt16)(( 2 * nDiff ) / 5);
570 : : }
571 : : }
572 : : }
573 : : else
574 : : {
575 : : // If all else fails, take 15% of the height, as emprically
576 : : // determined by CL
577 : : nGuessedLeading = (nWinHeight * 15) / 100;
578 : : }
579 : : pWin->SetFont( aOldFnt );
580 : : pWin->SetMapMode( aOldMap );
581 : : }
582 : : else
583 : : #endif
584 : 45 : nGuessedLeading = 0;
585 : : }
586 : :
587 : : /*************************************************************************
588 : : *
589 : : * void SwFntObj::SetDeviceFont( const OutputDevice *pOut ),
590 : : *
591 : : * Set the font at the given output device; for screens it may be
592 : : * necessary to do some adjustment first.
593 : : *
594 : : *************************************************************************/
595 : :
596 : 307835 : void SwFntObj::SetDevFont( const ViewShell *pSh, OutputDevice& rOut )
597 : : {
598 [ + + ]: 307835 : const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
599 : :
600 [ + + ][ + + ]: 307835 : if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
[ + + ]
601 : : {
602 : 33829 : CreateScrFont( *pSh, rOut );
603 [ + + ]: 33829 : if( !GetScrFont()->IsSameInstance( rOut.GetFont() ) )
604 : 26930 : rOut.SetFont( *pScrFont );
605 [ + - ][ + + ]: 33829 : if( pPrinter && ( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) ) )
[ + + ]
606 : 2568 : pPrinter->SetFont( *pPrtFont );
607 : : }
608 : : else
609 : : {
610 : 274006 : CreatePrtFont( rOut );
611 [ + + ]: 274006 : if( !pPrtFont->IsSameInstance( rOut.GetFont() ) )
612 : 5066 : rOut.SetFont( *pPrtFont );
613 : : }
614 : :
615 : : // Here, we actually do not need the leading values, but by calling
616 : : // GetFontLeading() we assure that the values are calculated for later use.
617 : 307835 : GetFontLeading( pSh, rRefDev );
618 : 307835 : }
619 : :
620 : : #define WRONG_SHOW_MIN 5
621 : : #define WRONG_SHOW_SMALL 11
622 : : #define WRONG_SHOW_MEDIUM 15
623 : :
624 : : /*************************************************************************
625 : : *
626 : : * void SwFntObj::DrawText( ... )
627 : : *
628 : : * Output text:
629 : : * on screen => DrawTextArray
630 : : * on printer, !Kerning => DrawText
631 : : * on printer + Kerning => DrawStretchText
632 : : *
633 : : *************************************************************************/
634 : :
635 : 0 : sal_uInt8 lcl_WhichPunctuation( xub_Unicode cChar )
636 : : {
637 [ # # ][ # # ]: 0 : if ( ( cChar < 0x3001 || cChar > 0x3002 ) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
638 : : ( cChar < 0x3008 || cChar > 0x3011 ) &&
639 : : ( cChar < 0x3014 || cChar > 0x301F ) &&
640 : : 0xFF62 != cChar && 0xFF63 != cChar )
641 : : // no punctuation
642 : 0 : return SwScriptInfo::NONE;
643 [ # # ][ # # ]: 0 : else if ( 0x3001 == cChar || 0x3002 == cChar ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
644 : : 0x3009 == cChar || 0x300B == cChar ||
645 : : 0x300D == cChar || 0x300F == cChar ||
646 : : 0x3011 == cChar || 0x3015 == cChar ||
647 : : 0x3017 == cChar || 0x3019 == cChar ||
648 : : 0x301B == cChar || 0x301E == cChar ||
649 : : 0x301F == cChar || 0xFF63 == cChar )
650 : : // right punctuation
651 : 0 : return SwScriptInfo::SPECIAL_RIGHT;
652 : :
653 : 0 : return SwScriptInfo::SPECIAL_LEFT;
654 : : }
655 : :
656 : 0 : static sal_Bool lcl_IsMonoSpaceFont( const OutputDevice& rOut )
657 : : {
658 : 0 : const rtl::OUString aStr1( xub_Unicode( 0x3008 ) );
659 : 0 : const rtl::OUString aStr2( xub_Unicode( 0x307C ) );
660 [ # # ][ # # ]: 0 : const long nWidth1 = rOut.GetTextWidth( aStr1 );
[ # # ]
661 [ # # ][ # # ]: 0 : const long nWidth2 = rOut.GetTextWidth( aStr2 );
[ # # ]
662 : 0 : return nWidth1 == nWidth2;
663 : : }
664 : :
665 : : // ER 09.07.95 20:34
666 : : // mit -Ox Optimierung stuerzt's unter win95 ab
667 : : // JP 12.07.95: unter WNT auch (i386); Alpha ??
668 : : // global optimization off
669 : : #ifdef _MSC_VER
670 : : #pragma optimize("g",off)
671 : : #endif
672 : :
673 : : /* This helper structure (SwForbidden) contains the already marked parts of the string
674 : : to avoid double lines (e.g grammar + spell check error) */
675 : :
676 : : typedef std::vector< std::pair< xub_StrLen, xub_StrLen > > SwForbidden;
677 : :
678 : 68115 : static void lcl_DrawLineForWrongListData(
679 : : SwForbidden &rForbidden,
680 : : const SwDrawTextInfo &rInf,
681 : : const SwWrongList *pWList,
682 : : const CalcLinePosData &rCalcLinePosData,
683 : : const Size &rPrtFontSize )
684 : : {
685 [ + + ]: 68115 : if (!pWList)
686 : 68115 : return;
687 : :
688 : 33757 : xub_StrLen nStart = rInf.GetIdx();
689 : 33757 : xub_StrLen nWrLen = rInf.GetLen();
690 : :
691 : : // check if respective data is available in the current text range
692 [ + + ][ + - ]: 33757 : if (pWList->Check( nStart, nWrLen ))
693 : : {
694 : : // get line color to use...
695 : 2149 : Color aLineColor;
696 [ + + ]: 2149 : if (pWList == rInf.GetWrong()) // ... for spell checking
697 [ + - ]: 1754 : aLineColor = SwViewOption::GetSpellColor();
698 [ + - ]: 395 : else if (pWList == rInf.GetGrammarCheck()) // ... for grammar checking
699 : : // currently there is no specific color for grammar check errors available in the configuration
700 : 395 : aLineColor = Color( COL_LIGHTBLUE );
701 [ # # ]: 0 : else if (pWList == rInf.GetSmartTags()) // ... for smart tags
702 [ # # ]: 0 : aLineColor = SwViewOption::GetSmarttagColor();
703 : :
704 [ + - ]: 2149 : long nHght = rInf.GetOut().LogicToPixel( rPrtFontSize ).Height();
705 : :
706 : : // Draw wavy lines for spell and grammar errors only if font is large enough.
707 : : // Lines for smart tags will always be drawn.
708 [ + - ][ + - ]: 2149 : if (pWList == rInf.GetSmartTags() || WRONG_SHOW_MIN < nHght)
[ + - ]
709 : : {
710 : 2149 : SwForbidden::iterator pIter = rForbidden.begin();
711 [ - + ]: 2149 : if (rInf.GetOut().GetConnectMetaFile())
712 [ # # ]: 0 : rInf.GetOut().Push();
713 : :
714 : 2149 : const Color aCol( rInf.GetOut().GetLineColor() );
715 : 2149 : const sal_Bool bColSave = aCol != aLineColor;
716 [ + - ]: 2149 : if (bColSave)
717 [ + - ]: 2149 : rInf.GetOut().SetLineColor( aLineColor );
718 : :
719 : : // iterate over all ranges stored in the respective SwWrongList
720 [ + + ][ + + ]: 5746 : do
[ + + ]
721 : : {
722 : 3463 : nStart = nStart - rInf.GetIdx();
723 : :
724 : 3463 : const xub_StrLen nEnd = nStart + nWrLen;
725 : 3463 : xub_StrLen nNext = nStart;
726 [ + + ]: 7067 : while( nNext < nEnd )
727 : : {
728 [ + - ][ + + ]: 8560 : while( pIter != rForbidden.end() && pIter->second <= nNext )
[ + - ][ + + ]
[ + - ]
[ + + # # ]
729 [ + - ]: 4956 : ++pIter;
730 : 3604 : xub_StrLen nNextStart = nNext;
731 : 3604 : xub_StrLen nNextEnd = nEnd;
732 [ + - ][ + + ]: 3604 : if( pIter == rForbidden.end() || nNextEnd <= pIter->first )
[ + - ][ - + ]
[ + - ]
[ + + # # ]
733 : : {
734 : : // No overlapping mark up found
735 : 3301 : std::pair< xub_StrLen, xub_StrLen > aNew;
736 : 3301 : aNew.first = nNextStart;
737 : 3301 : aNew.second = nNextEnd;
738 [ + - ]: 3301 : rForbidden.insert( pIter, aNew );
739 : 3301 : pIter = rForbidden.begin();
740 : 3301 : nNext = nEnd;
741 : : }
742 : : else
743 : : {
744 [ + - ]: 303 : nNext = pIter->second;
745 [ + - ][ + + ]: 303 : if( nNextStart < pIter->first )
746 : : {
747 [ + - ]: 162 : nNextEnd = pIter->first;
748 [ + - ]: 162 : pIter->first = nNextStart;
749 : : }
750 : : else
751 : 141 : continue;
752 : : }
753 : : // determine line pos
754 : 3463 : Point aStart( rInf.GetPos() );
755 : 3463 : Point aEnd;
756 [ + - ]: 3463 : lcl_calcLinePos( rCalcLinePosData, aStart, aEnd, nNextStart, nNextEnd - nNextStart );
757 : :
758 : : // draw line for smart tags?
759 [ - + ]: 3463 : if (pWList == rInf.GetSmartTags())
760 : : {
761 : 0 : aStart.Y() +=30;
762 : 0 : aEnd.Y() +=30;
763 : :
764 [ # # ]: 0 : LineInfo aLineInfo( LINE_DASH );
765 [ # # ]: 0 : aLineInfo.SetDistance( 40 );
766 [ # # ]: 0 : aLineInfo.SetDashLen( 1 );
767 [ # # ]: 0 : aLineInfo.SetDashCount(1);
768 : :
769 [ # # ][ # # ]: 0 : rInf.GetOut().DrawLine( aStart, aEnd, aLineInfo );
770 : : }
771 : : else // draw wavy lines for spell or grammar errors
772 : : {
773 : : // get wavy line type to use
774 : : sal_uInt16 nWave =
775 : : WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
776 [ + + ][ + + ]: 3463 : ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL : WAVE_FLAT );
777 : :
778 [ + - ]: 3463 : rInf.GetOut().DrawWaveLine( aStart, aEnd, nWave );
779 : : }
780 : : }
781 : :
782 : 3463 : nStart = nEnd + rInf.GetIdx();
783 : 3463 : nWrLen = rInf.GetIdx() + rInf.GetLen() - nStart;
784 : : }
785 [ + - ]: 2283 : while (nWrLen && pWList->Check( nStart, nWrLen ));
786 : :
787 [ + - ]: 2149 : if (bColSave)
788 [ + - ]: 2149 : rInf.GetOut().SetLineColor( aCol );
789 : :
790 [ - + ]: 2149 : if (rInf.GetOut().GetConnectMetaFile())
791 [ # # ]: 68115 : rInf.GetOut().Pop();
792 : : }
793 : : }
794 : : }
795 : :
796 : :
797 : 26445 : void SwFntObj::DrawText( SwDrawTextInfo &rInf )
798 : : {
799 : : OSL_ENSURE( rInf.GetShell(), "SwFntObj::DrawText without shell" );
800 : :
801 [ + - ]: 26445 : OutputDevice& rRefDev = rInf.GetShell()->GetRefDev();
802 : 26445 : OutputDevice* pWin = rInf.GetShell()->GetWin();
803 : :
804 : : // true if pOut is the printer and the printer has been used for formatting
805 : 26445 : const sal_Bool bPrt = OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() &&
806 [ # # ][ - + ]: 26445 : OUTDEV_PRINTER == rRefDev.GetOutDevType();
807 : : const sal_Bool bBrowse = ( pWin &&
808 : 26200 : rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
809 : 23 : !rInf.GetShell()->GetViewOptions()->IsPrtFormat() &&
810 : 23 : !rInf.GetBullet() &&
811 : 46 : ( rInf.GetSpace() || !rInf.GetKern() ) &&
812 : 23 : !rInf.GetWrong() &&
813 : 23 : !rInf.GetGrammarCheck() &&
814 : 23 : !rInf.GetSmartTags() &&
815 [ + + + + : 52806 : !rInf.GetGreyWave() );
+ - + - +
- + - + -
+ - + - ]
[ + - ]
816 : :
817 : : // bDirectPrint indicates that we can enter the branch which calls
818 : : // the DrawText functions instead of calling the DrawTextArray functions
819 [ + - ][ + + ]: 26445 : const sal_Bool bDirectPrint = bPrt || bBrowse;
820 : :
821 : : // Condition for output font / refdev font adjustment
822 : : const sal_Bool bUseScrFont =
823 : 26445 : lcl_IsFontAdjustNecessary( rInf.GetOut(), rRefDev );
824 : :
825 [ + + ]: 26445 : Font* pTmpFont = bUseScrFont ? pScrFont : pPrtFont;
826 : :
827 : : //
828 : : // bDirectPrint and bUseScrFont should have these values:
829 : : //
830 : : // Outdev / RefDef | Printer | VirtPrinter | Window
831 : : // ----------------------------------------------------
832 : : // Printer | 1 - 0 | 0 - 1 | -
833 : : // ----------------------------------------------------
834 : : // VirtPrinter/PDF | 0 - 1 | 0 - 1 | -
835 : : // ----------------------------------------------------
836 : : // Window/VirtWindow| 0 - 1 | 0 - 1 | 1 - 0
837 : : //
838 : : // Exception: During painting of a Writer OLE object, we do not have
839 : : // a window. Therefore bUseSrcFont is always 0 in this case.
840 : : //
841 : :
842 : : #if OSL_DEBUG_LEVEL > 0
843 : :
844 : : const sal_Bool bNoAdjust = bPrt ||
845 : : ( pWin &&
846 : : rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
847 : : !rInf.GetShell()->GetViewOptions()->IsPrtFormat() );
848 : :
849 : : if ( OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() )
850 : : {
851 : : // Printer output
852 : : if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
853 : : {
854 : : OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
855 : : }
856 : : else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
857 : : {
858 : : OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
859 : : }
860 : : else
861 : : {
862 : : OSL_FAIL( "Outdev Check failed" );
863 : : }
864 : : }
865 : : else if ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && ! pWin )
866 : : {
867 : : // PDF export
868 : : if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
869 : : {
870 : : OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
871 : : }
872 : : else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
873 : : {
874 : : OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
875 : : }
876 : : else
877 : : {
878 : : OSL_FAIL( "Outdev Check failed" );
879 : : }
880 : : }
881 : : else if ( OUTDEV_WINDOW == rInf.GetOut().GetOutDevType() ||
882 : : ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && pWin ) )
883 : : {
884 : : // Window or virtual window
885 : : if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
886 : : {
887 : : OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
888 : : }
889 : : else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
890 : : {
891 : : OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
892 : : }
893 : : else if ( OUTDEV_WINDOW == rRefDev.GetOutDevType() )
894 : : {
895 : : OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
896 : : }
897 : : else
898 : : {
899 : : OSL_FAIL( "Outdev Check failed" );
900 : : }
901 : : }
902 : : else
903 : : {
904 : : OSL_FAIL( "Outdev Check failed" );
905 : : }
906 : :
907 : : #endif
908 : :
909 : : // robust: better use the printer font instead of using no font at all
910 : : OSL_ENSURE( pTmpFont, "No screen or printer font?" );
911 [ - + ]: 26445 : if ( ! pTmpFont )
912 : 0 : pTmpFont = pPrtFont;
913 : :
914 : : // HACK: UNDERLINE_WAVE must not be abused any more, hence the grey wave
915 : : // line of the ExtendedAttributeSets will appear in the font color first
916 : :
917 [ + - ][ + - ]: 26445 : const sal_Bool bSwitchH2V = rInf.GetFrm() && rInf.GetFrm()->IsVertical();
[ - + ]
918 [ + - ]: 52890 : const sal_Bool bSwitchL2R = rInf.GetFrm() && rInf.GetFrm()->IsRightToLeft() &&
919 [ - + ][ # # ]: 52890 : ! rInf.IsIgnoreFrmRTL();
[ + - ]
920 : 26445 : const sal_uLong nMode = rInf.GetOut().GetLayoutMode();
921 : : const sal_Bool bBidiPor = ( bSwitchL2R !=
922 : 26445 : ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
923 : :
924 : : // be sure to have the correct layout mode at the printer
925 [ + - ]: 26445 : if ( pPrinter )
926 : : {
927 [ + - ]: 26445 : pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
928 [ + - ]: 26445 : pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
929 : : }
930 : :
931 : 26445 : Point aPos( rInf.GetPos() );
932 [ + - ]: 26445 : if( !bPrt )
933 : : {
934 [ + + ][ + - ]: 26445 : if( rInf.GetpOut() != pPixOut || rInf.GetOut().GetMapMode() != *pPixMap )
[ + + ][ + + ]
935 : : {
936 [ + - ]: 516 : *pPixMap = rInf.GetOut().GetMapMode();
937 : 516 : pPixOut = rInf.GetpOut();
938 : 516 : Size aTmp( 1, 1 );
939 [ + - ]: 516 : nPixWidth = rInf.GetOut().PixelToLogic( aTmp ).Width();
940 : : }
941 : :
942 [ + - ][ + - ]: 26445 : aPos.X() += rInf.GetFrm()->IsRightToLeft() ? 0 : nPixWidth;
943 : : }
944 : :
945 [ + - ]: 26445 : Color aOldColor( pTmpFont->GetColor() );
946 [ + - ]: 26445 : sal_Bool bChgColor = rInf.ApplyAutoColor( pTmpFont );
947 [ + - ][ + + ]: 26445 : if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
948 [ + - ]: 25908 : rInf.GetOut().SetFont( *pTmpFont );
949 [ + + ]: 26445 : if ( bChgColor )
950 [ + - ]: 25908 : pTmpFont->SetColor( aOldColor );
951 : :
952 [ - + ]: 26445 : if ( STRING_LEN == rInf.GetLen() )
953 : 0 : rInf.SetLen( rInf.GetText().Len() );
954 : :
955 : :
956 : : //
957 : : // ASIAN LINE AND CHARACTER GRID MODE START: snap to characters
958 : : //
959 : :
960 [ + - ][ + + ]: 51647 : if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
[ + - - + ]
[ - + ]
961 : 25202 : SW_CJK == rInf.GetFont()->GetActual() )
962 : : {
963 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
964 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars())
[ # # ][ # # ]
965 : : {
966 : : //for textgrid refactor
967 : : //const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
968 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
969 [ # # ][ # # ]: 0 : const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
970 [ # # ]: 0 : sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
971 : :
972 [ # # ]: 0 : if ( pPrinter )
973 : 0 : pPrinter->GetTextArray( rInf.GetText(), pKernArray,
974 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
975 : : else
976 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
977 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
978 : :
979 : 0 : long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
980 : :
981 : : const sal_uLong i = nWidthPerChar ?
982 : : ( nWidthPerChar - 1 ) / nGridWidth + 1:
983 [ # # ]: 0 : 1;
984 : :
985 : 0 : nWidthPerChar = i * nGridWidth;
986 : :
987 : : // position of first character, we take the printer position
988 : 0 : long nCharWidth = pKernArray[ 0 ];
989 : 0 : sal_uLong nHalfWidth = nWidthPerChar / 2;
990 : :
991 : : long nNextFix;
992 : :
993 : : // punctuation characters are not centered
994 : 0 : xub_Unicode cChar = rInf.GetText().GetChar( rInf.GetIdx() );
995 : 0 : sal_uInt8 nType = lcl_WhichPunctuation( cChar );
996 [ # # # ]: 0 : switch ( nType )
997 : : {
998 : : case SwScriptInfo::NONE :
999 : 0 : aPos.X() += ( nWidthPerChar - nCharWidth ) / 2;
1000 : 0 : nNextFix = nCharWidth / 2;
1001 : 0 : break;
1002 : : case SwScriptInfo::SPECIAL_RIGHT :
1003 : 0 : nNextFix = nHalfWidth;
1004 : 0 : break;
1005 : : default:
1006 : 0 : aPos.X() += nWidthPerChar - nCharWidth;
1007 : 0 : nNextFix = nCharWidth - nHalfWidth;
1008 : : }
1009 : :
1010 : : // calculate offsets
1011 [ # # ]: 0 : for ( xub_StrLen j = 1; j < rInf.GetLen(); ++j )
1012 : : {
1013 : 0 : long nScr = pKernArray[ j ] - pKernArray[ j - 1 ];
1014 : 0 : nNextFix += nWidthPerChar;
1015 : :
1016 : : // punctuation characters are not centered
1017 : 0 : cChar = rInf.GetText().GetChar( rInf.GetIdx() + j );
1018 : 0 : nType = lcl_WhichPunctuation( cChar );
1019 [ # # # ]: 0 : switch ( nType )
1020 : : {
1021 : : case SwScriptInfo::NONE :
1022 : 0 : pKernArray[ j - 1 ] = nNextFix - ( nScr / 2 );
1023 : 0 : break;
1024 : : case SwScriptInfo::SPECIAL_RIGHT :
1025 : 0 : pKernArray[ j - 1 ] = nNextFix - nHalfWidth;
1026 : 0 : break;
1027 : : default:
1028 : 0 : pKernArray[ j - 1 ] = nNextFix + nHalfWidth - nScr;
1029 : : }
1030 : : }
1031 : :
1032 : : // the layout engine requires the total width of the output
1033 : 0 : pKernArray[ rInf.GetLen() - 1 ] = rInf.GetWidth() -
1034 : 0 : aPos.X() + rInf.GetPos().X() ;
1035 : :
1036 [ # # ]: 0 : if ( bSwitchH2V )
1037 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1038 : :
1039 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1040 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1041 : :
1042 [ # # ]: 0 : delete[] pKernArray;
1043 : : return;
1044 : : }
1045 : : }
1046 : :
1047 : : // For text grid refactor
1048 : : // ASIAN LINE AND CHARACTER GRID MODE START: not snap to characters
1049 : : //
1050 [ + - ][ + + ]: 51647 : if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
[ + - - + ]
[ - + ]
1051 : 25202 : SW_CJK == rInf.GetFont()->GetActual() )
1052 : : {
1053 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1054 : :
1055 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
[ # # ][ # # ]
1056 : : {
1057 [ # # ]: 0 : const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
1058 : :
1059 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1060 [ # # ][ # # ]: 0 : long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
1061 [ # # ]: 0 : if( SW_LATIN == rInf.GetFont()->GetActual() )
1062 : 0 : nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
1063 : : else
1064 : 0 : nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
1065 : :
1066 [ # # ]: 0 : sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
1067 : :
1068 [ # # ]: 0 : if ( pPrinter )
1069 : 0 : pPrinter->GetTextArray( rInf.GetText(), pKernArray,
1070 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
1071 : : else
1072 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1073 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
1074 [ # # ]: 0 : if ( bSwitchH2V )
1075 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1076 [ # # ][ # # ]: 0 : if ( rInf.GetSpace() || rInf.GetKanaComp())
[ # # ]
1077 : : {
1078 : 0 : long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1079 : 0 : sal_Bool bSpecialJust = sal_False;
1080 [ # # ][ # # ]: 0 : if ( rInf.GetFont() && rInf.GetLen() )
[ # # ]
1081 : : {
1082 : 0 : const SwScriptInfo* pSI = rInf.GetScriptInfo();
1083 : 0 : const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1084 : : ///Kana Compression
1085 [ # # ]: 0 : if( SW_CJK == nActual && rInf.GetKanaComp() &&
[ # # # # ]
[ # # ][ # # ]
[ # # ]
1086 : 0 : pSI && pSI->CountCompChg() &&
1087 [ # # ]: 0 : lcl_IsMonoSpaceFont( *(rInf.GetpOut()) ) )
1088 : : {
1089 : 0 : pSI->Compress( pKernArray,rInf.GetIdx(), rInf.GetLen(),
1090 [ # # ][ # # ]: 0 : rInf.GetKanaComp(), (sal_uInt16)aFont.GetSize().Height(),&aPos );
1091 : 0 : bSpecialJust = sal_True;
1092 : : }
1093 : : ///Asian Justification
1094 [ # # ][ # # ]: 0 : if ( ( SW_CJK == nActual || SW_LATIN == nActual ) && nSpaceAdd )
[ # # ]
1095 : : {
1096 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1097 [ # # ][ # # ]: 0 : if (MsLangId::isKorean(aLang))
1098 : : {
1099 : 0 : long nSpaceSum = nSpaceAdd;
1100 [ # # ]: 0 : for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1101 : : {
1102 : 0 : pKernArray[ nI ] += nSpaceSum;
1103 : 0 : nSpaceSum += nSpaceAdd;
1104 : : }
1105 : 0 : bSpecialJust = sal_True;
1106 : 0 : nSpaceAdd = 0;
1107 : : }
1108 : : }
1109 : 0 : long nGridAddSum = nGridWidthAdd;
1110 [ # # ]: 0 : for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd )
1111 : : {
1112 : 0 : pKernArray[i] += nGridAddSum;
1113 : : }
1114 : 0 : long nKernSum = rInf.GetKern();
1115 [ # # ][ # # ]: 0 : if ( bSpecialJust || rInf.GetKern() )
[ # # ]
1116 : : {
1117 [ # # ]: 0 : for( xub_StrLen i = 0; i < rInf.GetLen(); i++, nKernSum += rInf.GetKern() )
1118 : : {
1119 [ # # ]: 0 : if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
1120 : 0 : nKernSum += nSpaceAdd;
1121 : 0 : pKernArray[i] += nKernSum;
1122 : : }
1123 : : ///With through/uderstr. Grouped style requires a blank at the end
1124 : : ///of a text edition special measures:
1125 [ # # ]: 0 : if( bPaintBlank && rInf.GetLen() && (CH_BLANK ==
[ # # # # ]
[ # # ]
1126 : 0 : rInf.GetText().GetChar( rInf.GetIdx() + rInf.GetLen() - 1) ) )
1127 : : {
1128 : : ///If it concerns a singular, underlined space acts,
1129 : : ///we must spend two:
1130 [ # # ]: 0 : if( 1 == rInf.GetLen() )
1131 : : {
1132 : 0 : pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
1133 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1134 [ # # ]: 0 : pKernArray, rInf.GetIdx(), 1 );
1135 : : }
1136 : : else
1137 : : {
1138 : 0 : pKernArray[ rInf.GetLen() - 2] += nSpaceAdd;
1139 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1140 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1141 : : }
1142 : : }
1143 : : else
1144 : : {
1145 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1146 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1147 : : }
1148 : : }
1149 : : else
1150 : : {
1151 : 0 : Point aTmpPos( aPos );
1152 : : xub_StrLen i;
1153 : 0 : xub_StrLen j = 0;
1154 : 0 : long nSpaceSum = 0;
1155 [ # # ]: 0 : for( i = 0; i < rInf.GetLen(); i++ )
1156 : : {
1157 [ # # ]: 0 : if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx() + i) )
1158 : : {
1159 : 0 : nSpaceSum += nSpaceAdd;
1160 [ # # ]: 0 : if( j < i)
1161 : 0 : rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1162 [ # # ]: 0 : rInf.GetIdx() + j, i - j );
1163 : 0 : j = i + 1;
1164 : 0 : pKernArray[i] = pKernArray[i] + nSpaceSum;
1165 : 0 : aTmpPos.X() = aPos.X() + pKernArray[ i ] + nKernSum;
1166 : : }
1167 : : }
1168 [ # # ]: 0 : if( j < i )
1169 : 0 : rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1170 [ # # ]: 0 : rInf.GetIdx() +j , i - j );
1171 : : }
1172 : : }
1173 : : }
1174 : : else
1175 : : {
1176 : : //long nKernAdd = rInf.GetKern();
1177 : 0 : long nKernAdd = 0;
1178 : 0 : long nGridAddSum = nGridWidthAdd + nKernAdd;
1179 [ # # ]: 0 : for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd + nKernAdd )
1180 : : {
1181 : 0 : pKernArray[i] += nGridAddSum;
1182 : : }
1183 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1184 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1185 : : }
1186 [ # # ]: 0 : delete[] pKernArray;
1187 : : return;
1188 : : }
1189 : : }
1190 : :
1191 : : //
1192 : : // DIRECT PAINTING WITHOUT SCREEN ADJUSTMENT
1193 : : //
1194 : :
1195 [ + + ]: 26445 : if ( bDirectPrint )
1196 : : {
1197 [ + - ]: 23 : const Fraction aTmp( 1, 1 );
1198 : 23 : sal_Bool bStretch = rInf.GetWidth() && ( rInf.GetLen() > 1 ) && bPrt
1199 [ # # ][ # # ]: 23 : && ( aTmp != rInf.GetOut().GetMapMode().GetScaleX() );
[ # # ]
[ - + # # ]
1200 : :
1201 [ - + ]: 23 : if ( bSwitchL2R )
1202 [ # # ]: 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1203 : :
1204 [ - + ]: 23 : if ( bSwitchH2V )
1205 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1206 : :
1207 : : // In the good old days we used to have a simple DrawText if the
1208 : : // output device is the printer. Now we need a DrawTextArray if
1209 : : // 1. KanaCompression is enabled
1210 : : // 2. Justified alignment
1211 : : // Simple kerning is handled by DrawStretchText
1212 [ + - ][ - + ]: 23 : if( rInf.GetSpace() || rInf.GetKanaComp() )
[ - + ]
1213 : : {
1214 [ # # ]: 0 : sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
1215 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1216 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
1217 : :
1218 [ # # ]: 0 : if( bStretch )
1219 : : {
1220 : 0 : xub_StrLen nZwi = rInf.GetLen() - 1;
1221 : 0 : long nDiff = rInf.GetWidth() - pKernArray[ nZwi ]
1222 : 0 : - rInf.GetLen() * rInf.GetKern();
1223 : 0 : long nRest = nDiff % nZwi;
1224 : : long nAdd;
1225 [ # # ]: 0 : if( nRest < 0 )
1226 : : {
1227 : 0 : nAdd = -1;
1228 : 0 : nRest += nZwi;
1229 : : }
1230 : : else
1231 : : {
1232 : 0 : nAdd = +1;
1233 : 0 : nRest = nZwi - nRest;
1234 : : }
1235 : 0 : nDiff /= nZwi;
1236 : 0 : long nSum = nDiff;
1237 [ # # ]: 0 : for( xub_StrLen i = 0; i < nZwi; )
1238 : : {
1239 : 0 : pKernArray[ i ] += nSum;
1240 [ # # ]: 0 : if( ++i == nRest )
1241 : 0 : nDiff += nAdd;
1242 : 0 : nSum += nDiff;
1243 : : }
1244 : : }
1245 : :
1246 : : //
1247 : : // Modify Array for special justifications
1248 : : //
1249 : 0 : long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1250 : 0 : sal_Bool bSpecialJust = sal_False;
1251 : :
1252 [ # # ][ # # ]: 0 : if ( rInf.GetFont() && rInf.GetLen() )
[ # # ]
1253 : : {
1254 : 0 : const SwScriptInfo* pSI = rInf.GetScriptInfo();
1255 : 0 : const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1256 : :
1257 : : // Kana Compression
1258 [ # # ]: 0 : if ( SW_CJK == nActual && rInf.GetKanaComp() &&
[ # # # # ]
[ # # ][ # # ]
[ # # ]
1259 : 0 : pSI && pSI->CountCompChg() &&
1260 [ # # ]: 0 : lcl_IsMonoSpaceFont( rInf.GetOut() ) )
1261 : : {
1262 : 0 : pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
1263 : 0 : rInf.GetKanaComp(),
1264 [ # # ][ # # ]: 0 : (sal_uInt16)aFont.GetSize().Height(), &aPos );
1265 : 0 : bSpecialJust = sal_True;
1266 : : }
1267 : :
1268 : : // Asian Justification
1269 [ # # ][ # # ]: 0 : if ( SW_CJK == nActual && nSpaceAdd )
1270 : : {
1271 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1272 : :
1273 [ # # ][ # # ]: 0 : if (MsLangId::isKorean(aLang))
1274 : : {
1275 : 0 : long nSpaceSum = nSpaceAdd;
1276 [ # # ]: 0 : for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1277 : : {
1278 : 0 : pKernArray[ nI ] += nSpaceSum;
1279 : 0 : nSpaceSum += nSpaceAdd;
1280 : : }
1281 : :
1282 : 0 : bSpecialJust = sal_True;
1283 : 0 : nSpaceAdd = 0;
1284 : : }
1285 : : }
1286 : :
1287 : : // Kashida Justification
1288 [ # # ][ # # ]: 0 : if ( SW_CTL == nActual && nSpaceAdd )
1289 : : {
1290 [ # # ][ # # ]: 0 : if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
[ # # ]
1291 : : {
1292 [ # # ][ # # ]: 0 : if ( pSI && pSI->CountKashida() &&
[ # # ][ # # ]
1293 : 0 : pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
1294 [ # # ]: 0 : rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
1295 : : {
1296 : 0 : bSpecialJust = sal_True;
1297 : 0 : nSpaceAdd = 0;
1298 : : }
1299 : : }
1300 : : }
1301 : :
1302 : : // Thai Justification
1303 [ # # ][ # # ]: 0 : if ( SW_CTL == nActual && nSpaceAdd )
1304 : : {
1305 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
1306 : :
1307 [ # # ]: 0 : if ( LANGUAGE_THAI == aLang )
1308 : : {
1309 : : // Use rInf.GetSpace() because it has more precision than
1310 : : // nSpaceAdd:
1311 : 0 : SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
1312 : 0 : rInf.GetIdx(), rInf.GetLen(),
1313 : 0 : rInf.GetNumberOfBlanks(),
1314 [ # # ][ # # ]: 0 : rInf.GetSpace() );
1315 : :
1316 : : // adding space to blanks is already done
1317 : 0 : bSpecialJust = sal_True;
1318 : 0 : nSpaceAdd = 0;
1319 : : }
1320 : : }
1321 : : }
1322 : :
1323 : 0 : long nKernSum = rInf.GetKern();
1324 : :
1325 [ # # ][ # # ]: 0 : if ( bStretch || bPaintBlank || rInf.GetKern() || bSpecialJust )
[ # # ][ # # ]
[ # # ]
1326 : : {
1327 [ # # ]: 0 : for( xub_StrLen i = 0; i < rInf.GetLen(); i++,
1328 : : nKernSum += rInf.GetKern() )
1329 : : {
1330 [ # # ]: 0 : if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
1331 : 0 : nKernSum += nSpaceAdd;
1332 : 0 : pKernArray[i] += nKernSum;
1333 : : }
1334 : :
1335 : : // In case of underlined/strike-through justified text
1336 : : // a blank at the end requires special handling:
1337 [ # # ]: 0 : if( bPaintBlank && rInf.GetLen() && ( CH_BLANK ==
[ # # # # ]
[ # # ]
1338 : 0 : rInf.GetText().GetChar( rInf.GetIdx()+rInf.GetLen()-1 ) ) )
1339 : : {
1340 : : // If it is a single underlined space, output 2 spaces:
1341 [ # # ]: 0 : if( 1 == rInf.GetLen() )
1342 : : {
1343 : 0 : pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
1344 : :
1345 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1346 [ # # ]: 0 : pKernArray, rInf.GetIdx(), 1 );
1347 : : }
1348 : : else
1349 : : {
1350 : 0 : pKernArray[ rInf.GetLen() - 2 ] += nSpaceAdd;
1351 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1352 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1353 : : }
1354 : : }
1355 : : else
1356 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1357 [ # # ]: 0 : pKernArray, rInf.GetIdx(), rInf.GetLen() );
1358 : : }
1359 : : else
1360 : : {
1361 : 0 : Point aTmpPos( aPos );
1362 : 0 : xub_StrLen j = 0;
1363 : : xub_StrLen i;
1364 [ # # ]: 0 : for( i = 0; i < rInf.GetLen(); i++ )
1365 : : {
1366 [ # # ]: 0 : if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx()+i ) )
1367 : : {
1368 : 0 : nKernSum += nSpaceAdd;
1369 [ # # ]: 0 : if( j < i )
1370 : 0 : rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1371 [ # # ]: 0 : rInf.GetIdx() + j, i - j );
1372 : 0 : j = i + 1;
1373 : 0 : SwTwips nAdd = pKernArray[ i ] + nKernSum;
1374 [ # # ]: 0 : if ( ( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ) == nMode )
1375 : 0 : nAdd *= -1;
1376 : 0 : aTmpPos.X() = aPos.X() + nAdd;
1377 : : }
1378 : : }
1379 [ # # ]: 0 : if( j < i )
1380 : 0 : rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
1381 [ # # ]: 0 : rInf.GetIdx() + j, i - j );
1382 : : }
1383 [ # # ]: 0 : delete[] pKernArray;
1384 : : }
1385 [ - + ]: 23 : else if( bStretch )
1386 : : {
1387 : 0 : long nTmpWidth = rInf.GetWidth();
1388 [ # # ][ # # ]: 0 : if( rInf.GetKern() && rInf.GetLen() && nTmpWidth > rInf.GetKern() )
[ # # ][ # # ]
1389 : 0 : nTmpWidth -= rInf.GetKern();
1390 : 0 : rInf.GetOut().DrawStretchText( aPos, nTmpWidth,
1391 [ # # ]: 0 : rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
1392 : : }
1393 [ - + ]: 23 : else if( rInf.GetKern() )
1394 : : {
1395 [ # # ]: 0 : const long nTmpWidth = GetTextSize( rInf ).Width();
1396 : :
1397 [ # # ]: 0 : const Color aSaveColor( pTmpFont->GetColor() );
1398 [ # # ]: 0 : const sal_Bool bColorChanged = rInf.ApplyAutoColor( pTmpFont );
1399 : :
1400 [ # # ]: 0 : if( bColorChanged )
1401 : : {
1402 [ # # ][ # # ]: 0 : if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
1403 [ # # ]: 0 : rInf.GetOut().SetFont( *pTmpFont );
1404 [ # # ]: 0 : pTmpFont->SetColor( aSaveColor );
1405 : : }
1406 : :
1407 : 0 : rInf.GetOut().DrawStretchText( aPos, (sal_uInt16)nTmpWidth,
1408 [ # # ]: 0 : rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
1409 : : }
1410 : : else
1411 : 23 : rInf.GetOut().DrawText( aPos, rInf.GetText(),
1412 [ + - ]: 46 : rInf.GetIdx(), rInf.GetLen() );
1413 : : }
1414 : :
1415 : : //
1416 : : // PAINTING WITH FORMATTING DEVICE/SCREEN ADJUSTMENT
1417 : : //
1418 : :
1419 : : else
1420 : : {
1421 : 26422 : const String* pStr = &rInf.GetText();
1422 [ + - ]: 26422 : String aStr( aEmptyStr );
1423 : 26422 : sal_Bool bBullet = rInf.GetBullet();
1424 [ + + ]: 26422 : if( bSymbol )
1425 : 14 : bBullet = sal_False;
1426 [ + - ]: 26422 : sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
1427 [ + - ]: 26422 : CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
1428 : : long nScrPos;
1429 : :
1430 : : // get screen array
1431 [ + - ]: 26422 : sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
1432 : 26422 : rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
1433 [ + - ]: 52844 : rInf.GetIdx(), rInf.GetLen() );
1434 : :
1435 : : // OLE: no printer available
1436 : : // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" )
1437 [ + - ]: 26422 : if ( pPrinter )
1438 : : {
1439 : : // pTmpFont has already been set as current font for rInf.GetOut()
1440 [ - + ][ # # ]: 26422 : if ( pPrinter != rInf.GetpOut() || pTmpFont != pPrtFont )
[ + - ]
1441 : : {
1442 [ + - ][ + + ]: 26422 : if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1443 [ + - ]: 25885 : pPrinter->SetFont( *pPrtFont );
1444 : : }
1445 : 26422 : pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),
1446 [ + - ]: 52844 : rInf.GetLen() );
1447 : : }
1448 : : else
1449 : : {
1450 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1451 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
1452 : : }
1453 : :
1454 : : //
1455 : : // Modify Printer and ScreenArrays for special justifications
1456 : : //
1457 : 26422 : long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1458 : 26422 : bool bNoHalfSpace = false;
1459 : :
1460 [ + - ][ + - ]: 26422 : if ( rInf.GetFont() && rInf.GetLen() )
[ + - ]
1461 : : {
1462 : 26422 : const sal_uInt8 nActual = rInf.GetFont()->GetActual();
1463 : 26422 : const SwScriptInfo* pSI = rInf.GetScriptInfo();
1464 : :
1465 : : // Kana Compression
1466 [ # # ]: 26422 : if ( SW_CJK == nActual && rInf.GetKanaComp() &&
[ # # # # ]
[ # # ][ - + ]
[ - + ]
1467 : 0 : pSI && pSI->CountCompChg() &&
1468 [ # # ]: 0 : lcl_IsMonoSpaceFont( rInf.GetOut() ) )
1469 : : {
1470 : 0 : Point aTmpPos( aPos );
1471 : 0 : pSI->Compress( pScrArray, rInf.GetIdx(), rInf.GetLen(),
1472 : 0 : rInf.GetKanaComp(),
1473 [ # # ][ # # ]: 0 : (sal_uInt16)aFont.GetSize().Height(), &aTmpPos );
1474 : 0 : pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
1475 : 0 : rInf.GetKanaComp(),
1476 [ # # ][ # # ]: 0 : (sal_uInt16)aFont.GetSize().Height(), &aPos );
1477 : : }
1478 : :
1479 : : // Asian Justification
1480 [ - + ][ # # ]: 26422 : if ( SW_CJK == nActual && nSpaceAdd )
1481 : : {
1482 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
1483 : :
1484 [ # # ][ # # ]: 0 : if (MsLangId::isKorean(aLang))
1485 : : {
1486 : 0 : long nSpaceSum = nSpaceAdd;
1487 [ # # ]: 0 : for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
1488 : : {
1489 : 0 : pKernArray[ nI ] += nSpaceSum;
1490 : 0 : pScrArray[ nI ] += nSpaceSum;
1491 : 0 : nSpaceSum += nSpaceAdd;
1492 : : }
1493 : :
1494 : 0 : nSpaceAdd = 0;
1495 : : }
1496 : : }
1497 : :
1498 : : // Kashida Justification
1499 [ - + ][ # # ]: 26422 : if ( SW_CTL == nActual && nSpaceAdd )
1500 : : {
1501 [ # # ][ # # ]: 0 : if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
[ # # ]
1502 : : {
1503 [ # # ][ # # ]: 0 : if ( pSI && pSI->CountKashida() &&
[ # # ][ # # ]
1504 : 0 : pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
1505 [ # # ]: 0 : rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
1506 : 0 : nSpaceAdd = 0;
1507 : : else
1508 : 0 : bNoHalfSpace = true;
1509 : : }
1510 : : }
1511 : :
1512 : : // Thai Justification
1513 [ - + ][ # # ]: 26422 : if ( SW_CTL == nActual && nSpaceAdd )
1514 : : {
1515 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
1516 : :
1517 [ # # ]: 0 : if ( LANGUAGE_THAI == aLang )
1518 : : {
1519 : 0 : SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray,
1520 : 0 : pScrArray, rInf.GetIdx(),
1521 : 0 : rInf.GetLen(),
1522 : 0 : rInf.GetNumberOfBlanks(),
1523 [ # # ][ # # ]: 0 : rInf.GetSpace() );
1524 : :
1525 : : // adding space to blanks is already done
1526 : 0 : nSpaceAdd = 0;
1527 : : }
1528 : : }
1529 : : }
1530 : :
1531 : 26422 : nScrPos = pScrArray[ 0 ];
1532 : :
1533 [ - + ]: 26422 : if( bBullet )
1534 : : {
1535 : : // !!! HACK !!!
1536 : : // The Arabic layout engine requires some context of the string
1537 : : // which should be painted.
1538 : 0 : xub_StrLen nCopyStart = rInf.GetIdx();
1539 [ # # ]: 0 : if ( nCopyStart )
1540 : 0 : --nCopyStart;
1541 : :
1542 : 0 : xub_StrLen nCopyLen = rInf.GetLen();
1543 [ # # ]: 0 : if ( nCopyStart + nCopyLen < rInf.GetText().Len() )
1544 : 0 : ++nCopyLen;
1545 : :
1546 [ # # ][ # # ]: 0 : aStr = rInf.GetText().Copy( nCopyStart, nCopyLen );
[ # # ]
1547 : 0 : pStr = &aStr;
1548 : :
1549 [ # # ]: 0 : for( xub_StrLen i = 0; i < aStr.Len(); ++i )
1550 [ # # ]: 0 : if( CH_BLANK == aStr.GetChar( i ) )
1551 [ # # ]: 0 : aStr.SetChar( i, CH_BULLET );
1552 : : }
1553 : :
1554 : 26422 : xub_StrLen nCnt = rInf.GetText().Len();
1555 [ - + ]: 26422 : if ( nCnt < rInf.GetIdx() )
1556 : 0 : nCnt = 0;
1557 : : else
1558 : 26422 : nCnt = nCnt - rInf.GetIdx();
1559 : 26422 : nCnt = Min( nCnt, rInf.GetLen() );
1560 : 26422 : long nKernSum = rInf.GetKern();
1561 : 26422 : xub_Unicode cChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
1562 : :
1563 : : // In case of a single underlined space in justified text,
1564 : : // have to output 2 spaces:
1565 [ - + ][ # # ]: 26422 : if ( ( nCnt == 1 ) && rInf.GetSpace() && ( cChPrev == CH_BLANK ) )
[ - + ][ + + ]
1566 : : {
1567 : 0 : pKernArray[0] = rInf.GetWidth() +
1568 : 0 : rInf.GetKern() +
1569 : 0 : ( rInf.GetSpace() / SPACING_PRECISION_FACTOR );
1570 : :
1571 [ # # ]: 0 : if ( bSwitchL2R )
1572 [ # # ]: 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1573 : :
1574 [ # # ]: 0 : if ( bSwitchH2V )
1575 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1576 : :
1577 : 0 : rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
1578 [ # # ]: 0 : pKernArray, rInf.GetIdx(), 1 );
1579 [ # # ]: 0 : if( bBullet )
1580 : 0 : rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray,
1581 [ # # ][ # # ]: 0 : rInf.GetIdx() ? 1 : 0, 1 );
1582 : : }
1583 : : else
1584 : : {
1585 : : xub_Unicode nCh;
1586 : :
1587 : : // In case of Pair Kerning the printer influence on the positioning
1588 : : // grows
1589 : 26422 : sal_uInt16 nMul = 3;
1590 : :
1591 [ + - ][ + + ]: 26422 : if ( pPrtFont->GetKerning() )
1592 : 26198 : nMul = 1;
1593 : :
1594 : 26422 : const sal_uInt16 nDiv = nMul+1;
1595 : :
1596 : : // nSpaceSum contains the sum of the intermediate space distributed
1597 : : // among Spaces by the Justification.
1598 : : // The Spaces themselves will be positioned in the middle of the
1599 : : // intermediate space, hence the nSpace/2.
1600 : : // In case of word-by-word underlining they have to be positioned
1601 : : // at the beginning of the intermediate space, so that the space
1602 : : // is not underlined.
1603 : : // A Space at the beginning or end of the text must be positioned
1604 : : // before (resp. after) the whole intermediate space, otherwise
1605 : : // the underline/strike-through would have gaps.
1606 : 26422 : long nSpaceSum = 0;
1607 : : // in word line mode and for Arabic, we disable the half space trick:
1608 [ + - ][ + + ]: 26422 : const long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2;
[ + - ]
1609 : 26422 : const long nOtherHalf = nSpaceAdd - nHalfSpace;
1610 [ - + ][ # # ]: 26422 : if ( nSpaceAdd && ( cChPrev == CH_BLANK ) )
1611 : 0 : nSpaceSum = nHalfSpace;
1612 [ + + ]: 1424710 : for ( xub_StrLen i=1; i<nCnt; ++i,nKernSum += rInf.GetKern() )
1613 : : {
1614 : 1398288 : nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
1615 : :
1616 : : OSL_ENSURE( pScrArray, "Where is the screen array?" );
1617 : : long nScr;
1618 : 1398288 : nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
1619 : :
1620 : : // If there is an (ex-)Space before us, position optimally,
1621 : : // i.e., our right margin to the 100% printer position;
1622 : : // if we _are_ an ex-Space, position us left-aligned to the
1623 : : // printer position.
1624 [ + + ]: 1398288 : if ( nCh == CH_BLANK )
1625 : : {
1626 : 134217 : nScrPos = pKernArray[i-1] + nScr;
1627 : :
1628 [ + + ]: 134217 : if ( cChPrev == CH_BLANK )
1629 : 22 : nSpaceSum += nOtherHalf;
1630 [ + + ]: 134217 : if ( i + 1 == nCnt )
1631 : 12269 : nSpaceSum += nSpaceAdd;
1632 : : else
1633 : 121948 : nSpaceSum += nHalfSpace;
1634 : : }
1635 : : else
1636 : : {
1637 [ + + ]: 1264071 : if ( cChPrev == CH_BLANK )
1638 : : {
1639 : 122873 : nScrPos = pKernArray[i-1] + nScr;
1640 : : // no Pixel is lost:
1641 : 122873 : nSpaceSum += nOtherHalf;
1642 : : }
1643 [ + + ]: 1141198 : else if ( cChPrev == '-' )
1644 : 9136 : nScrPos = pKernArray[i-1] + nScr;
1645 : : else
1646 : : {
1647 : 1132062 : nScrPos += nScr;
1648 : 1132062 : nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
1649 : : }
1650 : : }
1651 : 1398288 : cChPrev = nCh;
1652 : 1398288 : pKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum;
1653 : : // In word line mode and for Arabic, we disabled the half space trick. If a portion
1654 : : // ends with a blank, the full nSpaceAdd value has been added to the character in
1655 : : // front of the blank. This leads to painting artifacts, therefore we remove the
1656 : : // nSpaceAdd value again:
1657 [ + - ][ + - ]: 1398288 : if ( (bNoHalfSpace || pPrtFont->IsWordLineMode()) && i+1 == nCnt && nCh == CH_BLANK )
[ + + ][ + + ]
[ - + ][ - + ]
1658 : 0 : pKernArray[i-1] = pKernArray[i-1] - nSpaceAdd;
1659 : : }
1660 : :
1661 : : // the layout engine requires the total width of the output
1662 : 26422 : pKernArray[ rInf.GetLen() - 1 ] += nKernSum + nSpaceSum;
1663 : :
1664 [ - + ]: 26422 : if( rInf.GetGreyWave() )
1665 : : {
1666 [ # # ]: 0 : if( rInf.GetLen() )
1667 : : {
1668 : 0 : long nHght = rInf.GetOut().LogicToPixel(
1669 [ # # # # ]: 0 : pPrtFont->GetSize() ).Height();
1670 [ # # ]: 0 : if( WRONG_SHOW_MIN < nHght )
1671 : : {
1672 [ # # ]: 0 : if ( rInf.GetOut().GetConnectMetaFile() )
1673 [ # # ]: 0 : rInf.GetOut().Push();
1674 : :
1675 : : sal_uInt16 nWave =
1676 : : WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
1677 : : ( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL :
1678 [ # # ][ # # ]: 0 : WAVE_FLAT );
1679 : 0 : Color aCol( rInf.GetOut().GetLineColor() );
1680 : 0 : sal_Bool bColSave = aCol != *pWaveCol;
1681 [ # # ]: 0 : if ( bColSave )
1682 [ # # ]: 0 : rInf.GetOut().SetLineColor( *pWaveCol );
1683 : :
1684 : 0 : Point aEnd;
1685 : 0 : long nKernVal = pKernArray[ sal_uInt16( rInf.GetLen() - 1 ) ];
1686 : :
1687 : : sal_uInt16 nDir = bBidiPor ?
1688 : : 1800 :
1689 : : UnMapDirection(
1690 [ # # ]: 0 : GetFont()->GetOrientation(),
1691 [ # # ][ # # ]: 0 : bSwitchH2V );
1692 : :
1693 [ # # # # : 0 : switch ( nDir )
# ]
1694 : : {
1695 : : case 0 :
1696 : 0 : aEnd.X() = rInf.GetPos().X() + nKernVal;
1697 : 0 : aEnd.Y() = rInf.GetPos().Y();
1698 : 0 : break;
1699 : : case 900 :
1700 : 0 : aEnd.X() = rInf.GetPos().X();
1701 : 0 : aEnd.Y() = rInf.GetPos().Y() - nKernVal;
1702 : 0 : break;
1703 : : case 1800 :
1704 : 0 : aEnd.X() = rInf.GetPos().X() - nKernVal;
1705 : 0 : aEnd.Y() = rInf.GetPos().Y();
1706 : 0 : break;
1707 : : case 2700 :
1708 : 0 : aEnd.X() = rInf.GetPos().X();
1709 : 0 : aEnd.Y() = rInf.GetPos().Y() + nKernVal;
1710 : 0 : break;
1711 : : }
1712 : :
1713 : 0 : Point aCurrPos( rInf.GetPos() );
1714 : :
1715 [ # # ]: 0 : if ( bSwitchL2R )
1716 : : {
1717 [ # # ]: 0 : rInf.GetFrm()->SwitchLTRtoRTL( aCurrPos );
1718 [ # # ]: 0 : rInf.GetFrm()->SwitchLTRtoRTL( aEnd );
1719 : : }
1720 : :
1721 [ # # ]: 0 : if ( bSwitchH2V )
1722 : : {
1723 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aCurrPos );
1724 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aEnd );
1725 : : }
1726 [ # # ]: 0 : rInf.GetOut().DrawWaveLine( aCurrPos, aEnd, nWave );
1727 : :
1728 [ # # ]: 0 : if ( bColSave )
1729 [ # # ]: 0 : rInf.GetOut().SetLineColor( aCol );
1730 : :
1731 [ # # ]: 0 : if ( rInf.GetOut().GetConnectMetaFile() )
1732 [ # # ]: 0 : rInf.GetOut().Pop();
1733 : : }
1734 : : }
1735 : : }
1736 [ + + ][ + - ]: 26422 : else if( !bSymbol && rInf.GetLen() )
[ + + ]
1737 : : {
1738 : : // anything to do?
1739 [ + + ][ + + ]: 26408 : if (rInf.GetWrong() || rInf.GetGrammarCheck() || rInf.GetSmartTags())
[ - + ][ + + ]
1740 : : {
1741 : 22705 : CalcLinePosData aCalcLinePosData(rInf, *GetFont(),
1742 : : nCnt, bSwitchH2V, bSwitchL2R,
1743 : 22705 : nHalfSpace, pKernArray, bBidiPor);
1744 : :
1745 [ + - ]: 22705 : SwForbidden aForbidden;
1746 : : // draw line for smart tag data
1747 [ + - ]: 22705 : lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetSmartTags(), aCalcLinePosData, Size() );
1748 : : // draw wave line for spell check errors
1749 : : // draw them BEFORE the grammar check lines to 'override' the latter in case of conflict.
1750 : : // reason: some grammar errors can only be found if spelling errors are fixed,
1751 : : // therefore we don't want the user to miss a spelling error.
1752 [ + - ][ + - ]: 22705 : lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetWrong(), aCalcLinePosData, pPrtFont->GetSize() );
1753 : : // draw wave line for grammar check errors
1754 [ + - ][ + - ]: 22705 : lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetGrammarCheck(), aCalcLinePosData, pPrtFont->GetSize() );
1755 : : }
1756 : : }
1757 : :
1758 : 26422 : xub_StrLen nOffs = 0;
1759 : 26422 : xub_StrLen nLen = rInf.GetLen();
1760 : :
1761 [ + - ]: 26422 : if( nOffs < nLen )
1762 : : {
1763 : : // If we paint bullets instead of spaces, we use a copy of
1764 : : // the paragraph string. For the layout engine, the copy
1765 : : // of the string has to be an environment of the range which
1766 : : // is painted
1767 : : xub_StrLen nTmpIdx = bBullet ?
1768 : 0 : ( rInf.GetIdx() ? 1 : 0 ) :
1769 [ - + # # ]: 26422 : rInf.GetIdx();
1770 : :
1771 [ - + ]: 26422 : if ( bSwitchL2R )
1772 [ # # ]: 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
1773 : :
1774 [ - + ]: 26422 : if ( bSwitchH2V )
1775 [ # # ]: 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
1776 : :
1777 : 26422 : rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
1778 [ + - ]: 26422 : nTmpIdx + nOffs , nLen - nOffs );
1779 : : }
1780 : : }
1781 [ + - ]: 26422 : delete[] pScrArray;
1782 [ + - ][ + - ]: 26445 : delete[] pKernArray;
1783 : : }
1784 : : }
1785 : :
1786 : :
1787 : : // optimization disabled for DrawText()
1788 : : #ifdef _MSC_VER
1789 : : #pragma optimize("",on)
1790 : : #endif
1791 : :
1792 : :
1793 : : /*************************************************************************
1794 : : *
1795 : : * Size SwFntObj::GetTextSize( const OutputDevice *pOut, const String &rTxt,
1796 : : * const sal_uInt16 nIdx, const sal_uInt16 nLen, const short nKern = 0 );
1797 : : *
1798 : : * determine the TextSize (of the printer)
1799 : : *
1800 : : *************************************************************************/
1801 : :
1802 : 54588 : Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
1803 : : {
1804 : 54588 : Size aTxtSize;
1805 : 54588 : const xub_StrLen nLn = ( STRING_LEN != rInf.GetLen() ) ? rInf.GetLen() :
1806 [ + - ]: 54588 : rInf.GetText().Len();
1807 : :
1808 : : // be sure to have the correct layout mode at the printer
1809 [ + + ]: 54588 : if ( pPrinter )
1810 : : {
1811 : 54524 : pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
1812 : 54524 : pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
1813 : : }
1814 : :
1815 [ + + ][ + - ]: 107056 : if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
[ + + ]
[ + - + + ]
[ + + ]
1816 : 52468 : SW_CJK == rInf.GetFont()->GetActual() )
1817 : : {
1818 [ + - ][ - + ]: 3 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ - + ]
1819 [ - + ][ # # ]: 3 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
[ # # ][ - + ]
1820 : : {
1821 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1822 [ # # ]: 0 : const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
1823 : :
1824 : : OutputDevice* pOutDev;
1825 : :
1826 [ # # ]: 0 : if ( pPrinter )
1827 : : {
1828 [ # # ]: 0 : if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1829 : 0 : pPrinter->SetFont(*pPrtFont);
1830 : 0 : pOutDev = pPrinter;
1831 : : }
1832 : : else
1833 : 0 : pOutDev = rInf.GetpOut();
1834 : :
1835 : 0 : aTxtSize.Width() =
1836 : 0 : pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
1837 : :
1838 : : OSL_ENSURE( !rInf.GetShell() ||
1839 : : ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
1840 : : "Leading values should be already calculated" );
1841 : 0 : aTxtSize.Height() = pOutDev->GetTextHeight() +
1842 : 0 : GetFontLeading( rInf.GetShell(), rInf.GetOut() );
1843 : :
1844 : 0 : long nWidthPerChar = aTxtSize.Width() / nLn;
1845 : :
1846 : : const sal_uLong i = nWidthPerChar ?
1847 : : ( nWidthPerChar - 1 ) / nGridWidth + 1:
1848 [ # # ]: 0 : 1;
1849 : :
1850 : 0 : aTxtSize.Width() = i * nGridWidth * nLn;
1851 : 0 : rInf.SetKanaDiff( 0 );
1852 : 0 : return aTxtSize;
1853 : : }
1854 : : }
1855 : :
1856 : : //for textgrid refactor
1857 [ + + ][ + - ]: 107056 : if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
[ + + ]
[ + - + + ]
[ + + ]
1858 : 52468 : SW_CJK == rInf.GetFont()->GetActual() )
1859 : : {
1860 [ + - ][ - + ]: 3 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ - + ]
1861 [ - + ][ # # ]: 3 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
[ # # ][ - + ]
1862 : : {
1863 : 0 : const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
1864 : :
1865 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
1866 [ # # ]: 0 : long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
1867 [ # # ]: 0 : if( SW_LATIN == rInf.GetFont()->GetActual() )
1868 : 0 : nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
1869 : : else
1870 : 0 : nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
1871 : : OutputDevice* pOutDev;
1872 [ # # ]: 0 : if ( pPrinter )
1873 : : {
1874 [ # # ]: 0 : if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1875 : 0 : pPrinter->SetFont(*pPrtFont);
1876 : 0 : pOutDev = pPrinter;
1877 : : }
1878 : : else
1879 : 0 : pOutDev = rInf.GetpOut();
1880 : 0 : aTxtSize.Width() = pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
1881 : 0 : aTxtSize.Height() = pOutDev->GetTextHeight() +
1882 : 0 : GetFontLeading( rInf.GetShell(), rInf.GetOut() );
1883 : 0 : aTxtSize.Width() += (nLn) * long( nGridWidthAdd );
1884 : : //if ( rInf.GetKern() && nLn )
1885 : : // aTxtSize.Width() += ( nLn ) * long( rInf.GetKern() );
1886 : :
1887 : 0 : rInf.SetKanaDiff( 0 );
1888 : 0 : return aTxtSize;
1889 : : }
1890 : : }
1891 : :
1892 : 54588 : const sal_Bool bCompress = rInf.GetKanaComp() && nLn &&
1893 : 0 : rInf.GetFont() &&
1894 : 0 : SW_CJK == rInf.GetFont()->GetActual() &&
1895 : 0 : rInf.GetScriptInfo() &&
1896 : 0 : rInf.GetScriptInfo()->CountCompChg() &&
1897 [ # # # # : 54588 : lcl_IsMonoSpaceFont( rInf.GetOut() );
# # # # #
# ][ # # ]
[ - + ]
1898 : :
1899 : : OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
1900 : : CountCompChg()), "Compression without info" );
1901 : :
1902 : : // This is the part used e.g., for cursor travelling
1903 : : // See condition for DrawText or DrawTextArray (bDirectPrint)
1904 [ + + ][ + + ]: 54588 : if ( pPrinter && pPrinter != rInf.GetpOut() )
[ + + ]
1905 : : {
1906 [ - + ]: 1264 : if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
1907 : 0 : pPrinter->SetFont(*pPrtFont);
1908 : 2528 : aTxtSize.Width() = pPrinter->GetTextWidth( rInf.GetText(),
1909 : 2528 : rInf.GetIdx(), nLn );
1910 : 1264 : aTxtSize.Height() = pPrinter->GetTextHeight();
1911 : 1264 : sal_Int32 *pKernArray = new sal_Int32[nLn];
1912 : 1264 : CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
1913 [ - + ]: 1264 : if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
1914 : 0 : rInf.GetOut().SetFont( *pScrFont );
1915 : : long nScrPos;
1916 : :
1917 : 1264 : pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),nLn );
1918 [ - + ]: 1264 : if( bCompress )
1919 : : rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
1920 : 0 : rInf.GetIdx(), nLn, rInf.GetKanaComp(),
1921 : 0 : (sal_uInt16)aFont.GetSize().Height() ) );
1922 : : else
1923 : 1264 : rInf.SetKanaDiff( 0 );
1924 : :
1925 [ - + ]: 1264 : if ( rInf.GetKanaDiff() )
1926 : 0 : nScrPos = pKernArray[ nLn - 1 ];
1927 : : else
1928 : : {
1929 : 1264 : sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
1930 : 1264 : rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
1931 : 2528 : rInf.GetIdx(), rInf.GetLen() );
1932 : 1264 : nScrPos = pScrArray[ 0 ];
1933 : 1264 : xub_StrLen nCnt = rInf.GetText().Len();
1934 [ - + ]: 1264 : if ( nCnt < rInf.GetIdx() )
1935 : 0 : nCnt=0;
1936 : : else
1937 : 1264 : nCnt = nCnt - rInf.GetIdx();
1938 : 1264 : nCnt = Min (nCnt, nLn);
1939 : 1264 : xub_Unicode nChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
1940 : :
1941 : : xub_Unicode nCh;
1942 : :
1943 : : // In case of Pair Kerning the printer influence on the positioning
1944 : : // grows
1945 : 1264 : sal_uInt16 nMul = 3;
1946 [ + - ]: 1264 : if ( pPrtFont->GetKerning() )
1947 : 1264 : nMul = 1;
1948 : 1264 : const sal_uInt16 nDiv = nMul+1;
1949 [ + + ]: 10713 : for( xub_StrLen i=1; i<nCnt; i++ )
1950 : : {
1951 : 9449 : nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
1952 : : long nScr;
1953 : 9449 : nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
1954 [ + + ]: 9449 : if ( nCh == CH_BLANK )
1955 : 1158 : nScrPos = pKernArray[i-1]+nScr;
1956 : : else
1957 : : {
1958 [ + + ][ + + ]: 8291 : if ( nChPrev == CH_BLANK || nChPrev == '-' )
1959 : 1062 : nScrPos = pKernArray[i-1]+nScr;
1960 : : else
1961 : : {
1962 : 7229 : nScrPos += nScr;
1963 : 7229 : nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
1964 : : }
1965 : : }
1966 : 9449 : nChPrev = nCh;
1967 : 9449 : pKernArray[i-1] = nScrPos - nScr;
1968 : : }
1969 [ + - ]: 1264 : delete[] pScrArray;
1970 : : }
1971 : :
1972 [ + - ]: 1264 : delete[] pKernArray;
1973 : 1264 : aTxtSize.Width() = nScrPos;
1974 : : }
1975 : : else
1976 : : {
1977 [ - + ]: 53324 : if( !pPrtFont->IsSameInstance( rInf.GetOut().GetFont() ) )
1978 : 0 : rInf.GetOut().SetFont( *pPrtFont );
1979 [ - + ]: 53324 : if( bCompress )
1980 : : {
1981 : 0 : sal_Int32 *pKernArray = new sal_Int32[nLn];
1982 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
1983 : 0 : rInf.GetIdx(), nLn );
1984 : : rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
1985 : 0 : rInf.GetIdx(), nLn, rInf.GetKanaComp(),
1986 : 0 : (sal_uInt16) aFont.GetSize().Height() ) );
1987 : 0 : aTxtSize.Width() = pKernArray[ nLn - 1 ];
1988 [ # # ]: 0 : delete[] pKernArray;
1989 : : }
1990 : : else
1991 : : {
1992 : 106648 : aTxtSize.Width() = rInf.GetOut().GetTextWidth( rInf.GetText(),
1993 : 106648 : rInf.GetIdx(), nLn );
1994 : 53324 : rInf.SetKanaDiff( 0 );
1995 : : }
1996 : :
1997 : 53324 : aTxtSize.Height() = rInf.GetOut().GetTextHeight();
1998 : : }
1999 : :
2000 [ + + ][ + - ]: 54588 : if ( rInf.GetKern() && nLn )
[ + + ]
2001 : 284 : aTxtSize.Width() += ( nLn - 1 ) * long( rInf.GetKern() );
2002 : :
2003 : : OSL_ENSURE( !rInf.GetShell() ||
2004 : : ( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
2005 : : "Leading values should be already calculated" );
2006 : 54588 : aTxtSize.Height() += GetFontLeading( rInf.GetShell(), rInf.GetOut() );
2007 : 54588 : return aTxtSize;
2008 : : }
2009 : :
2010 : :
2011 : 0 : xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
2012 : : {
2013 : 0 : long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
2014 : 0 : const long nSperren = -rInf.GetSperren() / SPACING_PRECISION_FACTOR;
2015 : 0 : long nKern = rInf.GetKern();
2016 : :
2017 [ # # ]: 0 : if( 0 != nSperren )
2018 : 0 : nKern -= nSperren;
2019 : :
2020 [ # # ]: 0 : sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
2021 : :
2022 : : // be sure to have the correct layout mode at the printer
2023 [ # # ]: 0 : if ( pPrinter )
2024 : : {
2025 [ # # ]: 0 : pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
2026 [ # # ]: 0 : pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
2027 : 0 : pPrinter->GetTextArray( rInf.GetText(), pKernArray,
2028 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
2029 : : }
2030 : : else
2031 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2032 [ # # ]: 0 : rInf.GetIdx(), rInf.GetLen() );
2033 : :
2034 : 0 : const SwScriptInfo* pSI = rInf.GetScriptInfo();
2035 [ # # ][ # # ]: 0 : if ( rInf.GetFont() && rInf.GetLen() )
[ # # ]
2036 : : {
2037 : 0 : const sal_uInt8 nActual = rInf.GetFont()->GetActual();
2038 : :
2039 : : // Kana Compression
2040 [ # # ]: 0 : if ( SW_CJK == nActual && rInf.GetKanaComp() &&
[ # # # # ]
[ # # ][ # # ]
[ # # ]
2041 : 0 : pSI && pSI->CountCompChg() &&
2042 [ # # ]: 0 : lcl_IsMonoSpaceFont( rInf.GetOut() ) )
2043 : : {
2044 : 0 : pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
2045 : 0 : rInf.GetKanaComp(),
2046 [ # # ][ # # ]: 0 : (sal_uInt16) aFont.GetSize().Height() );
2047 : : }
2048 : :
2049 : : // Asian Justification
2050 [ # # ]: 0 : if ( SW_CJK == rInf.GetFont()->GetActual() )
2051 : : {
2052 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
2053 : :
2054 [ # # ][ # # ]: 0 : if (MsLangId::isKorean(aLang))
2055 : : {
2056 : 0 : long nSpaceSum = nSpaceAdd;
2057 [ # # ]: 0 : for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
2058 : : {
2059 : 0 : pKernArray[ nI ] += nSpaceSum;
2060 : 0 : nSpaceSum += nSpaceAdd;
2061 : : }
2062 : :
2063 : 0 : nSpaceAdd = 0;
2064 : : }
2065 : :
2066 : : }
2067 : :
2068 : : // Kashida Justification
2069 [ # # ][ # # ]: 0 : if ( SW_CTL == nActual && rInf.GetSpace() )
[ # # ]
2070 : : {
2071 [ # # ][ # # ]: 0 : if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
[ # # ]
2072 : : {
2073 [ # # ][ # # ]: 0 : if ( pSI && pSI->CountKashida() &&
[ # # ][ # # ]
2074 : 0 : pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
2075 [ # # ]: 0 : nSpaceAdd ) != STRING_LEN )
2076 : 0 : nSpaceAdd = 0;
2077 : : }
2078 : : }
2079 : :
2080 : : // Thai Justification
2081 [ # # ][ # # ]: 0 : if ( SW_CTL == nActual && nSpaceAdd )
2082 : : {
2083 : 0 : LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
2084 : :
2085 [ # # ]: 0 : if ( LANGUAGE_THAI == aLang )
2086 : : {
2087 : 0 : SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
2088 : 0 : rInf.GetIdx(), rInf.GetLen(),
2089 : 0 : rInf.GetNumberOfBlanks(),
2090 [ # # ][ # # ]: 0 : rInf.GetSpace() );
2091 : :
2092 : : // adding space to blanks is already done
2093 : 0 : nSpaceAdd = 0;
2094 : : }
2095 : : }
2096 : : }
2097 : :
2098 : 0 : long nLeft = 0;
2099 : 0 : long nRight = 0;
2100 : 0 : xub_StrLen nCnt = 0;
2101 : 0 : long nSpaceSum = 0;
2102 : 0 : long nKernSum = 0;
2103 : :
2104 [ # # ][ # # ]: 0 : if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
[ # # # #
# # ][ # # ]
2105 : 0 : rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2106 : : {
2107 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2108 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
[ # # ][ # # ]
2109 : : {
2110 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2111 [ # # ][ # # ]: 0 : const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
2112 : :
2113 : 0 : long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
2114 : :
2115 : : sal_uLong i = nWidthPerChar ?
2116 : : ( nWidthPerChar - 1 ) / nGridWidth + 1:
2117 [ # # ]: 0 : 1;
2118 : :
2119 : 0 : nWidthPerChar = i * nGridWidth;
2120 : :
2121 : 0 : nCnt = (sal_uInt16)(rInf.GetOfst() / nWidthPerChar);
2122 [ # # ]: 0 : if ( 2 * ( rInf.GetOfst() - nCnt * nWidthPerChar ) > nWidthPerChar )
2123 : 0 : ++nCnt;
2124 : :
2125 [ # # ]: 0 : delete[] pKernArray;
2126 : 0 : return nCnt;
2127 : : }
2128 : : }
2129 : :
2130 : : //for textgrid refactor
2131 [ # # ][ # # ]: 0 : if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
[ # # # #
# # ][ # # ]
2132 : 0 : rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2133 : : {
2134 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2135 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
[ # # ][ # # ]
2136 : : {
2137 : :
2138 [ # # ]: 0 : const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
2139 : :
2140 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2141 [ # # ][ # # ]: 0 : long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
2142 [ # # ]: 0 : if( SW_LATIN == rInf.GetFont()->GetActual() )
2143 : 0 : nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
2144 : : else
2145 : 0 : nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
2146 : :
2147 [ # # ]: 0 : for(xub_StrLen j = 0; j < rInf.GetLen(); j++)
2148 : : {
2149 : 0 : long nScr = pKernArray[ j ] + ( nSpaceAdd + nGridWidthAdd ) * ( j + 1 );
2150 [ # # ]: 0 : if( nScr >= rInf.GetOfst())
2151 : : {
2152 : 0 : nCnt = j;
2153 : 0 : break;
2154 : : }
2155 : : }
2156 [ # # ]: 0 : delete[] pKernArray;
2157 : 0 : return nCnt;
2158 : : }
2159 : : }
2160 : :
2161 : 0 : sal_uInt16 nItrMode = i18n::CharacterIteratorMode::SKIPCELL;
2162 : 0 : sal_Int32 nDone = 0;
2163 : 0 : LanguageType aLang = LANGUAGE_NONE;
2164 : 0 : bool bSkipCharacterCells = false;
2165 : 0 : xub_StrLen nIdx = rInf.GetIdx();
2166 : 0 : xub_StrLen nLastIdx = nIdx;
2167 : 0 : const xub_StrLen nEnd = rInf.GetIdx() + rInf.GetLen();
2168 : :
2169 : : // #i105901#
2170 : : // skip character cells for all script types
2171 [ # # ][ # # ]: 0 : if ( pBreakIt->GetBreakIter().is() )
2172 : : {
2173 : 0 : aLang = rInf.GetFont()->GetLanguage();
2174 : 0 : bSkipCharacterCells = true;
2175 : : }
2176 : :
2177 [ # # ][ # # ]: 0 : while ( ( nRight < long( rInf.GetOfst() ) ) && ( nIdx < nEnd ) )
[ # # ]
2178 : : {
2179 [ # # ][ # # ]: 0 : if ( nSpaceAdd && CH_BLANK == rInf.GetText().GetChar( nIdx ) )
[ # # ]
2180 : 0 : nSpaceSum += nSpaceAdd;
2181 : :
2182 : : // go to next character (cell).
2183 : 0 : nLastIdx = nIdx;
2184 : :
2185 [ # # ]: 0 : if ( bSkipCharacterCells )
2186 : : {
2187 [ # # ][ # # ]: 0 : nIdx = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rInf.GetText(),
2188 [ # # # # ]: 0 : nIdx, pBreakIt->GetLocale( aLang ), nItrMode, 1, nDone );
[ # # ]
2189 [ # # ]: 0 : if ( nIdx <= nLastIdx )
2190 : 0 : break;
2191 : : }
2192 : : else
2193 : 0 : ++nIdx;
2194 : :
2195 : 0 : nLeft = nRight;
2196 : 0 : nRight = pKernArray[ nIdx - rInf.GetIdx() - 1 ] + nKernSum + nSpaceSum;
2197 : :
2198 : 0 : nKernSum += nKern;
2199 : : }
2200 : :
2201 : : // step back if position is before the middle of the character
2202 : : // or if we do not want to go to the next character
2203 [ # # # # : 0 : if ( nIdx > rInf.GetIdx() &&
# # # # ]
[ # # ]
2204 : 0 : ( rInf.IsPosMatchesBounds() ||
2205 : 0 : ( ( nRight > long( rInf.GetOfst() ) ) &&
2206 : 0 : ( nRight - rInf.GetOfst() > rInf.GetOfst() - nLeft ) ) ) )
2207 : 0 : nCnt = nLastIdx - rInf.GetIdx(); // first half
2208 : : else
2209 : 0 : nCnt = nIdx - rInf.GetIdx(); // second half
2210 : :
2211 [ # # ]: 0 : if ( pSI )
2212 [ # # ]: 0 : rInf.SetCursorBidiLevel( pSI->DirType( nLastIdx ) );
2213 : :
2214 [ # # ]: 0 : delete[] pKernArray;
2215 : 0 : return nCnt;
2216 : : }
2217 : :
2218 : :
2219 : : /*************************************************************************
2220 : : |*
2221 : : |* SwFntAccess::SwFntAccess()
2222 : : |*
2223 : : |*************************************************************************/
2224 : :
2225 : 547177 : SwFntAccess::SwFntAccess( const void* &rMagic,
2226 : : sal_uInt16 &rIndex, const void *pOwn, ViewShell *pSh,
2227 : : sal_Bool bCheck ) :
2228 : : SwCacheAccess( *pFntCache, rMagic, rIndex ),
2229 : 547177 : pShell( pSh )
2230 : : {
2231 : : // the used ctor of SwCacheAccess searches for rMagic+rIndex in the cache
2232 [ + + ]: 547177 : if ( IsAvail() )
2233 : : {
2234 : : // fast case: known Font (rMagic), no need to check printer and zoom
2235 [ + + ]: 528873 : if ( !bCheck )
2236 : 234121 : return;
2237 : :
2238 : : // Font is known, but has to be checked
2239 : : }
2240 : : else
2241 : : { // Font not known, must be searched
2242 : 18304 : bCheck = sal_False;
2243 : : }
2244 : :
2245 : :
2246 : : {
2247 : 313056 : OutputDevice* pOut = 0;
2248 : 313056 : sal_uInt16 nZoom = USHRT_MAX;
2249 : :
2250 : : // Get the reference device
2251 [ + + ]: 313056 : if ( pSh )
2252 : : {
2253 [ + - ]: 312978 : pOut = &pSh->GetRefDev();
2254 : 312978 : nZoom = pSh->GetViewOptions()->GetZoom();
2255 : : }
2256 : :
2257 : : SwFntObj *pFntObj;
2258 [ + + ]: 313056 : if ( bCheck )
2259 : : {
2260 [ + - ]: 294752 : pFntObj = Get();
2261 [ + + ]: 586681 : if ( ( pFntObj->GetZoom( ) == nZoom ) &&
[ + + + - ]
[ + + ]
2262 : : ( pFntObj->pPrinter == pOut ) &&
2263 : 291929 : pFntObj->GetPropWidth() ==
2264 : 291929 : ((SwSubFont*)pOwn)->GetPropWidth() )
2265 : : {
2266 : 291929 : return; // result of Check: Drucker+Zoom okay.
2267 : : }
2268 : 2823 : pFntObj->Unlock(); // forget this object, printer/zoom differs
2269 : 2823 : pObj = NULL;
2270 : : }
2271 : :
2272 : : // Search by font comparison, quite expensive!
2273 : : // Look for same font and same printer
2274 : 21127 : pFntObj = pFntCache->First();
2275 [ + + ][ + - ]: 58271 : while ( pFntObj && !( pFntObj->aFont == *(Font *)pOwn &&
[ + + ][ + + ]
2276 : 19920 : pFntObj->GetZoom() == nZoom &&
2277 : 18885 : pFntObj->GetPropWidth() ==
2278 : 18885 : ((SwSubFont*)pOwn)->GetPropWidth() &&
2279 [ + + ][ + + ]: 38805 : ( !pFntObj->pPrinter || pFntObj->pPrinter == pOut ) ) )
[ + + + + ]
2280 : 17224 : pFntObj = pFntCache->Next( pFntObj );
2281 : :
2282 [ + + ][ + + ]: 21127 : if( pFntObj && pFntObj->pPrinter != pOut )
2283 : : {
2284 : : // found one without printer, let's see if there is one with
2285 : : // the same printer as well
2286 : 2064 : SwFntObj *pTmpObj = pFntObj;
2287 [ + + ][ + - ]: 12913 : while( pTmpObj && !( pTmpObj->aFont == *(Font *)pOwn &&
[ + + ][ + + ]
2288 : 2107 : pTmpObj->GetZoom()==nZoom && pTmpObj->pPrinter==pOut &&
2289 : 12 : pTmpObj->GetPropWidth() ==
2290 [ + + + - ]: 2119 : ((SwSubFont*)pOwn)->GetPropWidth() ) )
[ + + ]
2291 : 8742 : pTmpObj = pFntCache->Next( pTmpObj );
2292 [ - + ]: 2064 : if( pTmpObj )
2293 : 0 : pFntObj = pTmpObj;
2294 : : }
2295 : :
2296 [ + + ]: 21127 : if ( !pFntObj ) // Font has not been found, create one
2297 : : {
2298 : : // Have to create new Object, hence Owner must be a SwFont, later
2299 : : // the Owner will be the "MagicNumber"
2300 : 2288 : SwCacheAccess::pOwner = pOwn;
2301 [ + - ]: 2288 : pFntObj = Get(); // will create via NewObj() and lock
2302 : : OSL_ENSURE(pFntObj, "No Font, no Fun.");
2303 : : }
2304 : : else // Font has been found, so we lock it.
2305 : : {
2306 : 18839 : pFntObj->Lock();
2307 [ + + ]: 18839 : if (pFntObj->pPrinter != pOut) // if no printer is known by now
2308 : : {
2309 : : OSL_ENSURE( !pFntObj->pPrinter, "SwFntAccess: Printer Changed" );
2310 [ + - ]: 2064 : pFntObj->CreatePrtFont( *pOut );
2311 : 2064 : pFntObj->pPrinter = pOut;
2312 : 2064 : pFntObj->pScrFont = NULL;
2313 : 2064 : pFntObj->nGuessedLeading = USHRT_MAX;
2314 : 2064 : pFntObj->nExtLeading = USHRT_MAX;
2315 : 2064 : pFntObj->nPrtAscent = USHRT_MAX;
2316 : 2064 : pFntObj->nPrtHeight = USHRT_MAX;
2317 : : }
2318 : 18839 : pObj = pFntObj;
2319 : : }
2320 : :
2321 : : // no matter if new or found, now the Owner of the Object is a
2322 : : // MagicNumber, and will be given to the SwFont, as well as the Index
2323 : : // for later direct access
2324 : 21127 : rMagic = pFntObj->GetOwner();
2325 : 21127 : SwCacheAccess::pOwner = rMagic;
2326 : 547177 : rIndex = pFntObj->GetCachePos();
2327 : : }
2328 : : }
2329 : :
2330 : 2288 : SwCacheObj *SwFntAccess::NewObj( )
2331 : : {
2332 : : // a new Font, a new "MagicNumber".
2333 [ + - ]: 2288 : return new SwFntObj( *(SwSubFont *)pOwner, ++pMagicNo, pShell );
2334 : : }
2335 : :
2336 : : extern xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt,
2337 : : const XubString& rOrigString,
2338 : : xub_StrLen nOfst,
2339 : : xub_StrLen nLen,
2340 : : xub_StrLen nIdx );
2341 : :
2342 : 42491 : xub_StrLen SwFont::GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth )
2343 : : {
2344 : 42491 : ChgFnt( rInf.GetShell(), rInf.GetOut() );
2345 : :
2346 : 42491 : const sal_Bool bCompress = rInf.GetKanaComp() && rInf.GetLen() &&
2347 : 0 : SW_CJK == GetActual() &&
2348 : 0 : rInf.GetScriptInfo() &&
2349 : 0 : rInf.GetScriptInfo()->CountCompChg() &&
2350 [ # # ][ - + : 42491 : lcl_IsMonoSpaceFont( rInf.GetOut() );
# # # # #
# # # ]
2351 : :
2352 : : OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
2353 : : CountCompChg()), "Compression without info" );
2354 : :
2355 : 42491 : sal_uInt16 nTxtBreak = 0;
2356 : 42491 : long nKern = 0;
2357 : :
2358 : 42491 : sal_uInt16 nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
2359 [ - + ]: 42491 : : rInf.GetLen() );
2360 : :
2361 [ + - ][ + - ]: 120587 : if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() &&
[ + + + -
- + ][ - + ]
2362 : 78096 : rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
2363 : : {
2364 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
2365 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
[ # # ][ # # ]
2366 : : {
2367 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2368 [ # # ]: 0 : const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
2369 : :
2370 : 0 : sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
2371 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2372 : 0 : rInf.GetIdx(), rInf.GetLen() );
2373 : :
2374 : 0 : long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
2375 : :
2376 : : const sal_uLong i = nWidthPerChar ?
2377 : : ( nWidthPerChar - 1 ) / nGridWidth + 1:
2378 [ # # ]: 0 : 1;
2379 : :
2380 : 0 : nWidthPerChar = i * nGridWidth;
2381 : 0 : long nCurrPos = nWidthPerChar;
2382 : :
2383 [ # # ][ # # ]: 0 : while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos )
[ # # ]
2384 : : {
2385 : 0 : nCurrPos += nWidthPerChar;
2386 : 0 : ++nTxtBreak;
2387 : : }
2388 : :
2389 [ # # ]: 0 : delete[] pKernArray;
2390 : 0 : return nTxtBreak + rInf.GetIdx();
2391 : : }
2392 : : }
2393 : :
2394 : : //for text grid enhancement
2395 [ + - ][ + - ]: 81539 : if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
[ + + ]
[ + - - + ]
[ - + ]
2396 : 39048 : SW_CJK == rInf.GetFont()->GetActual() )
2397 : : {
2398 [ # # ][ # # ]: 0 : GETGRID( rInf.GetFrm()->FindPageFrm() )
[ # # ][ # # ]
2399 [ # # ][ # # ]: 0 : if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
[ # # ][ # # ]
2400 : : {
2401 : 0 : const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
2402 : :
2403 : 0 : const SwDoc* pDoc = rInf.GetShell()->GetDoc();
2404 [ # # ]: 0 : long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
2405 [ # # ]: 0 : if( SW_LATIN == rInf.GetFont()->GetActual() )
2406 : 0 : nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2 ;
2407 : : else
2408 : 0 : nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
2409 : :
2410 : 0 : sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
2411 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2412 : 0 : rInf.GetIdx(), rInf.GetLen() );
2413 : 0 : long nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd;
2414 [ # # ][ # # ]: 0 : while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos)
[ # # ]
2415 : : {
2416 : 0 : nTxtBreak++;
2417 : 0 : nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd * ( nTxtBreak + 1 );
2418 : : }
2419 [ # # ]: 0 : delete[] pKernArray;
2420 : 0 : return nTxtBreak + rInf.GetIdx();
2421 : : }
2422 : : }
2423 : :
2424 [ - + ][ # # ]: 42491 : if( aSub[nActual].IsCapital() && nLn )
[ - + ]
2425 : 0 : nTxtBreak = GetCapitalBreak( rInf.GetShell(), rInf.GetpOut(),
2426 : 0 : rInf.GetScriptInfo(), rInf.GetText(), nTextWidth,0, rInf.GetIdx(),nLn );
2427 : : else
2428 : : {
2429 [ + - ]: 42491 : nKern = CheckKerning();
2430 : :
2431 : : const XubString* pTmpText;
2432 [ + - ]: 42491 : XubString aTmpText;
2433 : : xub_StrLen nTmpIdx;
2434 : : xub_StrLen nTmpLen;
2435 : 42491 : bool bTextReplaced = false;
2436 : :
2437 [ + + ]: 42491 : if ( !aSub[nActual].IsCaseMap() )
2438 : : {
2439 : 42251 : pTmpText = &rInf.GetText();
2440 : 42251 : nTmpIdx = rInf.GetIdx();
2441 : 42251 : nTmpLen = nLn;
2442 : : }
2443 : : else
2444 : : {
2445 [ + - ]: 240 : const XubString aSnippet( rInf.GetText(), rInf.GetIdx(), nLn );
2446 [ + - ][ + - ]: 240 : aTmpText = aSub[nActual].CalcCaseMap( aSnippet );
[ + - ]
2447 : 240 : const bool bTitle = SVX_CASEMAP_TITEL == aSub[nActual].GetCaseMap() &&
2448 [ # # ][ # # ]: 240 : pBreakIt->GetBreakIter().is();
[ - + ][ # # ]
[ - + ]
2449 : :
2450 : : // Uaaaaahhhh!!! In title case mode, we would get wrong results
2451 [ - + ][ # # ]: 240 : if ( bTitle && nLn )
2452 : : {
2453 : : // check if rInf.GetIdx() is begin of word
2454 [ # # ]: 0 : if ( !pBreakIt->GetBreakIter()->isBeginWord(
[ # # # # ]
2455 : 0 : rInf.GetText(), rInf.GetIdx(),
2456 [ # # ]: 0 : pBreakIt->GetLocale( aSub[nActual].GetLanguage() ),
2457 [ # # ][ # # ]: 0 : i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
2458 : : {
2459 : : // In this case, the beginning of aTmpText is wrong.
2460 [ # # ]: 0 : XubString aSnippetTmp( aSnippet, 0, 1 );
2461 [ # # ][ # # ]: 0 : aSnippetTmp = aSub[nActual].CalcCaseMap( aSnippetTmp );
[ # # ]
2462 [ # # ]: 0 : aTmpText.Erase( 0, aSnippetTmp.Len() );
2463 [ # # ][ # # ]: 0 : aTmpText.Insert( aSnippet.GetChar( 0 ), 0 );
2464 : : }
2465 : : }
2466 : :
2467 : 240 : pTmpText = &aTmpText;
2468 : 240 : nTmpIdx = 0;
2469 : 240 : nTmpLen = aTmpText.Len();
2470 [ + - ]: 240 : bTextReplaced = true;
2471 : : }
2472 : :
2473 [ - + ]: 42491 : if( rInf.GetHyphPos() )
2474 : 0 : nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
2475 : 0 : '-', *rInf.GetHyphPos(),
2476 [ # # ]: 0 : nTmpIdx, nTmpLen, nKern );
2477 : : else
2478 : 42491 : nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
2479 [ + - ]: 42491 : nTmpIdx, nTmpLen, nKern );
2480 : :
2481 [ + + ][ + + ]: 42491 : if ( bTextReplaced && STRING_LEN != nTxtBreak )
2482 : : {
2483 [ - + ]: 160 : if ( nTmpLen != nLn )
2484 : 0 : nTxtBreak = lcl_CalcCaseMap( *this, rInf.GetText(),
2485 [ # # ]: 0 : rInf.GetIdx(), nLn, nTxtBreak );
2486 : : else
2487 : 160 : nTxtBreak = nTxtBreak + rInf.GetIdx();
2488 [ + - ]: 42491 : }
2489 : : }
2490 : :
2491 [ + - ]: 42491 : if ( ! bCompress )
2492 : 42491 : return nTxtBreak;
2493 : :
2494 : 0 : nTxtBreak = nTxtBreak - rInf.GetIdx();
2495 : :
2496 [ # # ]: 0 : if( nTxtBreak < nLn )
2497 : : {
2498 [ # # ][ # # ]: 0 : if( !nTxtBreak && nLn )
2499 : 0 : nLn = 1;
2500 [ # # ]: 0 : else if( nLn > 2 * nTxtBreak )
2501 : 0 : nLn = 2 * nTxtBreak;
2502 : 0 : sal_Int32 *pKernArray = new sal_Int32[ nLn ];
2503 : 0 : rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
2504 : 0 : rInf.GetIdx(), nLn );
2505 [ # # ]: 0 : if( rInf.GetScriptInfo()->Compress( pKernArray, rInf.GetIdx(), nLn,
2506 : 0 : rInf.GetKanaComp(), (sal_uInt16)GetHeight( nActual ) ) )
2507 : : {
2508 : 0 : long nKernAdd = nKern;
2509 : 0 : xub_StrLen nTmpBreak = nTxtBreak;
2510 [ # # ][ # # ]: 0 : if( nKern && nTxtBreak )
2511 : 0 : nKern *= nTxtBreak - 1;
2512 [ # # ][ # # ]: 0 : while( nTxtBreak<nLn && nTextWidth >= pKernArray[nTxtBreak] +nKern )
[ # # ]
2513 : : {
2514 : 0 : nKern += nKernAdd;
2515 : 0 : ++nTxtBreak;
2516 : : }
2517 [ # # ]: 0 : if( rInf.GetHyphPos() )
2518 : 0 : *rInf.GetHyphPos() += nTxtBreak - nTmpBreak; // It's not perfect
2519 : : }
2520 [ # # ]: 0 : delete[] pKernArray;
2521 : : }
2522 : 0 : nTxtBreak = nTxtBreak + rInf.GetIdx();
2523 : :
2524 : 42491 : return nTxtBreak;
2525 : : }
2526 : :
2527 : : extern Color aGlobalRetoucheColor;
2528 : :
2529 : 26568 : sal_Bool SwDrawTextInfo::ApplyAutoColor( Font* pFont )
2530 : : {
2531 [ + + ]: 26568 : const Font& rFnt = pFont ? *pFont : GetOut().GetFont();
2532 [ + - ][ + + ]: 26568 : sal_Bool bPrt = GetShell() && ! GetShell()->GetWin();
2533 : 26568 : ColorData nNewColor = COL_BLACK;
2534 : 26568 : sal_Bool bChgFntColor = sal_False;
2535 : 26568 : sal_Bool bChgLineColor = sal_False;
2536 : :
2537 [ + + ][ + - ]: 26568 : if( bPrt && GetShell() && GetShell()->GetViewOptions()->IsBlackFont() )
[ - + ][ - + ]
2538 : : {
2539 [ # # ]: 0 : if ( COL_BLACK != rFnt.GetColor().GetColor() )
2540 : 0 : bChgFntColor = sal_True;
2541 : :
2542 [ # # # # ]: 0 : if ( (COL_BLACK != GetOut().GetLineColor().GetColor()) ||
[ # # ]
2543 : 0 : (COL_BLACK != GetOut().GetOverlineColor().GetColor()) )
2544 : 0 : bChgLineColor = sal_True;
2545 : : }
2546 : : else
2547 : : {
2548 : : // FontColor has to be changed if:
2549 : : // 1. FontColor = AUTO or 2. IsAlwaysAutoColor is set
2550 : : // LineColor has to be changed if:
2551 : : // 1. IsAlwaysAutoColor is set
2552 : :
2553 : 26323 : bChgLineColor = ! bPrt && GetShell() &&
2554 [ + + + - ]: 52891 : GetShell()->GetAccessibilityOptions()->IsAlwaysAutoColor();
[ - + ]
2555 : :
2556 [ + + ][ - + ]: 26568 : bChgFntColor = COL_AUTO == rFnt.GetColor().GetColor() || bChgLineColor;
2557 : :
2558 [ + + ]: 26568 : if ( bChgFntColor )
2559 : : {
2560 : : // check if current background has a user defined setting
2561 [ + - ]: 25912 : const Color* pCol = GetFont() ? GetFont()->GetBackColor() : NULL;
2562 [ - + ][ # # ]: 25912 : if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
[ + - ]
2563 : : {
2564 : : const SvxBrushItem* pItem;
2565 : 25912 : SwRect aOrigBackRect;
2566 : :
2567 : : /// OD 21.08.2002
2568 : : /// consider, that [GetBackgroundBrush(...)] can set <pCol>
2569 : : /// - see implementation in /core/layout/paintfrm.cxx
2570 : : /// OD 21.08.2002 #99657#
2571 : : /// There is a user defined setting for the background, if there
2572 : : /// is a background brush and its color is *not* "no fill"/"auto fill".
2573 [ + + ][ + - ]: 25912 : if( GetFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
2574 : : {
2575 [ + + ]: 38 : if ( !pCol )
2576 : : {
2577 : 24 : pCol = &pItem->GetColor();
2578 : : }
2579 : :
2580 : : /// OD 30.08.2002 #99657#
2581 : : /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
2582 [ - + ]: 38 : if ( pCol->GetColor() == COL_TRANSPARENT)
2583 : 0 : pCol = NULL;
2584 : : }
2585 : : else
2586 : 25912 : pCol = NULL;
2587 : : }
2588 : :
2589 : : // no user defined color at paragraph or font background
2590 [ + + ]: 25912 : if ( ! pCol )
2591 : 25874 : pCol = &aGlobalRetoucheColor;
2592 : :
2593 [ + - ][ + + ]: 25912 : if( GetShell() && GetShell()->GetWin() )
[ + + ]
2594 : : {
2595 : : // here we determine the prefered window text color for painting
2596 : 25667 : const SwViewOption* pViewOption = GetShell()->GetViewOptions();
2597 [ # # ][ - + ]: 25667 : if(pViewOption->IsPagePreview() &&
[ - + ]
2598 [ # # ][ # # ]: 0 : !SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews())
[ # # ]
2599 : 0 : nNewColor = COL_BLACK;
2600 : : else
2601 : : // we take the font color from the appearence page
2602 [ + - ]: 25667 : nNewColor = SwViewOption::GetFontColor().GetColor();
2603 : : }
2604 : :
2605 : : // change painting color depending of dark/bright background
2606 : 25912 : Color aTmpColor( nNewColor );
2607 [ + + ][ + - ]: 25912 : if ( pCol->IsDark() && aTmpColor.IsDark() )
[ + - ][ + + ]
[ + - ]
2608 : 16 : nNewColor = COL_WHITE;
2609 [ + - ][ + + ]: 25896 : else if ( pCol->IsBright() && aTmpColor.IsBright() )
[ + - ][ - + ]
[ - + ]
2610 : 25912 : nNewColor = COL_BLACK;
2611 : : }
2612 : : }
2613 : :
2614 [ + + ][ - + ]: 26568 : if ( bChgFntColor || bChgLineColor )
2615 : : {
2616 : 25912 : Color aNewColor( nNewColor );
2617 : :
2618 [ + - ]: 25912 : if ( bChgFntColor )
2619 : : {
2620 [ + + ][ + - ]: 25912 : if ( pFont && aNewColor != pFont->GetColor() )
[ + - ][ + + ]
2621 : : {
2622 : : // only set the new color at the font passed as argument
2623 [ + - ]: 25908 : pFont->SetColor( aNewColor );
2624 : : }
2625 [ + - ][ + - ]: 4 : else if ( aNewColor != GetOut().GetFont().GetColor() )
2626 : : {
2627 : : // set new font with new color at output device
2628 [ + - ]: 4 : Font aFont( rFnt );
2629 [ + - ]: 4 : aFont.SetColor( aNewColor );
2630 [ + - ][ + - ]: 4 : GetOut().SetFont( aFont );
2631 : : }
2632 : : }
2633 : :
2634 : : // the underline and overline colors have to be set separately
2635 [ - + ]: 25912 : if ( bChgLineColor )
2636 : : {
2637 : : // get current font color or color set at output device
2638 [ # # ][ # # ]: 0 : aNewColor = pFont ? pFont->GetColor() : GetOut().GetFont().GetColor();
[ # # ]
2639 [ # # ]: 0 : if ( aNewColor != GetOut().GetLineColor() )
2640 [ # # ]: 0 : GetOut().SetLineColor( aNewColor );
2641 [ # # ]: 0 : if ( aNewColor != GetOut().GetOverlineColor() )
2642 [ # # ]: 0 : GetOut().SetOverlineColor( aNewColor );
2643 : : }
2644 : :
2645 : 25912 : return sal_True;
2646 : : }
2647 : :
2648 : 26568 : return sal_False;
2649 : : }
2650 : :
2651 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|