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

Generated by: LCOV version 1.10