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