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