bump product version to 5.0.4.1
[LibreOffice.git] / editeng / source / items / svxfont.cxx
blob7de20d1eed9dbc2065326e6bf90df5fec6a92f4c
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 <comphelper/string.hxx>
21 #include <vcl/outdev.hxx>
22 #include <vcl/print.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>
31 const sal_Unicode CH_BLANK = ' '; // ' ' Space character
34 SvxFont::SvxFont()
36 nKern = nEsc = 0;
37 nPropr = 100;
38 eCaseMap = SVX_CASEMAP_NOT_MAPPED;
39 SetLanguage(LANGUAGE_SYSTEM);
42 SvxFont::SvxFont( const vcl::Font &rFont )
43 : Font( rFont )
45 nKern = nEsc = 0;
46 nPropr = 100;
47 eCaseMap = SVX_CASEMAP_NOT_MAPPED;
48 SetLanguage(LANGUAGE_SYSTEM);
51 SvxFont::SvxFont( const SvxFont &rFont )
52 : Font( rFont )
54 nKern = rFont.GetFixKerning();
55 nEsc = rFont.GetEscapement();
56 nPropr = rFont.GetPropr();
57 eCaseMap = rFont.GetCaseMap();
58 SetLanguage(rFont.GetLanguage());
61 void SvxFont::DrawArrow( OutputDevice &rOut, const Rectangle& rRect,
62 const Size& rSize, const Color& rCol, bool bLeft )
64 long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2;
65 long nRight = nLeft + rSize.Width();
66 long nMid = ( rRect.Top() + rRect.Bottom() ) / 2;
67 long nTop = nMid - rSize.Height() / 2;
68 long nBottom = nTop + rSize.Height();
69 if( nLeft < rRect.Left() )
71 nLeft = rRect.Left();
72 nRight = rRect.Right();
74 if( nTop < rRect.Top() )
76 nTop = rRect.Top();
77 nBottom = rRect.Bottom();
79 Polygon aPoly;
80 Point aTmp( bLeft ? nLeft : nRight, nMid );
81 Point aNxt( bLeft ? nRight : nLeft, nTop );
82 aPoly.Insert( 0, aTmp );
83 aPoly.Insert( 0, aNxt );
84 aNxt.Y() = nBottom;
85 aPoly.Insert( 0, aNxt );
86 aPoly.Insert( 0, aTmp );
87 Color aOldLineColor = rOut.GetLineColor();
88 Color aOldFillColor = rOut.GetFillColor();
89 rOut.SetFillColor( rCol );
90 rOut.SetLineColor( Color( COL_BLACK ) );
91 rOut.DrawPolygon( aPoly );
92 rOut.DrawLine( aTmp, aNxt );
93 rOut.SetLineColor( aOldLineColor );
94 rOut.SetFillColor( aOldFillColor );
98 OUString SvxFont::CalcCaseMap(const OUString &rTxt) const
100 if (!IsCaseMap() || rTxt.isEmpty())
101 return rTxt;
102 OUString aTxt(rTxt);
103 // I still have to get the language
104 const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage()
105 ? LANGUAGE_SYSTEM : GetLanguage();
107 LanguageTag aLanguageTag(eLang);
108 CharClass aCharClass( aLanguageTag );
110 switch( eCaseMap )
112 case SVX_CASEMAP_KAPITAELCHEN:
113 case SVX_CASEMAP_VERSALIEN:
115 aTxt = aCharClass.uppercase( aTxt );
116 break;
119 case SVX_CASEMAP_GEMEINE:
121 aTxt = aCharClass.lowercase( aTxt );
122 break;
124 case SVX_CASEMAP_TITEL:
126 // Every beginning of a word is capitalized, the rest of the word
127 // is taken over as is.
128 // Bug: if the attribute starts in the middle of the word.
129 bool bBlank = true;
131 for (sal_Int32 i = 0; i < aTxt.getLength(); ++i)
133 if( aTxt[i] == ' ' || aTxt[i] == '\t')
134 bBlank = true;
135 else
137 if (bBlank)
139 OUString sTitle(aCharClass.uppercase(OUString(aTxt[i])));
140 aTxt = aTxt.replaceAt(i, 1, sTitle);
142 bBlank = false;
145 break;
147 default:
149 DBG_ASSERT(false, "SvxFont::CaseMapTxt: unknown casemap");
150 break;
153 return aTxt;
156 /*************************************************************************
157 * class SvxDoCapitals
158 * The virtual Method Do si called by SvxFont::DoOnCapitals alternately
159 * the uppercase and lowercase parts. The derivate of SvxDoCapitals fills
160 * this method with life.
161 *************************************************************************/
163 class SvxDoCapitals
165 protected:
166 VclPtr<OutputDevice> pOut;
167 const OUString &rTxt;
168 const sal_Int32 nIdx;
169 const sal_Int32 nLen;
171 public:
172 SvxDoCapitals( OutputDevice *_pOut, const OUString &_rTxt,
173 const sal_Int32 _nIdx, const sal_Int32 _nLen )
174 : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen)
177 virtual ~SvxDoCapitals() {}
179 virtual void DoSpace( const bool bDraw );
180 virtual void SetSpace();
181 virtual void Do( const OUString &rTxt,
182 const sal_Int32 nIdx, const sal_Int32 nLen,
183 const bool bUpper ) = 0;
185 const OUString &GetTxt() const { return rTxt; }
186 sal_Int32 GetIdx() const { return nIdx; }
187 sal_Int32 GetLen() const { return nLen; }
190 void SvxDoCapitals::DoSpace( const bool /*bDraw*/ ) { }
192 void SvxDoCapitals::SetSpace() { }
194 /*************************************************************************
195 * SvxFont::DoOnCapitals() const
196 * Decomposes the String into uppercase and lowercase letters and then
197 * calls the method SvxDoCapitals::Do( ).
198 *************************************************************************/
200 void SvxFont::DoOnCapitals(SvxDoCapitals &rDo) const
202 const OUString &rTxt = rDo.GetTxt();
203 const sal_Int32 nIdx = rDo.GetIdx();
204 const sal_Int32 nLen = rDo.GetLen();
206 const OUString aTxt( CalcCaseMap( rTxt ) );
207 const sal_Int32 nTxtLen = std::min( rTxt.getLength(), nLen );
208 sal_Int32 nPos = 0;
209 sal_Int32 nOldPos = nPos;
211 // #108210#
212 // Test if string length differ between original and CaseMapped
213 bool bCaseMapLengthDiffers(aTxt.getLength() != rTxt.getLength());
215 const LanguageType eLang = LANGUAGE_DONTKNOW == GetLanguage()
216 ? LANGUAGE_SYSTEM : GetLanguage();
218 LanguageTag aLanguageTag(eLang);
219 CharClass aCharClass( aLanguageTag );
220 OUString aCharString;
222 while( nPos < nTxtLen )
224 // first in turn are the uppercase letters
226 // There are characters that are both upper- and lower-case L (eg blank)
227 // Such ambiguities lead to chaos, this is why these characters are
228 // allocated to the lowercase characters!
230 while( nPos < nTxtLen )
232 aCharString = rTxt.copy( nPos + nIdx, 1 );
233 sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
234 if ( nCharacterType & ::com::sun::star::i18n::KCharacterType::LOWER )
235 break;
236 if ( ! ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
237 break;
238 ++nPos;
240 if( nOldPos != nPos )
242 if(bCaseMapLengthDiffers)
244 // #108210#
245 // If strings differ work preparing the necessary snippet to address that
246 // potential difference
247 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos-nOldPos);
248 OUString aNewText = CalcCaseMap(aSnippet);
250 rDo.Do( aNewText, 0, aNewText.getLength(), true );
252 else
254 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, true );
257 nOldPos = nPos;
259 // Now the lowercase are processed (without blanks)
260 while( nPos < nTxtLen )
262 sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
263 if ( ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
264 break;
265 if ( comphelper::string::equals(aCharString, CH_BLANK) )
266 break;
267 if( ++nPos < nTxtLen )
268 aCharString = rTxt.copy( nPos + nIdx, 1 );
270 if( nOldPos != nPos )
272 if(bCaseMapLengthDiffers)
274 // #108210#
275 // If strings differ work preparing the necessary snippet to address that
276 // potential difference
277 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos);
278 OUString aNewText = CalcCaseMap(aSnippet);
280 rDo.Do( aNewText, 0, aNewText.getLength(), false );
282 else
284 rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, false );
287 nOldPos = nPos;
289 // Now the blanks are<processed
290 while( nPos < nTxtLen && comphelper::string::equals(aCharString, CH_BLANK) && ++nPos < nTxtLen )
291 aCharString = rTxt.copy( nPos + nIdx, 1 );
293 if( nOldPos != nPos )
295 rDo.DoSpace( false );
297 if(bCaseMapLengthDiffers)
299 // #108210#
300 // If strings differ work preparing the necessary snippet to address that
301 // potential difference
302 const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos);
303 OUString aNewText = CalcCaseMap(aSnippet);
305 rDo.Do( aNewText, 0, aNewText.getLength(), false );
307 else
309 rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, false );
312 nOldPos = nPos;
313 rDo.SetSpace();
316 rDo.DoSpace( true );
320 void SvxFont::SetPhysFont( OutputDevice *pOut ) const
322 const vcl::Font& rCurrentFont = pOut->GetFont();
323 if ( nPropr == 100 )
325 if ( !rCurrentFont.IsSameInstance( *this ) )
326 pOut->SetFont( *this );
328 else
330 Font aNewFont( *this );
331 Size aSize( aNewFont.GetSize() );
332 aNewFont.SetSize( Size( aSize.Width() * nPropr / 100L,
333 aSize.Height() * nPropr / 100L ) );
334 if ( !rCurrentFont.IsSameInstance( aNewFont ) )
335 pOut->SetFont( aNewFont );
340 vcl::Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const
342 vcl::Font aOldFont( pOut->GetFont() );
343 SetPhysFont( pOut );
344 return aOldFont;
348 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt,
349 const sal_Int32 nIdx, const sal_Int32 nLen ) const
351 if ( !IsCaseMap() && !IsKern() )
352 return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ),
353 pOut->GetTextHeight() );
355 Size aTxtSize;
356 aTxtSize.setHeight( pOut->GetTextHeight() );
357 if ( !IsCaseMap() )
358 aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) );
359 else
361 // #108210#
362 const OUString aNewText = CalcCaseMap(rTxt);
363 bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength());
364 sal_Int32 nWidth(0L);
366 if(bCaseMapLengthDiffers)
368 // If strings differ work preparing the necessary snippet to address that
369 // potential difference
370 const OUString aSnippet = rTxt.copy(nIdx, nLen);
371 OUString _aNewText = CalcCaseMap(aSnippet);
372 nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.getLength() );
374 else
376 nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen );
379 aTxtSize.setWidth(nWidth);
382 if( IsKern() && ( nLen > 1 ) )
383 aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
385 return aTxtSize;
388 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt )
390 if ( !IsCaseMap() && !IsKern() )
391 return Size( pOut->GetTextWidth( rTxt ), pOut->GetTextHeight() );
393 Size aTxtSize;
394 aTxtSize.setHeight( pOut->GetTextHeight() );
395 if ( !IsCaseMap() )
396 aTxtSize.setWidth( pOut->GetTextWidth( rTxt ) );
397 else
398 aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( rTxt ) ) );
400 if( IsKern() && ( rTxt.getLength() > 1 ) )
401 aTxtSize.Width() += ( ( rTxt.getLength()-1 ) * long( nKern ) );
403 return aTxtSize;
406 Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
407 const sal_Int32 nIdx, const sal_Int32 nLen, long* pDXArray ) const
409 if ( !IsCaseMap() && !IsKern() )
410 return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ),
411 pOut->GetTextHeight() );
413 Size aTxtSize;
414 aTxtSize.setHeight( pOut->GetTextHeight() );
415 if ( !IsCaseMap() )
416 aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) );
417 else
418 aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ),
419 pDXArray, nIdx, nLen ) );
421 if( IsKern() && ( nLen > 1 ) )
423 aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
425 if ( pDXArray )
427 for ( sal_Int32 i = 0; i < nLen; i++ )
428 pDXArray[i] += ( (i+1) * long( nKern ) );
429 // The last one is a nKern too big:
430 pDXArray[nLen-1] -= nKern;
433 return aTxtSize;
437 Size SvxFont::GetTextSize( const OutputDevice *pOut, const OUString &rTxt,
438 const sal_Int32 nIdx, const sal_Int32 nLen ) const
440 sal_Int32 nTmp = nLen;
441 if ( nTmp == SAL_MAX_INT32 ) // already initialized?
442 nTmp = rTxt.getLength();
443 Font aOldFont( ChgPhysFont(const_cast<OutputDevice *>(pOut)) );
444 Size aTxtSize;
445 if( IsCapital() && !rTxt.isEmpty() )
447 aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp );
449 else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp);
450 const_cast<OutputDevice *>(pOut)->SetFont( aOldFont );
451 return aTxtSize;
455 void SvxFont::QuickDrawText( OutputDevice *pOut,
456 const Point &rPos, const OUString &rTxt,
457 const sal_Int32 nIdx, const sal_Int32 nLen, const long* pDXArray ) const
460 // Font has to be selected in OutputDevice...
461 if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
463 pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen );
464 return;
467 Point aPos( rPos );
469 if ( nEsc )
471 long nDiff = GetSize().Height();
472 nDiff *= nEsc;
473 nDiff /= 100;
475 if ( !IsVertical() )
476 aPos.Y() -= nDiff;
477 else
478 aPos.X() += nDiff;
481 if( IsCapital() )
483 DBG_ASSERT( !pDXArray, "DrawCapital not for TextArray!" );
484 DrawCapital( pOut, aPos, rTxt, nIdx, nLen );
486 else
488 if ( IsKern() && !pDXArray )
490 Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen );
492 if ( !IsCaseMap() )
493 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen );
494 else
495 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen );
497 else
499 if ( !IsCaseMap() )
500 pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen );
501 else
502 pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
508 void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter,
509 const Point &rPos, const OUString &rTxt,
510 const sal_Int32 nIdx, const sal_Int32 nLen ) const
512 if ( !nLen || rTxt.isEmpty() )
513 return;
514 sal_Int32 nTmp = nLen;
516 if ( nTmp == SAL_MAX_INT32 ) // already initialized?
517 nTmp = rTxt.getLength();
518 Point aPos( rPos );
520 if ( nEsc )
522 short nTmpEsc;
523 if( DFLT_ESC_AUTO_SUPER == nEsc )
524 nTmpEsc = 33;
525 else if( DFLT_ESC_AUTO_SUB == nEsc )
526 nTmpEsc = -20;
527 else
528 nTmpEsc = nEsc;
529 Size aSize = ( this->GetSize() );
530 aPos.Y() -= ( ( nTmpEsc * long( aSize.Height() ) ) / 100L );
532 Font aOldFont( ChgPhysFont( pOut ) );
533 Font aOldPrnFont( ChgPhysFont( pPrinter ) );
535 if ( IsCapital() )
536 DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
537 else
539 Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp );
541 if ( !IsCaseMap() )
542 pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
543 else
545 // #108210#
546 const OUString aNewText = CalcCaseMap(rTxt);
547 bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength());
549 if(bCaseMapLengthDiffers)
551 // If strings differ work preparing the necessary snippet to address that
552 // potential difference
553 const OUString aSnippet(rTxt.copy( nIdx, nTmp));
554 OUString _aNewText = CalcCaseMap(aSnippet);
556 pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.getLength() );
558 else
560 pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp );
564 pOut->SetFont(aOldFont);
565 pPrinter->SetFont( aOldPrnFont );
569 SvxFont& SvxFont::operator=( const vcl::Font& rFont )
571 Font::operator=( rFont );
572 return *this;
575 SvxFont& SvxFont::operator=( const SvxFont& rFont )
577 Font::operator=( rFont );
578 eCaseMap = rFont.eCaseMap;
579 nEsc = rFont.nEsc;
580 nPropr = rFont.nPropr;
581 nKern = rFont.nKern;
582 return *this;
585 class SvxDoGetCapitalSize : public SvxDoCapitals
587 protected:
588 SvxFont* pFont;
589 Size aTxtSize;
590 short nKern;
591 public:
592 SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut,
593 const OUString &_rTxt, const sal_Int32 _nIdx,
594 const sal_Int32 _nLen, const short _nKrn )
595 : SvxDoCapitals( const_cast<OutputDevice*>(_pOut), _rTxt, _nIdx, _nLen ),
596 pFont( _pFnt ),
597 nKern( _nKrn )
600 virtual ~SvxDoGetCapitalSize() {}
602 virtual void Do( const OUString &rTxt, const sal_Int32 nIdx,
603 const sal_Int32 nLen, const bool bUpper ) SAL_OVERRIDE;
605 const Size &GetSize() const { return aTxtSize; };
608 void SvxDoGetCapitalSize::Do( const OUString &_rTxt, const sal_Int32 _nIdx,
609 const sal_Int32 _nLen, const bool bUpper )
611 Size aPartSize;
612 if ( !bUpper )
614 sal_uInt8 nProp = pFont->GetPropr();
615 pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
616 pFont->SetPhysFont( pOut );
617 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
618 aPartSize.setHeight( pOut->GetTextHeight() );
619 aTxtSize.Height() = aPartSize.Height();
620 pFont->SetPropr( nProp );
621 pFont->SetPhysFont( pOut );
623 else
625 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
626 aPartSize.setHeight( pOut->GetTextHeight() );
628 aTxtSize.Width() += aPartSize.Width();
629 aTxtSize.Width() += ( _nLen * long( nKern ) );
632 Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const OUString &rTxt,
633 const sal_Int32 nIdx, const sal_Int32 nLen) const
635 // Start:
636 SvxDoGetCapitalSize aDo( const_cast<SvxFont *>(this), pOut, rTxt, nIdx, nLen, nKern );
637 DoOnCapitals( aDo );
638 Size aTxtSize( aDo.GetSize() );
640 // End:
641 if( !aTxtSize.Height() )
643 aTxtSize.setWidth( 0 );
644 aTxtSize.setHeight( pOut->GetTextHeight() );
646 return aTxtSize;
649 class SvxDoDrawCapital : public SvxDoCapitals
651 protected:
652 SvxFont *pFont;
653 Point aPos;
654 Point aSpacePos;
655 short nKern;
656 public:
657 SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const OUString &_rTxt,
658 const sal_Int32 _nIdx, const sal_Int32 _nLen,
659 const Point &rPos, const short nKrn )
660 : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ),
661 pFont( pFnt ),
662 aPos( rPos ),
663 aSpacePos( rPos ),
664 nKern( nKrn )
666 virtual void DoSpace( const bool bDraw ) SAL_OVERRIDE;
667 virtual void SetSpace() SAL_OVERRIDE;
668 virtual void Do( const OUString &rTxt, const sal_Int32 nIdx,
669 const sal_Int32 nLen, const bool bUpper ) SAL_OVERRIDE;
672 void SvxDoDrawCapital::DoSpace( const bool bDraw )
674 if ( bDraw || pFont->IsWordLineMode() )
676 sal_uLong nDiff = (sal_uLong)(aPos.X() - aSpacePos.X());
677 if ( nDiff )
679 bool bWordWise = pFont->IsWordLineMode();
680 bool bTrans = pFont->IsTransparent();
681 pFont->SetWordLineMode( false );
682 pFont->SetTransparent( true );
683 pFont->SetPhysFont( pOut );
684 pOut->DrawStretchText( aSpacePos, nDiff, " ", 0, 2 );
685 pFont->SetWordLineMode( bWordWise );
686 pFont->SetTransparent( bTrans );
687 pFont->SetPhysFont( pOut );
692 void SvxDoDrawCapital::SetSpace()
694 if ( pFont->IsWordLineMode() )
695 aSpacePos.X() = aPos.X();
698 void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx,
699 const sal_Int32 _nLen, const bool bUpper)
701 sal_uInt8 nProp = 0;
702 Size aPartSize;
704 // Set the desired font
705 FontUnderline eUnder = pFont->GetUnderline();
706 FontStrikeout eStrike = pFont->GetStrikeout();
707 pFont->SetUnderline( UNDERLINE_NONE );
708 pFont->SetStrikeout( STRIKEOUT_NONE );
709 if ( !bUpper )
711 nProp = pFont->GetPropr();
712 pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
714 pFont->SetPhysFont( pOut );
716 aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
717 aPartSize.setHeight( pOut->GetTextHeight() );
718 long nWidth = aPartSize.Width();
719 if ( nKern )
721 aPos.X() += (nKern/2);
722 if ( _nLen ) nWidth += (_nLen*long(nKern));
724 pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen);
726 // Restore Font
727 pFont->SetUnderline( eUnder );
728 pFont->SetStrikeout( eStrike );
729 if ( !bUpper )
730 pFont->SetPropr( nProp );
731 pFont->SetPhysFont( pOut );
733 aPos.X() += nWidth-(nKern/2);
736 /*************************************************************************
737 * SvxFont::DrawCapital() draws the uppercase letter.
738 *************************************************************************/
740 void SvxFont::DrawCapital( OutputDevice *pOut,
741 const Point &rPos, const OUString &rTxt,
742 const sal_Int32 nIdx, const sal_Int32 nLen ) const
744 SvxDoDrawCapital aDo( const_cast<SvxFont *>(this),pOut,rTxt,nIdx,nLen,rPos,nKern );
745 DoOnCapitals( aDo );
748 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */