bump product version to 6.3.0.0.beta1
[LibreOffice.git] / editeng / source / items / svxfont.cxx
blob2f9119a0f143ddd2540bcd0c69ca6b77a9122853
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 <vcl/outdev.hxx>
21 #include <vcl/print.hxx>
22 #include <tools/debug.hxx>
23 #include <tools/gen.hxx>
24 #include <tools/poly.hxx>
25 #include <unotools/charclass.hxx>
26 #include <editeng/unolingu.hxx>
27 #include <com/sun/star/i18n/KCharacterType.hpp>
28 #include <editeng/svxfont.hxx>
29 #include <editeng/escapementitem.hxx>
30 #include <sal/log.hxx>
32 SvxFont::SvxFont()
34 nKern = nEsc = 0;
35 nPropr = 100;
36 eCaseMap = SvxCaseMap::NotMapped;
37 SetLanguage(LANGUAGE_SYSTEM);
40 SvxFont::SvxFont( const vcl::Font &rFont )
41 : Font( rFont )
43 nKern = nEsc = 0;
44 nPropr = 100;
45 eCaseMap = SvxCaseMap::NotMapped;
46 SetLanguage(LANGUAGE_SYSTEM);
49 SvxFont::SvxFont( const SvxFont &rFont )
50 : Font( rFont )
52 nKern = rFont.GetFixKerning();
53 nEsc = rFont.GetEscapement();
54 nPropr = rFont.GetPropr();
55 eCaseMap = rFont.GetCaseMap();
56 SetLanguage(rFont.GetLanguage());
59 void SvxFont::DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect,
60 const Size& rSize, const Color& rCol, bool bLeft )
62 long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2;
63 long nRight = nLeft + rSize.Width();
64 long nMid = ( rRect.Top() + rRect.Bottom() ) / 2;
65 long nTop = nMid - rSize.Height() / 2;
66 long nBottom = nTop + rSize.Height();
67 if( nLeft < rRect.Left() )
69 nLeft = rRect.Left();
70 nRight = rRect.Right();
72 if( nTop < rRect.Top() )
74 nTop = rRect.Top();
75 nBottom = rRect.Bottom();
77 tools::Polygon aPoly;
78 Point aTmp( bLeft ? nLeft : nRight, nMid );
79 Point aNxt( bLeft ? nRight : nLeft, nTop );
80 aPoly.Insert( 0, aTmp );
81 aPoly.Insert( 0, aNxt );
82 aNxt.setY( nBottom );
83 aPoly.Insert( 0, aNxt );
84 aPoly.Insert( 0, aTmp );
85 Color aOldLineColor = rOut.GetLineColor();
86 Color aOldFillColor = rOut.GetFillColor();
87 rOut.SetFillColor( rCol );
88 rOut.SetLineColor( COL_BLACK );
89 rOut.DrawPolygon( aPoly );
90 rOut.DrawLine( aTmp, aNxt );
91 rOut.SetLineColor( aOldLineColor );
92 rOut.SetFillColor( aOldFillColor );
96 OUString SvxFont::CalcCaseMap(const OUString &rTxt) const
98 if (!IsCaseMap() || rTxt.isEmpty())
99 return rTxt;
100 OUString aTxt(rTxt);
101 // I still have to get the language
102 const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage()
103 ? LANGUAGE_SYSTEM : GetLanguage();
105 LanguageTag aLanguageTag(eLang);
106 CharClass aCharClass( aLanguageTag );
108 switch( eCaseMap )
110 case SvxCaseMap::SmallCaps:
111 case SvxCaseMap::Uppercase:
113 aTxt = aCharClass.uppercase( aTxt );
114 break;
117 case SvxCaseMap::Lowercase:
119 aTxt = aCharClass.lowercase( aTxt );
120 break;
122 case SvxCaseMap::Capitalize:
124 // Every beginning of a word is capitalized, the rest of the word
125 // is taken over as is.
126 // Bug: if the attribute starts in the middle of the word.
127 bool bBlank = true;
129 for (sal_Int32 i = 0; i < aTxt.getLength(); ++i)
131 if( aTxt[i] == ' ' || aTxt[i] == '\t')
132 bBlank = true;
133 else
135 if (bBlank)
137 OUString sTitle(aCharClass.uppercase(OUString(aTxt[i])));
138 aTxt = aTxt.replaceAt(i, 1, sTitle);
140 bBlank = false;
143 break;
145 default:
147 SAL_WARN( "editeng", "SvxFont::CaseMapTxt: unknown casemap");
148 break;
151 return aTxt;
154 /*************************************************************************
155 * class SvxDoCapitals
156 * The virtual Method Do si called by SvxFont::DoOnCapitals alternately
157 * the uppercase and lowercase parts. The derivate of SvxDoCapitals fills
158 * this method with life.
159 *************************************************************************/
161 class SvxDoCapitals
163 protected:
164 VclPtr<OutputDevice> pOut;
165 const OUString &rTxt;
166 const sal_Int32 nIdx;
167 const sal_Int32 nLen;
169 public:
170 SvxDoCapitals( OutputDevice *_pOut, const OUString &_rTxt,
171 const sal_Int32 _nIdx, const sal_Int32 _nLen )
172 : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen)
175 virtual ~SvxDoCapitals() {}
177 virtual void DoSpace( const bool bDraw );
178 virtual void SetSpace();
179 virtual void Do( const OUString &rTxt,
180 const sal_Int32 nIdx, const sal_Int32 nLen,
181 const bool bUpper ) = 0;
183 const OUString &GetTxt() const { return rTxt; }
184 sal_Int32 GetIdx() const { return nIdx; }
185 sal_Int32 GetLen() const { return nLen; }
188 void SvxDoCapitals::DoSpace( const bool /*bDraw*/ ) { }
190 void SvxDoCapitals::SetSpace() { }
192 /*************************************************************************
193 * SvxFont::DoOnCapitals() const
194 * Decomposes the String into uppercase and lowercase letters and then
195 * calls the method SvxDoCapitals::Do( ).
196 *************************************************************************/
198 void SvxFont::DoOnCapitals(SvxDoCapitals &rDo) const
200 const OUString &rTxt = rDo.GetTxt();
201 const sal_Int32 nIdx = rDo.GetIdx();
202 const sal_Int32 nLen = rDo.GetLen();
204 const OUString aTxt( CalcCaseMap( rTxt ) );
205 const sal_Int32 nTxtLen = std::min( rTxt.getLength(), nLen );
206 sal_Int32 nPos = 0;
207 sal_Int32 nOldPos = nPos;
209 // Test if string length differ between original and CaseMapped
210 bool bCaseMapLengthDiffers(aTxt.getLength() != rTxt.getLength());
212 const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage()
213 ? LANGUAGE_SYSTEM : GetLanguage();
215 LanguageTag aLanguageTag(eLang);
216 CharClass aCharClass( aLanguageTag );
217 OUString aCharString;
219 while( nPos < nTxtLen )
221 // first in turn are the uppercase letters
223 // There are characters that are both upper- and lower-case L (eg blank)
224 // Such ambiguities lead to chaos, this is why these characters are
225 // allocated to the lowercase characters!
227 while( nPos < nTxtLen )
229 aCharString = rTxt.copy( nPos + nIdx, 1 );
230 sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
231 if ( nCharacterType & css::i18n::KCharacterType::LOWER )
232 break;
233 if ( ! ( nCharacterType & css::i18n::KCharacterType::UPPER ) )
234 break;
235 ++nPos;
237 if( nOldPos != nPos )
239 if(bCaseMapLengthDiffers)
241 // If strings differ work preparing the necessary snippet to address that
242 // potential difference
243 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos-nOldPos);
244 OUString aNewText = CalcCaseMap(aSnippet);
246 rDo.Do( aNewText, 0, aNewText.getLength(), true );
248 else
250 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, true );
253 nOldPos = nPos;
255 // Now the lowercase are processed (without blanks)
256 while( nPos < nTxtLen )
258 sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
259 if ( nCharacterType & css::i18n::KCharacterType::UPPER )
260 break;
261 if ( aCharString == " " )
262 break;
263 if( ++nPos < nTxtLen )
264 aCharString = rTxt.copy( nPos + nIdx, 1 );
266 if( nOldPos != nPos )
268 if(bCaseMapLengthDiffers)
270 // If strings differ work preparing the necessary snippet to address that
271 // potential difference
272 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos);
273 OUString aNewText = CalcCaseMap(aSnippet);
275 rDo.Do( aNewText, 0, aNewText.getLength(), false );
277 else
279 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, false );
282 nOldPos = nPos;
284 // Now the blanks are<processed
285 while( nPos < nTxtLen && aCharString == " " && ++nPos < nTxtLen )
286 aCharString = rTxt.copy( nPos + nIdx, 1 );
288 if( nOldPos != nPos )
290 rDo.DoSpace( false );
292 if(bCaseMapLengthDiffers)
294 // If strings differ work preparing the necessary snippet to address that
295 // potential difference
296 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos);
297 OUString aNewText = CalcCaseMap(aSnippet);
299 rDo.Do( aNewText, 0, aNewText.getLength(), false );
301 else
303 rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, false );
306 nOldPos = nPos;
307 rDo.SetSpace();
310 rDo.DoSpace( true );
314 void SvxFont::SetPhysFont( OutputDevice *pOut ) const
316 const vcl::Font& rCurrentFont = pOut->GetFont();
317 if ( nPropr == 100 )
319 if ( !rCurrentFont.IsSameInstance( *this ) )
320 pOut->SetFont( *this );
322 else
324 Font aNewFont( *this );
325 Size aSize( aNewFont.GetFontSize() );
326 aNewFont.SetFontSize( Size( aSize.Width() * nPropr / 100,
327 aSize.Height() * nPropr / 100 ) );
328 if ( !rCurrentFont.IsSameInstance( aNewFont ) )
329 pOut->SetFont( aNewFont );
334 vcl::Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const
336 vcl::Font aOldFont( pOut->GetFont() );
337 SetPhysFont( pOut );
338 return aOldFont;
342 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt,
343 const sal_Int32 nIdx, const sal_Int32 nLen ) const
345 if ( !IsCaseMap() && !IsKern() )
346 return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ),
347 pOut->GetTextHeight() );
349 Size aTxtSize;
350 aTxtSize.setHeight( pOut->GetTextHeight() );
351 if ( !IsCaseMap() )
352 aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) );
353 else
355 const OUString aNewText = CalcCaseMap(rTxt);
356 bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength());
357 sal_Int32 nWidth(0);
359 if(bCaseMapLengthDiffers)
361 // If strings differ work preparing the necessary snippet to address that
362 // potential difference
363 const OUString aSnippet = rTxt.copy(nIdx, nLen);
364 OUString _aNewText = CalcCaseMap(aSnippet);
365 nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.getLength() );
367 else
369 nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen );
372 aTxtSize.setWidth(nWidth);
375 if( IsKern() && ( nLen > 1 ) )
376 aTxtSize.AdjustWidth( ( nLen-1 ) * long( nKern ) );
378 return aTxtSize;
381 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut )
383 if ( !IsCaseMap() && !IsKern() )
384 return Size( pOut->GetTextWidth( "" ), pOut->GetTextHeight() );
386 Size aTxtSize;
387 aTxtSize.setHeight( pOut->GetTextHeight() );
388 if ( !IsCaseMap() )
389 aTxtSize.setWidth( pOut->GetTextWidth( "" ) );
390 else
391 aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( "" ) ) );
393 return aTxtSize;
396 Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
397 const sal_Int32 nIdx, const sal_Int32 nLen, long* pDXArray ) const
399 if ( !IsCaseMap() && !IsKern() )
400 return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ),
401 pOut->GetTextHeight() );
403 Size aTxtSize;
404 aTxtSize.setHeight( pOut->GetTextHeight() );
405 if ( !IsCaseMap() )
406 aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) );
407 else
408 aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ),
409 pDXArray, nIdx, nLen ) );
411 if( IsKern() && ( nLen > 1 ) )
413 aTxtSize.AdjustWidth( ( nLen-1 ) * long( nKern ) );
415 if ( pDXArray )
417 for ( sal_Int32 i = 0; i < nLen; i++ )
418 pDXArray[i] += ( (i+1) * long( nKern ) );
419 // The last one is a nKern too big:
420 pDXArray[nLen-1] -= nKern;
423 return aTxtSize;
427 Size SvxFont::GetTextSize( const OutputDevice *pOut, const OUString &rTxt,
428 const sal_Int32 nIdx, const sal_Int32 nLen ) const
430 sal_Int32 nTmp = nLen;
431 if ( nTmp == SAL_MAX_INT32 ) // already initialized?
432 nTmp = rTxt.getLength();
433 Font aOldFont( ChgPhysFont(const_cast<OutputDevice *>(pOut)) );
434 Size aTxtSize;
435 if( IsCapital() && !rTxt.isEmpty() )
437 aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp );
439 else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp);
440 const_cast<OutputDevice *>(pOut)->SetFont( aOldFont );
441 return aTxtSize;
445 void SvxFont::QuickDrawText( OutputDevice *pOut,
446 const Point &rPos, const OUString &rTxt,
447 const sal_Int32 nIdx, const sal_Int32 nLen, const long* pDXArray ) const
450 // Font has to be selected in OutputDevice...
451 if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
453 pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen );
454 return;
457 Point aPos( rPos );
459 if ( nEsc )
461 long nDiff = GetFontSize().Height();
462 nDiff *= nEsc;
463 nDiff /= 100;
465 if ( !IsVertical() )
466 aPos.AdjustY( -nDiff );
467 else
468 aPos.AdjustX(nDiff );
471 if( IsCapital() )
473 DBG_ASSERT( !pDXArray, "DrawCapital not for TextArray!" );
474 DrawCapital( pOut, aPos, rTxt, nIdx, nLen );
476 else
478 if ( IsKern() && !pDXArray )
480 Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen );
482 if ( !IsCaseMap() )
483 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen );
484 else
485 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen );
487 else
489 if ( !IsCaseMap() )
490 pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen );
491 else
492 pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
498 void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter,
499 const Point &rPos, const OUString &rTxt,
500 const sal_Int32 nIdx, const sal_Int32 nLen ) const
502 if ( !nLen || rTxt.isEmpty() )
503 return;
504 sal_Int32 nTmp = nLen;
506 if ( nTmp == SAL_MAX_INT32 ) // already initialized?
507 nTmp = rTxt.getLength();
508 Point aPos( rPos );
510 if ( nEsc )
512 short nTmpEsc;
513 if( DFLT_ESC_AUTO_SUPER == nEsc )
514 nTmpEsc = 33;
515 else if( DFLT_ESC_AUTO_SUB == nEsc )
516 nTmpEsc = -20;
517 else
518 nTmpEsc = nEsc;
519 Size aSize = GetFontSize();
520 aPos.AdjustY( -(( nTmpEsc * aSize.Height() ) / 100) );
522 Font aOldFont( ChgPhysFont( pOut ) );
523 Font aOldPrnFont( ChgPhysFont( pPrinter ) );
525 if ( IsCapital() )
526 DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
527 else
529 Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp );
531 if ( !IsCaseMap() )
532 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
533 else
535 const OUString aNewText = CalcCaseMap(rTxt);
536 bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength());
538 if(bCaseMapLengthDiffers)
540 // If strings differ work preparing the necessary snippet to address that
541 // potential difference
542 const OUString aSnippet(rTxt.copy( nIdx, nTmp));
543 OUString _aNewText = CalcCaseMap(aSnippet);
545 pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.getLength() );
547 else
549 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp );
553 pOut->SetFont(aOldFont);
554 pPrinter->SetFont( aOldPrnFont );
558 SvxFont& SvxFont::operator=( const vcl::Font& rFont )
560 Font::operator=( rFont );
561 return *this;
564 SvxFont& SvxFont::operator=( const SvxFont& rFont )
566 Font::operator=( rFont );
567 eCaseMap = rFont.eCaseMap;
568 nEsc = rFont.nEsc;
569 nPropr = rFont.nPropr;
570 nKern = rFont.nKern;
571 return *this;
574 class SvxDoGetCapitalSize : public SvxDoCapitals
576 protected:
577 SvxFont* pFont;
578 Size aTxtSize;
579 short nKern;
580 public:
581 SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut,
582 const OUString &_rTxt, const sal_Int32 _nIdx,
583 const sal_Int32 _nLen, const short _nKrn )
584 : SvxDoCapitals( const_cast<OutputDevice*>(_pOut), _rTxt, _nIdx, _nLen ),
585 pFont( _pFnt ),
586 nKern( _nKrn )
589 virtual void Do( const OUString &rTxt, const sal_Int32 nIdx,
590 const sal_Int32 nLen, const bool bUpper ) override;
592 const Size &GetSize() const { return aTxtSize; };
595 void SvxDoGetCapitalSize::Do( const OUString &_rTxt, const sal_Int32 _nIdx,
596 const sal_Int32 _nLen, const bool bUpper )
598 Size aPartSize;
599 if ( !bUpper )
601 sal_uInt8 nProp = pFont->GetPropr();
602 pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
603 pFont->SetPhysFont( pOut );
604 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
605 aPartSize.setHeight( pOut->GetTextHeight() );
606 aTxtSize.setHeight( aPartSize.Height() );
607 pFont->SetPropr( nProp );
608 pFont->SetPhysFont( pOut );
610 else
612 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
613 aPartSize.setHeight( pOut->GetTextHeight() );
615 aTxtSize.AdjustWidth(aPartSize.Width() );
616 aTxtSize.AdjustWidth( _nLen * long( nKern ) );
619 Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const OUString &rTxt,
620 const sal_Int32 nIdx, const sal_Int32 nLen) const
622 // Start:
623 SvxDoGetCapitalSize aDo( const_cast<SvxFont *>(this), pOut, rTxt, nIdx, nLen, nKern );
624 DoOnCapitals( aDo );
625 Size aTxtSize( aDo.GetSize() );
627 // End:
628 if( !aTxtSize.Height() )
630 aTxtSize.setWidth( 0 );
631 aTxtSize.setHeight( pOut->GetTextHeight() );
633 return aTxtSize;
636 class SvxDoDrawCapital : public SvxDoCapitals
638 protected:
639 SvxFont *pFont;
640 Point aPos;
641 Point aSpacePos;
642 short nKern;
643 public:
644 SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const OUString &_rTxt,
645 const sal_Int32 _nIdx, const sal_Int32 _nLen,
646 const Point &rPos, const short nKrn )
647 : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ),
648 pFont( pFnt ),
649 aPos( rPos ),
650 aSpacePos( rPos ),
651 nKern( nKrn )
653 virtual void DoSpace( const bool bDraw ) override;
654 virtual void SetSpace() override;
655 virtual void Do( const OUString &rTxt, const sal_Int32 nIdx,
656 const sal_Int32 nLen, const bool bUpper ) override;
659 void SvxDoDrawCapital::DoSpace( const bool bDraw )
661 if ( bDraw || pFont->IsWordLineMode() )
663 sal_uLong nDiff = static_cast<sal_uLong>(aPos.X() - aSpacePos.X());
664 if ( nDiff )
666 bool bWordWise = pFont->IsWordLineMode();
667 bool bTrans = pFont->IsTransparent();
668 pFont->SetWordLineMode( false );
669 pFont->SetTransparent( true );
670 pFont->SetPhysFont( pOut );
671 pOut->DrawStretchText( aSpacePos, nDiff, " ", 0, 2 );
672 pFont->SetWordLineMode( bWordWise );
673 pFont->SetTransparent( bTrans );
674 pFont->SetPhysFont( pOut );
679 void SvxDoDrawCapital::SetSpace()
681 if ( pFont->IsWordLineMode() )
682 aSpacePos.setX( aPos.X() );
685 void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx,
686 const sal_Int32 _nLen, const bool bUpper)
688 sal_uInt8 nProp = 0;
689 Size aPartSize;
691 // Set the desired font
692 FontLineStyle eUnder = pFont->GetUnderline();
693 FontStrikeout eStrike = pFont->GetStrikeout();
694 pFont->SetUnderline( LINESTYLE_NONE );
695 pFont->SetStrikeout( STRIKEOUT_NONE );
696 if ( !bUpper )
698 nProp = pFont->GetPropr();
699 pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
701 pFont->SetPhysFont( pOut );
703 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
704 aPartSize.setHeight( pOut->GetTextHeight() );
705 long nWidth = aPartSize.Width();
706 if ( nKern )
708 aPos.AdjustX(nKern/2);
709 if ( _nLen ) nWidth += (_nLen*long(nKern));
711 pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen);
713 // Restore Font
714 pFont->SetUnderline( eUnder );
715 pFont->SetStrikeout( eStrike );
716 if ( !bUpper )
717 pFont->SetPropr( nProp );
718 pFont->SetPhysFont( pOut );
720 aPos.AdjustX(nWidth-(nKern/2) );
723 /*************************************************************************
724 * SvxFont::DrawCapital() draws the uppercase letter.
725 *************************************************************************/
727 void SvxFont::DrawCapital( OutputDevice *pOut,
728 const Point &rPos, const OUString &rTxt,
729 const sal_Int32 nIdx, const sal_Int32 nLen ) const
731 SvxDoDrawCapital aDo( const_cast<SvxFont *>(this),pOut,rTxt,nIdx,nLen,rPos,nKern );
732 DoOnCapitals( aDo );
735 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */