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* pCapInf; // refers to additional information
97  // required by the ::Do function
98  explicit SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( nullptr ) { }
100 public:
101  virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
102  virtual void Do() = 0;
103  OutputDevice& GetOut() { return rInf.GetOut(); }
104  SwDrawTextInfo& GetInf() { return rInf; }
105  SwCapitalInfo* GetCapInf() const { return pCapInf; }
106  void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; }
107 };
108 
109 namespace {
110 
111 class SwDoGetCapitalSize : public SwDoCapitals
112 {
113 protected:
114  Size aTextSize;
115 public:
116  explicit SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
117  virtual ~SwDoGetCapitalSize() {}
118  virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
119  virtual void Do() override;
120  const Size &GetSize() const { return aTextSize; }
121 };
122 
123 }
124 
125 void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
126 {
127  aTextSize.setHeight( 0 );
128  aTextSize.setWidth( 0 );
129 }
130 
131 void SwDoGetCapitalSize::Do()
132 {
133  aTextSize.AdjustWidth(rInf.GetSize().Width() );
134  if( rInf.GetUpper() )
135  aTextSize.setHeight( rInf.GetSize().Height() );
136 }
137 
139 {
140  // Start:
141  const tools::Long nOldKern = rInf.GetKern();
142  rInf.SetKern( CheckKerning() );
143  rInf.SetPos( Point() );
144  rInf.SetSpace( 0 );
145  rInf.SetDrawSpace( false );
146  SwDoGetCapitalSize aDo( rInf );
147  DoOnCapitals( aDo );
148  Size aTextSize( aDo.GetSize() );
149 
150  // End:
151  if( !aTextSize.Height() )
152  {
153  SV_STAT( nGetTextSize );
154  aTextSize.setHeight( short ( rInf.GetpOut()->GetTextHeight() ) );
155  }
156  rInf.SetKern( nOldKern );
157  return aTextSize;
158 }
159 
160 namespace {
161 
162 class SwDoGetCapitalBreak : public SwDoCapitals
163 {
164 protected:
165  tools::Long m_nTextWidth;
166  TextFrameIndex m_nBreak;
167 
168 public:
169  SwDoGetCapitalBreak(SwDrawTextInfo& rInfo, tools::Long const nWidth)
170  : SwDoCapitals(rInfo)
171  , m_nTextWidth(nWidth)
172  , m_nBreak(-1)
173  { }
174  virtual ~SwDoGetCapitalBreak() {}
175  virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
176  virtual void Do() override;
177  TextFrameIndex getBreak() const { return m_nBreak; }
178 };
179 
180 }
181 
182 void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
183 {
184 }
185 
186 void SwDoGetCapitalBreak::Do()
187 {
188  if (!m_nTextWidth)
189  return;
190 
191  if (rInf.GetSize().Width() < m_nTextWidth)
192  m_nTextWidth -= rInf.GetSize().Width();
193  else
194  {
195  TextFrameIndex nEnd = rInf.GetEnd();
196  m_nBreak = TextFrameIndex(GetOut().GetTextBreak(rInf.GetText(), m_nTextWidth,
197  sal_Int32(rInf.GetIdx()),
198  sal_Int32(rInf.GetLen()), rInf.GetKern()));
199 
200  if (m_nBreak > nEnd || m_nBreak < TextFrameIndex(0))
201  m_nBreak = nEnd;
202 
203  // m_nBreak may be relative to the display string. It has to be
204  // calculated relative to the original string:
205  if ( GetCapInf() )
206  {
207  if ( GetCapInf()->nLen != rInf.GetLen() )
208  m_nBreak = sw_CalcCaseMap( *rInf.GetFont(),
209  GetCapInf()->rString,
210  GetCapInf()->nIdx,
211  GetCapInf()->nLen, m_nBreak );
212  else
213  m_nBreak = m_nBreak + GetCapInf()->nIdx;
214  }
215 
216  m_nTextWidth = 0;
217  }
218 }
219 
221  const SwScriptInfo* pScript, const OUString& rText, tools::Long const nTextWidth,
222  TextFrameIndex const nIdx, TextFrameIndex const nLen)
223 {
224  // Start:
225  Point aPos( 0, 0 );
226  SwDrawTextInfo aInfo(pSh, *const_cast<OutputDevice*>(pOut), pScript, rText, nIdx, nLen,
227  0, false);
228  aInfo.SetPos( aPos );
229  aInfo.SetSpace( 0 );
230  aInfo.SetWrong( nullptr );
231  aInfo.SetGrammarCheck( nullptr );
232  aInfo.SetSmartTags( nullptr );
233  aInfo.SetDrawSpace( false );
234  aInfo.SetKern( CheckKerning() );
235  aInfo.SetKanaComp( pScript ? 0 : 100 );
236  aInfo.SetFont( this );
237 
238  SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
239  DoOnCapitals( aDo );
240  return aDo.getBreak();
241 }
242 
243 namespace {
244 
245 class SwDoDrawCapital : public SwDoCapitals
246 {
247 protected:
248  SwFntObj* m_pUpperFnt;
249  SwFntObj* m_pLowerFnt;
250 
251 public:
252  explicit SwDoDrawCapital(SwDrawTextInfo& rInfo)
253  : SwDoCapitals(rInfo)
254  , m_pUpperFnt(nullptr)
255  , m_pLowerFnt(nullptr)
256  { }
257  virtual ~SwDoDrawCapital() {}
258  virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
259  virtual void Do() override;
260  void DrawSpace( Point &rPos );
261 };
262 
263 }
264 
265 void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
266 {
267  m_pUpperFnt = pUpperFont;
268  m_pLowerFnt = pLowerFont;
269 }
270 
271 void SwDoDrawCapital::Do()
272 {
273  SV_STAT( nDrawText );
274  const sal_uInt16 nOrgWidth = rInf.GetWidth();
275  rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) );
276  if ( rInf.GetUpper() )
277  m_pUpperFnt->DrawText(rInf);
278  else
279  {
280  bool bOldBullet = rInf.GetBullet();
281  rInf.SetBullet( false );
282  m_pLowerFnt->DrawText(rInf);
283  rInf.SetBullet( bOldBullet );
284  }
285 
286  OSL_ENSURE(m_pUpperFnt, "No upper font, dying soon!");
287  rInf.Shift(m_pUpperFnt->GetFont().GetOrientation());
288  rInf.SetWidth( nOrgWidth );
289 }
290 
291 void SwDoDrawCapital::DrawSpace( Point &rPos )
292 {
293  tools::Long nDiff = rInf.GetPos().X() - rPos.X();
294 
295  Point aPos( rPos );
296  const bool bSwitchL2R = rInf.GetFrame()->IsRightToLeft() &&
297  ! rInf.IsIgnoreFrameRTL();
298 
299  if ( bSwitchL2R )
300  rInf.GetFrame()->SwitchLTRtoRTL( aPos );
301 
302  const ComplexTextLayoutFlags nMode = rInf.GetpOut()->GetLayoutMode();
303  const bool bBidiPor = ( bSwitchL2R !=
304  ( ComplexTextLayoutFlags::Default != ( ComplexTextLayoutFlags::BiDiRtl & nMode ) ) );
305 
306  if ( bBidiPor )
307  nDiff = -nDiff;
308 
309  if ( rInf.GetFrame()->IsVertical() )
310  rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
311 
312  if ( nDiff )
313  {
314  rInf.ApplyAutoColor();
315  GetOut().DrawStretchText( aPos, nDiff,
316  " ", 0, 2 );
317  }
318  rPos.setX( rInf.GetPos().X() + rInf.GetWidth() );
319 }
320 
322 {
323  // Precondition: rInf.GetPos() has already been calculated
324 
325  rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
326  GetOverline() != LINESTYLE_NONE ||
327  GetStrikeout() != STRIKEOUT_NONE );
328  SwDoDrawCapital aDo( rInf );
329  DoOnCapitals( aDo );
330 }
331 
332 namespace {
333 
334 class SwDoCapitalCursorOfst : public SwDoCapitals
335 {
336 protected:
337  SwFntObj* m_pUpperFnt;
338  SwFntObj* m_pLowerFnt;
339  TextFrameIndex m_nCursor;
340  sal_uInt16 m_nOfst;
341 
342 public:
343  SwDoCapitalCursorOfst(SwDrawTextInfo& rInfo, const sal_uInt16 nOfs)
344  : SwDoCapitals(rInfo)
345  , m_pUpperFnt(nullptr)
346  , m_pLowerFnt(nullptr)
347  , m_nCursor(0)
348  , m_nOfst(nOfs)
349  { }
350  virtual ~SwDoCapitalCursorOfst() {}
351  virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) override;
352  virtual void Do() override;
353 
354  TextFrameIndex GetCursor() const { return m_nCursor; }
355 };
356 
357 }
358 
359 void SwDoCapitalCursorOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
360 {
361  m_pUpperFnt = pUpperFont;
362  m_pLowerFnt = pLowerFont;
363 }
364 
365 void SwDoCapitalCursorOfst::Do()
366 {
367  if (!m_nOfst)
368  return;
369 
370  if (static_cast<tools::Long>(m_nOfst) > rInf.GetSize().Width())
371  {
372  m_nOfst -= rInf.GetSize().Width();
373  m_nCursor = m_nCursor + rInf.GetLen();
374  }
375  else
376  {
377  SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(),
378  rInf.GetScriptInfo(),
379  rInf.GetText(),
380  rInf.GetIdx(),
381  rInf.GetLen(), 0, false );
382  aDrawInf.SetOffset(m_nOfst);
383  aDrawInf.SetKern( rInf.GetKern() );
384  aDrawInf.SetKanaComp( rInf.GetKanaComp() );
385  aDrawInf.SetFrame( rInf.GetFrame() );
386  aDrawInf.SetFont( rInf.GetFont() );
387 
388  if ( rInf.GetUpper() )
389  {
390  aDrawInf.SetSpace( 0 );
391  m_nCursor = m_nCursor + m_pUpperFnt->GetModelPositionForViewPoint(aDrawInf);
392  }
393  else
394  {
395  aDrawInf.SetSpace( rInf.GetSpace() );
396  m_nCursor = m_nCursor + m_pLowerFnt->GetModelPositionForViewPoint(aDrawInf);
397  }
398  m_nOfst = 0;
399  }
400 }
401 
403 {
404  const tools::Long nOldKern = rInf.GetKern();
405  rInf.SetKern( CheckKerning() );
406  SwDoCapitalCursorOfst aDo( rInf, rInf.GetOffset() );
407  rInf.SetPos( Point() );
408  rInf.SetDrawSpace( false );
409  DoOnCapitals( aDo );
410  rInf.SetKern( nOldKern );
411  return aDo.GetCursor();
412 }
413 
414 namespace {
415 
416 class SwDoDrawStretchCapital : public SwDoDrawCapital
417 {
418  const TextFrameIndex m_nStrLen;
419  const sal_uInt16 m_nCapWidth;
420  const sal_uInt16 m_nOrgWidth;
421 
422 public:
423  virtual void Do() override;
424 
425  SwDoDrawStretchCapital(SwDrawTextInfo& rInfo, const sal_uInt16 nCapitalWidth)
426  : SwDoDrawCapital(rInfo)
427  , m_nStrLen(rInfo.GetLen())
428  , m_nCapWidth(nCapitalWidth)
429  , m_nOrgWidth(rInfo.GetWidth())
430  { }
431 };
432 
433 }
434 
435 void SwDoDrawStretchCapital::Do()
436 {
437  SV_STAT( nDrawStretchText );
438  tools::Long nPartWidth = rInf.GetSize().Width();
439 
440  if( rInf.GetLen() )
441  {
442  // small caps and kerning
443  tools::Long nDiff = tools::Long(m_nOrgWidth) - tools::Long(m_nCapWidth);
444  if( nDiff )
445  {
446  nDiff *= sal_Int32(rInf.GetLen());
447  nDiff /= sal_Int32(m_nStrLen);
448  nDiff += nPartWidth;
449  if( 0 < nDiff )
450  nPartWidth = nDiff;
451  }
452 
453  rInf.ApplyAutoColor();
454 
455  Point aPos( rInf.GetPos() );
456  const bool bSwitchL2R = rInf.GetFrame()->IsRightToLeft() &&
457  ! rInf.IsIgnoreFrameRTL();
458 
459  if ( bSwitchL2R )
460  rInf.GetFrame()->SwitchLTRtoRTL( aPos );
461 
462  if ( rInf.GetFrame()->IsVertical() )
463  rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
464 
465  // Optimise:
466  if (TextFrameIndex(1) >= rInf.GetLen())
467  GetOut().DrawText(aPos, rInf.GetText(), sal_Int32(rInf.GetIdx()),
468  sal_Int32(rInf.GetLen()));
469  else
470  GetOut().DrawStretchText(aPos, nPartWidth, rInf.GetText(),
471  sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
472  }
473  const_cast<Point&>(rInf.GetPos()).AdjustX(nPartWidth );
474 }
475 
477 {
478  // Precondition: rInf.GetPos() has already been calculated
479 
480  if (rInf.GetLen() == TextFrameIndex(COMPLETE_STRING))
481  rInf.SetLen(TextFrameIndex(rInf.GetText().getLength()));
482 
483  const Point aOldPos = rInf.GetPos();
484  const sal_uInt16 nCapWidth = static_cast<sal_uInt16>( GetCapitalSize( rInf ).Width() );
485  rInf.SetPos(aOldPos);
486 
487  rInf.SetDrawSpace( GetUnderline() != LINESTYLE_NONE ||
488  GetOverline() != LINESTYLE_NONE ||
489  GetStrikeout() != STRIKEOUT_NONE );
490  SwDoDrawStretchCapital aDo( rInf, nCapWidth );
491  DoOnCapitals( aDo );
492 }
493 
495 {
496  OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
497 
498  tools::Long nKana = 0;
499  const OUString aText( CalcCaseMap( rDo.GetInf().GetText() ) );
500  TextFrameIndex nMaxPos = std::min(
501  TextFrameIndex(rDo.GetInf().GetText().getLength()) - rDo.GetInf().GetIdx(),
502  rDo.GetInf().GetLen() );
503  rDo.GetInf().SetLen( nMaxPos );
504 
505  const OUString oldText = rDo.GetInf().GetText();
506  rDo.GetInf().SetText( aText );
507  TextFrameIndex nPos = rDo.GetInf().GetIdx();
508  TextFrameIndex nOldPos = nPos;
509  nMaxPos = nMaxPos + nPos;
510 
511  // Look if the length of the original text and the ToUpper-converted
512  // text is different. If yes, do special handling.
513  SwCapitalInfo aCapInf(oldText);
514  bool bCaseMapLengthDiffers(aText.getLength() != oldText.getLength());
515  if ( bCaseMapLengthDiffers )
516  rDo.SetCapInf( aCapInf );
517 
518  SwFntObj *pOldLast = pLastFont;
519  std::unique_ptr<SwFntAccess> pBigFontAccess;
520  SwFntObj *pBigFont;
521  std::unique_ptr<SwFntAccess> pSpaceFontAccess;
522  SwFntObj *pSpaceFont = nullptr;
523 
524  const void* nFontCacheId2 = nullptr;
525  sal_uInt16 nIndex2 = 0;
526  SwSubFont aFont( *this );
527  Point aStartPos( rDo.GetInf().GetPos() );
528 
529  const bool bTextLines = aFont.GetUnderline() != LINESTYLE_NONE
530  || aFont.GetOverline() != LINESTYLE_NONE
531  || aFont.GetStrikeout() != STRIKEOUT_NONE;
532  const bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
533  rDo.GetInf().GetDrawSpace();
534  const tools::Long nTmpKern = rDo.GetInf().GetKern();
535 
536  if ( bTextLines )
537  {
538  if ( bWordWise )
539  {
540  aFont.SetWordLineMode( false );
541  pSpaceFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
542  rDo.GetInf().GetShell() ));
543  pSpaceFont = pSpaceFontAccess->Get();
544  }
545  else
546  pSpaceFont = pLastFont;
547 
548  // Construct a font for the capitals:
549  aFont.SetUnderline( LINESTYLE_NONE );
550  aFont.SetOverline( LINESTYLE_NONE );
551  aFont.SetStrikeout( STRIKEOUT_NONE );
552  nFontCacheId2 = nullptr;
553  nIndex2 = 0;
554  pBigFontAccess.reset(new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
555  rDo.GetInf().GetShell() ));
556  pBigFont = pBigFontAccess->Get();
557  }
558  else
559  pBigFont = pLastFont;
560 
561  // Older LO versions had 66 as the small caps percentage size, later changed to 80,
562  // therefore a backwards compatibility option is kept (otherwise layout is changed).
563  // NOTE: There are more uses of SMALL_CAPS_PERCENTAGE in editeng, but it seems they
564  // do not matter for Writer (and if they did it'd be pretty ugly to propagate
565  // the option there).
566  int smallCapsPercentage = m_bSmallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE;
567  aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 );
568  nFontCacheId2 = nullptr;
569  nIndex2 = 0;
570  std::unique_ptr<SwFntAccess> pSmallFontAccess( new SwFntAccess( nFontCacheId2, nIndex2, &aFont,
571  rDo.GetInf().GetShell() ));
572  SwFntObj *pSmallFont = pSmallFontAccess->Get();
573 
574  rDo.Init( pBigFont, pSmallFont );
575  OutputDevice* pOutSize = pSmallFont->GetPrt();
576  if( !pOutSize )
577  pOutSize = &rDo.GetOut();
578  OutputDevice* pOldOut = &rDo.GetOut();
579 
580  const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
582 
583  if( nPos < nMaxPos )
584  {
585  nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock(
586  oldText, sal_Int32(nPos),
587  g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
588  if (nPos < TextFrameIndex(0))
589  nPos = nOldPos;
590  else if( nPos > nMaxPos )
591  nPos = nMaxPos;
592  }
593 
594  while( nOldPos < nMaxPos )
595  {
596 
597  // The lower ones...
598  if( nOldPos != nPos )
599  {
600  SV_STAT( nGetTextSize );
601  pLastFont = pSmallFont;
602  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
603 
604  // #107816#, #i14820#
605  if( bCaseMapLengthDiffers )
606  {
607  // Build an own 'changed' string for the given part of the
608  // source string and use it. That new string may differ in length
609  // from the source string.
610  const OUString aNewText = CalcCaseMap(
611  oldText.copy(sal_Int32(nOldPos), sal_Int32(nPos-nOldPos)));
612  aCapInf.nIdx = nOldPos;
613  aCapInf.nLen = nPos - nOldPos;
614  rDo.GetInf().SetIdx(TextFrameIndex(0));
615  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
616  rDo.GetInf().SetText( aNewText );
617  }
618  else
619  {
620  rDo.GetInf().SetIdx( nOldPos );
621  rDo.GetInf().SetLen( nPos - nOldPos );
622  }
623 
624  rDo.GetInf().SetUpper( false );
625  rDo.GetInf().SetOut( *pOutSize );
626  Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
627  nKana += rDo.GetInf().GetKanaDiff();
628  rDo.GetInf().SetOut( *pOldOut );
629  if( nTmpKern && nPos < nMaxPos )
630  aPartSize.AdjustWidth(nTmpKern );
631  rDo.GetInf().SetSize( aPartSize );
632  rDo.Do();
633  nOldPos = nPos;
634  }
635  nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->nextCharBlock(
636  oldText, sal_Int32(nPos),
637  g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
638  if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
639  nPos = nMaxPos;
640  OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
641 #if OSL_DEBUG_LEVEL > 1
642  if( !nPos )
643  nPos = nMaxPos;
644 #endif
645  // The upper ones...
646  if( nOldPos != nPos )
647  {
648  const tools::Long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
649 
650  do
651  {
652  rDo.GetInf().SetUpper( true );
653  pLastFont = pBigFont;
654  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
655  TextFrameIndex nTmp;
656  if( bWordWise )
657  {
658  nTmp = nOldPos;
659  while (nTmp < nPos && CH_BLANK == oldText[sal_Int32(nTmp)])
660  ++nTmp;
661  if( nOldPos < nTmp )
662  {
663  pLastFont = pSpaceFont;
665  rDo.GetOut() );
666  static_cast<SwDoDrawCapital&>(rDo).DrawSpace( aStartPos );
667  pLastFont = pBigFont;
669  rDo.GetOut() );
670 
671  // #107816#, #i14820#
672  if( bCaseMapLengthDiffers )
673  {
674  // Build an own 'changed' string for the given part of the
675  // source string and use it. That new string may differ in length
676  // from the source string.
677  const OUString aNewText = CalcCaseMap(
678  oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
679  aCapInf.nIdx = nOldPos;
680  aCapInf.nLen = nTmp - nOldPos;
681  rDo.GetInf().SetIdx(TextFrameIndex(0));
682  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
683  rDo.GetInf().SetText( aNewText );
684  }
685  else
686  {
687  rDo.GetInf().SetIdx( nOldPos );
688  rDo.GetInf().SetLen( nTmp - nOldPos );
689  }
690 
691  rDo.GetInf().SetOut( *pOutSize );
692  Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
693  nKana += rDo.GetInf().GetKanaDiff();
694  rDo.GetInf().SetOut( *pOldOut );
695  if( nSpaceAdd )
696  aPartSize.AdjustWidth(nSpaceAdd * sal_Int32(nTmp - nOldPos));
697  if( nTmpKern && nPos < nMaxPos )
698  aPartSize.AdjustWidth(nTmpKern );
699  rDo.GetInf().SetSize( aPartSize );
700  rDo.Do();
701  aStartPos = rDo.GetInf().GetPos();
702  nOldPos = nTmp;
703  }
704 
705  while (nTmp < nPos && CH_BLANK != oldText[sal_Int32(nTmp)])
706  ++nTmp;
707  }
708  else
709  nTmp = nPos;
710  if( nTmp > nOldPos )
711  {
712  // #107816#, #i14820#
713  if( bCaseMapLengthDiffers )
714  {
715  // Build an own 'changed' string for the given part of the
716  // source string and use it. That new string may differ in length
717  // from the source string.
718  const OUString aNewText = CalcCaseMap(
719  oldText.copy(sal_Int32(nOldPos), sal_Int32(nTmp-nOldPos)));
720  aCapInf.nIdx = nOldPos;
721  aCapInf.nLen = nTmp - nOldPos;
722  rDo.GetInf().SetIdx(TextFrameIndex(0));
723  rDo.GetInf().SetLen(TextFrameIndex(aNewText.getLength()));
724  rDo.GetInf().SetText( aNewText );
725  }
726  else
727  {
728  rDo.GetInf().SetIdx( nOldPos );
729  rDo.GetInf().SetLen( nTmp - nOldPos );
730  }
731 
732  rDo.GetInf().SetOut( *pOutSize );
733  Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
734  nKana += rDo.GetInf().GetKanaDiff();
735  rDo.GetInf().SetOut( *pOldOut );
736  if( !bWordWise && rDo.GetInf().GetSpace() )
737  {
738  for (TextFrameIndex nI = nOldPos; nI < nPos; ++nI)
739  {
740  if (CH_BLANK == oldText[sal_Int32(nI)])
741  aPartSize.AdjustWidth(nSpaceAdd );
742  }
743  }
744  if( nTmpKern && nPos < nMaxPos )
745  aPartSize.AdjustWidth(nTmpKern );
746  rDo.GetInf().SetSize( aPartSize );
747  rDo.Do();
748  nOldPos = nTmp;
749  }
750  } while( nOldPos != nPos );
751  }
752  nPos = TextFrameIndex(g_pBreakIt->GetBreakIter()->endOfCharBlock(
753  oldText, sal_Int32(nPos),
754  g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER));
755  if (nPos < TextFrameIndex(0) || nPos > nMaxPos)
756  nPos = nMaxPos;
757  OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
758 #if OSL_DEBUG_LEVEL > 1
759  if( !nPos )
760  nPos = nMaxPos;
761 #endif
762  }
763 
764  // clean up:
765  if( pBigFont != pOldLast )
766  pBigFontAccess.reset();
767 
768  if( bTextLines )
769  {
770  if( rDo.GetInf().GetDrawSpace() )
771  {
772  pLastFont = pSpaceFont;
773  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
774  static_cast<SwDoDrawCapital&>( rDo ).DrawSpace( aStartPos );
775  }
776  if ( bWordWise )
777  pSpaceFontAccess.reset();
778  }
779  pLastFont = pOldLast;
780  pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
781 
782  pSmallFontAccess.reset();
783  rDo.GetInf().SetText(oldText);
784  rDo.GetInf().SetKanaDiff( nKana );
785 }
786 
787 /* 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:66
SwDrawTextInfo & rInf
Definition: fntcap.cxx:95
SwViewShell const * GetShell() const
Definition: drawfont.hxx:175
sal_uInt8 GetPropr() const
short CheckKerning()
Definition: swfont.hxx:320
SwCapitalInfo * pCapInf
Definition: fntcap.cxx:96
vcl::RenderContext * GetpOut() const
Definition: drawfont.hxx:185
bool m_bSmallCapsPercentage66
Definition: swfont.hxx:62
TextFrameIndex GetCapitalCursorOfst(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:402
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:321
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
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:476
#define LANGUAGE_SYSTEM
ComplexTextLayoutFlags
Size GetCapitalSize(SwDrawTextInfo &rInf)
Definition: fntcap.cxx:138
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:220
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:678
LanguageType GetLanguage() const
Definition: swfont.hxx:279
void DoOnCapitals(SwDoCapitals &rDo)
Definition: fntcap.cxx:494
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
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...
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
sal_uInt16 nPos
Size GetTextSize(SwDrawTextInfo &rInf)
determine the TextSize (of the printer)
Definition: fntcache.cxx:1918
virtual void Do()=0
SwDoCapitals(SwDrawTextInfo &rInfo)
Definition: fntcap.cxx:98
short CheckKerning()
Definition: swfont.hxx:112