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 
34 using namespace ::com::sun::star::i18n;
35 
36 namespace {
37 
38 // The information encapsulated in SwCapitalInfo is required
39 // by the ::Do functions. They contain the information about
40 // the original string, whereas rDo.GetInf() contains information
41 // about the display string.
42 class SwCapitalInfo
43 {
44 public:
45  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),
79  g_pBreakIt->GetLocale( rFnt.GetLanguage() ),
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 {
94 protected:
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 ) { }
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; }
107 };
108 
109 namespace {
110 
111 class SwDoGetCapitalSize : public SwDoCapitals
112 {
113 protected:
114  Size m_aTextSize;
115 
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; }
122 };
123 
124 }
125 
126 void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
127 {
128  m_aTextSize.setHeight(0);
129  m_aTextSize.setWidth(0);
130 }
131 
132 void 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 
161 namespace {
162 
163 class SwDoGetCapitalBreak : public SwDoCapitals
164 {
165 protected:
166  tools::Long m_nTextWidth;
167  TextFrameIndex m_nBreak;
168 
169 public:
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 
183 void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
184 {
185 }
186 
187 void 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 
244 namespace {
245 
246 class SwDoDrawCapital : public SwDoCapitals
247 {
248 protected:
249  SwFntObj* m_pUpperFnt;
250  SwFntObj* m_pLowerFnt;
251 
252 public:
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 
266 void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
267 {
268  m_pUpperFnt = pUpperFont;
269  m_pLowerFnt = pLowerFont;
270 }
271 
272 void 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 
292 void 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 ComplexTextLayoutFlags nMode = m_rInf.GetpOut()->GetLayoutMode();
304  const bool bBidiPor = ( bSwitchL2R !=
305  ( ComplexTextLayoutFlags::Default != ( ComplexTextLayoutFlags::BiDiRtl & nMode ) ) );
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 
333 namespace {
334 
335 class SwDoCapitalCursorOfst : public SwDoCapitals
336 {
337 protected:
338  SwFntObj* m_pUpperFnt;
339  SwFntObj* m_pLowerFnt;
340  TextFrameIndex m_nCursor;
341  sal_uInt16 m_nOfst;
342 
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)
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 
360 void SwDoCapitalCursorOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
361 {
362  m_pUpperFnt = pUpperFont;
363  m_pLowerFnt = pLowerFont;
364 }
365 
366 void 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 
415 namespace {
416 
417 class SwDoDrawStretchCapital : public SwDoDrawCapital
418 {
419  const TextFrameIndex m_nStrLen;
420  const sal_uInt16 m_nCapWidth;
421  const sal_uInt16 m_nOrgWidth;
422 
423 public:
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 
436 void 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 
481  if (rInf.GetLen() == TextFrameIndex(COMPLETE_STRING))
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 );
508  TextFrameIndex nPos = rDo.GetInf().GetIdx();
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::unique_ptr<SwFntAccess> pBigFontAccess;
521  SwFntObj *pBigFont;
522  std::unique_ptr<SwFntAccess> pSpaceFontAccess;
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  pSpaceFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
543  rDo.GetInf().GetShell() ));
544  pSpaceFont = pSpaceFontAccess->Get();
545  }
546  else
547  pSpaceFont = pLastFont;
548 
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  pBigFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
556  rDo.GetInf().GetShell() ));
557  pBigFont = pBigFontAccess->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::unique_ptr<SwFntAccess> pSmallFontAccess( new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
572  rDo.GetInf().GetShell() ));
573  SwFntObj *pSmallFont = pSmallFontAccess->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 
581  const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
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().SetIdx(TextFrameIndex(0));
616  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
617  rDo.GetInf().SetText( aNewText );
618  }
619  else
620  {
621  rDo.GetInf().SetIdx( nOldPos );
622  rDo.GetInf().SetLen( nPos - nOldPos );
623  }
624 
625  rDo.GetInf().SetUpper( false );
626  rDo.GetInf().SetOut( *pOutSize );
627  Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
628  nKana += rDo.GetInf().GetKanaDiff();
629  rDo.GetInf().SetOut( *pOldOut );
630  if( nTmpKern && nPos < nMaxPos )
631  aPartSize.AdjustWidth(nTmpKern );
632  rDo.GetInf().SetSize( aPartSize );
633  rDo.Do();
634  nOldPos = nPos;
635  }
636  nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->nextCharBlock(
637  oldText, sal_Int32(nPos),
638  g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
639  if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
640  nPos = nMaxPos;
641  OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
642 #if OSL_DEBUG_LEVEL > 1
643  if( !nPos )
644  nPos = nMaxPos;
645 #endif
646  // The upper ones...
647  if( nOldPos != nPos )
648  {
649  const tools::Long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
650 
651  do
652  {
653  rDo.GetInf().SetUpper( true );
654  pLastFont = pBigFont;
655  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
656  TextFrameIndex nTmp;
657  if( bWordWise )
658  {
659  nTmp = nOldPos;
660  while (nTmp < nPos && CH_BLANK == oldText[sal_Int32(nTmp)])
661  ++nTmp;
662  if( nOldPos < nTmp )
663  {
664  pLastFont = pSpaceFont;
666  rDo.GetOut() );
667  static_cast<SwDoDrawCapital&>(rDo).DrawSpace( aStartPos );
668  pLastFont = pBigFont;
670  rDo.GetOut() );
671 
672  // #107816#, #i14820#
673  if( bCaseMapLengthDiffers )
674  {
675  // Build an own 'changed' string for the given part of the
676  // source string and use it. That new string may differ in length
677  // from the source string.
678  const OUString aNewText = CalcCaseMap(
679  oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
680  aCapInf.nIdx = nOldPos;
681  aCapInf.nLen = nTmp - nOldPos;
682  rDo.GetInf().SetIdx(TextFrameIndex(0));
683  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
684  rDo.GetInf().SetText( aNewText );
685  }
686  else
687  {
688  rDo.GetInf().SetIdx( nOldPos );
689  rDo.GetInf().SetLen( nTmp - nOldPos );
690  }
691 
692  rDo.GetInf().SetOut( *pOutSize );
693  Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
694  nKana += rDo.GetInf().GetKanaDiff();
695  rDo.GetInf().SetOut( *pOldOut );
696  if( nSpaceAdd )
697  aPartSize.AdjustWidth(nSpaceAdd * sal_Int32(nTmp - nOldPos));
698  if( nTmpKern && nPos < nMaxPos )
699  aPartSize.AdjustWidth(nTmpKern );
700  rDo.GetInf().SetSize( aPartSize );
701  rDo.Do();
702  aStartPos = rDo.GetInf().GetPos();
703  nOldPos = nTmp;
704  }
705 
706  while (nTmp < nPos && CH_BLANK != oldText[sal_Int32(nTmp)])
707  ++nTmp;
708  }
709  else
710  nTmp = nPos;
711  if( nTmp > nOldPos )
712  {
713  // #107816#, #i14820#
714  if( bCaseMapLengthDiffers )
715  {
716  // Build an own 'changed' string for the given part of the
717  // source string and use it. That new string may differ in length
718  // from the source string.
719  const OUString aNewText = CalcCaseMap(
720  oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
721  aCapInf.nIdx = nOldPos;
722  aCapInf.nLen = nTmp - nOldPos;
723  rDo.GetInf().SetIdx(TextFrameIndex(0));
724  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
725  rDo.GetInf().SetText( aNewText );
726  }
727  else
728  {
729  rDo.GetInf().SetIdx( nOldPos );
730  rDo.GetInf().SetLen( nTmp - nOldPos );
731  }
732 
733  rDo.GetInf().SetOut( *pOutSize );
734  Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
735  nKana += rDo.GetInf().GetKanaDiff();
736  rDo.GetInf().SetOut( *pOldOut );
737  if( !bWordWise && rDo.GetInf().GetSpace() )
738  {
739  for (TextFrameIndex nI = nOldPos; nI < nPos; ++nI)
740  {
741  if (CH_BLANK == oldText[sal_Int32(nI)])
742  aPartSize.AdjustWidth(nSpaceAdd );
743  }
744  }
745  if( nTmpKern && nPos < nMaxPos )
746  aPartSize.AdjustWidth(nTmpKern );
747  rDo.GetInf().SetSize( aPartSize );
748  rDo.Do();
749  nOldPos = nTmp;
750  }
751  } while( nOldPos != nPos );
752  }
753  nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock(
754  oldText, sal_Int32(nPos),
755  g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
756  if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
757  nPos = nMaxPos;
758  OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
759 #if OSL_DEBUG_LEVEL > 1
760  if( !nPos )
761  nPos = nMaxPos;
762 #endif
763  }
764 
765  // clean up:
766  if( pBigFont != pOldLast )
767  pBigFontAccess.reset();
768 
769  if( bTextLines )
770  {
771  if( rDo.GetInf().GetDrawSpace() )
772  {
773  pLastFont = pSpaceFont;
774  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
775  static_cast<SwDoDrawCapital&>( rDo ).DrawSpace( aStartPos );
776  }
777  if ( bWordWise )
778  pSpaceFontAccess.reset();
779  }
780  pLastFont = pOldLast;
781  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
782 
783  pSmallFontAccess.reset();
784  rDo.GetInf().SetText(oldText);
785  rDo.GetInf().SetKanaDiff( nKana );
786 }
787 
788 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetSmartTags(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:435
OutputDevice * GetPrt() const
Definition: fntcache.hxx:114
SwFntObj * pLastFont
Definition: fntcache.cxx:67
SwViewShell const * GetShell() const
Definition: drawfont.hxx:175
sal_uInt8 GetPropr() const
short CheckKerning()
Definition: swfont.hxx:320
vcl::RenderContext * GetpOut() const
Definition: drawfont.hxx:185
bool m_bSmallCapsPercentage66
Definition: swfont.hxx:62
TextFrameIndex GetCapitalCursorOfst(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:403
void SetCapInf(SwCapitalInfo &rNew)
Definition: fntcap.cxx:106
bool GetDrawSpace() const
Definition: drawfont.hxx:359
#define SMALL_CAPS_PERCENTAGE
void SetSize(const Size &rNew)
Definition: drawfont.hxx:440
long Long
LanguageType GetLanguage(SfxItemSet const &aSet, sal_uInt16 nLangWhichId)
Definition: langhelper.cxx:390
void SetIdx(TextFrameIndex const nNew)
Definition: drawfont.hxx:456
void SetUnderline(const FontLineStyle eUnderline)
Definition: swfont.hxx:536
tools::Long GetLen(const Point &rPnt)
const SvxFont & GetActualFont() const
Definition: swfont.hxx:184
void SetKanaComp(short nNew)
Definition: drawfont.hxx:531
void SetPos(const Point &rNew)
Definition: drawfont.hxx:397
~SwDoCapitals()
Definition: fntcap.cxx:99
void DrawCapital(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:322
constexpr tools::Long Width() const
TextFrameIndex sw_CalcCaseMap(const SwFont &rFnt, const OUString &rOrigString, TextFrameIndex const nOfst, TextFrameIndex const nLen, TextFrameIndex const nIdx)
Definition: fntcap.cxx:60
LINESTYLE_NONE
void SetOut(OutputDevice &rNew)
Definition: drawfont.hxx:392
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
void SetKern(tools::Long nNew)
Definition: drawfont.hxx:495
void SetKanaDiff(tools::Long nNew)
Definition: drawfont.hxx:474
virtual void Init(SwFntObj *pUpperFont, SwFntObj *pLowerFont)=0
SvxCaseMap GetCaseMap() const
Definition: swfont.hxx:276
SwCapitalInfo * m_pCapInf
Definition: fntcap.cxx:96
void SetWrong(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:419
void SetLen(TextFrameIndex const nNew)
Definition: drawfont.hxx:461
const OUString & GetText() const
Definition: drawfont.hxx:216
void SetOverline(const FontLineStyle eOverline)
Definition: swfont.hxx:551
tools::Long GetKanaDiff() const
Definition: drawfont.hxx:286
void SetWordLineMode(const bool bWordLineMode)
Definition: swfont.hxx:662
int i
void SetOffset(sal_Int32 nNew)
Definition: drawfont.hxx:466
void DrawStretchCapital(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:477
#define LANGUAGE_SYSTEM
ComplexTextLayoutFlags
SwDrawTextInfo & m_rInf
Definition: fntcap.cxx:95
Size GetCapitalSize(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:139
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
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
void SetProportion(const sal_uInt8 nNewPropr)
Definition: swfont.hxx:754
void SetUpper(bool bNew)
Definition: drawfont.hxx:546
#define LANGUAGE_DONTKNOW
void SetSpace(tools::Long nNew)
Definition: drawfont.hxx:500
void SetGrammarCheck(sw::WrongListIterator *const pNew)
Definition: drawfont.hxx:427
void DoOnCapitals(SwDoCapitals &rDo)
Definition: swfont.hxx:303
#define SV_STAT(nWhich)
Definition: swfont.hxx:991
void SetDrawSpace(bool bNew)
Definition: drawfont.hxx:554
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
SwCapitalInfo * GetCapInf() const
Definition: fntcap.cxx:105
void SetDevFont(const SwViewShell *pSh, OutputDevice &rOut)
Definition: fntcache.cxx:679
LanguageType GetLanguage() const
Definition: swfont.hxx:279
void DoOnCapitals(SwDoCapitals &rDo)
Definition: fntcap.cxx:495
tools::Long GetSpace() const
Definition: drawfont.hxx:325
const Point & GetPos() const
Definition: drawfont.hxx:195
tools::Long GetTextHeight() const
TextFrameIndex GetLen() const
Definition: drawfont.hxx:268
OutputDevice & GetOut()
Definition: fntcap.cxx:103
tools::Long AdjustWidth(tools::Long n)
OUString CalcCaseMap(const OUString &rTxt) const
vcl::RenderContext & GetOut() const
Definition: drawfont.hxx:180
tools::Long GetKern() const
Definition: drawfont.hxx:320
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:56
void setHeight(tools::Long nHeight)
#define SPACING_PRECISION_FACTOR
Definition: scriptinfo.hxx:40
void SetText(const OUString &rNew)
Definition: drawfont.hxx:413
TextFrameIndex GetIdx() const
Definition: drawfont.hxx:263
void SetFont(SwFont *pNew)
Definition: drawfont.hxx:448
STRIKEOUT_NONE
SwDrawTextInfo & GetInf()
Definition: fntcap.cxx:104
sal_Int32 GetOffset() const
Definition: drawfont.hxx:273
void SetStrikeout(const FontStrikeout eStrikeout)
Definition: swfont.hxx:566
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...
sal_uInt16 nPos
Size GetTextSize(SwDrawTextInfo &rInf)
determine the TextSize (of the printer)
Definition: fntcache.cxx:1919
virtual void Do()=0
SwDoCapitals(SwDrawTextInfo &rInfo)
Definition: fntcap.cxx:98
short CheckKerning()
Definition: swfont.hxx:112