LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/txtnode - fntcache.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 520 1201 43.3 %
Date: 2012-12-17 Functions: 21 25 84.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10