/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star::i18n; namespace { // 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 OUString& rOrigText ) : rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {}; const OUString& rString; TextFrameIndex nIdx; TextFrameIndex nLen; }; } // rFnt: required for CalcCaseMap // rOrigString: The original string // nOfst: Position of the substring in rOrigString // nLen: Length if the substring in rOrigString // nIdx: Refers to a position in the display string and should be mapped // to a position in rOrigString TextFrameIndex sw_CalcCaseMap(const SwFont& rFnt, const OUString& rOrigString, TextFrameIndex const nOfst, TextFrameIndex const nLen, TextFrameIndex const nIdx) { int j = 0; const TextFrameIndex nEnd = nOfst + nLen; OSL_ENSURE( sal_Int32(nEnd) <= rOrigString.getLength(), "sw_CalcCaseMap: Wrong parameters" ); // special case for title case: const bool bTitle = SvxCaseMap::Capitalize == rFnt.GetCaseMap(); for (TextFrameIndex i = nOfst; i < nEnd; ++i) { OUString aTmp(rOrigString.copy(sal_Int32(i), 1)); if ( !bTitle || g_pBreakIt->GetBreakIter()->isBeginWord( rOrigString, sal_Int32(i), g_pBreakIt->GetLocale( rFnt.GetLanguage() ), WordType::ANYWORD_IGNOREWHITESPACES ) ) aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp ); j += aTmp.getLength(); if (TextFrameIndex(j) > nIdx) return i; } return nOfst + nLen; } class SwDoCapitals { protected: SwDrawTextInfo &m_rInf; SwCapitalInfo* m_pCapInf; // refers to additional information // required by the ::Do function explicit SwDoCapitals ( SwDrawTextInfo &rInfo ) : m_rInf( rInfo ), m_pCapInf( nullptr ) { } ~SwDoCapitals() {} public: virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0; virtual void Do() = 0; OutputDevice& GetOut() { return m_rInf.GetOut(); } SwDrawTextInfo& GetInf() { return m_rInf; } SwCapitalInfo* GetCapInf() const { return m_pCapInf; } void SetCapInf( SwCapitalInfo& rNew ) { m_pCapInf = &rNew; } }; namespace { class SwDoGetCapitalSize : public SwDoCapitals { protected: Size m_aTextSize; public: explicit SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { } virtual ~SwDoGetCapitalSize() {} virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override; virtual void Do() override; const Size& GetSize() const { return m_aTextSize; } }; } void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * ) { m_aTextSize.setHeight(0); m_aTextSize.setWidth(0); } void SwDoGetCapitalSize::Do() { m_aTextSize.AdjustWidth(m_rInf.GetSize().Width()); if( m_rInf.GetUpper() ) m_aTextSize.setHeight(m_rInf.GetSize().Height()); } Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf ) { // Start: const tools::Long nOldKern = rInf.GetKern(); rInf.SetKern( CheckKerning() ); rInf.SetPos( Point() ); rInf.SetSpace( 0 ); rInf.SetDrawSpace( false ); SwDoGetCapitalSize aDo( rInf ); DoOnCapitals( aDo ); Size aTextSize( aDo.GetSize() ); // End: if( !aTextSize.Height() ) { SV_STAT( nGetTextSize ); aTextSize.setHeight( short ( rInf.GetpOut()->GetTextHeight() ) ); } rInf.SetKern( nOldKern ); return aTextSize; } namespace { class SwDoGetCapitalBreak : public SwDoCapitals { protected: tools::Long m_nTextWidth; TextFrameIndex m_nBreak; public: SwDoGetCapitalBreak(SwDrawTextInfo& rInfo, tools::Long const nWidth) : SwDoCapitals(rInfo) , m_nTextWidth(nWidth) , m_nBreak(-1) { } virtual ~SwDoGetCapitalBreak() {} virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override; virtual void Do() override; TextFrameIndex getBreak() const { return m_nBreak; } }; } void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * ) { } void SwDoGetCapitalBreak::Do() { if (!m_nTextWidth) return; if (m_rInf.GetSize().Width() < m_nTextWidth) m_nTextWidth -= m_rInf.GetSize().Width(); else { TextFrameIndex nEnd = m_rInf.GetEnd(); m_nBreak = TextFrameIndex(GetOut().GetTextBreak(m_rInf.GetText(), m_nTextWidth, sal_Int32(m_rInf.GetIdx()), sal_Int32(m_rInf.GetLen()), m_rInf.GetKern())); if (m_nBreak > nEnd || m_nBreak < TextFrameIndex(0)) m_nBreak = nEnd; // m_nBreak may be relative to the display string. It has to be // calculated relative to the original string: if ( GetCapInf() ) { if ( GetCapInf()->nLen != m_rInf.GetLen() ) m_nBreak = sw_CalcCaseMap( *m_rInf.GetFont(), GetCapInf()->rString, GetCapInf()->nIdx, GetCapInf()->nLen, m_nBreak ); else m_nBreak = m_nBreak + GetCapInf()->nIdx; } m_nTextWidth = 0; } } TextFrameIndex SwFont::GetCapitalBreak( SwViewShell const * pSh, const OutputDevice* pOut, const SwScriptInfo* pScript, const OUString& rText, tools::Long const nTextWidth, TextFrameIndex const nIdx, TextFrameIndex const nLen) { // Start: Point aPos( 0, 0 ); SwDrawTextInfo aInfo(pSh, *const_cast(pOut), pScript, rText, nIdx, nLen, 0, false); aInfo.SetPos( aPos ); aInfo.SetSpace( 0 ); aInfo.SetWrong( nullptr ); aInfo.SetGrammarCheck( nullptr ); aInfo.SetSmartTags( nullptr ); aInfo.SetDrawSpace( false ); aInfo.SetKern( CheckKerning() ); aInfo.SetKanaComp( pScript ? 0 : 100 ); aInfo.SetFont( this ); SwDoGetCapitalBreak aDo(aInfo, nTextWidth); DoOnCapitals( aDo ); return aDo.getBreak(); } namespace { class SwDoDrawCapital : public SwDoCapitals { protected: SwFntObj* m_pUpperFnt; SwFntObj* m_pLowerFnt; public: explicit SwDoDrawCapital(SwDrawTextInfo& rInfo) : SwDoCapitals(rInfo) , m_pUpperFnt(nullptr) , m_pLowerFnt(nullptr) { } virtual ~SwDoDrawCapital() {} virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override; virtual void Do() override; void DrawSpace( Point &rPos ); }; } void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) { m_pUpperFnt = pUpperFont; m_pLowerFnt = pLowerFont; } void SwDoDrawCapital::Do() { SV_STAT( nDrawText ); const sal_uInt16 nOrgWidth = m_rInf.GetWidth(); m_rInf.SetWidth( sal_uInt16(m_rInf.GetSize().Width()) ); if ( m_rInf.GetUpper() ) m_pUpperFnt->DrawText(m_rInf); else { bool bOldBullet = m_rInf.GetBullet(); m_rInf.SetBullet( false ); m_pLowerFnt->DrawText(m_rInf); m_rInf.SetBullet( bOldBullet ); } OSL_ENSURE(m_pUpperFnt, "No upper font, dying soon!"); m_rInf.Shift(m_pUpperFnt->GetFont().GetOrientation()); m_rInf.SetWidth( nOrgWidth ); } void SwDoDrawCapital::DrawSpace( Point &rPos ) { tools::Long nDiff = m_rInf.GetPos().X() - rPos.X(); Point aPos( rPos ); const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() && ! m_rInf.IsIgnoreFrameRTL(); if ( bSwitchL2R ) m_rInf.GetFrame()->SwitchLTRtoRTL( aPos ); const ComplexTextLayoutFlags nMode = m_rInf.GetpOut()->GetLayoutMode(); const bool bBidiPor = ( bSwitchL2R != ( ComplexTextLayoutFlags::Default != ( ComplexTextLayoutFlags::BiDiRtl & nMode ) ) ); if ( bBidiPor ) nDiff = -nDiff; if ( m_rInf.GetFrame()->IsVertical() ) m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos ); if ( nDiff ) { m_rInf.ApplyAutoColor(); GetOut().DrawStretchText( aPos, nDiff, " ", 0, 2 ); } rPos.setX( m_rInf.GetPos().X() + m_rInf.GetWidth() ); } void SwSubFont::DrawCapital( SwDrawTextInfo &rInf ) { // Precondition: rInf.GetPos() has already been calculated rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE || GetOverline() != LINESTYLE_NONE || GetStrikeout() != STRIKEOUT_NONE ); SwDoDrawCapital aDo( rInf ); DoOnCapitals( aDo ); } namespace { class SwDoCapitalCursorOfst : public SwDoCapitals { protected: SwFntObj* m_pUpperFnt; SwFntObj* m_pLowerFnt; TextFrameIndex m_nCursor; sal_uInt16 m_nOfst; public: SwDoCapitalCursorOfst(SwDrawTextInfo& rInfo, const sal_uInt16 nOfs) : SwDoCapitals(rInfo) , m_pUpperFnt(nullptr) , m_pLowerFnt(nullptr) , m_nCursor(0) , m_nOfst(nOfs) { } virtual ~SwDoCapitalCursorOfst() {} virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override; virtual void Do() override; TextFrameIndex GetCursor() const { return m_nCursor; } }; } void SwDoCapitalCursorOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) { m_pUpperFnt = pUpperFont; m_pLowerFnt = pLowerFont; } void SwDoCapitalCursorOfst::Do() { if (!m_nOfst) return; if (static_cast(m_nOfst) > m_rInf.GetSize().Width()) { m_nOfst -= m_rInf.GetSize().Width(); m_nCursor = m_nCursor + m_rInf.GetLen(); } else { SwDrawTextInfo aDrawInf( m_rInf.GetShell(), *m_rInf.GetpOut(), m_rInf.GetScriptInfo(), m_rInf.GetText(), m_rInf.GetIdx(), m_rInf.GetLen(), 0, false ); aDrawInf.SetOffset(m_nOfst); aDrawInf.SetKern( m_rInf.GetKern() ); aDrawInf.SetKanaComp( m_rInf.GetKanaComp() ); aDrawInf.SetFrame( m_rInf.GetFrame() ); aDrawInf.SetFont( m_rInf.GetFont() ); if ( m_rInf.GetUpper() ) { aDrawInf.SetSpace( 0 ); m_nCursor = m_nCursor + m_pUpperFnt->GetModelPositionForViewPoint(aDrawInf); } else { aDrawInf.SetSpace( m_rInf.GetSpace() ); m_nCursor = m_nCursor + m_pLowerFnt->GetModelPositionForViewPoint(aDrawInf); } m_nOfst = 0; } } TextFrameIndex SwSubFont::GetCapitalCursorOfst( SwDrawTextInfo& rInf ) { const tools::Long nOldKern = rInf.GetKern(); rInf.SetKern( CheckKerning() ); SwDoCapitalCursorOfst aDo( rInf, rInf.GetOffset() ); rInf.SetPos( Point() ); rInf.SetDrawSpace( false ); DoOnCapitals( aDo ); rInf.SetKern( nOldKern ); return aDo.GetCursor(); } namespace { class SwDoDrawStretchCapital : public SwDoDrawCapital { const TextFrameIndex m_nStrLen; const sal_uInt16 m_nCapWidth; const sal_uInt16 m_nOrgWidth; public: virtual void Do() override; SwDoDrawStretchCapital(SwDrawTextInfo& rInfo, const sal_uInt16 nCapitalWidth) : SwDoDrawCapital(rInfo) , m_nStrLen(rInfo.GetLen()) , m_nCapWidth(nCapitalWidth) , m_nOrgWidth(rInfo.GetWidth()) { } }; } void SwDoDrawStretchCapital::Do() { SV_STAT( nDrawStretchText ); tools::Long nPartWidth = m_rInf.GetSize().Width(); if( m_rInf.GetLen() ) { // small caps and kerning tools::Long nDiff = tools::Long(m_nOrgWidth) - tools::Long(m_nCapWidth); if( nDiff ) { nDiff *= sal_Int32(m_rInf.GetLen()); nDiff /= sal_Int32(m_nStrLen); nDiff += nPartWidth; if( 0 < nDiff ) nPartWidth = nDiff; } m_rInf.ApplyAutoColor(); Point aPos( m_rInf.GetPos() ); const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() && ! m_rInf.IsIgnoreFrameRTL(); if ( bSwitchL2R ) m_rInf.GetFrame()->SwitchLTRtoRTL( aPos ); if ( m_rInf.GetFrame()->IsVertical() ) m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos ); // Optimise: if (TextFrameIndex(1) >= m_rInf.GetLen()) GetOut().DrawText(aPos, m_rInf.GetText(), sal_Int32(m_rInf.GetIdx()), sal_Int32(m_rInf.GetLen())); else GetOut().DrawStretchText(aPos, nPartWidth, m_rInf.GetText(), sal_Int32(m_rInf.GetIdx()), sal_Int32(m_rInf.GetLen())); } const_cast(m_rInf.GetPos()).AdjustX(nPartWidth ); } void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf ) { // Precondition: rInf.GetPos() has already been calculated if (rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)) rInf.SetLen(TextFrameIndex(rInf.GetText().getLength())); const Point aOldPos = rInf.GetPos(); const sal_uInt16 nCapWidth = o3tl::narrowing( GetCapitalSize( rInf ).Width() ); rInf.SetPos(aOldPos); rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE || GetOverline() != LINESTYLE_NONE || GetStrikeout() != STRIKEOUT_NONE ); SwDoDrawStretchCapital aDo( rInf, nCapWidth ); DoOnCapitals( aDo ); } void SwSubFont::DoOnCapitals( SwDoCapitals &rDo ) { OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" ); tools::Long nKana = 0; const OUString aText( CalcCaseMap( rDo.GetInf().GetText() ) ); TextFrameIndex nMaxPos = std::min( TextFrameIndex(rDo.GetInf().GetText().getLength()) - rDo.GetInf().GetIdx(), rDo.GetInf().GetLen() ); rDo.GetInf().SetLen( nMaxPos ); const OUString oldText = rDo.GetInf().GetText(); rDo.GetInf().SetText( aText ); TextFrameIndex nPos = rDo.GetInf().GetIdx(); TextFrameIndex nOldPos = nPos; nMaxPos = nMaxPos + nPos; // Look if the length of the original text and the ToUpper-converted // text is different. If yes, do special handling. SwCapitalInfo aCapInf(oldText); bool bCaseMapLengthDiffers(aText.getLength() != oldText.getLength()); if ( bCaseMapLengthDiffers ) rDo.SetCapInf( aCapInf ); SwFntObj *pOldLast = pLastFont; std::unique_ptr pBigFontAccess; SwFntObj *pBigFont; std::unique_ptr pSpaceFontAccess; SwFntObj *pSpaceFont = nullptr; const void* nFontCacheId2 = nullptr; sal_uInt16 nIndex2 = 0; SwSubFont aFont( *this ); Point aStartPos( rDo.GetInf().GetPos() ); const bool bTextLines = aFont.GetUnderline() != LINESTYLE_NONE || aFont.GetOverline() != LINESTYLE_NONE || aFont.GetStrikeout() != STRIKEOUT_NONE; const bool bWordWise = bTextLines && aFont.IsWordLineMode() && rDo.GetInf().GetDrawSpace(); const tools::Long nTmpKern = rDo.GetInf().GetKern(); if ( bTextLines ) { if ( bWordWise ) { aFont.SetWordLineMode( false ); pSpaceFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont, rDo.GetInf().GetShell() )); pSpaceFont = pSpaceFontAccess->Get(); } else pSpaceFont = pLastFont; // Construct a font for the capitals: aFont.SetUnderline( LINESTYLE_NONE ); aFont.SetOverline( LINESTYLE_NONE ); aFont.SetStrikeout( STRIKEOUT_NONE ); nFontCacheId2 = nullptr; nIndex2 = 0; pBigFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont, rDo.GetInf().GetShell() )); pBigFont = pBigFontAccess->Get(); } else pBigFont = pLastFont; // Older LO versions had 66 as the small caps percentage size, later changed to 80, // therefore a backwards compatibility option is kept (otherwise layout is changed). // NOTE: There are more uses of SMALL_CAPS_PERCENTAGE in editeng, but it seems they // do not matter for Writer (and if they did it'd be pretty ugly to propagate // the option there). int smallCapsPercentage = m_bSmallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE; aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 ); nFontCacheId2 = nullptr; nIndex2 = 0; std::unique_ptr pSmallFontAccess( new SwFntAccess( nFontCacheId2, 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 = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock( oldText, sal_Int32(nPos), g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER)); if (nPos < TextFrameIndex(0)) 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 OUString aNewText = CalcCaseMap( oldText.copy(sal_Int32(nOldPos), sal_Int32(nPos-nOldPos))); aCapInf.nIdx = nOldPos; aCapInf.nLen = nPos - nOldPos; rDo.GetInf().SetIdx(TextFrameIndex(0)); rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength())); rDo.GetInf().SetText( aNewText ); } else { rDo.GetInf().SetIdx( nOldPos ); rDo.GetInf().SetLen( nPos - nOldPos ); } rDo.GetInf().SetUpper( false ); rDo.GetInf().SetOut( *pOutSize ); Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() ); nKana += rDo.GetInf().GetKanaDiff(); rDo.GetInf().SetOut( *pOldOut ); if( nTmpKern && nPos < nMaxPos ) aPartSize.AdjustWidth(nTmpKern ); rDo.GetInf().SetSize( aPartSize ); rDo.Do(); nOldPos = nPos; } nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->nextCharBlock( oldText, sal_Int32(nPos), g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER)); if (nPos < TextFrameIndex(0) || nPos > nMaxPos) nPos = nMaxPos; OSL_ENSURE( nPos, "nextCharBlock not implemented?" ); #if OSL_DEBUG_LEVEL > 1 if( !nPos ) nPos = nMaxPos; #endif // The upper ones... if( nOldPos != nPos ) { const tools::Long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR; do { rDo.GetInf().SetUpper( true ); pLastFont = pBigFont; pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); TextFrameIndex nTmp; if( bWordWise ) { nTmp = nOldPos; while (nTmp < nPos && CH_BLANK == oldText[sal_Int32(nTmp)]) ++nTmp; if( nOldPos < nTmp ) { pLastFont = pSpaceFont; pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); static_cast(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 OUString aNewText = CalcCaseMap( oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos))); aCapInf.nIdx = nOldPos; aCapInf.nLen = nTmp - nOldPos; rDo.GetInf().SetIdx(TextFrameIndex(0)); rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength())); rDo.GetInf().SetText( aNewText ); } else { rDo.GetInf().SetIdx( nOldPos ); rDo.GetInf().SetLen( nTmp - nOldPos ); } rDo.GetInf().SetOut( *pOutSize ); Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); nKana += rDo.GetInf().GetKanaDiff(); rDo.GetInf().SetOut( *pOldOut ); if( nSpaceAdd ) aPartSize.AdjustWidth(nSpaceAdd * sal_Int32(nTmp - nOldPos)); if( nTmpKern && nPos < nMaxPos ) aPartSize.AdjustWidth(nTmpKern ); rDo.GetInf().SetSize( aPartSize ); rDo.Do(); aStartPos = rDo.GetInf().GetPos(); nOldPos = nTmp; } while (nTmp < nPos && CH_BLANK != oldText[sal_Int32(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 OUString aNewText = CalcCaseMap( oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos))); aCapInf.nIdx = nOldPos; aCapInf.nLen = nTmp - nOldPos; rDo.GetInf().SetIdx(TextFrameIndex(0)); rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength())); rDo.GetInf().SetText( aNewText ); } else { rDo.GetInf().SetIdx( nOldPos ); rDo.GetInf().SetLen( nTmp - nOldPos ); } rDo.GetInf().SetOut( *pOutSize ); Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() ); nKana += rDo.GetInf().GetKanaDiff(); rDo.GetInf().SetOut( *pOldOut ); if( !bWordWise && rDo.GetInf().GetSpace() ) { for (TextFrameIndex nI = nOldPos; nI < nPos; ++nI) { if (CH_BLANK == oldText[sal_Int32(nI)]) aPartSize.AdjustWidth(nSpaceAdd ); } } if( nTmpKern && nPos < nMaxPos ) aPartSize.AdjustWidth(nTmpKern ); rDo.GetInf().SetSize( aPartSize ); rDo.Do(); nOldPos = nTmp; } } while( nOldPos != nPos ); } nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock( oldText, sal_Int32(nPos), g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER)); if (nPos < TextFrameIndex(0) || nPos > nMaxPos) nPos = nMaxPos; OSL_ENSURE( nPos, "endOfCharBlock not implemented?" ); #if OSL_DEBUG_LEVEL > 1 if( !nPos ) nPos = nMaxPos; #endif } // clean up: if( pBigFont != pOldLast ) pBigFontAccess.reset(); if( bTextLines ) { if( rDo.GetInf().GetDrawSpace() ) { pLastFont = pSpaceFont; pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); static_cast( rDo ).DrawSpace( aStartPos ); } if ( bWordWise ) pSpaceFontAccess.reset(); } pLastFont = pOldLast; pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() ); pSmallFontAccess.reset(); rDo.GetInf().SetText(oldText); rDo.GetInf().SetKanaDiff( nKana ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */