android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / txtnode / fntcap.cxx
blobc4802af5a09996c8f3434b4b1f9b1634363810b4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <editeng/svxfont.hxx>
22 #include <vcl/outdev.hxx>
23 #include <com/sun/star/i18n/CharType.hpp>
24 #include <com/sun/star/i18n/WordType.hpp>
25 #include <com/sun/star/i18n/XBreakIterator.hpp>
27 #include <fntcache.hxx>
28 #include <swfont.hxx>
29 #include <breakit.hxx>
30 #include <txtfrm.hxx>
31 #include <scriptinfo.hxx>
32 #include <fntcap.hxx>
34 using namespace ::com::sun::star::i18n;
36 namespace {
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
44 public:
45 explicit SwCapitalInfo( const OUString& rOrigText ) :
46 rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {};
47 const OUString& rString;
48 TextFrameIndex nIdx;
49 TextFrameIndex nLen;
54 // rFnt: required for CalcCaseMap
55 // rOrigString: The original string
56 // nOfst: Position of the substring in rOrigString
57 // nLen: Length if the substring in rOrigString
58 // nIdx: Refers to a position in the display string and should be mapped
59 // to a position in rOrigString
60 TextFrameIndex sw_CalcCaseMap(const SwFont& rFnt,
61 const OUString& rOrigString,
62 TextFrameIndex const nOfst,
63 TextFrameIndex const nLen,
64 TextFrameIndex const nIdx)
66 int j = 0;
67 const TextFrameIndex nEnd = nOfst + nLen;
68 OSL_ENSURE( sal_Int32(nEnd) <= rOrigString.getLength(), "sw_CalcCaseMap: Wrong parameters" );
70 // special case for title case:
71 const bool bTitle = SvxCaseMap::Capitalize == rFnt.GetCaseMap();
72 for (TextFrameIndex i = nOfst; i < nEnd; ++i)
74 OUString aTmp(rOrigString.copy(sal_Int32(i), 1));
76 if ( !bTitle ||
77 g_pBreakIt->GetBreakIter()->isBeginWord(
78 rOrigString, sal_Int32(i),
79 g_pBreakIt->GetLocale( rFnt.GetLanguage() ),
80 WordType::ANYWORD_IGNOREWHITESPACES ) )
81 aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp );
83 j += aTmp.getLength();
85 if (TextFrameIndex(j) > nIdx)
86 return i;
89 return nOfst + nLen;
92 class SwDoCapitals
94 protected:
95 SwDrawTextInfo &m_rInf;
96 SwCapitalInfo* m_pCapInf; // refers to additional information
97 // required by the ::Do function
98 explicit SwDoCapitals ( SwDrawTextInfo &rInfo ) : m_rInf( rInfo ), m_pCapInf( nullptr ) { }
99 ~SwDoCapitals() {}
100 public:
101 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
102 virtual void Do() = 0;
103 OutputDevice& GetOut() { return m_rInf.GetOut(); }
104 SwDrawTextInfo& GetInf() { return m_rInf; }
105 SwCapitalInfo* GetCapInf() const { return m_pCapInf; }
106 void SetCapInf( SwCapitalInfo& rNew ) { m_pCapInf = &rNew; }
109 namespace {
111 class SwDoGetCapitalSize : public SwDoCapitals
113 protected:
114 Size m_aTextSize;
116 public:
117 explicit SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
118 virtual ~SwDoGetCapitalSize() {}
119 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
120 virtual void Do() override;
121 const Size& GetSize() const { return m_aTextSize; }
126 void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
128 m_aTextSize.setHeight(0);
129 m_aTextSize.setWidth(0);
132 void SwDoGetCapitalSize::Do()
134 m_aTextSize.AdjustWidth(m_rInf.GetSize().Width());
135 if( m_rInf.GetUpper() )
136 m_aTextSize.setHeight(m_rInf.GetSize().Height());
139 Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf )
141 // Start:
142 const tools::Long nOldKern = rInf.GetKern();
143 rInf.SetKern( CheckKerning() );
144 rInf.SetPos( Point() );
145 rInf.SetSpace( 0 );
146 rInf.SetDrawSpace( false );
147 SwDoGetCapitalSize aDo( rInf );
148 DoOnCapitals( aDo );
149 Size aTextSize( aDo.GetSize() );
151 // End:
152 if( !aTextSize.Height() )
154 SV_STAT( nGetTextSize );
155 aTextSize.setHeight( short ( rInf.GetpOut()->GetTextHeight() ) );
157 rInf.SetKern( nOldKern );
158 return aTextSize;
161 namespace {
163 class SwDoGetCapitalBreak : public SwDoCapitals
165 protected:
166 tools::Long m_nTextWidth;
167 TextFrameIndex m_nBreak;
169 public:
170 SwDoGetCapitalBreak(SwDrawTextInfo& rInfo, tools::Long const nWidth)
171 : SwDoCapitals(rInfo)
172 , m_nTextWidth(nWidth)
173 , m_nBreak(-1)
175 virtual ~SwDoGetCapitalBreak() {}
176 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
177 virtual void Do() override;
178 TextFrameIndex getBreak() const { return m_nBreak; }
183 void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
187 void SwDoGetCapitalBreak::Do()
189 if (!m_nTextWidth)
190 return;
192 if (m_rInf.GetSize().Width() < m_nTextWidth)
193 m_nTextWidth -= m_rInf.GetSize().Width();
194 else
196 TextFrameIndex nEnd = m_rInf.GetEnd();
197 m_nBreak = TextFrameIndex(GetOut().GetTextBreak(m_rInf.GetText(), m_nTextWidth,
198 sal_Int32(m_rInf.GetIdx()),
199 sal_Int32(m_rInf.GetLen()), m_rInf.GetKern()));
201 if (m_nBreak > nEnd || m_nBreak < TextFrameIndex(0))
202 m_nBreak = nEnd;
204 // m_nBreak may be relative to the display string. It has to be
205 // calculated relative to the original string:
206 if ( GetCapInf() )
208 if ( GetCapInf()->nLen != m_rInf.GetLen() )
209 m_nBreak = sw_CalcCaseMap( *m_rInf.GetFont(),
210 GetCapInf()->rString,
211 GetCapInf()->nIdx,
212 GetCapInf()->nLen, m_nBreak );
213 else
214 m_nBreak = m_nBreak + GetCapInf()->nIdx;
217 m_nTextWidth = 0;
221 TextFrameIndex SwFont::GetCapitalBreak( SwViewShell const * pSh, const OutputDevice* pOut,
222 const SwScriptInfo* pScript, const OUString& rText, tools::Long const nTextWidth,
223 TextFrameIndex const nIdx, TextFrameIndex const nLen)
225 // Start:
226 Point aPos( 0, 0 );
227 SwDrawTextInfo aInfo(pSh, *const_cast<OutputDevice*>(pOut), pScript, rText, nIdx, nLen,
228 0, false);
229 aInfo.SetPos( aPos );
230 aInfo.SetSpace( 0 );
231 aInfo.SetWrong( nullptr );
232 aInfo.SetGrammarCheck( nullptr );
233 aInfo.SetSmartTags( nullptr );
234 aInfo.SetDrawSpace( false );
235 aInfo.SetKern( CheckKerning() );
236 aInfo.SetKanaComp( pScript ? 0 : 100 );
237 aInfo.SetFont( this );
239 SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
240 DoOnCapitals( aDo );
241 return aDo.getBreak();
244 namespace {
246 class SwDoDrawCapital : public SwDoCapitals
248 protected:
249 SwFntObj* m_pUpperFnt;
250 SwFntObj* m_pLowerFnt;
252 public:
253 explicit SwDoDrawCapital(SwDrawTextInfo& rInfo)
254 : SwDoCapitals(rInfo)
255 , m_pUpperFnt(nullptr)
256 , m_pLowerFnt(nullptr)
258 virtual ~SwDoDrawCapital() {}
259 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
260 virtual void Do() override;
261 void DrawSpace( Point &rPos );
266 void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
268 m_pUpperFnt = pUpperFont;
269 m_pLowerFnt = pLowerFont;
272 void SwDoDrawCapital::Do()
274 SV_STAT( nDrawText );
275 const sal_uInt16 nOrgWidth = m_rInf.GetWidth();
276 m_rInf.SetWidth( sal_uInt16(m_rInf.GetSize().Width()) );
277 if ( m_rInf.GetUpper() )
278 m_pUpperFnt->DrawText(m_rInf);
279 else
281 bool bOldBullet = m_rInf.GetBullet();
282 m_rInf.SetBullet( false );
283 m_pLowerFnt->DrawText(m_rInf);
284 m_rInf.SetBullet( bOldBullet );
287 OSL_ENSURE(m_pUpperFnt, "No upper font, dying soon!");
288 m_rInf.Shift(m_pUpperFnt->GetFont().GetOrientation());
289 m_rInf.SetWidth( nOrgWidth );
292 void SwDoDrawCapital::DrawSpace( Point &rPos )
294 tools::Long nDiff = m_rInf.GetPos().X() - rPos.X();
296 Point aPos( rPos );
297 const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() &&
298 ! m_rInf.IsIgnoreFrameRTL();
300 if ( bSwitchL2R )
301 m_rInf.GetFrame()->SwitchLTRtoRTL( aPos );
303 const vcl::text::ComplexTextLayoutFlags nMode = m_rInf.GetpOut()->GetLayoutMode();
304 const bool bBidiPor = ( bSwitchL2R !=
305 ( vcl::text::ComplexTextLayoutFlags::Default != ( vcl::text::ComplexTextLayoutFlags::BiDiRtl & nMode ) ) );
307 if ( bBidiPor )
308 nDiff = -nDiff;
310 if ( m_rInf.GetFrame()->IsVertical() )
311 m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
313 if ( nDiff )
315 m_rInf.ApplyAutoColor();
316 GetOut().DrawStretchText( aPos, nDiff,
317 " ", 0, 2 );
319 rPos.setX( m_rInf.GetPos().X() + m_rInf.GetWidth() );
322 void SwSubFont::DrawCapital( SwDrawTextInfo &rInf )
324 // Precondition: rInf.GetPos() has already been calculated
326 rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
327 GetOverline() != LINESTYLE_NONE ||
328 GetStrikeout() != STRIKEOUT_NONE );
329 SwDoDrawCapital aDo( rInf );
330 DoOnCapitals( aDo );
333 namespace {
335 class SwDoCapitalCursorOfst : public SwDoCapitals
337 protected:
338 SwFntObj* m_pUpperFnt;
339 SwFntObj* m_pLowerFnt;
340 TextFrameIndex m_nCursor;
341 sal_uInt16 m_nOfst;
343 public:
344 SwDoCapitalCursorOfst(SwDrawTextInfo& rInfo, const sal_uInt16 nOfs)
345 : SwDoCapitals(rInfo)
346 , m_pUpperFnt(nullptr)
347 , m_pLowerFnt(nullptr)
348 , m_nCursor(0)
349 , m_nOfst(nOfs)
351 virtual ~SwDoCapitalCursorOfst() {}
352 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
353 virtual void Do() override;
355 TextFrameIndex GetCursor() const { return m_nCursor; }
360 void SwDoCapitalCursorOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
362 m_pUpperFnt = pUpperFont;
363 m_pLowerFnt = pLowerFont;
366 void SwDoCapitalCursorOfst::Do()
368 if (!m_nOfst)
369 return;
371 if (static_cast<tools::Long>(m_nOfst) > m_rInf.GetSize().Width())
373 m_nOfst -= m_rInf.GetSize().Width();
374 m_nCursor = m_nCursor + m_rInf.GetLen();
376 else
378 SwDrawTextInfo aDrawInf( m_rInf.GetShell(), *m_rInf.GetpOut(),
379 m_rInf.GetScriptInfo(),
380 m_rInf.GetText(),
381 m_rInf.GetIdx(),
382 m_rInf.GetLen(), 0, false );
383 aDrawInf.SetOffset(m_nOfst);
384 aDrawInf.SetKern( m_rInf.GetKern() );
385 aDrawInf.SetKanaComp( m_rInf.GetKanaComp() );
386 aDrawInf.SetFrame( m_rInf.GetFrame() );
387 aDrawInf.SetFont( m_rInf.GetFont() );
389 if ( m_rInf.GetUpper() )
391 aDrawInf.SetSpace( 0 );
392 m_nCursor = m_nCursor + m_pUpperFnt->GetModelPositionForViewPoint(aDrawInf);
394 else
396 aDrawInf.SetSpace( m_rInf.GetSpace() );
397 m_nCursor = m_nCursor + m_pLowerFnt->GetModelPositionForViewPoint(aDrawInf);
399 m_nOfst = 0;
403 TextFrameIndex SwSubFont::GetCapitalCursorOfst( SwDrawTextInfo& rInf )
405 const tools::Long nOldKern = rInf.GetKern();
406 rInf.SetKern( CheckKerning() );
407 SwDoCapitalCursorOfst aDo( rInf, rInf.GetOffset() );
408 rInf.SetPos( Point() );
409 rInf.SetDrawSpace( false );
410 DoOnCapitals( aDo );
411 rInf.SetKern( nOldKern );
412 return aDo.GetCursor();
415 namespace {
417 class SwDoDrawStretchCapital : public SwDoDrawCapital
419 const TextFrameIndex m_nStrLen;
420 const sal_uInt16 m_nCapWidth;
421 const sal_uInt16 m_nOrgWidth;
423 public:
424 virtual void Do() override;
426 SwDoDrawStretchCapital(SwDrawTextInfo& rInfo, const sal_uInt16 nCapitalWidth)
427 : SwDoDrawCapital(rInfo)
428 , m_nStrLen(rInfo.GetLen())
429 , m_nCapWidth(nCapitalWidth)
430 , m_nOrgWidth(rInfo.GetWidth())
436 void SwDoDrawStretchCapital::Do()
438 SV_STAT( nDrawStretchText );
439 tools::Long nPartWidth = m_rInf.GetSize().Width();
441 if( m_rInf.GetLen() )
443 // small caps and kerning
444 tools::Long nDiff = tools::Long(m_nOrgWidth) - tools::Long(m_nCapWidth);
445 if( nDiff )
447 nDiff *= sal_Int32(m_rInf.GetLen());
448 nDiff /= sal_Int32(m_nStrLen);
449 nDiff += nPartWidth;
450 if( 0 < nDiff )
451 nPartWidth = nDiff;
454 m_rInf.ApplyAutoColor();
456 Point aPos( m_rInf.GetPos() );
457 const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() &&
458 ! m_rInf.IsIgnoreFrameRTL();
460 if ( bSwitchL2R )
461 m_rInf.GetFrame()->SwitchLTRtoRTL( aPos );
463 if ( m_rInf.GetFrame()->IsVertical() )
464 m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
466 // Optimise:
467 if (TextFrameIndex(1) >= m_rInf.GetLen())
468 GetOut().DrawText(aPos, m_rInf.GetText(), sal_Int32(m_rInf.GetIdx()),
469 sal_Int32(m_rInf.GetLen()));
470 else
471 GetOut().DrawStretchText(aPos, nPartWidth, m_rInf.GetText(),
472 sal_Int32(m_rInf.GetIdx()), sal_Int32(m_rInf.GetLen()));
474 const_cast<Point&>(m_rInf.GetPos()).AdjustX(nPartWidth );
477 void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf )
479 // Precondition: rInf.GetPos() has already been calculated
481 if (rInf.GetLen() == TextFrameIndex(COMPLETE_STRING))
482 rInf.SetLen(TextFrameIndex(rInf.GetText().getLength()));
484 const Point aOldPos = rInf.GetPos();
485 const sal_uInt16 nCapWidth = o3tl::narrowing<sal_uInt16>( GetCapitalSize( rInf ).Width() );
486 rInf.SetPos(aOldPos);
488 rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
489 GetOverline() != LINESTYLE_NONE ||
490 GetStrikeout() != STRIKEOUT_NONE );
491 SwDoDrawStretchCapital aDo( rInf, nCapWidth );
492 DoOnCapitals( aDo );
495 void SwSubFont::DoOnCapitals( SwDoCapitals &rDo )
497 OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
499 tools::Long nKana = 0;
500 const OUString aText( CalcCaseMap( rDo.GetInf().GetText() ) );
501 TextFrameIndex nMaxPos = std::min(
502 TextFrameIndex(rDo.GetInf().GetText().getLength()) - rDo.GetInf().GetIdx(),
503 rDo.GetInf().GetLen() );
504 rDo.GetInf().SetLen( nMaxPos );
506 const OUString oldText = rDo.GetInf().GetText();
507 rDo.GetInf().SetText( aText );
508 TextFrameIndex nPos = rDo.GetInf().GetIdx();
509 TextFrameIndex nOldPos = nPos;
510 nMaxPos = nMaxPos + nPos;
512 // Look if the length of the original text and the ToUpper-converted
513 // text is different. If yes, do special handling.
514 SwCapitalInfo aCapInf(oldText);
515 bool bCaseMapLengthDiffers(aText.getLength() != oldText.getLength());
516 if ( bCaseMapLengthDiffers )
517 rDo.SetCapInf( aCapInf );
519 SwFntObj *pOldLast = pLastFont;
520 std::optional<SwFntAccess> oBigFontAccess;
521 SwFntObj *pBigFont;
522 std::optional<SwFntAccess> oSpaceFontAccess;
523 SwFntObj *pSpaceFont = nullptr;
525 const void* nFontCacheId2 = nullptr;
526 sal_uInt16 nIndex2 = 0;
527 SwSubFont aFont( *this );
528 Point aStartPos( rDo.GetInf().GetPos() );
530 const bool bTextLines = aFont.GetUnderline() != LINESTYLE_NONE
531 || aFont.GetOverline() != LINESTYLE_NONE
532 || aFont.GetStrikeout() != STRIKEOUT_NONE;
533 const bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
534 rDo.GetInf().GetDrawSpace();
535 const tools::Long nTmpKern = rDo.GetInf().GetKern();
537 if ( bTextLines )
539 if ( bWordWise )
541 aFont.SetWordLineMode( false );
542 oSpaceFontAccess.emplace( nFontCacheId2, nIndex2, &aFont,
543 rDo.GetInf().GetShell() );
544 pSpaceFont = oSpaceFontAccess->Get();
546 else
547 pSpaceFont = pLastFont;
549 // Construct a font for the capitals:
550 aFont.SetUnderline( LINESTYLE_NONE );
551 aFont.SetOverline( LINESTYLE_NONE );
552 aFont.SetStrikeout( STRIKEOUT_NONE );
553 nFontCacheId2 = nullptr;
554 nIndex2 = 0;
555 oBigFontAccess.emplace( nFontCacheId2, nIndex2, &aFont,
556 rDo.GetInf().GetShell() );
557 pBigFont = oBigFontAccess->Get();
559 else
560 pBigFont = pLastFont;
562 // Older LO versions had 66 as the small caps percentage size, later changed to 80,
563 // therefore a backwards compatibility option is kept (otherwise layout is changed).
564 // NOTE: There are more uses of SMALL_CAPS_PERCENTAGE in editeng, but it seems they
565 // do not matter for Writer (and if they did it'd be pretty ugly to propagate
566 // the option there).
567 int smallCapsPercentage = m_bSmallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE;
568 aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 );
569 nFontCacheId2 = nullptr;
570 nIndex2 = 0;
571 std::optional<SwFntAccess> oSmallFontAccess( std::in_place, nFontCacheId2, nIndex2, &aFont,
572 rDo.GetInf().GetShell() );
573 SwFntObj *pSmallFont = oSmallFontAccess->Get();
575 rDo.Init( pBigFont, pSmallFont );
576 OutputDevice* pOutSize = pSmallFont->GetPrt();
577 if( !pOutSize )
578 pOutSize = &rDo.GetOut();
579 OutputDevice* pOldOut = &rDo.GetOut();
581 const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
582 ? LANGUAGE_SYSTEM : GetLanguage();
584 if( nPos < nMaxPos )
586 nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock(
587 oldText, sal_Int32(nPos),
588 g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
589 if (nPos < TextFrameIndex(0))
590 nPos = nOldPos;
591 else if( nPos > nMaxPos )
592 nPos = nMaxPos;
595 while( nOldPos < nMaxPos )
598 // The lower ones...
599 if( nOldPos != nPos )
601 SV_STAT( nGetTextSize );
602 pLastFont = pSmallFont;
603 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
605 // #107816#, #i14820#
606 if( bCaseMapLengthDiffers )
608 // Build an own 'changed' string for the given part of the
609 // source string and use it. That new string may differ in length
610 // from the source string.
611 const OUString aNewText = CalcCaseMap(
612 oldText.copy(sal_Int32(nOldPos), sal_Int32(nPos-nOldPos)));
613 aCapInf.nIdx = nOldPos;
614 aCapInf.nLen = nPos - nOldPos;
615 rDo.GetInf().SetTextIdxLen(aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
617 else
619 rDo.GetInf().SetIdxLen(nOldPos, nPos - nOldPos);
622 rDo.GetInf().SetUpper( false );
623 rDo.GetInf().SetOut( *pOutSize );
624 Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
625 nKana += rDo.GetInf().GetKanaDiff();
626 rDo.GetInf().SetOut( *pOldOut );
627 if( nTmpKern && nPos < nMaxPos )
628 aPartSize.AdjustWidth(nTmpKern );
629 rDo.GetInf().SetSize( aPartSize );
630 rDo.Do();
631 nOldPos = nPos;
633 nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->nextCharBlock(
634 oldText, sal_Int32(nPos),
635 g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
636 if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
637 nPos = nMaxPos;
638 OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
639 #if OSL_DEBUG_LEVEL > 1
640 if( !nPos )
641 nPos = nMaxPos;
642 #endif
643 // The upper ones...
644 if( nOldPos != nPos )
646 const tools::Long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
650 rDo.GetInf().SetUpper( true );
651 pLastFont = pBigFont;
652 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
653 TextFrameIndex nTmp;
654 if( bWordWise )
656 nTmp = nOldPos;
657 while (nTmp < nPos && CH_BLANK == oldText[sal_Int32(nTmp)])
658 ++nTmp;
659 if( nOldPos < nTmp )
661 pLastFont = pSpaceFont;
662 pLastFont->SetDevFont( rDo.GetInf().GetShell(),
663 rDo.GetOut() );
664 static_cast<SwDoDrawCapital&>(rDo).DrawSpace( aStartPos );
665 pLastFont = pBigFont;
666 pLastFont->SetDevFont( rDo.GetInf().GetShell(),
667 rDo.GetOut() );
669 // #107816#, #i14820#
670 if( bCaseMapLengthDiffers )
672 // Build an own 'changed' string for the given part of the
673 // source string and use it. That new string may differ in length
674 // from the source string.
675 const OUString aNewText = CalcCaseMap(
676 oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
677 aCapInf.nIdx = nOldPos;
678 aCapInf.nLen = nTmp - nOldPos;
679 rDo.GetInf().SetIdx(TextFrameIndex(0));
680 rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
681 rDo.GetInf().SetText( aNewText );
683 else
685 rDo.GetInf().SetIdx( nOldPos );
686 rDo.GetInf().SetLen( nTmp - nOldPos );
689 rDo.GetInf().SetOut( *pOutSize );
690 Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
691 nKana += rDo.GetInf().GetKanaDiff();
692 rDo.GetInf().SetOut( *pOldOut );
693 if( nSpaceAdd )
694 aPartSize.AdjustWidth(nSpaceAdd * sal_Int32(nTmp - nOldPos));
695 if( nTmpKern && nPos < nMaxPos )
696 aPartSize.AdjustWidth(nTmpKern );
697 rDo.GetInf().SetSize( aPartSize );
698 rDo.Do();
699 aStartPos = rDo.GetInf().GetPos();
700 nOldPos = nTmp;
703 while (nTmp < nPos && CH_BLANK != oldText[sal_Int32(nTmp)])
704 ++nTmp;
706 else
707 nTmp = nPos;
708 if( nTmp > nOldPos )
710 // #107816#, #i14820#
711 if( bCaseMapLengthDiffers )
713 // Build an own 'changed' string for the given part of the
714 // source string and use it. That new string may differ in length
715 // from the source string.
716 const OUString aNewText = CalcCaseMap(
717 oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
718 aCapInf.nIdx = nOldPos;
719 aCapInf.nLen = nTmp - nOldPos;
720 rDo.GetInf().SetTextIdxLen( aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
722 else
724 rDo.GetInf().SetIdxLen( nOldPos, nTmp - nOldPos );
727 rDo.GetInf().SetOut( *pOutSize );
728 Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
729 nKana += rDo.GetInf().GetKanaDiff();
730 rDo.GetInf().SetOut( *pOldOut );
731 if( !bWordWise && rDo.GetInf().GetSpace() )
733 for (TextFrameIndex nI = nOldPos; nI < nPos; ++nI)
735 if (CH_BLANK == oldText[sal_Int32(nI)])
736 aPartSize.AdjustWidth(nSpaceAdd );
739 if( nTmpKern && nPos < nMaxPos )
740 aPartSize.AdjustWidth(nTmpKern );
741 rDo.GetInf().SetSize( aPartSize );
742 rDo.Do();
743 nOldPos = nTmp;
745 } while( nOldPos != nPos );
747 nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock(
748 oldText, sal_Int32(nPos),
749 g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
750 if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
751 nPos = nMaxPos;
752 OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
753 #if OSL_DEBUG_LEVEL > 1
754 if( !nPos )
755 nPos = nMaxPos;
756 #endif
759 // clean up:
760 if( pBigFont != pOldLast )
761 oBigFontAccess.reset();
763 if( bTextLines )
765 if( rDo.GetInf().GetDrawSpace() )
767 pLastFont = pSpaceFont;
768 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
769 static_cast<SwDoDrawCapital&>( rDo ).DrawSpace( aStartPos );
771 if ( bWordWise )
772 oSpaceFontAccess.reset();
774 pLastFont = pOldLast;
775 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
777 oSmallFontAccess.reset();
778 rDo.GetInf().SetText(oldText);
779 rDo.GetInf().SetKanaDiff( nKana );
782 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */