LCOV - code coverage report
Current view: top level - sw/source/core/txtnode - fntcap.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 231 397 58.2 %
Date: 2014-11-03 Functions: 27 44 61.4 %
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 <hintids.hxx>
      21             : #include <editeng/cmapitem.hxx>
      22             : #include <editeng/svxfont.hxx>
      23             : 
      24             : #include <vcl/outdev.hxx>
      25             : #include <com/sun/star/i18n/CharType.hpp>
      26             : #include <com/sun/star/i18n/WordType.hpp>
      27             : 
      28             : #include <vcl/print.hxx>
      29             : #include <fntcache.hxx>
      30             : #include <swfont.hxx>
      31             : #include <breakit.hxx>
      32             : #include <txtfrm.hxx>
      33             : #include <scriptinfo.hxx>
      34             : #include <fntcap.hxx>
      35             : 
      36             : using namespace ::com::sun::star::i18n;
      37             : 
      38             : // The information encapsulated in SwCapitalInfo is required
      39             : // by the ::Do functions. They contain the information about
      40             : // the original string, whereas rDo.GetInf() contains information
      41             : // about the display string.
      42             : class SwCapitalInfo
      43             : {
      44             : public:
      45         440 :     explicit SwCapitalInfo( const OUString& rOrigText ) :
      46         440 :         rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {};
      47             :     const OUString& rString;
      48             :     sal_Int32 nIdx;
      49             :     sal_Int32 nLen;
      50             : };
      51             : 
      52             : // rFnt: required for CalcCaseMap
      53             : // rOrigString: The original string
      54             : // nOfst: Position of the substring in rOrigString
      55             : // nLen: Length if the substring in rOrigString
      56             : // nIdx: Referes to a position in the display string and should be mapped
      57             : //       to a position in rOrigString
      58           0 : sal_Int32 sw_CalcCaseMap( const SwFont& rFnt,
      59             :                             const OUString& rOrigString,
      60             :                             sal_Int32 nOfst,
      61             :                             sal_Int32 nLen,
      62             :                             sal_Int32 nIdx )
      63             : {
      64           0 :     int j = 0;
      65           0 :     const sal_Int32 nEnd = nOfst + nLen;
      66             :     OSL_ENSURE( nEnd <= rOrigString.getLength(), "sw_CalcCaseMap: Wrong parameters" );
      67             : 
      68             :     // special case for title case:
      69           0 :     const bool bTitle = SVX_CASEMAP_TITEL == rFnt.GetCaseMap() &&
      70           0 :                         g_pBreakIt->GetBreakIter().is();
      71           0 :     for ( sal_Int32 i = nOfst; i < nEnd; ++i )
      72             :     {
      73           0 :         OUString aTmp(rOrigString.copy(i, 1));
      74             : 
      75           0 :         if ( !bTitle ||
      76           0 :              g_pBreakIt->GetBreakIter()->isBeginWord(
      77             :                  rOrigString, i,
      78           0 :                  g_pBreakIt->GetLocale( rFnt.GetLanguage() ),
      79           0 :                  WordType::ANYWORD_IGNOREWHITESPACES ) )
      80           0 :             aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp );
      81             : 
      82           0 :         j += aTmp.getLength();
      83             : 
      84           0 :         if ( j > nIdx )
      85           0 :             return i;
      86           0 :     }
      87             : 
      88           0 :     return nOfst + nLen;
      89             : }
      90             : 
      91             : class SwDoCapitals
      92             : {
      93             : protected:
      94             :     SwDrawTextInfo &rInf;
      95             :     SwCapitalInfo* pCapInf; // referes to additional information
      96             :                            // required by the ::Do function
      97         440 :     SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { }
      98         440 :     ~SwDoCapitals() {}
      99             : public:
     100             :     virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
     101             :     virtual void Do() = 0;
     102        4296 :     inline OutputDevice& GetOut() { return rInf.GetOut(); }
     103       40058 :     inline SwDrawTextInfo& GetInf() { return rInf; }
     104           4 :     inline SwCapitalInfo* GetCapInf() const { return pCapInf; }
     105           0 :     inline void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; }
     106             : };
     107             : 
     108             : class SwDoGetCapitalSize : public SwDoCapitals
     109             : {
     110             : protected:
     111             :     Size aTxtSize;
     112             : public:
     113         322 :     SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
     114         322 :     virtual ~SwDoGetCapitalSize() {}
     115             :     virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
     116             :     virtual void Do() SAL_OVERRIDE;
     117         322 :     const Size &GetSize() const { return aTxtSize; }
     118             : };
     119             : 
     120         322 : void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
     121             : {
     122         322 :     aTxtSize.Height() = 0;
     123         322 :     aTxtSize.Width() = 0;
     124         322 : }
     125             : 
     126        2306 : void SwDoGetCapitalSize::Do()
     127             : {
     128        2306 :     aTxtSize.Width() += rInf.GetSize().Width();
     129        2306 :     if( rInf.GetUpper() )
     130        1254 :         aTxtSize.Height() = rInf.GetSize().Height();
     131        2306 : }
     132             : 
     133         322 : Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf )
     134             : {
     135             :     // Start:
     136         322 :     const long nOldKern = rInf.GetKern();
     137         322 :     rInf.SetKern( CheckKerning() );
     138         322 :     Point aPos;
     139         322 :     rInf.SetPos( aPos );
     140         322 :     rInf.SetSpace( 0 );
     141         322 :     rInf.SetDrawSpace( false );
     142         322 :     SwDoGetCapitalSize aDo( rInf );
     143         322 :     DoOnCapitals( aDo );
     144         322 :     Size aTxtSize( aDo.GetSize() );
     145             : 
     146             :     // End:
     147         322 :     if( !aTxtSize.Height() )
     148             :     {
     149             :         SV_STAT( nGetTextSize );
     150          26 :         aTxtSize.Height() = short ( rInf.GetpOut()->GetTextHeight() );
     151             :     }
     152         322 :     rInf.SetKern( nOldKern );
     153         322 :     return aTxtSize;
     154             : }
     155             : 
     156             : class SwDoGetCapitalBreak : public SwDoCapitals
     157             : {
     158             : protected:
     159             :     long nTxtWidth;
     160             :     sal_Int32 m_nBreak;
     161             : public:
     162           4 :     SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long const nWidth)
     163             :         :   SwDoCapitals ( rInfo )
     164             :         ,   nTxtWidth( nWidth )
     165           4 :         ,   m_nBreak( -1 )
     166           4 :         { }
     167           4 :     virtual ~SwDoGetCapitalBreak() {}
     168             :     virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
     169             :     virtual void Do() SAL_OVERRIDE;
     170           4 :     sal_Int32 getBreak() const { return m_nBreak; }
     171             : };
     172             : 
     173           4 : void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
     174             : {
     175           4 : }
     176             : 
     177          12 : void SwDoGetCapitalBreak::Do()
     178             : {
     179          12 :     if ( nTxtWidth )
     180             :     {
     181          12 :         if ( rInf.GetSize().Width() < nTxtWidth )
     182           8 :             nTxtWidth -= rInf.GetSize().Width();
     183             :         else
     184             :         {
     185           4 :             sal_Int32 nEnd = rInf.GetEnd();
     186           4 :             m_nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth,
     187           8 :                                rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() );
     188             : 
     189           4 :             if (m_nBreak > nEnd || m_nBreak < 0)
     190           0 :                 m_nBreak = nEnd;
     191             : 
     192             :             // m_nBreak may be relative to the display string. It has to be
     193             :             // calculated relative to the original string:
     194           4 :             if ( GetCapInf()  )
     195             :             {
     196           0 :                 if ( GetCapInf()->nLen != rInf.GetLen() )
     197           0 :                     m_nBreak = sw_CalcCaseMap( *rInf.GetFont(),
     198           0 :                                               GetCapInf()->rString,
     199           0 :                                               GetCapInf()->nIdx,
     200           0 :                                               GetCapInf()->nLen, m_nBreak );
     201             :                 else
     202           0 :                     m_nBreak = m_nBreak + GetCapInf()->nIdx;
     203             :             }
     204             : 
     205           4 :             nTxtWidth = 0;
     206             :         }
     207             :     }
     208          12 : }
     209             : 
     210           4 : sal_Int32 SwFont::GetCapitalBreak( SwViewShell const * pSh, const OutputDevice* pOut,
     211             :     const SwScriptInfo* pScript, const OUString& rTxt, long const nTextWidth,
     212             :     const sal_Int32 nIdx, const sal_Int32 nLen )
     213             : {
     214             :     // Start:
     215           4 :     Point aPos( 0, 0 );
     216             :     SwDrawTextInfo aInfo(pSh, *(OutputDevice*)pOut, pScript, rTxt, nIdx, nLen,
     217           4 :         0, false);
     218           4 :     aInfo.SetPos( aPos );
     219           4 :     aInfo.SetSpace( 0 );
     220           4 :     aInfo.SetWrong( NULL );
     221           4 :     aInfo.SetGrammarCheck( NULL );
     222           4 :     aInfo.SetSmartTags( NULL );
     223           4 :     aInfo.SetDrawSpace( false );
     224           4 :     aInfo.SetKern( CheckKerning() );
     225           4 :     aInfo.SetKanaComp( pScript ? 0 : 100 );
     226           4 :     aInfo.SetFont( this );
     227             : 
     228           8 :     SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
     229           4 :     DoOnCapitals( aDo );
     230           8 :     return aDo.getBreak();
     231             : }
     232             : 
     233             : class SwDoDrawCapital : public SwDoCapitals
     234             : {
     235             : protected:
     236             :     SwFntObj *pUpperFnt;
     237             :     SwFntObj *pLowerFnt;
     238             : public:
     239         114 :     SwDoDrawCapital( SwDrawTextInfo &rInfo ) :
     240         114 :         SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0)
     241         114 :         { }
     242         114 :     virtual ~SwDoDrawCapital() {}
     243             :     virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
     244             :     virtual void Do() SAL_OVERRIDE;
     245             :     void DrawSpace( Point &rPos );
     246             : };
     247             : 
     248         114 : void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
     249             : {
     250         114 :     pUpperFnt = pUpperFont;
     251         114 :     pLowerFnt = pLowerFont;
     252         114 : }
     253             : 
     254        1014 : void SwDoDrawCapital::Do()
     255             : {
     256             :     SV_STAT( nDrawText );
     257        1014 :     const sal_uInt16 nOrgWidth = rInf.GetWidth();
     258        1014 :     rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) );
     259        1014 :     if ( rInf.GetUpper() )
     260         552 :         pUpperFnt->DrawText( rInf );
     261             :     else
     262             :     {
     263         462 :         bool bOldBullet = rInf.GetBullet();
     264         462 :         rInf.SetBullet( false );
     265         462 :         pLowerFnt->DrawText( rInf );
     266         462 :         rInf.SetBullet( bOldBullet );
     267             :     }
     268             : 
     269             :     OSL_ENSURE( pUpperFnt, "No upper font, dying soon!");
     270        1014 :     rInf.Shift( pUpperFnt->GetFont().GetOrientation() );
     271        1014 :     rInf.SetWidth( nOrgWidth );
     272        1014 : }
     273             : 
     274           6 : void SwDoDrawCapital::DrawSpace( Point &rPos )
     275             : {
     276           6 :     long nDiff = rInf.GetPos().X() - rPos.X();
     277             : 
     278           6 :     Point aPos( rPos );
     279           6 :     const bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
     280           6 :                           ! rInf.IsIgnoreFrmRTL();
     281             : 
     282           6 :     if ( bSwitchL2R )
     283           0 :        rInf.GetFrm()->SwitchLTRtoRTL( aPos );
     284             : 
     285           6 :     const ComplexTextLayoutMode nMode = rInf.GetpOut()->GetLayoutMode();
     286           6 :     const bool bBidiPor = ( bSwitchL2R !=
     287           6 :                             ( TEXT_LAYOUT_DEFAULT != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
     288             : 
     289           6 :     if ( bBidiPor )
     290           0 :         nDiff = -nDiff;
     291             : 
     292           6 :     if ( rInf.GetFrm()->IsVertical() )
     293           0 :         rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
     294             : 
     295           6 :     if ( nDiff )
     296             :     {
     297           6 :         rInf.ApplyAutoColor();
     298           6 :         GetOut().DrawStretchText( aPos, nDiff,
     299          12 :             OUString("  "), 0, 2 );
     300             :     }
     301           6 :     rPos.X() = rInf.GetPos().X() + rInf.GetWidth();
     302           6 : }
     303             : 
     304         114 : void SwSubFont::DrawCapital( SwDrawTextInfo &rInf )
     305             : {
     306             :     // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
     307             :     // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
     308         222 :     rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
     309         222 :                        GetOverline()  != UNDERLINE_NONE ||
     310         222 :                        GetStrikeout() != STRIKEOUT_NONE );
     311         114 :     SwDoDrawCapital aDo( rInf );
     312         114 :     DoOnCapitals( aDo );
     313         114 : }
     314             : 
     315             : class SwDoCapitalCrsrOfst : public SwDoCapitals
     316             : {
     317             : protected:
     318             :     SwFntObj *pUpperFnt;
     319             :     SwFntObj *pLowerFnt;
     320             :     sal_Int32 nCrsr;
     321             :     sal_uInt16 nOfst;
     322             : public:
     323           0 :     SwDoCapitalCrsrOfst( SwDrawTextInfo &rInfo, const sal_uInt16 nOfs ) :
     324           0 :         SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0), nCrsr( 0 ), nOfst( nOfs )
     325           0 :         { }
     326           0 :     virtual ~SwDoCapitalCrsrOfst() {}
     327             :     virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
     328             :     virtual void Do() SAL_OVERRIDE;
     329             : 
     330           0 :     inline sal_Int32 GetCrsr(){ return nCrsr; }
     331             : };
     332             : 
     333           0 : void SwDoCapitalCrsrOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
     334             : {
     335           0 :     pUpperFnt = pUpperFont;
     336           0 :     pLowerFnt = pLowerFont;
     337           0 : }
     338             : 
     339           0 : void SwDoCapitalCrsrOfst::Do()
     340             : {
     341           0 :     if ( nOfst )
     342             :     {
     343           0 :         if ( static_cast<long>(nOfst) > rInf.GetSize().Width() )
     344             :         {
     345           0 :             nOfst -= rInf.GetSize().Width();
     346           0 :             nCrsr = nCrsr + rInf.GetLen();
     347             :         }
     348             :         else
     349             :         {
     350           0 :             SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(),
     351             :                                      rInf.GetScriptInfo(),
     352           0 :                                      rInf.GetText(),
     353             :                                      rInf.GetIdx(),
     354           0 :                                      rInf.GetLen(), 0, false );
     355           0 :             aDrawInf.SetOfst( nOfst );
     356           0 :             aDrawInf.SetKern( rInf.GetKern() );
     357           0 :             aDrawInf.SetKanaComp( rInf.GetKanaComp() );
     358           0 :             aDrawInf.SetFrm( rInf.GetFrm() );
     359           0 :             aDrawInf.SetFont( rInf.GetFont() );
     360             : 
     361           0 :             if ( rInf.GetUpper() )
     362             :             {
     363           0 :                 aDrawInf.SetSpace( 0 );
     364           0 :                 nCrsr = nCrsr + pUpperFnt->GetCrsrOfst( aDrawInf );
     365             :             }
     366             :             else
     367             :             {
     368           0 :                 aDrawInf.SetSpace( rInf.GetSpace() );
     369           0 :                 nCrsr = nCrsr + pLowerFnt->GetCrsrOfst( aDrawInf );
     370             :             }
     371           0 :             nOfst = 0;
     372             :         }
     373             :     }
     374           0 : }
     375             : 
     376           0 : sal_Int32 SwSubFont::GetCapitalCrsrOfst( SwDrawTextInfo& rInf )
     377             : {
     378           0 :     const long nOldKern = rInf.GetKern();
     379           0 :     rInf.SetKern( CheckKerning() );
     380           0 :     SwDoCapitalCrsrOfst aDo( rInf, rInf.GetOfst() );
     381           0 :     Point aPos;
     382           0 :     rInf.SetPos( aPos );
     383           0 :     rInf.SetDrawSpace( false );
     384           0 :     DoOnCapitals( aDo );
     385           0 :     rInf.SetKern( nOldKern );
     386           0 :     return aDo.GetCrsr();
     387             : }
     388             : 
     389             : class SwDoDrawStretchCapital : public SwDoDrawCapital
     390             : {
     391             :     const sal_Int32 nStrLen;
     392             :     const sal_uInt16 nCapWidth;
     393             :     const sal_uInt16 nOrgWidth;
     394             : public:
     395             :     virtual void Do() SAL_OVERRIDE;
     396             : 
     397           0 :     SwDoDrawStretchCapital( SwDrawTextInfo &rInfo, const sal_uInt16 nCapitalWidth )
     398             :             : SwDoDrawCapital( rInfo ),
     399           0 :               nStrLen( rInfo.GetLen() ),
     400             :               nCapWidth( nCapitalWidth ),
     401           0 :               nOrgWidth( rInfo.GetWidth() )
     402           0 :         { }
     403             : 
     404           0 :     virtual ~SwDoDrawStretchCapital() {}
     405             : };
     406             : 
     407           0 : void SwDoDrawStretchCapital::Do()
     408             : {
     409             :     SV_STAT( nDrawStretchText );
     410           0 :     long nPartWidth = rInf.GetSize().Width();
     411             : 
     412           0 :     if( rInf.GetLen() )
     413             :     {
     414             :         // 4023: Kapitaelchen und Kerning.
     415           0 :         long nDiff = long(nOrgWidth) - long(nCapWidth);
     416           0 :         if( nDiff )
     417             :         {
     418           0 :             nDiff *= rInf.GetLen();
     419           0 :             nDiff /= nStrLen;
     420           0 :             nDiff += nPartWidth;
     421           0 :             if( 0 < nDiff )
     422           0 :                 nPartWidth = nDiff;
     423             :         }
     424             : 
     425           0 :         rInf.ApplyAutoColor();
     426             : 
     427           0 :         Point aPos( rInf.GetPos() );
     428           0 :         const bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
     429           0 :                               ! rInf.IsIgnoreFrmRTL();
     430             : 
     431           0 :         if ( bSwitchL2R )
     432           0 :             rInf.GetFrm()->SwitchLTRtoRTL( aPos );
     433             : 
     434           0 :         if ( rInf.GetFrm()->IsVertical() )
     435           0 :             rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
     436             : 
     437             :         // Optimierung:
     438           0 :         if( 1 >= rInf.GetLen() )
     439           0 :             GetOut().DrawText( aPos, rInf.GetText(), rInf.GetIdx(),
     440           0 :                 rInf.GetLen() );
     441             :         else
     442           0 :             GetOut().DrawStretchText( aPos, nPartWidth,
     443           0 :                                 rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
     444             :     }
     445           0 :     ((Point&)rInf.GetPos()).X() += nPartWidth;
     446           0 : }
     447             : 
     448           0 : void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf )
     449             : {
     450             :     // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
     451             :     // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
     452             : 
     453           0 :     if( rInf.GetLen() == COMPLETE_STRING )
     454           0 :         rInf.SetLen( rInf.GetText().getLength() );
     455             : 
     456           0 :     const Point aOldPos = rInf.GetPos();
     457           0 :     const sal_uInt16 nCapWidth = (sal_uInt16)( GetCapitalSize( rInf ).Width() );
     458           0 :     rInf.SetPos(aOldPos);
     459             : 
     460           0 :     rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
     461           0 :                        GetOverline()  != UNDERLINE_NONE ||
     462           0 :                        GetStrikeout() != STRIKEOUT_NONE );
     463           0 :     SwDoDrawStretchCapital aDo( rInf, nCapWidth );
     464           0 :     DoOnCapitals( aDo );
     465           0 : }
     466             : 
     467         440 : void SwSubFont::DoOnCapitals( SwDoCapitals &rDo )
     468             : {
     469             :     OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
     470             : 
     471         440 :     long nKana = 0;
     472         440 :     const OUString aTxt( CalcCaseMap( rDo.GetInf().GetText() ) );
     473         440 :     sal_Int32 nMaxPos = std::min( rDo.GetInf().GetText().getLength() - rDo.GetInf().GetIdx(),
     474         880 :                              rDo.GetInf().GetLen() );
     475         440 :     rDo.GetInf().SetLen( nMaxPos );
     476             : 
     477         880 :     const OUString oldText = rDo.GetInf().GetText();
     478         440 :     rDo.GetInf().SetText( aTxt );
     479         440 :     sal_Int32 nPos = rDo.GetInf().GetIdx();
     480         440 :     sal_Int32 nOldPos = nPos;
     481         440 :     nMaxPos = nMaxPos + nPos;
     482             : 
     483             :     // #107816#
     484             :     // Look if the length of the original text and the ToUpper-converted
     485             :     // text is different. If yes, do special handling.
     486         880 :     OUString aNewText;
     487         440 :     SwCapitalInfo aCapInf(oldText);
     488         440 :     bool bCaseMapLengthDiffers(aTxt.getLength() != oldText.getLength());
     489         440 :     if ( bCaseMapLengthDiffers )
     490           0 :         rDo.SetCapInf( aCapInf );
     491             : 
     492         440 :     SwFntObj *pOldLast = pLastFont;
     493         440 :     SwFntAccess *pBigFontAccess = NULL;
     494             :     SwFntObj *pBigFont;
     495         440 :     SwFntAccess *pSpaceFontAccess = NULL;
     496         440 :     SwFntObj *pSpaceFont = NULL;
     497             : 
     498         440 :     const void *pMagic2 = NULL;
     499         440 :     sal_uInt16 nIndex2 = 0;
     500         880 :     SwSubFont aFont( *this );
     501         440 :     Point aStartPos( rDo.GetInf().GetPos() );
     502             : 
     503         440 :     const bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE
     504         298 :                          || aFont.GetOverline()  != UNDERLINE_NONE
     505         738 :                          || aFont.GetStrikeout() != STRIKEOUT_NONE;
     506         440 :     const bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
     507         440 :                            rDo.GetInf().GetDrawSpace();
     508         440 :     const long nTmpKern = rDo.GetInf().GetKern();
     509             : 
     510         440 :     if ( bTextLines )
     511             :     {
     512         142 :         if ( bWordWise )
     513             :         {
     514           0 :             aFont.SetWordLineMode( false );
     515             :             pSpaceFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
     516           0 :                                                 rDo.GetInf().GetShell() );
     517           0 :             pSpaceFont = pSpaceFontAccess->Get();
     518             :         }
     519             :         else
     520         142 :             pSpaceFont = pLastFont;
     521             : 
     522             :         // Wir basteln uns einen Font fuer die Grossbuchstaben:
     523         142 :         aFont.SetUnderline( UNDERLINE_NONE );
     524         142 :         aFont.SetOverline( UNDERLINE_NONE );
     525         142 :         aFont.SetStrikeout( STRIKEOUT_NONE );
     526         142 :         pMagic2 = NULL;
     527         142 :         nIndex2 = 0;
     528             :         pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
     529         142 :                                           rDo.GetInf().GetShell() );
     530         142 :         pBigFont = pBigFontAccess->Get();
     531             :     }
     532             :     else
     533         298 :         pBigFont = pLastFont;
     534             : 
     535             :     // Older LO versions had 66 as the small caps percentage size, later changed to 80,
     536             :     // therefore a backwards compatibility option is kept (otherwise layout is changed).
     537             :     // NOTE: There are more uses of SMALL_CAPS_PERCENTAGE in editeng, but it seems they
     538             :     // do not matter for Writer (and if they did it'd be pretty ugly to propagate
     539             :     // the option there).
     540         440 :     int smallCapsPercentage = smallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE;
     541         440 :     aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 );
     542         440 :     pMagic2 = NULL;
     543         440 :     nIndex2 = 0;
     544             :     SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
     545         440 :                                                      rDo.GetInf().GetShell() );
     546         440 :     SwFntObj *pSmallFont = pSmallFontAccess->Get();
     547             : 
     548         440 :     rDo.Init( pBigFont, pSmallFont );
     549         440 :     OutputDevice* pOutSize = pSmallFont->GetPrt();
     550         440 :     if( !pOutSize )
     551          68 :         pOutSize = &rDo.GetOut();
     552         440 :     OutputDevice* pOldOut = &rDo.GetOut();
     553             : 
     554         440 :     const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
     555         440 :                             ? LANGUAGE_SYSTEM : GetLanguage();
     556             : 
     557         440 :     if( nPos < nMaxPos )
     558             :     {
     559         880 :         nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
     560             :                         oldText, nPos,
     561         440 :             g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
     562         440 :         if (nPos < 0)
     563         400 :             nPos = nOldPos;
     564          40 :         else if( nPos > nMaxPos )
     565          12 :             nPos = nMaxPos;
     566             :     }
     567             : 
     568        2802 :     while( nOldPos < nMaxPos )
     569             :     {
     570             : 
     571             :         //  The lower ones...
     572        1922 :         if( nOldPos != nPos )
     573             :         {
     574             :             SV_STAT( nGetTextSize );
     575        1522 :             pLastFont = pSmallFont;
     576        1522 :             pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
     577             : 
     578             :             // #107816#, #i14820#
     579        1522 :             if( bCaseMapLengthDiffers )
     580             :             {
     581             :                 // Build an own 'changed' string for the given part of the
     582             :                 // source string and use it. That new string may differ in length
     583             :                 // from the source string.
     584           0 :                 const OUString aSnippet(oldText.copy(nOldPos, nPos - nOldPos));
     585           0 :                 aNewText = CalcCaseMap( aSnippet );
     586           0 :                 aCapInf.nIdx = nOldPos;
     587           0 :                 aCapInf.nLen = nPos - nOldPos;
     588           0 :                 rDo.GetInf().SetIdx( 0 );
     589           0 :                 rDo.GetInf().SetLen( aNewText.getLength() );
     590           0 :                 rDo.GetInf().SetText( aNewText );
     591             :             }
     592             :             else
     593             :             {
     594        1522 :                 rDo.GetInf().SetIdx( nOldPos );
     595        1522 :                 rDo.GetInf().SetLen( nPos - nOldPos );
     596             :             }
     597             : 
     598        1522 :             rDo.GetInf().SetUpper( false );
     599        1522 :             rDo.GetInf().SetOut( *pOutSize );
     600        1522 :             Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
     601        1522 :             nKana += rDo.GetInf().GetKanaDiff();
     602        1522 :             rDo.GetInf().SetOut( *pOldOut );
     603        1522 :             if( nTmpKern && nPos < nMaxPos )
     604          18 :                 aPartSize.Width() += nTmpKern;
     605        1522 :             rDo.GetInf().SetSize( aPartSize );
     606        1522 :             rDo.Do();
     607        1522 :             nOldPos = nPos;
     608             :         }
     609        3844 :         nPos = g_pBreakIt->GetBreakIter()->nextCharBlock(
     610             :                             oldText, nPos,
     611        1922 :                g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
     612        1922 :         if (nPos < 0 || nPos > nMaxPos)
     613         436 :             nPos = nMaxPos;
     614             :         OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
     615             : #if OSL_DEBUG_LEVEL > 1
     616             :         if( !nPos )
     617             :             nPos = nMaxPos;
     618             : #endif
     619             :         // The upper ones...
     620        1922 :         if( nOldPos != nPos )
     621             :         {
     622        1810 :             const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
     623             : 
     624        1810 :             do
     625             :             {
     626        1810 :                 rDo.GetInf().SetUpper( true );
     627        1810 :                 pLastFont = pBigFont;
     628        1810 :                 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
     629             :                 sal_Int32 nTmp;
     630        1810 :                 if( bWordWise )
     631             :                 {
     632           0 :                     nTmp = nOldPos;
     633           0 :                     while (nTmp < nPos && CH_BLANK == oldText[nTmp])
     634           0 :                         ++nTmp;
     635           0 :                     if( nOldPos < nTmp )
     636             :                     {
     637           0 :                         pLastFont = pSpaceFont;
     638           0 :                         pLastFont->SetDevFont( rDo.GetInf().GetShell(),
     639           0 :                                                rDo.GetOut() );
     640           0 :                         ((SwDoDrawCapital&)rDo).DrawSpace( aStartPos );
     641           0 :                         pLastFont = pBigFont;
     642           0 :                         pLastFont->SetDevFont( rDo.GetInf().GetShell(),
     643           0 :                                                rDo.GetOut() );
     644             : 
     645             :                         // #107816#, #i14820#
     646           0 :                         if( bCaseMapLengthDiffers )
     647             :                         {
     648             :                             // Build an own 'changed' string for the given part of the
     649             :                             // source string and use it. That new string may differ in length
     650             :                             // from the source string.
     651           0 :                             const OUString aSnippet(oldText.copy(nOldPos, nTmp - nOldPos));
     652           0 :                             aNewText = CalcCaseMap( aSnippet );
     653           0 :                             aCapInf.nIdx = nOldPos;
     654           0 :                             aCapInf.nLen = nTmp - nOldPos;
     655           0 :                             rDo.GetInf().SetIdx( 0 );
     656           0 :                             rDo.GetInf().SetLen( aNewText.getLength() );
     657           0 :                             rDo.GetInf().SetText( aNewText );
     658             :                         }
     659             :                         else
     660             :                         {
     661           0 :                             rDo.GetInf().SetIdx( nOldPos );
     662           0 :                             rDo.GetInf().SetLen( nTmp - nOldPos );
     663             :                         }
     664             : 
     665           0 :                         rDo.GetInf().SetOut( *pOutSize );
     666           0 :                         Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
     667           0 :                         nKana += rDo.GetInf().GetKanaDiff();
     668           0 :                         rDo.GetInf().SetOut( *pOldOut );
     669           0 :                         if( nSpaceAdd )
     670           0 :                             aPartSize.Width() += nSpaceAdd * ( nTmp - nOldPos );
     671           0 :                         if( nTmpKern && nPos < nMaxPos )
     672           0 :                             aPartSize.Width() += nTmpKern;
     673           0 :                         rDo.GetInf().SetSize( aPartSize );
     674           0 :                         rDo.Do();
     675           0 :                         aStartPos = rDo.GetInf().GetPos();
     676           0 :                         nOldPos = nTmp;
     677             :                     }
     678             : 
     679           0 :                     while (nTmp < nPos && CH_BLANK != oldText[nTmp])
     680           0 :                         ++nTmp;
     681             :                 }
     682             :                 else
     683        1810 :                     nTmp = nPos;
     684        1810 :                 if( nTmp > nOldPos )
     685             :                 {
     686             :                       // #107816#, #i14820#
     687        1810 :                     if( bCaseMapLengthDiffers )
     688             :                     {
     689             :                         // Build an own 'changed' string for the given part of the
     690             :                         // source string and use it. That new string may differ in length
     691             :                         // from the source string.
     692           0 :                         const OUString aSnippet(oldText.copy(nOldPos, nTmp - nOldPos));
     693           0 :                         aNewText = CalcCaseMap( aSnippet );
     694           0 :                         aCapInf.nIdx = nOldPos;
     695           0 :                         aCapInf.nLen = nTmp - nOldPos;
     696           0 :                         rDo.GetInf().SetIdx( 0 );
     697           0 :                         rDo.GetInf().SetLen( aNewText.getLength() );
     698           0 :                         rDo.GetInf().SetText( aNewText );
     699             :                     }
     700             :                     else
     701             :                     {
     702        1810 :                         rDo.GetInf().SetIdx( nOldPos );
     703        1810 :                         rDo.GetInf().SetLen( nTmp - nOldPos );
     704             :                     }
     705             : 
     706        1810 :                     rDo.GetInf().SetOut( *pOutSize );
     707        1810 :                     Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
     708        1810 :                     nKana += rDo.GetInf().GetKanaDiff();
     709        1810 :                     rDo.GetInf().SetOut( *pOldOut );
     710        1810 :                     if( !bWordWise && rDo.GetInf().GetSpace() )
     711             :                     {
     712           0 :                         for( sal_Int32 nI = nOldPos; nI < nPos; ++nI )
     713             :                         {
     714           0 :                             if (CH_BLANK == oldText[nI])
     715           0 :                                 aPartSize.Width() += nSpaceAdd;
     716             :                         }
     717             :                     }
     718        1810 :                     if( nTmpKern && nPos < nMaxPos )
     719          24 :                         aPartSize.Width() += nTmpKern;
     720        1810 :                     rDo.GetInf().SetSize( aPartSize );
     721        1810 :                     rDo.Do();
     722        1810 :                     nOldPos = nTmp;
     723             :                 }
     724             :             } while( nOldPos != nPos );
     725             :         }
     726        3844 :         nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
     727             :                             oldText, nPos,
     728        1922 :                g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
     729        1922 :         if (nPos < 0 || nPos > nMaxPos)
     730         444 :             nPos = nMaxPos;
     731             :         OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
     732             : #if OSL_DEBUG_LEVEL > 1
     733             :         if( !nPos )
     734             :             nPos = nMaxPos;
     735             : #endif
     736             :     }
     737             : 
     738             :     // Aufraeumen:
     739         440 :     if( pBigFont != pOldLast )
     740         142 :         delete pBigFontAccess;
     741             : 
     742         440 :     if( bTextLines )
     743             :     {
     744         142 :         if( rDo.GetInf().GetDrawSpace() )
     745             :         {
     746           6 :             pLastFont = pSpaceFont;
     747           6 :             pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
     748           6 :             ( (SwDoDrawCapital&) rDo ).DrawSpace( aStartPos );
     749             :         }
     750         142 :         if ( bWordWise )
     751           0 :             delete pSpaceFontAccess;
     752             :     }
     753         440 :     pLastFont = pOldLast;
     754         440 :     pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
     755             : 
     756         440 :     delete pSmallFontAccess;
     757         440 :     rDo.GetInf().SetText(oldText);
     758         880 :     rDo.GetInf().SetKanaDiff( nKana );
     759         710 : }
     760             : 
     761             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10