LibreOffice Module sw (master) 1
fntcap.cxx
Go to the documentation of this file.
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 <editeng/svxfont.hxx>
21
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>
26
27#include <fntcache.hxx>
28#include <swfont.hxx>
29#include <breakit.hxx>
30#include <txtfrm.hxx>
31#include <scriptinfo.hxx>
32#include <fntcap.hxx>
33
34using namespace ::com::sun::star::i18n;
35
36namespace {
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.
42class SwCapitalInfo
43{
44public:
45 explicit SwCapitalInfo( const OUString& rOrigText ) :
46 rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {};
47 const OUString& rString;
48 TextFrameIndex nIdx;
49 TextFrameIndex nLen;
50};
51
52}
53
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
61 const OUString& rOrigString,
62 TextFrameIndex const nOfst,
63 TextFrameIndex const nLen,
64 TextFrameIndex const nIdx)
65{
66 int j = 0;
67 const TextFrameIndex nEnd = nOfst + nLen;
68 OSL_ENSURE( sal_Int32(nEnd) <= rOrigString.getLength(), "sw_CalcCaseMap: Wrong parameters" );
69
70 // special case for title case:
71 const bool bTitle = SvxCaseMap::Capitalize == rFnt.GetCaseMap();
72 for (TextFrameIndex i = nOfst; i < nEnd; ++i)
73 {
74 OUString aTmp(rOrigString.copy(sal_Int32(i), 1));
75
76 if ( !bTitle ||
77 g_pBreakIt->GetBreakIter()->isBeginWord(
78 rOrigString, sal_Int32(i),
80 WordType::ANYWORD_IGNOREWHITESPACES ) )
81 aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp );
82
83 j += aTmp.getLength();
84
85 if (TextFrameIndex(j) > nIdx)
86 return i;
87 }
88
89 return nOfst + nLen;
90}
91
93{
94protected:
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 ) { }
100public:
101 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
102 virtual void Do() = 0;
105 SwCapitalInfo* GetCapInf() const { return m_pCapInf; }
106 void SetCapInf( SwCapitalInfo& rNew ) { m_pCapInf = &rNew; }
107};
108
109namespace {
110
111class SwDoGetCapitalSize : public SwDoCapitals
112{
113protected:
114 Size m_aTextSize;
115
116public:
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; }
122};
123
124}
125
126void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
127{
128 m_aTextSize.setHeight(0);
129 m_aTextSize.setWidth(0);
130}
131
132void SwDoGetCapitalSize::Do()
133{
134 m_aTextSize.AdjustWidth(m_rInf.GetSize().Width());
135 if( m_rInf.GetUpper() )
136 m_aTextSize.setHeight(m_rInf.GetSize().Height());
137}
138
140{
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() );
150
151 // End:
152 if( !aTextSize.Height() )
153 {
154 SV_STAT( nGetTextSize );
155 aTextSize.setHeight( short ( rInf.GetpOut()->GetTextHeight() ) );
156 }
157 rInf.SetKern( nOldKern );
158 return aTextSize;
159}
160
161namespace {
162
163class SwDoGetCapitalBreak : public SwDoCapitals
164{
165protected:
166 tools::Long m_nTextWidth;
167 TextFrameIndex m_nBreak;
168
169public:
170 SwDoGetCapitalBreak(SwDrawTextInfo& rInfo, tools::Long const nWidth)
171 : SwDoCapitals(rInfo)
172 , m_nTextWidth(nWidth)
173 , m_nBreak(-1)
174 { }
175 virtual ~SwDoGetCapitalBreak() {}
176 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
177 virtual void Do() override;
178 TextFrameIndex getBreak() const { return m_nBreak; }
179};
180
181}
182
183void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
184{
185}
186
187void SwDoGetCapitalBreak::Do()
188{
189 if (!m_nTextWidth)
190 return;
191
192 if (m_rInf.GetSize().Width() < m_nTextWidth)
193 m_nTextWidth -= m_rInf.GetSize().Width();
194 else
195 {
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()));
200
201 if (m_nBreak > nEnd || m_nBreak < TextFrameIndex(0))
202 m_nBreak = nEnd;
203
204 // m_nBreak may be relative to the display string. It has to be
205 // calculated relative to the original string:
206 if ( GetCapInf() )
207 {
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;
215 }
216
217 m_nTextWidth = 0;
218 }
219}
220
222 const SwScriptInfo* pScript, const OUString& rText, tools::Long const nTextWidth,
223 TextFrameIndex const nIdx, TextFrameIndex const nLen)
224{
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 );
238
239 SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
240 DoOnCapitals( aDo );
241 return aDo.getBreak();
242}
243
244namespace {
245
246class SwDoDrawCapital : public SwDoCapitals
247{
248protected:
249 SwFntObj* m_pUpperFnt;
250 SwFntObj* m_pLowerFnt;
251
252public:
253 explicit SwDoDrawCapital(SwDrawTextInfo& rInfo)
254 : SwDoCapitals(rInfo)
255 , m_pUpperFnt(nullptr)
256 , m_pLowerFnt(nullptr)
257 { }
258 virtual ~SwDoDrawCapital() {}
259 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
260 virtual void Do() override;
261 void DrawSpace( Point &rPos );
262};
263
264}
265
266void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
267{
268 m_pUpperFnt = pUpperFont;
269 m_pLowerFnt = pLowerFont;
270}
271
272void SwDoDrawCapital::Do()
273{
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
280 {
281 bool bOldBullet = m_rInf.GetBullet();
282 m_rInf.SetBullet( false );
283 m_pLowerFnt->DrawText(m_rInf);
284 m_rInf.SetBullet( bOldBullet );
285 }
286
287 OSL_ENSURE(m_pUpperFnt, "No upper font, dying soon!");
288 m_rInf.Shift(m_pUpperFnt->GetFont().GetOrientation());
289 m_rInf.SetWidth( nOrgWidth );
290}
291
292void SwDoDrawCapital::DrawSpace( Point &rPos )
293{
294 tools::Long nDiff = m_rInf.GetPos().X() - rPos.X();
295
296 Point aPos( rPos );
297 const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() &&
298 ! m_rInf.IsIgnoreFrameRTL();
299
300 if ( bSwitchL2R )
301 m_rInf.GetFrame()->SwitchLTRtoRTL( aPos );
302
303 const vcl::text::ComplexTextLayoutFlags nMode = m_rInf.GetpOut()->GetLayoutMode();
304 const bool bBidiPor = ( bSwitchL2R !=
306
307 if ( bBidiPor )
308 nDiff = -nDiff;
309
310 if ( m_rInf.GetFrame()->IsVertical() )
311 m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
312
313 if ( nDiff )
314 {
315 m_rInf.ApplyAutoColor();
316 GetOut().DrawStretchText( aPos, nDiff,
317 " ", 0, 2 );
318 }
319 rPos.setX( m_rInf.GetPos().X() + m_rInf.GetWidth() );
320}
321
323{
324 // Precondition: rInf.GetPos() has already been calculated
325
326 rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
327 GetOverline() != LINESTYLE_NONE ||
328 GetStrikeout() != STRIKEOUT_NONE );
329 SwDoDrawCapital aDo( rInf );
330 DoOnCapitals( aDo );
331}
332
333namespace {
334
335class SwDoCapitalCursorOfst : public SwDoCapitals
336{
337protected:
338 SwFntObj* m_pUpperFnt;
339 SwFntObj* m_pLowerFnt;
340 TextFrameIndex m_nCursor;
341 sal_uInt16 m_nOfst;
342
343public:
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)
350 { }
351 virtual ~SwDoCapitalCursorOfst() {}
352 virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
353 virtual void Do() override;
354
355 TextFrameIndex GetCursor() const { return m_nCursor; }
356};
357
358}
359
360void SwDoCapitalCursorOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
361{
362 m_pUpperFnt = pUpperFont;
363 m_pLowerFnt = pLowerFont;
364}
365
366void SwDoCapitalCursorOfst::Do()
367{
368 if (!m_nOfst)
369 return;
370
371 if (static_cast<tools::Long>(m_nOfst) > m_rInf.GetSize().Width())
372 {
373 m_nOfst -= m_rInf.GetSize().Width();
374 m_nCursor = m_nCursor + m_rInf.GetLen();
375 }
376 else
377 {
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() );
388
389 if ( m_rInf.GetUpper() )
390 {
391 aDrawInf.SetSpace( 0 );
392 m_nCursor = m_nCursor + m_pUpperFnt->GetModelPositionForViewPoint(aDrawInf);
393 }
394 else
395 {
396 aDrawInf.SetSpace( m_rInf.GetSpace() );
397 m_nCursor = m_nCursor + m_pLowerFnt->GetModelPositionForViewPoint(aDrawInf);
398 }
399 m_nOfst = 0;
400 }
401}
402
404{
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();
413}
414
415namespace {
416
417class SwDoDrawStretchCapital : public SwDoDrawCapital
418{
419 const TextFrameIndex m_nStrLen;
420 const sal_uInt16 m_nCapWidth;
421 const sal_uInt16 m_nOrgWidth;
422
423public:
424 virtual void Do() override;
425
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())
431 { }
432};
433
434}
435
436void SwDoDrawStretchCapital::Do()
437{
438 SV_STAT( nDrawStretchText );
439 tools::Long nPartWidth = m_rInf.GetSize().Width();
440
441 if( m_rInf.GetLen() )
442 {
443 // small caps and kerning
444 tools::Long nDiff = tools::Long(m_nOrgWidth) - tools::Long(m_nCapWidth);
445 if( nDiff )
446 {
447 nDiff *= sal_Int32(m_rInf.GetLen());
448 nDiff /= sal_Int32(m_nStrLen);
449 nDiff += nPartWidth;
450 if( 0 < nDiff )
451 nPartWidth = nDiff;
452 }
453
454 m_rInf.ApplyAutoColor();
455
456 Point aPos( m_rInf.GetPos() );
457 const bool bSwitchL2R = m_rInf.GetFrame()->IsRightToLeft() &&
458 ! m_rInf.IsIgnoreFrameRTL();
459
460 if ( bSwitchL2R )
461 m_rInf.GetFrame()->SwitchLTRtoRTL( aPos );
462
463 if ( m_rInf.GetFrame()->IsVertical() )
464 m_rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
465
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()));
473 }
474 const_cast<Point&>(m_rInf.GetPos()).AdjustX(nPartWidth );
475}
476
478{
479 // Precondition: rInf.GetPos() has already been calculated
480
482 rInf.SetLen(TextFrameIndex(rInf.GetText().getLength()));
483
484 const Point aOldPos = rInf.GetPos();
485 const sal_uInt16 nCapWidth = o3tl::narrowing<sal_uInt16>( GetCapitalSize( rInf ).Width() );
486 rInf.SetPos(aOldPos);
487
488 rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
489 GetOverline() != LINESTYLE_NONE ||
490 GetStrikeout() != STRIKEOUT_NONE );
491 SwDoDrawStretchCapital aDo( rInf, nCapWidth );
492 DoOnCapitals( aDo );
493}
494
496{
497 OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
498
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 );
505
506 const OUString oldText = rDo.GetInf().GetText();
507 rDo.GetInf().SetText( aText );
509 TextFrameIndex nOldPos = nPos;
510 nMaxPos = nMaxPos + nPos;
511
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 );
518
519 SwFntObj *pOldLast = pLastFont;
520 std::optional<SwFntAccess> oBigFontAccess;
521 SwFntObj *pBigFont;
522 std::optional<SwFntAccess> oSpaceFontAccess;
523 SwFntObj *pSpaceFont = nullptr;
524
525 const void* nFontCacheId2 = nullptr;
526 sal_uInt16 nIndex2 = 0;
527 SwSubFont aFont( *this );
528 Point aStartPos( rDo.GetInf().GetPos() );
529
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();
536
537 if ( bTextLines )
538 {
539 if ( bWordWise )
540 {
541 aFont.SetWordLineMode( false );
542 oSpaceFontAccess.emplace( nFontCacheId2, nIndex2, &aFont,
543 rDo.GetInf().GetShell() );
544 pSpaceFont = oSpaceFontAccess->Get();
545 }
546 else
547 pSpaceFont = pLastFont;
548
549 // Construct a font for the capitals:
553 nFontCacheId2 = nullptr;
554 nIndex2 = 0;
555 oBigFontAccess.emplace( nFontCacheId2, nIndex2, &aFont,
556 rDo.GetInf().GetShell() );
557 pBigFont = oBigFontAccess->Get();
558 }
559 else
560 pBigFont = pLastFont;
561
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();
574
575 rDo.Init( pBigFont, pSmallFont );
576 OutputDevice* pOutSize = pSmallFont->GetPrt();
577 if( !pOutSize )
578 pOutSize = &rDo.GetOut();
579 OutputDevice* pOldOut = &rDo.GetOut();
580
583
584 if( nPos < nMaxPos )
585 {
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;
593 }
594
595 while( nOldPos < nMaxPos )
596 {
597
598 // The lower ones...
599 if( nOldPos != nPos )
600 {
601 SV_STAT( nGetTextSize );
602 pLastFont = pSmallFont;
603 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
604
605 // #107816#, #i14820#
606 if( bCaseMapLengthDiffers )
607 {
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()));
616 }
617 else
618 {
619 rDo.GetInf().SetIdxLen(nOldPos, nPos - nOldPos);
620 }
621
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;
632 }
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 )
645 {
646 const tools::Long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
647
648 do
649 {
650 rDo.GetInf().SetUpper( true );
651 pLastFont = pBigFont;
652 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
653 TextFrameIndex nTmp;
654 if( bWordWise )
655 {
656 nTmp = nOldPos;
657 while (nTmp < nPos && CH_BLANK == oldText[sal_Int32(nTmp)])
658 ++nTmp;
659 if( nOldPos < nTmp )
660 {
661 pLastFont = pSpaceFont;
663 rDo.GetOut() );
664 static_cast<SwDoDrawCapital&>(rDo).DrawSpace( aStartPos );
665 pLastFont = pBigFont;
667 rDo.GetOut() );
668
669 // #107816#, #i14820#
670 if( bCaseMapLengthDiffers )
671 {
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 );
682 }
683 else
684 {
685 rDo.GetInf().SetIdx( nOldPos );
686 rDo.GetInf().SetLen( nTmp - nOldPos );
687 }
688
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;
701 }
702
703 while (nTmp < nPos && CH_BLANK != oldText[sal_Int32(nTmp)])
704 ++nTmp;
705 }
706 else
707 nTmp = nPos;
708 if( nTmp > nOldPos )
709 {
710 // #107816#, #i14820#
711 if( bCaseMapLengthDiffers )
712 {
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()));
721 }
722 else
723 {
724 rDo.GetInf().SetIdxLen( nOldPos, nTmp - nOldPos );
725 }
726
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() )
732 {
733 for (TextFrameIndex nI = nOldPos; nI < nPos; ++nI)
734 {
735 if (CH_BLANK == oldText[sal_Int32(nI)])
736 aPartSize.AdjustWidth(nSpaceAdd );
737 }
738 }
739 if( nTmpKern && nPos < nMaxPos )
740 aPartSize.AdjustWidth(nTmpKern );
741 rDo.GetInf().SetSize( aPartSize );
742 rDo.Do();
743 nOldPos = nTmp;
744 }
745 } while( nOldPos != nPos );
746 }
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
757 }
758
759 // clean up:
760 if( pBigFont != pOldLast )
761 oBigFontAccess.reset();
762
763 if( bTextLines )
764 {
765 if( rDo.GetInf().GetDrawSpace() )
766 {
767 pLastFont = pSpaceFont;
768 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
769 static_cast<SwDoDrawCapital&>( rDo ).DrawSpace( aStartPos );
770 }
771 if ( bWordWise )
772 oSpaceFontAccess.reset();
773 }
774 pLastFont = pOldLast;
775 pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
776
777 oSmallFontAccess.reset();
778 rDo.GetInf().SetText(oldText);
779 rDo.GetInf().SetKanaDiff( nKana );
780}
781
782/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
tools::Long GetTextHeight() const
constexpr tools::Long Height() const
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
sal_uInt8 GetPropr() const
OUString CalcCaseMap(const OUString &rTxt) const
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:67
SwDoCapitals(SwDrawTextInfo &rInfo)
Definition: fntcap.cxx:98
void SetCapInf(SwCapitalInfo &rNew)
Definition: fntcap.cxx:106
virtual void Init(SwFntObj *pUpperFont, SwFntObj *pLowerFont)=0
SwDrawTextInfo & m_rInf
Definition: fntcap.cxx:95
SwCapitalInfo * m_pCapInf
Definition: fntcap.cxx:96
SwDrawTextInfo & GetInf()
Definition: fntcap.cxx:104
~SwDoCapitals()
Definition: fntcap.cxx:99
OutputDevice & GetOut()
Definition: fntcap.cxx:103
virtual void Do()=0
SwCapitalInfo * GetCapInf() const
Definition: fntcap.cxx:105
void SetKern(tools::Long nNew)
Definition: drawfont.hxx:533
void SetDrawSpace(bool bNew)
Definition: drawfont.hxx:592
TextFrameIndex GetIdx() const
Definition: drawfont.hxx:269
bool GetDrawSpace() const
Definition: drawfont.hxx:370
void SetPos(const Point &rNew)
Definition: drawfont.hxx:408
TextFrameIndex GetLen() const
Definition: drawfont.hxx:274
void SetSize(const Size &rNew)
Definition: drawfont.hxx:470
const OUString & GetText() const
Definition: drawfont.hxx:222
void SetFont(SwFont *pNew)
Definition: drawfont.hxx:478
void SetSmartTags(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:465
SwViewShell const * GetShell() const
Definition: drawfont.hxx:181
tools::Long GetKern() const
Definition: drawfont.hxx:331
void SetUpper(bool bNew)
Definition: drawfont.hxx:584
void SetKanaDiff(tools::Long nNew)
Definition: drawfont.hxx:512
void SetKanaComp(short nNew)
Definition: drawfont.hxx:569
void SetText(const OUString &rNew)
Definition: drawfont.hxx:424
vcl::RenderContext & GetOut() const
Definition: drawfont.hxx:186
tools::Long GetKanaDiff() const
Definition: drawfont.hxx:297
void SetIdx(TextFrameIndex const nNew)
Definition: drawfont.hxx:486
vcl::RenderContext * GetpOut() const
Definition: drawfont.hxx:191
void SetTextIdxLen(const OUString &rNewStr, TextFrameIndex const nNewIdx, TextFrameIndex const nNewLen)
Definition: drawfont.hxx:432
void SetLen(TextFrameIndex const nNew)
Definition: drawfont.hxx:492
void SetIdxLen(TextFrameIndex const nNewIdx, TextFrameIndex const nNewLen)
Definition: drawfont.hxx:442
void SetGrammarCheck(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:457
const Point & GetPos() const
Definition: drawfont.hxx:201
sal_Int32 GetOffset() const
Definition: drawfont.hxx:284
void SetOut(OutputDevice &rNew)
Definition: drawfont.hxx:403
void SetSpace(tools::Long nNew)
Definition: drawfont.hxx:538
tools::Long GetSpace() const
Definition: drawfont.hxx:336
void SetWrong(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:449
OutputDevice * GetPrt() const
Definition: fntcache.hxx:107
void SetDevFont(const SwViewShell *pSh, OutputDevice &rOut)
Definition: fntcache.cxx:557
Size GetTextSize(SwDrawTextInfo &rInf)
determine the TextSize (of the printer)
Definition: fntcache.cxx:1529
TextFrameIndex GetCapitalBreak(SwViewShell const *pSh, const OutputDevice *pOut, const SwScriptInfo *pScript, const OUString &rText, tools::Long nTextWidth, TextFrameIndex nIdx, TextFrameIndex nLen)
Definition: fntcap.cxx:221
const SvxFont & GetActualFont() const
Definition: swfont.hxx:186
short CheckKerning()
Definition: swfont.hxx:324
void DoOnCapitals(SwDoCapitals &rDo)
Definition: swfont.hxx:307
SvxCaseMap GetCaseMap() const
Definition: swfont.hxx:280
LanguageType GetLanguage() const
Definition: swfont.hxx:283
short CheckKerning()
Definition: swfont.hxx:113
void SetProportion(const sal_uInt8 nNewPropr)
Definition: swfont.hxx:761
void DoOnCapitals(SwDoCapitals &rDo)
Definition: fntcap.cxx:495
void DrawCapital(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:322
Size GetCapitalSize(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:139
bool m_bSmallCapsPercentage66
Definition: swfont.hxx:62
void SetOverline(const FontLineStyle eOverline)
Definition: swfont.hxx:558
TextFrameIndex GetCapitalCursorOfst(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:403
void SetUnderline(const FontLineStyle eUnderline)
Definition: swfont.hxx:543
void SetStrikeout(const FontStrikeout eStrikeout)
Definition: swfont.hxx:573
void DrawStretchCapital(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:477
void SetWordLineMode(const bool bWordLineMode)
Definition: swfont.hxx:669
SwFntObj * pLastFont
Definition: fntcache.cxx:67
TextFrameIndex sw_CalcCaseMap(const SwFont &rFnt, const OUString &rOrigString, TextFrameIndex const nOfst, TextFrameIndex const nLen, TextFrameIndex const nIdx)
Definition: fntcap.cxx:60
LINESTYLE_NONE
STRIKEOUT_NONE
#define LANGUAGE_SYSTEM
#define LANGUAGE_DONTKNOW
sal_uInt16 nPos
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:390
int i
long Long
ComplexTextLayoutFlags
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
#define SPACING_PRECISION_FACTOR
Definition: scriptinfo.hxx:41
tools::Long GetLen(const Point &rPnt)
#define SMALL_CAPS_PERCENTAGE
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
#define SV_STAT(nWhich)
Definition: swfont.hxx:998
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
oslFileHandle & pOut