| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #include <hintids.hxx> |
| #include <editeng/cmapitem.hxx> |
| |
| #ifndef _OUTDEV_HXX //autogen |
| #include <vcl/outdev.hxx> |
| #endif |
| #ifndef _COM_SUN_STAR_I18N_CHARTYPE_HDL |
| #include <com/sun/star/i18n/CharType.hdl> |
| #endif |
| #ifndef _COM_SUN_STAR_I18N_WORDTYPE_HDL |
| #include <com/sun/star/i18n/WordType.hdl> |
| #endif |
| |
| #ifndef _PRINT_HXX //autogen |
| #include <vcl/print.hxx> |
| #endif |
| #include <errhdl.hxx> |
| #include <fntcache.hxx> |
| #include <swfont.hxx> |
| #include <breakit.hxx> |
| #include <txtfrm.hxx> // SwTxtFrm |
| #include <scriptinfo.hxx> |
| |
| using namespace ::com::sun::star::i18n; |
| |
| |
| #define KAPITAELCHENPROP 74 |
| |
| /************************************************************************* |
| * class SwCapitalInfo |
| * |
| * The information encapsulated in SwCapitalInfo is required |
| * by the ::Do functions. They contain the information about |
| * the original string, whereas rDo.GetInf() contains information |
| * about the display string. |
| *************************************************************************/ |
| |
| class SwCapitalInfo |
| { |
| public: |
| explicit SwCapitalInfo( const XubString& rOrigText ) : |
| rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {}; |
| const XubString& rString; |
| xub_StrLen nIdx; |
| xub_StrLen nLen; |
| }; |
| |
| /************************************************************************* |
| * xub_StrLen lcl_CalcCaseMap() |
| * |
| * rFnt: required for CalcCaseMap |
| * rOrigString: The original string |
| * nOfst: Position of the substring in rOrigString |
| * nLen: Length if the substring in rOrigString |
| * nIdx: Referes to a position in the display string and should be mapped |
| * to a position in rOrigString |
| *************************************************************************/ |
| |
| xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt, |
| const XubString& rOrigString, |
| xub_StrLen nOfst, |
| xub_StrLen nLen, |
| xub_StrLen nIdx ) |
| { |
| int j = 0; |
| const xub_StrLen nEnd = nOfst + nLen; |
| ASSERT( nEnd <= rOrigString.Len(), "lcl_CalcCaseMap: Wrong parameters" ) |
| |
| // special case for title case: |
| const bool bTitle = SVX_CASEMAP_TITEL == rFnt.GetCaseMap() && |
| pBreakIt->GetBreakIter().is(); |
| for ( xub_StrLen i = nOfst; i < nEnd; ++i ) |
| { |
| XubString aTmp( rOrigString, i, 1 ); |
| |
| if ( !bTitle || |
| pBreakIt->GetBreakIter()->isBeginWord( |
| rOrigString, i, |
| pBreakIt->GetLocale( rFnt.GetLanguage() ), |
| WordType::ANYWORD_IGNOREWHITESPACES ) ) |
| aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp ); |
| |
| j += aTmp.Len(); |
| |
| if ( j > nIdx ) |
| return i; |
| } |
| |
| return nOfst + nLen; |
| } |
| |
| /************************************************************************* |
| * class SwDoCapitals |
| *************************************************************************/ |
| |
| class SwDoCapitals |
| { |
| protected: |
| SwDrawTextInfo &rInf; |
| SwCapitalInfo* pCapInf; // referes to additional information |
| // required by the ::Do function |
| public: |
| SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { } |
| virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0; |
| virtual void Do() = 0; |
| inline OutputDevice& GetOut() { return rInf.GetOut(); } |
| inline SwDrawTextInfo& GetInf() { return rInf; } |
| inline SwCapitalInfo* GetCapInf() const { return pCapInf; } |
| inline void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; } |
| }; |
| |
| /************************************************************************* |
| * class SwDoGetCapitalSize |
| *************************************************************************/ |
| |
| class SwDoGetCapitalSize : public SwDoCapitals |
| { |
| protected: |
| Size aTxtSize; |
| public: |
| SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { } |
| virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); |
| virtual void Do(); |
| const Size &GetSize() const { return aTxtSize; } |
| }; |
| |
| void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * ) |
| { |
| aTxtSize.Height() = 0; |
| aTxtSize.Width() = 0; |
| } |
| |
| void SwDoGetCapitalSize::Do() |
| { |
| aTxtSize.Width() += rInf.GetSize().Width(); |
| if( rInf.GetUpper() ) |
| aTxtSize.Height() = rInf.GetSize().Height(); |
| } |
| |
| /************************************************************************* |
| * SwSubFont::GetCapitalSize() |
| *************************************************************************/ |
| |
| Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf ) |
| { |
| // Start: |
| const long nOldKern = rInf.GetKern(); |
| rInf.SetKern( CheckKerning() ); |
| Point aPos; |
| rInf.SetPos( aPos ); |
| rInf.SetSpace( 0 ); |
| rInf.SetDrawSpace( sal_False ); |
| SwDoGetCapitalSize aDo( rInf ); |
| DoOnCapitals( aDo ); |
| Size aTxtSize( aDo.GetSize() ); |
| |
| // End: |
| if( !aTxtSize.Height() ) |
| { |
| SV_STAT( nGetTextSize ); |
| aTxtSize.Height() = short ( rInf.GetpOut()->GetTextHeight() ); |
| } |
| rInf.SetKern( nOldKern ); |
| return aTxtSize; |
| } |
| |
| /************************************************************************* |
| * class SwDoGetCapitalBreak |
| *************************************************************************/ |
| |
| class SwDoGetCapitalBreak : public SwDoCapitals |
| { |
| protected: |
| xub_StrLen *pExtraPos; |
| long nTxtWidth; |
| xub_StrLen nBreak; |
| public: |
| SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long nWidth, xub_StrLen *pExtra) |
| : SwDoCapitals ( rInfo ), pExtraPos( pExtra ), nTxtWidth( nWidth ), |
| nBreak( STRING_LEN ) |
| { } |
| virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); |
| virtual void Do(); |
| xub_StrLen GetBreak() const { return nBreak; } |
| }; |
| |
| void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * ) |
| { |
| } |
| |
| void SwDoGetCapitalBreak::Do() |
| { |
| if ( nTxtWidth ) |
| { |
| if ( rInf.GetSize().Width() < nTxtWidth ) |
| nTxtWidth -= rInf.GetSize().Width(); |
| else |
| { |
| xub_StrLen nEnd = rInf.GetEnd(); |
| if( pExtraPos ) |
| { |
| nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth, '-', |
| *pExtraPos, rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() ); |
| if( *pExtraPos > nEnd ) |
| *pExtraPos = nEnd; |
| } |
| else |
| nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth, |
| rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() ); |
| |
| if( nBreak > nEnd ) |
| nBreak = nEnd; |
| |
| // nBreak may be relative to the display string. It has to be |
| // calculated relative to the original string: |
| if ( GetCapInf() ) |
| { |
| if ( GetCapInf()->nLen != rInf.GetLen() ) |
| nBreak = lcl_CalcCaseMap( *rInf.GetFont(), |
| GetCapInf()->rString, |
| GetCapInf()->nIdx, |
| GetCapInf()->nLen, nBreak ); |
| else |
| nBreak = nBreak + GetCapInf()->nIdx; |
| } |
| |
| nTxtWidth = 0; |
| } |
| } |
| } |
| |
| /************************************************************************* |
| * SwFont::GetCapitalBreak() |
| *************************************************************************/ |
| |
| xub_StrLen SwFont::GetCapitalBreak( ViewShell* pSh, const OutputDevice* pOut, |
| const SwScriptInfo* pScript, const XubString& rTxt, long nTextWidth, |
| xub_StrLen *pExtra, const xub_StrLen nIdx, const xub_StrLen nLen ) |
| { |
| // Start: |
| Point aPos( 0, 0 ); |
| SwDrawTextInfo aInfo(pSh, *(OutputDevice*)pOut, pScript, rTxt, nIdx, nLen, |
| 0, sal_False); |
| aInfo.SetPos( aPos ); |
| aInfo.SetSpace( 0 ); |
| aInfo.SetWrong( NULL ); |
| aInfo.SetGrammarCheck( NULL ); |
| aInfo.SetSmartTags( NULL ); // SMARTTAGS |
| aInfo.SetDrawSpace( sal_False ); |
| aInfo.SetKern( CheckKerning() ); |
| aInfo.SetKanaComp( pScript ? 0 : 100 ); |
| aInfo.SetFont( this ); |
| |
| SwDoGetCapitalBreak aDo( aInfo, nTextWidth, pExtra ); |
| DoOnCapitals( aDo ); |
| return aDo.GetBreak(); |
| } |
| |
| /************************************************************************* |
| * class SwDoDrawCapital |
| *************************************************************************/ |
| |
| class SwDoDrawCapital : public SwDoCapitals |
| { |
| protected: |
| SwFntObj *pUpperFnt; |
| SwFntObj *pLowerFnt; |
| public: |
| SwDoDrawCapital( SwDrawTextInfo &rInfo ) : |
| SwDoCapitals( rInfo ) |
| { } |
| virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); |
| virtual void Do(); |
| void DrawSpace( Point &rPos ); |
| }; |
| |
| void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) |
| { |
| pUpperFnt = pUpperFont; |
| pLowerFnt = pLowerFont; |
| } |
| |
| void SwDoDrawCapital::Do() |
| { |
| SV_STAT( nDrawText ); |
| sal_uInt16 nOrgWidth = rInf.GetWidth(); |
| rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) ); |
| if ( rInf.GetUpper() ) |
| pUpperFnt->DrawText( rInf ); |
| else |
| { |
| sal_Bool bOldBullet = rInf.GetBullet(); |
| rInf.SetBullet( sal_False ); |
| pLowerFnt->DrawText( rInf ); |
| rInf.SetBullet( bOldBullet ); |
| } |
| |
| ASSERT( pUpperFnt, "No upper font, dying soon!"); |
| rInf.Shift( pUpperFnt->GetFont()->GetOrientation() ); |
| rInf.SetWidth( nOrgWidth ); |
| } |
| |
| /************************************************************************* |
| * SwDoDrawCapital::DrawSpace() |
| *************************************************************************/ |
| |
| void SwDoDrawCapital::DrawSpace( Point &rPos ) |
| { |
| static sal_Char __READONLY_DATA sDoubleSpace[] = " "; |
| |
| long nDiff = rInf.GetPos().X() - rPos.X(); |
| |
| Point aPos( rPos ); |
| const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() && |
| ! rInf.IsIgnoreFrmRTL(); |
| |
| |
| if ( bSwitchL2R ) |
| rInf.GetFrm()->SwitchLTRtoRTL( aPos ); |
| |
| const sal_uLong nMode = rInf.GetpOut()->GetLayoutMode(); |
| const sal_Bool bBidiPor = ( bSwitchL2R != |
| ( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) ); |
| |
| if ( bBidiPor ) |
| nDiff = -nDiff; |
| |
| if ( rInf.GetFrm()->IsVertical() ) |
| rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); |
| |
| if ( nDiff ) |
| { |
| rInf.ApplyAutoColor(); |
| GetOut().DrawStretchText( aPos, nDiff, |
| XubString( sDoubleSpace, RTL_TEXTENCODING_MS_1252 ), 0, 2 ); |
| } |
| rPos.X() = rInf.GetPos().X() + rInf.GetWidth(); |
| } |
| |
| /************************************************************************* |
| * SwSubFont::DrawCapital() |
| *************************************************************************/ |
| |
| void SwSubFont::DrawCapital( SwDrawTextInfo &rInf ) |
| { |
| // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist! |
| // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) ); |
| rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE || |
| GetOverline() != UNDERLINE_NONE || |
| GetStrikeout() != STRIKEOUT_NONE ); |
| SwDoDrawCapital aDo( rInf ); |
| DoOnCapitals( aDo ); |
| } |
| |
| /************************************************************************* |
| * class SwDoDrawCapital |
| *************************************************************************/ |
| |
| class SwDoCapitalCrsrOfst : public SwDoCapitals |
| { |
| protected: |
| SwFntObj *pUpperFnt; |
| SwFntObj *pLowerFnt; |
| xub_StrLen nCrsr; |
| sal_uInt16 nOfst; |
| public: |
| SwDoCapitalCrsrOfst( SwDrawTextInfo &rInfo, const sal_uInt16 nOfs ) : |
| SwDoCapitals( rInfo ), nCrsr( 0 ), nOfst( nOfs ) |
| { } |
| virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ); |
| virtual void Do(); |
| |
| void DrawSpace( const Point &rPos ); |
| inline xub_StrLen GetCrsr(){ return nCrsr; } |
| }; |
| |
| void SwDoCapitalCrsrOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) |
| { |
| pUpperFnt = pUpperFont; |
| pLowerFnt = pLowerFont; |
| } |
| |
| void SwDoCapitalCrsrOfst::Do() |
| { |
| if ( nOfst ) |
| { |
| if ( nOfst > rInf.GetSize().Width() ) |
| { |
| nOfst = nOfst - sal_uInt16(rInf.GetSize().Width()); |
| nCrsr = nCrsr + rInf.GetLen(); |
| } |
| else |
| { |
| SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(), |
| rInf.GetScriptInfo(), |
| rInf.GetText(), |
| rInf.GetIdx(), |
| rInf.GetLen(), 0, sal_False ); |
| aDrawInf.SetOfst( nOfst ); |
| aDrawInf.SetKern( rInf.GetKern() ); |
| aDrawInf.SetKanaComp( rInf.GetKanaComp() ); |
| aDrawInf.SetFrm( rInf.GetFrm() ); |
| aDrawInf.SetFont( rInf.GetFont() ); |
| |
| if ( rInf.GetUpper() ) |
| { |
| aDrawInf.SetSpace( 0 ); |
| nCrsr = nCrsr + pUpperFnt->GetCrsrOfst( aDrawInf ); |
| } |
| else |
| { |
| aDrawInf.SetSpace( rInf.GetSpace() ); |
| nCrsr = nCrsr + pLowerFnt->GetCrsrOfst( aDrawInf ); |
| } |
| nOfst = 0; |
| } |
| } |
| } |
| |
| /************************************************************************* |
| * SwSubFont::GetCapitalCrsrOfst() |
| *************************************************************************/ |
| |
| xub_StrLen SwSubFont::GetCapitalCrsrOfst( SwDrawTextInfo& rInf ) |
| { |
| const long nOldKern = rInf.GetKern(); |
| rInf.SetKern( CheckKerning() ); |
| SwDoCapitalCrsrOfst aDo( rInf, rInf.GetOfst() ); |
| Point aPos; |
| rInf.SetPos( aPos ); |
| rInf.SetDrawSpace( sal_False ); |
| DoOnCapitals( aDo ); |
| rInf.SetKern( nOldKern ); |
| return aDo.GetCrsr(); |
| } |
| |
| /************************************************************************* |
| * class SwDoDrawStretchCapital |
| *************************************************************************/ |
| |
| class SwDoDrawStretchCapital : public SwDoDrawCapital |
| { |
| const xub_StrLen nStrLen; |
| const sal_uInt16 nCapWidth; |
| const sal_uInt16 nOrgWidth; |
| public: |
| virtual void Do(); |
| |
| SwDoDrawStretchCapital( SwDrawTextInfo &rInfo, const sal_uInt16 nCapitalWidth ) |
| : SwDoDrawCapital( rInfo ), |
| nStrLen( rInfo.GetLen() ), |
| nCapWidth( nCapitalWidth ), |
| nOrgWidth( rInfo.GetWidth() ) |
| { } |
| }; |
| |
| /************************************************************************* |
| * SwDoDrawStretchCapital |
| *************************************************************************/ |
| |
| void SwDoDrawStretchCapital::Do() |
| { |
| SV_STAT( nDrawStretchText ); |
| sal_uInt16 nPartWidth = sal_uInt16(rInf.GetSize().Width()); |
| |
| if( rInf.GetLen() ) |
| { |
| // 4023: Kapitaelchen und Kerning. |
| long nDiff = long(nOrgWidth) - long(nCapWidth); |
| if( nDiff ) |
| { |
| nDiff *= rInf.GetLen(); |
| nDiff /= (long) nStrLen; |
| nDiff += nPartWidth; |
| if( 0 < nDiff ) |
| nPartWidth = sal_uInt16(nDiff); |
| } |
| |
| rInf.ApplyAutoColor(); |
| |
| Point aPos( rInf.GetPos() ); |
| const sal_Bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() && |
| ! rInf.IsIgnoreFrmRTL(); |
| |
| if ( bSwitchL2R ) |
| rInf.GetFrm()->SwitchLTRtoRTL( aPos ); |
| |
| if ( rInf.GetFrm()->IsVertical() ) |
| rInf.GetFrm()->SwitchHorizontalToVertical( aPos ); |
| |
| // Optimierung: |
| if( 1 >= rInf.GetLen() ) |
| GetOut().DrawText( aPos, rInf.GetText(), rInf.GetIdx(), |
| rInf.GetLen() ); |
| else |
| GetOut().DrawStretchText( aPos, nPartWidth, |
| rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ); |
| } |
| ((Point&)rInf.GetPos()).X() += nPartWidth; |
| } |
| |
| /************************************************************************* |
| * SwSubFont::DrawStretchCapital() |
| *************************************************************************/ |
| |
| void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf ) |
| { |
| // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist! |
| // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) ); |
| |
| if( rInf.GetLen() == STRING_LEN ) |
| rInf.SetLen( rInf.GetText().Len() ); |
| |
| const Point& rOldPos = rInf.GetPos(); |
| const sal_uInt16 nCapWidth = (sal_uInt16)( GetCapitalSize( rInf ).Width() ); |
| rInf.SetPos( rOldPos ); |
| |
| rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE || |
| GetOverline() != UNDERLINE_NONE || |
| GetStrikeout() != STRIKEOUT_NONE ); |
| SwDoDrawStretchCapital aDo( rInf, nCapWidth ); |
| DoOnCapitals( aDo ); |
| } |
| |
| /************************************************************************* |
| * SwSubFont::DoOnCapitals() const |
| *************************************************************************/ |
| |
| // JP 22.8.2001 - global optimization off - Bug 91245 / 91223 |
| #ifdef _MSC_VER |
| #pragma optimize("g",off) |
| #endif |
| |
| void SwSubFont::DoOnCapitals( SwDoCapitals &rDo ) |
| { |
| ASSERT( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" ); |
| |
| Size aPartSize; |
| long nKana = 0; |
| const XubString aTxt( CalcCaseMap( rDo.GetInf().GetText() ) ); |
| xub_StrLen nMaxPos = Min( sal_uInt16(rDo.GetInf().GetText().Len() |
| - rDo.GetInf().GetIdx()), rDo.GetInf().GetLen() ); |
| rDo.GetInf().SetLen( nMaxPos ); |
| |
| const XubString& rOldText = rDo.GetInf().GetText(); |
| rDo.GetInf().SetText( aTxt ); |
| rDo.GetInf().SetSize( aPartSize ); |
| xub_StrLen nPos = rDo.GetInf().GetIdx(); |
| xub_StrLen nOldPos = nPos; |
| nMaxPos = nMaxPos + nPos; |
| |
| // #107816# |
| // Look if the length of the original text and the ToUpper-converted |
| // text is different. If yes, do special handling. |
| XubString aNewText; |
| SwCapitalInfo aCapInf( rOldText ); |
| sal_Bool bCaseMapLengthDiffers( aTxt.Len() != rOldText.Len() ); |
| if ( bCaseMapLengthDiffers ) |
| rDo.SetCapInf( aCapInf ); |
| |
| SwFntObj *pOldLast = pLastFont; |
| SwFntAccess *pBigFontAccess = NULL; |
| SwFntObj *pBigFont; |
| SwFntAccess *pSpaceFontAccess = NULL; |
| SwFntObj *pSpaceFont = NULL; |
| |
| const void *pMagic2 = NULL; |
| sal_uInt16 nIndex2 = 0; |
| SwSubFont aFont( *this ); |
| Point aStartPos( rDo.GetInf().GetPos() ); |
| |
| const sal_Bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE |
| || aFont.GetOverline() != UNDERLINE_NONE |
| || aFont.GetStrikeout() != STRIKEOUT_NONE; |
| const sal_Bool bWordWise = bTextLines && aFont.IsWordLineMode() && |
| rDo.GetInf().GetDrawSpace(); |
| const long nTmpKern = rDo.GetInf().GetKern(); |
| |
| if ( bTextLines ) |
| { |
| if ( bWordWise ) |
| { |
| aFont.SetWordLineMode( sal_False ); |
| pSpaceFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, |
| rDo.GetInf().GetShell() ); |
| pSpaceFont = pSpaceFontAccess->Get(); |
| } |
| else |
| pSpaceFont = pLastFont; |
| |
| // Wir basteln uns einen Font fuer die Grossbuchstaben: |
| aFont.SetUnderline( UNDERLINE_NONE ); |
| aFont.SetOverline( UNDERLINE_NONE ); |
| aFont.SetStrikeout( STRIKEOUT_NONE ); |
| pMagic2 = NULL; |
| nIndex2 = 0; |
| pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, |
| rDo.GetInf().GetShell() ); |
| pBigFont = pBigFontAccess->Get(); |
| } |
| else |
| pBigFont = pLastFont; |
| |
| // Hier entsteht der Kleinbuchstabenfont: |
| aFont.SetProportion( sal_uInt8( (aFont.GetPropr()*KAPITAELCHENPROP) / 100L) ); |
| pMagic2 = NULL; |
| nIndex2 = 0; |
| SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont, |
| rDo.GetInf().GetShell() ); |
| SwFntObj *pSmallFont = pSmallFontAccess->Get(); |
| |
| rDo.Init( pBigFont, pSmallFont ); |
| OutputDevice* pOutSize = pSmallFont->GetPrt(); |
| if( !pOutSize ) |
| pOutSize = &rDo.GetOut(); |
| OutputDevice* pOldOut = &rDo.GetOut(); |
| |
| const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage() |
| ? LANGUAGE_SYSTEM : GetLanguage(); |
| |
| if( nPos < nMaxPos ) |
| { |
| nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos, |
| pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); |
| if( nPos == STRING_LEN ) |
| nPos = nOldPos; |
| else if( nPos > nMaxPos ) |
| nPos = nMaxPos; |
| } |
| |
| while( nOldPos < nMaxPos ) |
| { |
| |
| // The lower ones... |
| if( nOldPos != nPos ) |
| { |
| SV_STAT( nGetTextSize ); |
| pLastFont = pSmallFont; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); |
| |
| // #107816#, #i14820# |
| if( bCaseMapLengthDiffers ) |
| { |
| // Build an own 'changed' string for the given part of the |
| // source string and use it. That new string may differ in length |
| // from the source string. |
| const XubString aSnippet( rOldText, nOldPos, nPos - nOldPos); |
| aNewText = CalcCaseMap( aSnippet ); |
| aCapInf.nIdx = nOldPos; |
| aCapInf.nLen = nPos - nOldPos; |
| rDo.GetInf().SetIdx( 0 ); |
| rDo.GetInf().SetLen( aNewText.Len() ); |
| rDo.GetInf().SetText( aNewText ); |
| } |
| else |
| { |
| rDo.GetInf().SetIdx( nOldPos ); |
| rDo.GetInf().SetLen( nPos - nOldPos ); |
| } |
| |
| rDo.GetInf().SetUpper( sal_False ); |
| rDo.GetInf().SetOut( *pOutSize ); |
| aPartSize = pSmallFont->GetTextSize( rDo.GetInf() ); |
| nKana += rDo.GetInf().GetKanaDiff(); |
| rDo.GetInf().SetOut( *pOldOut ); |
| if( nTmpKern && nPos < nMaxPos ) |
| aPartSize.Width() += nTmpKern; |
| rDo.Do(); |
| nOldPos = nPos; |
| } |
| nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharBlock( rOldText, nPos, |
| pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); |
| if( nPos == STRING_LEN || nPos > nMaxPos ) |
| nPos = nMaxPos; |
| ASSERT( nPos, "nextCharBlock not implemented?" ); |
| #ifdef DBG_UTIL |
| if( !nPos ) |
| nPos = nMaxPos; |
| #endif |
| // The upper ones... |
| if( nOldPos != nPos ) |
| { |
| const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR; |
| |
| do |
| { |
| rDo.GetInf().SetUpper( sal_True ); |
| pLastFont = pBigFont; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); |
| xub_StrLen nTmp; |
| if( bWordWise ) |
| { |
| nTmp = nOldPos; |
| while( nTmp < nPos && CH_BLANK == rOldText.GetChar( nTmp ) ) |
| ++nTmp; |
| if( nOldPos < nTmp ) |
| { |
| pLastFont = pSpaceFont; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), |
| rDo.GetOut() ); |
| ((SwDoDrawCapital&)rDo).DrawSpace( aStartPos ); |
| pLastFont = pBigFont; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), |
| rDo.GetOut() ); |
| |
| // #107816#, #i14820# |
| if( bCaseMapLengthDiffers ) |
| { |
| // Build an own 'changed' string for the given part of the |
| // source string and use it. That new string may differ in length |
| // from the source string. |
| const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos); |
| aNewText = CalcCaseMap( aSnippet ); |
| aCapInf.nIdx = nOldPos; |
| aCapInf.nLen = nTmp - nOldPos; |
| rDo.GetInf().SetIdx( 0 ); |
| rDo.GetInf().SetLen( aNewText.Len() ); |
| rDo.GetInf().SetText( aNewText ); |
| } |
| else |
| { |
| rDo.GetInf().SetIdx( nOldPos ); |
| rDo.GetInf().SetLen( nTmp - nOldPos ); |
| } |
| |
| rDo.GetInf().SetOut( *pOutSize ); |
| aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); |
| nKana += rDo.GetInf().GetKanaDiff(); |
| rDo.GetInf().SetOut( *pOldOut ); |
| if( nSpaceAdd ) |
| aPartSize.Width() += nSpaceAdd * ( nTmp - nOldPos ); |
| if( nTmpKern && nPos < nMaxPos ) |
| aPartSize.Width() += nTmpKern; |
| rDo.Do(); |
| aStartPos = rDo.GetInf().GetPos(); |
| nOldPos = nTmp; |
| } |
| |
| while( nTmp < nPos && CH_BLANK != rOldText.GetChar( nTmp ) ) |
| ++nTmp; |
| } |
| else |
| nTmp = nPos; |
| if( nTmp > nOldPos ) |
| { |
| // #107816#, #i14820# |
| if( bCaseMapLengthDiffers ) |
| { |
| // Build an own 'changed' string for the given part of the |
| // source string and use it. That new string may differ in length |
| // from the source string. |
| const XubString aSnippet( rOldText, nOldPos, nTmp - nOldPos); |
| aNewText = CalcCaseMap( aSnippet ); |
| aCapInf.nIdx = nOldPos; |
| aCapInf.nLen = nTmp - nOldPos; |
| rDo.GetInf().SetIdx( 0 ); |
| rDo.GetInf().SetLen( aNewText.Len() ); |
| rDo.GetInf().SetText( aNewText ); |
| } |
| else |
| { |
| rDo.GetInf().SetIdx( nOldPos ); |
| rDo.GetInf().SetLen( nTmp - nOldPos ); |
| } |
| |
| rDo.GetInf().SetOut( *pOutSize ); |
| aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); |
| nKana += rDo.GetInf().GetKanaDiff(); |
| rDo.GetInf().SetOut( *pOldOut ); |
| if( !bWordWise && rDo.GetInf().GetSpace() ) |
| { |
| for( xub_StrLen nI = nOldPos; nI < nPos; ++nI ) |
| { |
| if( CH_BLANK == rOldText.GetChar( nI ) ) |
| aPartSize.Width() += nSpaceAdd; |
| } |
| } |
| if( nTmpKern && nPos < nMaxPos ) |
| aPartSize.Width() += nTmpKern; |
| rDo.Do(); |
| nOldPos = nTmp; |
| } |
| } while( nOldPos != nPos ); |
| } |
| nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfCharBlock( rOldText, nPos, |
| pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER); |
| if( nPos == STRING_LEN || nPos > nMaxPos ) |
| nPos = nMaxPos; |
| ASSERT( nPos, "endOfCharBlock not implemented?" ); |
| #ifdef DBG_UTIL |
| if( !nPos ) |
| nPos = nMaxPos; |
| #endif |
| } |
| |
| // Aufraeumen: |
| if( pBigFont != pOldLast ) |
| delete pBigFontAccess; |
| |
| if( bTextLines ) |
| { |
| if( rDo.GetInf().GetDrawSpace() ) |
| { |
| pLastFont = pSpaceFont; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); |
| ( (SwDoDrawCapital&) rDo ).DrawSpace( aStartPos ); |
| } |
| if ( bWordWise ) |
| delete pSpaceFontAccess; |
| } |
| pLastFont = pOldLast; |
| pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); |
| |
| delete pSmallFontAccess; |
| rDo.GetInf().SetText( rOldText ); |
| rDo.GetInf().SetKanaDiff( nKana ); |
| } |
| |
| // JP 22.8.2001 - global optimization off - Bug 91245 / 91223 |
| #ifdef _MSC_VER |
| #pragma optimize("g",on) |
| #endif |
| |
| |