blob: 09ca3a9f7e1b2e4543fe95b487d55b09f88da19a [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_editeng.hxx"
// include ----------------------------------------------------------------
#include <vcl/outdev.hxx>
#include <vcl/print.hxx>
#include <tools/poly.hxx>
#include <unotools/charclass.hxx>
#include <editeng/unolingu.hxx>
#include <com/sun/star/i18n/KCharacterType.hpp>
#define _SVX_SVXFONT_CXX
#include <editeng/svxfont.hxx>
#include <editeng/escpitem.hxx>
// Minimum: Prozentwert fuers kernen
#define MINKERNPERCENT 5
// prop. Size of the small cap letters
#define KAPITAELCHENPROP 74
#ifndef REDUCEDSVXFONT
const sal_Unicode CH_BLANK = sal_Unicode(' '); // ' ' Leerzeichen
static sal_Char __READONLY_DATA sDoubleSpace[] = " ";
#endif
/*************************************************************************
* class SvxFont
*************************************************************************/
SvxFont::SvxFont()
{
nKern = nEsc = 0;
nPropr = 100;
eCaseMap = SVX_CASEMAP_NOT_MAPPED;
eLang = LANGUAGE_SYSTEM;
}
SvxFont::SvxFont( const Font &rFont )
: Font( rFont )
{
nKern = nEsc = 0;
nPropr = 100;
eCaseMap = SVX_CASEMAP_NOT_MAPPED;
eLang = LANGUAGE_SYSTEM;
}
/*************************************************************************
* class SvxFont: Copy-Ctor
*************************************************************************/
SvxFont::SvxFont( const SvxFont &rFont )
: Font( rFont )
{
nKern = rFont.GetFixKerning();
nEsc = rFont.GetEscapement();
nPropr = rFont.GetPropr();
eCaseMap = rFont.GetCaseMap();
eLang = rFont.GetLanguage();
}
/*************************************************************************
* static SvxFont::DrawArrow
*************************************************************************/
void SvxFont::DrawArrow( OutputDevice &rOut, const Rectangle& rRect,
const Size& rSize, const Color& rCol, sal_Bool bLeft )
{
long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2;
long nRight = nLeft + rSize.Width();
long nMid = ( rRect.Top() + rRect.Bottom() ) / 2;
long nTop = nMid - rSize.Height() / 2;
long nBottom = nTop + rSize.Height();
if( nLeft < rRect.Left() )
{
nLeft = rRect.Left();
nRight = rRect.Right();
}
if( nTop < rRect.Top() )
{
nTop = rRect.Top();
nBottom = rRect.Bottom();
}
Polygon aPoly;
Point aTmp( bLeft ? nLeft : nRight, nMid );
Point aNxt( bLeft ? nRight : nLeft, nTop );
aPoly.Insert( 0, aTmp );
aPoly.Insert( 0, aNxt );
aNxt.Y() = nBottom;
aPoly.Insert( 0, aNxt );
aPoly.Insert( 0, aTmp );
Color aOldLineColor = rOut.GetLineColor();
Color aOldFillColor = rOut.GetFillColor();
rOut.SetFillColor( rCol );
rOut.SetLineColor( Color( COL_BLACK ) );
rOut.DrawPolygon( aPoly );
rOut.DrawLine( aTmp, aNxt );
rOut.SetLineColor( aOldLineColor );
rOut.SetFillColor( aOldFillColor );
}
/*************************************************************************
* SvxFont::CalcCaseMap
*************************************************************************/
XubString SvxFont::CalcCaseMap( const XubString &rTxt ) const
{
if( !IsCaseMap() || !rTxt.Len() ) return rTxt;
XubString aTxt( rTxt );
// Ich muss mir noch die Sprache besorgen
const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
? LANGUAGE_SYSTEM : eLang;
CharClass aCharClass( SvxCreateLocale( eLng ) );
switch( eCaseMap )
{
case SVX_CASEMAP_KAPITAELCHEN:
case SVX_CASEMAP_VERSALIEN:
{
aCharClass.toUpper( aTxt );
break;
}
case SVX_CASEMAP_GEMEINE:
{
aCharClass.toLower( aTxt );
break;
}
case SVX_CASEMAP_TITEL:
{
// Jeder Wortbeginn wird gross geschrieben,
// der Rest des Wortes wird unbesehen uebernommen.
// Bug: wenn das Attribut mitten im Wort beginnt.
sal_Bool bBlank = sal_True;
for( sal_uInt16 i = 0; i < aTxt.Len(); ++i )
{
if( sal_Unicode(' ') == aTxt.GetChar(i) || sal_Unicode('\t') == aTxt.GetChar(i) )
bBlank = sal_True;
else
{
if( bBlank )
{
String aTemp( aTxt.GetChar( i ) );
aCharClass.toUpper( aTemp );
aTxt.Replace( i, 1, aTemp );
}
bBlank = sal_False;
}
}
break;
}
default:
{
DBG_ASSERT(!this, "SvxFont::CaseMapTxt: unknown casemap");
break;
}
}
return aTxt;
}
/*************************************************************************
* Hier beginnen die Methoden, die im Writer nicht benutzt werden koennen,
* deshalb kann man diesen Bereich durch setzen von REDUCEDSVXFONT ausklammern.
*************************************************************************/
#ifndef REDUCEDSVXFONT
/*************************************************************************
* class SvxDoCapitals
* die virtuelle Methode Do wird von SvxFont::DoOnCapitals abwechselnd mit
* den "Gross-" und "Kleinbuchstaben"-Teilen aufgerufen.
* Die Ableitungen von SvxDoCapitals erfuellen diese Methode mit Leben.
*************************************************************************/
class SvxDoCapitals
{
protected:
OutputDevice *pOut;
const XubString &rTxt;
const xub_StrLen nIdx;
const xub_StrLen nLen;
public:
SvxDoCapitals( OutputDevice *_pOut, const XubString &_rTxt,
const xub_StrLen _nIdx, const xub_StrLen _nLen )
: pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen)
{ }
virtual void DoSpace( const sal_Bool bDraw );
virtual void SetSpace();
virtual void Do( const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen,
const sal_Bool bUpper ) = 0;
inline OutputDevice *GetOut() { return pOut; }
inline const XubString &GetTxt() const { return rTxt; }
xub_StrLen GetIdx() const { return nIdx; }
xub_StrLen GetLen() const { return nLen; }
};
void SvxDoCapitals::DoSpace( const sal_Bool /*bDraw*/ ) { }
void SvxDoCapitals::SetSpace() { }
void SvxDoCapitals::Do( const XubString &/*_rTxt*/, const xub_StrLen /*_nIdx*/,
const xub_StrLen /*_nLen*/, const sal_Bool /*bUpper*/ ) { }
/*************************************************************************
* SvxFont::DoOnCapitals() const
* zerlegt den String in Gross- und Kleinbuchstaben und ruft jeweils die
* Methode SvxDoCapitals::Do( ) auf.
*************************************************************************/
void SvxFont::DoOnCapitals(SvxDoCapitals &rDo, const xub_StrLen nPartLen) const
{
const XubString &rTxt = rDo.GetTxt();
const xub_StrLen nIdx = rDo.GetIdx();
const xub_StrLen nLen = STRING_LEN == nPartLen ? rDo.GetLen() : nPartLen;
const XubString aTxt( CalcCaseMap( rTxt ) );
const sal_uInt16 nTxtLen = Min( rTxt.Len(), nLen );
sal_uInt16 nPos = 0;
sal_uInt16 nOldPos = nPos;
// #108210#
// Test if string length differ between original and CaseMapped
sal_Bool bCaseMapLengthDiffers(aTxt.Len() != rTxt.Len());
const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
? LANGUAGE_SYSTEM : eLang;
CharClass aCharClass( SvxCreateLocale( eLng ) );
String aCharString;
while( nPos < nTxtLen )
{
// Erst kommen die Upper-Chars dran
// 4251: Es gibt Zeichen, die Upper _und_ Lower sind (z.B. das Blank).
// Solche Zweideutigkeiten fuehren ins Chaos, deswegen werden diese
// Zeichen der Menge Lower zugeordnet !
while( nPos < nTxtLen )
{
aCharString = rTxt.GetChar( nPos + nIdx );
sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
if ( nCharacterType & ::com::sun::star::i18n::KCharacterType::LOWER )
break;
if ( ! ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
break;
++nPos;
}
if( nOldPos != nPos )
{
if(bCaseMapLengthDiffers)
{
// #108210#
// If strings differ work preparing the necessary snippet to address that
// potential difference
const XubString aSnippet(rTxt, nIdx + nOldPos, nPos-nOldPos);
XubString aNewText = CalcCaseMap(aSnippet);
rDo.Do( aNewText, 0, aNewText.Len(), sal_True );
}
else
{
rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_True );
}
nOldPos = nPos;
}
// Nun werden die Lower-Chars verarbeitet (ohne Blanks)
while( nPos < nTxtLen )
{
sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
if ( ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
break;
if ( CH_BLANK == aCharString )
break;
if( ++nPos < nTxtLen )
aCharString = rTxt.GetChar( nPos + nIdx );
}
if( nOldPos != nPos )
{
if(bCaseMapLengthDiffers)
{
// #108210#
// If strings differ work preparing the necessary snippet to address that
// potential difference
const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
XubString aNewText = CalcCaseMap(aSnippet);
rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
}
else
{
rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_False );
}
nOldPos = nPos;
}
// Nun werden die Blanks verarbeitet
while( nPos < nTxtLen && CH_BLANK == aCharString && ++nPos < nTxtLen )
aCharString = rTxt.GetChar( nPos + nIdx );
if( nOldPos != nPos )
{
rDo.DoSpace( sal_False );
if(bCaseMapLengthDiffers)
{
// #108210#
// If strings differ work preparing the necessary snippet to address that
// potential difference
const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
XubString aNewText = CalcCaseMap(aSnippet);
rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
}
else
{
rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, sal_False );
}
nOldPos = nPos;
rDo.SetSpace();
}
}
rDo.DoSpace( sal_True );
}
/**************************************************************************
* SvxFont::SetPhysFont()
*************************************************************************/
void SvxFont::SetPhysFont( OutputDevice *pOut ) const
{
const Font& rCurrentFont = pOut->GetFont();
if ( nPropr == 100 )
{
if ( !rCurrentFont.IsSameInstance( *this ) )
pOut->SetFont( *this );
}
else
{
Font aNewFont( *this );
Size aSize( aNewFont.GetSize() );
aNewFont.SetSize( Size( aSize.Width() * nPropr / 100L,
aSize.Height() * nPropr / 100L ) );
if ( !rCurrentFont.IsSameInstance( aNewFont ) )
pOut->SetFont( aNewFont );
}
}
/*************************************************************************
* SvxFont::ChgPhysFont()
*************************************************************************/
Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const
{
Font aOldFont( pOut->GetFont() );
SetPhysFont( pOut );
return aOldFont;
}
/*************************************************************************
* SvxFont::GetPhysTxtSize()
*************************************************************************/
Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen ) const
{
if ( !IsCaseMap() && !IsKern() )
return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ),
pOut->GetTextHeight() );
Size aTxtSize;
aTxtSize.setHeight( pOut->GetTextHeight() );
if ( !IsCaseMap() )
aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) );
else
{
// #108210#
const XubString aNewText = CalcCaseMap(rTxt);
sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
sal_Int32 nWidth(0L);
if(bCaseMapLengthDiffers)
{
// If strings differ work preparing the necessary snippet to address that
// potential difference
const XubString aSnippet(rTxt, nIdx, nLen);
XubString _aNewText = CalcCaseMap(aSnippet);
nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.Len() );
}
else
{
nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen );
}
aTxtSize.setWidth(nWidth);
}
if( IsKern() && ( nLen > 1 ) )
aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
return aTxtSize;
}
Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt )
{
if ( !IsCaseMap() && !IsKern() )
return Size( pOut->GetTextWidth( rTxt ), pOut->GetTextHeight() );
Size aTxtSize;
aTxtSize.setHeight( pOut->GetTextHeight() );
if ( !IsCaseMap() )
aTxtSize.setWidth( pOut->GetTextWidth( rTxt ) );
else
aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( rTxt ) ) );
if( IsKern() && ( rTxt.Len() > 1 ) )
aTxtSize.Width() += ( ( rTxt.Len()-1 ) * long( nKern ) );
return aTxtSize;
}
Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const XubString &rTxt,
const sal_uInt16 nIdx, const sal_uInt16 nLen, sal_Int32* pDXArray ) const
{
if ( !IsCaseMap() && !IsKern() )
return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ),
pOut->GetTextHeight() );
Size aTxtSize;
aTxtSize.setHeight( pOut->GetTextHeight() );
if ( !IsCaseMap() )
aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) );
else
aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ),
pDXArray, nIdx, nLen ) );
if( IsKern() && ( nLen > 1 ) )
{
aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
if ( pDXArray )
{
for ( xub_StrLen i = 0; i < nLen; i++ )
pDXArray[i] += ( (i+1) * long( nKern ) );
// Der letzte ist um ein nKern zu gross:
pDXArray[nLen-1] -= nKern;
}
}
return aTxtSize;
}
/*************************************************************************
* SvxFont::GetTxtSize()
*************************************************************************/
Size SvxFont::GetTxtSize( const OutputDevice *pOut, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen )
{
xub_StrLen nTmp = nLen;
if ( nTmp == STRING_LEN ) // schon initialisiert?
nTmp = rTxt.Len();
Font aOldFont( ChgPhysFont((OutputDevice *)pOut) );
Size aTxtSize;
if( IsCapital() && rTxt.Len() )
{
aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp );
}
else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp);
((OutputDevice *)pOut)->SetFont( aOldFont );
return aTxtSize;
}
/*************************************************************************
* SvxFont::DrawText()
*************************************************************************/
void SvxFont::DrawText( OutputDevice *pOut,
const Point &rPos, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen ) const
{
if( !nLen || !rTxt.Len() ) return;
xub_StrLen nTmp = nLen;
if ( nTmp == STRING_LEN ) // schon initialisiert?
nTmp = rTxt.Len();
Point aPos( rPos );
if ( nEsc )
{
Size aSize = (this->GetSize());
aPos.Y() -= ((nEsc*long(aSize.Height()))/ 100L);
}
Font aOldFont( ChgPhysFont( pOut ) );
if ( IsCapital() )
DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
else
{
Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nTmp );
if ( !IsCaseMap() )
pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
else
pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ),
nIdx, nTmp );
}
pOut->SetFont(aOldFont);
}
void SvxFont::QuickDrawText( OutputDevice *pOut,
const Point &rPos, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen, const sal_Int32* pDXArray ) const
{
// Font muss ins OutputDevice selektiert sein...
if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
{
pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen );
return;
}
Point aPos( rPos );
if ( nEsc )
{
long nDiff = GetSize().Height();
nDiff *= nEsc;
nDiff /= 100;
if ( !IsVertical() )
aPos.Y() -= nDiff;
else
aPos.X() += nDiff;
}
if( IsCapital() )
{
DBG_ASSERT( !pDXArray, "DrawCapital nicht fuer TextArray!" );
DrawCapital( pOut, aPos, rTxt, nIdx, nLen );
}
else
{
if ( IsKern() && !pDXArray )
{
Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen );
if ( !IsCaseMap() )
pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen );
else
pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen );
}
else
{
if ( !IsCaseMap() )
pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen );
else
pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
}
}
}
// -----------------------------------------------------------------------
void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter,
const Point &rPos, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen ) const
{
if ( !nLen || !rTxt.Len() )
return;
xub_StrLen nTmp = nLen;
if ( nTmp == STRING_LEN ) // schon initialisiert?
nTmp = rTxt.Len();
Point aPos( rPos );
if ( nEsc )
{
short nTmpEsc;
if( DFLT_ESC_AUTO_SUPER == nEsc )
nTmpEsc = 33;
else if( DFLT_ESC_AUTO_SUB == nEsc )
nTmpEsc = -20;
else
nTmpEsc = nEsc;
Size aSize = ( this->GetSize() );
aPos.Y() -= ( ( nTmpEsc * long( aSize.Height() ) ) / 100L );
}
Font aOldFont( ChgPhysFont( pOut ) );
Font aOldPrnFont( ChgPhysFont( pPrinter ) );
if ( IsCapital() )
DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
else
{
Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp );
if ( !IsCaseMap() )
pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
else
{
// #108210#
const XubString aNewText = CalcCaseMap(rTxt);
sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
if(bCaseMapLengthDiffers)
{
// If strings differ work preparing the necessary snippet to address that
// potential difference
const XubString aSnippet(rTxt, nIdx, nTmp);
XubString _aNewText = CalcCaseMap(aSnippet);
pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.Len() );
}
else
{
pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp );
}
}
}
pOut->SetFont(aOldFont);
pPrinter->SetFont( aOldPrnFont );
}
// -----------------------------------------------------------------------
SvxFont& SvxFont::operator=( const Font& rFont )
{
Font::operator=( rFont );
return *this;
}
SvxFont& SvxFont::operator=( const SvxFont& rFont )
{
Font::operator=( rFont );
eLang = rFont.eLang;
eCaseMap = rFont.eCaseMap;
nEsc = rFont.nEsc;
nPropr = rFont.nPropr;
nKern = rFont.nKern;
return *this;
}
/*************************************************************************
* class SvxDoGetCapitalSize
* wird von SvxFont::GetCapitalSize() zur Berechnung der TxtSize bei
* eingestellten Kapitaelchen benutzt.
*************************************************************************/
class SvxDoGetCapitalSize : public SvxDoCapitals
{
protected:
SvxFont* pFont;
Size aTxtSize;
short nKern;
public:
SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut,
const XubString &_rTxt, const xub_StrLen _nIdx,
const xub_StrLen _nLen, const short _nKrn )
: SvxDoCapitals( (OutputDevice*)_pOut, _rTxt, _nIdx, _nLen ),
pFont( _pFnt ),
nKern( _nKrn )
{ }
virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
const xub_StrLen nLen, const sal_Bool bUpper );
inline const Size &GetSize() const { return aTxtSize; };
};
void SvxDoGetCapitalSize::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
const xub_StrLen _nLen, const sal_Bool bUpper )
{
Size aPartSize;
if ( !bUpper )
{
sal_uInt8 nProp = pFont->GetPropr();
pFont->SetProprRel( KAPITAELCHENPROP );
pFont->SetPhysFont( pOut );
aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
aPartSize.setHeight( pOut->GetTextHeight() );
aTxtSize.Height() = aPartSize.Height();
pFont->SetPropr( nProp );
pFont->SetPhysFont( pOut );
}
else
{
aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
aPartSize.setHeight( pOut->GetTextHeight() );
}
aTxtSize.Width() += aPartSize.Width();
aTxtSize.Width() += ( _nLen * long( nKern ) );
}
/*************************************************************************
* SvxFont::GetCapitalSize()
* berechnet TxtSize, wenn Kapitaelchen eingestellt sind.
*************************************************************************/
Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen) const
{
// Start:
SvxDoGetCapitalSize aDo( (SvxFont *)this, pOut, rTxt, nIdx, nLen, nKern );
DoOnCapitals( aDo );
Size aTxtSize( aDo.GetSize() );
// End:
if( !aTxtSize.Height() )
{
aTxtSize.setWidth( 0 );
aTxtSize.setHeight( pOut->GetTextHeight() );
}
return aTxtSize;
}
/*************************************************************************
* class SvxDoDrawCapital
* wird von SvxFont::DrawCapital zur Ausgabe von Kapitaelchen benutzt.
*************************************************************************/
class SvxDoDrawCapital : public SvxDoCapitals
{
protected:
SvxFont *pFont;
Point aPos;
Point aSpacePos;
short nKern;
public:
SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const XubString &_rTxt,
const xub_StrLen _nIdx, const xub_StrLen _nLen,
const Point &rPos, const short nKrn )
: SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ),
pFont( pFnt ),
aPos( rPos ),
aSpacePos( rPos ),
nKern( nKrn )
{ }
virtual void DoSpace( const sal_Bool bDraw );
virtual void SetSpace();
virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
const xub_StrLen nLen, const sal_Bool bUpper );
};
void SvxDoDrawCapital::DoSpace( const sal_Bool bDraw )
{
if ( bDraw || pFont->IsWordLineMode() )
{
sal_uInt16 nDiff = (sal_uInt16)(aPos.X() - aSpacePos.X());
if ( nDiff )
{
sal_Bool bWordWise = pFont->IsWordLineMode();
sal_Bool bTrans = pFont->IsTransparent();
pFont->SetWordLineMode( sal_False );
pFont->SetTransparent( sal_True );
pFont->SetPhysFont( pOut );
pOut->DrawStretchText( aSpacePos, nDiff, XubString( sDoubleSpace,
RTL_TEXTENCODING_MS_1252 ), 0, 2 );
pFont->SetWordLineMode( bWordWise );
pFont->SetTransparent( bTrans );
pFont->SetPhysFont( pOut );
}
}
}
void SvxDoDrawCapital::SetSpace()
{
if ( pFont->IsWordLineMode() )
aSpacePos.X() = aPos.X();
}
void SvxDoDrawCapital::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
const xub_StrLen _nLen, const sal_Bool bUpper)
{
sal_uInt8 nProp = 0;
Size aPartSize;
// Einstellen der gewuenschten Fonts
FontUnderline eUnder = pFont->GetUnderline();
FontStrikeout eStrike = pFont->GetStrikeout();
pFont->SetUnderline( UNDERLINE_NONE );
pFont->SetStrikeout( STRIKEOUT_NONE );
if ( !bUpper )
{
nProp = pFont->GetPropr();
pFont->SetProprRel( KAPITAELCHENPROP );
}
pFont->SetPhysFont( pOut );
aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
aPartSize.setHeight( pOut->GetTextHeight() );
long nWidth = aPartSize.Width();
if ( nKern )
{
aPos.X() += (nKern/2);
if ( _nLen ) nWidth += (_nLen*long(nKern));
}
pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen);
// Font restaurieren
pFont->SetUnderline( eUnder );
pFont->SetStrikeout( eStrike );
if ( !bUpper )
pFont->SetPropr( nProp );
pFont->SetPhysFont( pOut );
aPos.X() += nWidth-(nKern/2);
}
/*************************************************************************
* SvxFont::DrawCapital() gibt Kapitaelchen aus.
*************************************************************************/
void SvxFont::DrawCapital( OutputDevice *pOut,
const Point &rPos, const XubString &rTxt,
const xub_StrLen nIdx, const xub_StrLen nLen ) const
{
SvxDoDrawCapital aDo( (SvxFont *)this,pOut,rTxt,nIdx,nLen,rPos,nKern );
DoOnCapitals( aDo );
}
#endif // !REDUCEDSVXFONT