LCOV - code coverage report
Current view: top level - sw/source/core/txtnode - fntcache.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 614 1205 51.0 %
Date: 2014-11-03 Functions: 24 27 88.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10