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

Generated by: LCOV version 1.10