xref: /trunk/main/editeng/source/items/svxfont.cxx (revision 870262e3)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26 
27 // include ----------------------------------------------------------------
28 
29 #include <vcl/outdev.hxx>
30 #include <vcl/print.hxx>
31 #include <tools/poly.hxx>
32 #include <unotools/charclass.hxx>
33 #include <editeng/unolingu.hxx>
34 #include <com/sun/star/i18n/KCharacterType.hpp>
35 
36 #define _SVX_SVXFONT_CXX
37 
38 #include <editeng/svxfont.hxx>
39 #include <editeng/escpitem.hxx>
40 
41 // Minimum: Prozentwert fuers kernen
42 #define MINKERNPERCENT 5
43 
44 // prop. Size of the small cap letters
45 #define KAPITAELCHENPROP 74
46 
47 #ifndef REDUCEDSVXFONT
48 	const sal_Unicode CH_BLANK = sal_Unicode(' ');  	// ' ' Leerzeichen
49 	static sal_Char __READONLY_DATA sDoubleSpace[] = "  ";
50 #endif
51 
52 /*************************************************************************
53  *						class SvxFont
54  *************************************************************************/
55 
SvxFont()56 SvxFont::SvxFont()
57 {
58 	nKern = nEsc = 0;
59 	nPropr = 100;
60 	eCaseMap = SVX_CASEMAP_NOT_MAPPED;
61 	eLang = LANGUAGE_SYSTEM;
62 }
63 
SvxFont(const Font & rFont)64 SvxFont::SvxFont( const Font &rFont )
65 	: Font( rFont )
66 {
67 	nKern = nEsc = 0;
68 	nPropr = 100;
69 	eCaseMap = SVX_CASEMAP_NOT_MAPPED;
70 	eLang = LANGUAGE_SYSTEM;
71 }
72 
73 /*************************************************************************
74  *						class SvxFont: Copy-Ctor
75  *************************************************************************/
76 
SvxFont(const SvxFont & rFont)77 SvxFont::SvxFont( const SvxFont &rFont )
78 	: Font( rFont )
79 {
80 	nKern = rFont.GetFixKerning();
81 	nEsc  = rFont.GetEscapement();
82 	nPropr = rFont.GetPropr();
83 	eCaseMap = rFont.GetCaseMap();
84 	eLang = rFont.GetLanguage();
85 }
86 
87 /*************************************************************************
88  *				 static	SvxFont::DrawArrow
89  *************************************************************************/
90 
DrawArrow(OutputDevice & rOut,const Rectangle & rRect,const Size & rSize,const Color & rCol,sal_Bool bLeft)91 void SvxFont::DrawArrow( OutputDevice &rOut, const Rectangle& rRect,
92 	const Size& rSize, const Color& rCol, sal_Bool bLeft )
93 {
94 	long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2;
95 	long nRight = nLeft + rSize.Width();
96 	long nMid = ( rRect.Top() + rRect.Bottom() ) / 2;
97 	long nTop = nMid - rSize.Height() / 2;
98 	long nBottom = nTop + rSize.Height();
99 	if( nLeft < rRect.Left() )
100 	{
101 		nLeft = rRect.Left();
102 		nRight = rRect.Right();
103 	}
104 	if( nTop < rRect.Top() )
105 	{
106 		nTop = rRect.Top();
107 		nBottom = rRect.Bottom();
108 	}
109 	Polygon aPoly;
110 	Point aTmp( bLeft ? nLeft : nRight, nMid );
111 	Point aNxt( bLeft ? nRight : nLeft, nTop );
112 	aPoly.Insert( 0, aTmp );
113 	aPoly.Insert( 0, aNxt );
114 	aNxt.Y() = nBottom;
115 	aPoly.Insert( 0, aNxt );
116 	aPoly.Insert( 0, aTmp );
117 	Color aOldLineColor = rOut.GetLineColor();
118 	Color aOldFillColor = rOut.GetFillColor();
119 	rOut.SetFillColor( rCol );
120 	rOut.SetLineColor( Color( COL_BLACK ) );
121 	rOut.DrawPolygon( aPoly );
122 	rOut.DrawLine( aTmp, aNxt );
123 	rOut.SetLineColor( aOldLineColor );
124 	rOut.SetFillColor( aOldFillColor );
125 }
126 
127 /*************************************************************************
128  *                      SvxFont::CalcCaseMap
129  *************************************************************************/
130 
CalcCaseMap(const XubString & rTxt) const131 XubString SvxFont::CalcCaseMap( const XubString &rTxt ) const
132 {
133 	if( !IsCaseMap() || !rTxt.Len() ) return rTxt;
134 	XubString aTxt( rTxt );
135 	// Ich muss mir noch die Sprache besorgen
136 	const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
137 							? LANGUAGE_SYSTEM : eLang;
138 
139 	CharClass aCharClass( SvxCreateLocale( eLng ) );
140 
141 	switch( eCaseMap )
142 	{
143 		case SVX_CASEMAP_KAPITAELCHEN:
144 		case SVX_CASEMAP_VERSALIEN:
145 		{
146 			aCharClass.toUpper( aTxt );
147 			break;
148 		}
149 
150 		case SVX_CASEMAP_GEMEINE:
151 		{
152 			aCharClass.toLower( aTxt );
153 			break;
154 		}
155 		case SVX_CASEMAP_TITEL:
156 		{
157 			// Jeder Wortbeginn wird gross geschrieben,
158 			// der Rest des Wortes wird unbesehen uebernommen.
159 			// Bug: wenn das Attribut mitten im Wort beginnt.
160 			sal_Bool bBlank = sal_True;
161 
162 			for( sal_uInt16 i = 0; i < aTxt.Len(); ++i )
163 			{
164 				if( sal_Unicode(' ') == aTxt.GetChar(i) || sal_Unicode('\t') == aTxt.GetChar(i) )
165 					bBlank = sal_True;
166 				else
167 				{
168 					if( bBlank )
169 					{
170 						String aTemp( aTxt.GetChar( i ) );
171 						aCharClass.toUpper( aTemp );
172 						aTxt.Replace( i, 1, aTemp );
173 					}
174 					bBlank = sal_False;
175 				}
176 			}
177 			break;
178 		}
179 		default:
180 		{
181 			DBG_ASSERT(sal_False, "SvxFont::CaseMapTxt: unknown casemap");
182 			break;
183 		}
184 	}
185 	return aTxt;
186 }
187 
188 /*************************************************************************
189  * Hier beginnen die Methoden, die im Writer nicht benutzt werden koennen,
190  * deshalb kann man diesen Bereich durch setzen von REDUCEDSVXFONT ausklammern.
191  *************************************************************************/
192 #ifndef REDUCEDSVXFONT
193 
194 /*************************************************************************
195  *						class SvxDoCapitals
196  * die virtuelle Methode Do wird von SvxFont::DoOnCapitals abwechselnd mit
197  * den "Gross-" und "Kleinbuchstaben"-Teilen aufgerufen.
198  * Die Ableitungen von SvxDoCapitals erfuellen diese Methode mit Leben.
199  *************************************************************************/
200 
201 class SvxDoCapitals
202 {
203 protected:
204 	OutputDevice *pOut;
205 	const XubString &rTxt;
206 	const xub_StrLen nIdx;
207 	const xub_StrLen nLen;
208 
209 public:
SvxDoCapitals(OutputDevice * _pOut,const XubString & _rTxt,const xub_StrLen _nIdx,const xub_StrLen _nLen)210     SvxDoCapitals( OutputDevice *_pOut, const XubString &_rTxt,
211                    const xub_StrLen _nIdx, const xub_StrLen _nLen )
212         : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen)
213 		{ }
214 
215 	virtual void DoSpace( const sal_Bool bDraw );
216 	virtual void SetSpace();
217 	virtual void Do( const XubString &rTxt,
218 					 const xub_StrLen nIdx, const xub_StrLen nLen,
219 					 const sal_Bool bUpper ) = 0;
220 
GetOut()221 	inline OutputDevice *GetOut() { return pOut; }
GetTxt() const222 	inline const XubString &GetTxt() const { return rTxt; }
GetIdx() const223 	xub_StrLen GetIdx() const { return nIdx; }
GetLen() const224 	xub_StrLen GetLen() const { return nLen; }
225 };
226 
DoSpace(const sal_Bool)227 void SvxDoCapitals::DoSpace( const sal_Bool /*bDraw*/ ) { }
228 
SetSpace()229 void SvxDoCapitals::SetSpace() { }
230 
Do(const XubString &,const xub_StrLen,const xub_StrLen,const sal_Bool)231 void SvxDoCapitals::Do( const XubString &/*_rTxt*/, const xub_StrLen /*_nIdx*/,
232     const xub_StrLen /*_nLen*/, const sal_Bool /*bUpper*/ ) { }
233 
234 /*************************************************************************
235  *					SvxFont::DoOnCapitals() const
236  * zerlegt den String in Gross- und Kleinbuchstaben und ruft jeweils die
237  * Methode SvxDoCapitals::Do( ) auf.
238  *************************************************************************/
239 
DoOnCapitals(SvxDoCapitals & rDo,const xub_StrLen nPartLen) const240 void SvxFont::DoOnCapitals(SvxDoCapitals &rDo, const xub_StrLen nPartLen) const
241 {
242 	const XubString &rTxt = rDo.GetTxt();
243 	const xub_StrLen nIdx = rDo.GetIdx();
244 	const xub_StrLen nLen = STRING_LEN == nPartLen ? rDo.GetLen() : nPartLen;
245 
246 	const XubString aTxt( CalcCaseMap( rTxt ) );
247 	const sal_uInt16 nTxtLen = Min( rTxt.Len(), nLen );
248 	sal_uInt16 nPos = 0;
249 	sal_uInt16 nOldPos = nPos;
250 
251 	// #108210#
252 	// Test if string length differ between original and CaseMapped
253 	sal_Bool bCaseMapLengthDiffers(aTxt.Len() != rTxt.Len());
254 
255 	const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
256 							? LANGUAGE_SYSTEM : eLang;
257 
258 	CharClass	aCharClass( SvxCreateLocale( eLng ) );
259 	String		aCharString;
260 
261 	while( nPos < nTxtLen )
262 	{
263 		// Erst kommen die Upper-Chars dran
264 
265 		// 4251: Es gibt Zeichen, die Upper _und_ Lower sind (z.B. das Blank).
266 		// Solche Zweideutigkeiten fuehren ins Chaos, deswegen werden diese
267 		// Zeichen der Menge Lower zugeordnet !
268 
269 		while( nPos < nTxtLen )
270 		{
271 			aCharString = rTxt.GetChar( nPos + nIdx );
272 			sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
273 			if ( nCharacterType & ::com::sun::star::i18n::KCharacterType::LOWER )
274 				break;
275 			if ( ! ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
276 				break;
277 			++nPos;
278 		}
279 		if( nOldPos != nPos )
280 		{
281 			if(bCaseMapLengthDiffers)
282 			{
283 				// #108210#
284 				// If strings differ work preparing the necessary snippet to address that
285 				// potential difference
286 				const XubString aSnippet(rTxt, nIdx + nOldPos, nPos-nOldPos);
287 				XubString aNewText = CalcCaseMap(aSnippet);
288 
289 				rDo.Do( aNewText, 0, aNewText.Len(), sal_True );
290 			}
291 			else
292 			{
293 				rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_True );
294 			}
295 
296 			nOldPos = nPos;
297 		}
298 		// Nun werden die Lower-Chars verarbeitet (ohne Blanks)
299 		while( nPos < nTxtLen )
300 		{
301 			sal_uInt32	nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
302 			if ( ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
303 				break;
304 			if ( CH_BLANK == aCharString )
305 				break;
306 			if( ++nPos < nTxtLen )
307 				aCharString = rTxt.GetChar( nPos + nIdx );
308 		}
309 		if( nOldPos != nPos )
310 		{
311 			if(bCaseMapLengthDiffers)
312 			{
313 				// #108210#
314 				// If strings differ work preparing the necessary snippet to address that
315 				// potential difference
316 				const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
317 				XubString aNewText = CalcCaseMap(aSnippet);
318 
319 				rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
320 			}
321 			else
322 			{
323 				rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_False );
324 			}
325 
326 			nOldPos = nPos;
327 		}
328 		// Nun werden die Blanks verarbeitet
329 		while( nPos < nTxtLen && CH_BLANK == aCharString && ++nPos < nTxtLen )
330 			aCharString = rTxt.GetChar( nPos + nIdx );
331 
332 		if( nOldPos != nPos )
333 		{
334 			rDo.DoSpace( sal_False );
335 
336 			if(bCaseMapLengthDiffers)
337 			{
338 				// #108210#
339 				// If strings differ work preparing the necessary snippet to address that
340 				// potential difference
341 				const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
342 				XubString aNewText = CalcCaseMap(aSnippet);
343 
344 				rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
345 			}
346 			else
347 			{
348 				rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, sal_False );
349 			}
350 
351 			nOldPos = nPos;
352 			rDo.SetSpace();
353 		}
354 	}
355 	rDo.DoSpace( sal_True );
356 }
357 
358 /**************************************************************************
359  *					  SvxFont::SetPhysFont()
360  *************************************************************************/
361 
SetPhysFont(OutputDevice * pOut) const362 void SvxFont::SetPhysFont( OutputDevice *pOut ) const
363 {
364 	const Font& rCurrentFont = pOut->GetFont();
365 	if ( nPropr == 100 )
366 	{
367 		if ( !rCurrentFont.IsSameInstance( *this ) )
368 			pOut->SetFont( *this );
369 	}
370 	else
371 	{
372 		Font aNewFont( *this );
373 		Size aSize( aNewFont.GetSize() );
374 		aNewFont.SetSize( Size(	aSize.Width() * nPropr / 100L,
375 									aSize.Height() * nPropr / 100L ) );
376 		if ( !rCurrentFont.IsSameInstance( aNewFont ) )
377 			pOut->SetFont( aNewFont );
378 	}
379 }
380 
381 /*************************************************************************
382  *					  SvxFont::ChgPhysFont()
383  *************************************************************************/
384 
ChgPhysFont(OutputDevice * pOut) const385 Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const
386 {
387 	Font aOldFont( pOut->GetFont() );
388 	SetPhysFont( pOut );
389 	return aOldFont;
390 }
391 
392 /*************************************************************************
393  *					  SvxFont::GetPhysTxtSize()
394  *************************************************************************/
395 
GetPhysTxtSize(const OutputDevice * pOut,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen) const396 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt,
397 						 const xub_StrLen nIdx, const xub_StrLen nLen ) const
398 {
399 	if ( !IsCaseMap() && !IsKern() )
400 		return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ),
401 					 pOut->GetTextHeight() );
402 
403 	Size aTxtSize;
404 	aTxtSize.setHeight( pOut->GetTextHeight() );
405 	if ( !IsCaseMap() )
406 		aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) );
407 	else
408 	{
409 		// #108210#
410 		const XubString aNewText = CalcCaseMap(rTxt);
411 		sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
412 		sal_Int32 nWidth(0L);
413 
414 		if(bCaseMapLengthDiffers)
415 		{
416 			// If strings differ work preparing the necessary snippet to address that
417 			// potential difference
418 			const XubString aSnippet(rTxt, nIdx, nLen);
419             XubString _aNewText = CalcCaseMap(aSnippet);
420             nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.Len() );
421 		}
422 		else
423 		{
424 			nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen );
425 		}
426 
427 		aTxtSize.setWidth(nWidth);
428 	}
429 
430 	if( IsKern() && ( nLen > 1 ) )
431 		aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
432 
433 	return aTxtSize;
434 }
435 
GetPhysTxtSize(const OutputDevice * pOut,const XubString & rTxt)436 Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt )
437 {
438 	if ( !IsCaseMap() && !IsKern() )
439 		return Size( pOut->GetTextWidth( rTxt ), pOut->GetTextHeight() );
440 
441 	Size aTxtSize;
442 	aTxtSize.setHeight( pOut->GetTextHeight() );
443 	if ( !IsCaseMap() )
444 		aTxtSize.setWidth( pOut->GetTextWidth( rTxt ) );
445 	else
446 		aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( rTxt ) ) );
447 
448 	if( IsKern() && ( rTxt.Len() > 1 ) )
449 		aTxtSize.Width() += ( ( rTxt.Len()-1 ) * long( nKern ) );
450 
451 	return aTxtSize;
452 }
453 
QuickGetTextSize(const OutputDevice * pOut,const XubString & rTxt,const sal_uInt16 nIdx,const sal_uInt16 nLen,sal_Int32 * pDXArray) const454 Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const XubString &rTxt,
455 						 const sal_uInt16 nIdx, const sal_uInt16 nLen, sal_Int32* pDXArray ) const
456 {
457 	if ( !IsCaseMap() && !IsKern() )
458 		return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ),
459 					 pOut->GetTextHeight() );
460 
461 	Size aTxtSize;
462 	aTxtSize.setHeight( pOut->GetTextHeight() );
463 	if ( !IsCaseMap() )
464 		aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) );
465 	else
466 		aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ),
467 						   pDXArray, nIdx, nLen ) );
468 
469 	if( IsKern() && ( nLen > 1 ) )
470 	{
471 		aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
472 
473 		if ( pDXArray )
474 		{
475 			for ( xub_StrLen i = 0; i < nLen; i++ )
476 				pDXArray[i] += ( (i+1) * long( nKern ) );
477 			// Der letzte ist um ein nKern zu gross:
478 			pDXArray[nLen-1] -= nKern;
479 		}
480 	}
481 	return aTxtSize;
482 }
483 
484 /*************************************************************************
485  *					  SvxFont::GetTxtSize()
486  *************************************************************************/
487 
GetTxtSize(const OutputDevice * pOut,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen)488 Size SvxFont::GetTxtSize( const OutputDevice *pOut, const XubString &rTxt,
489 						 const xub_StrLen nIdx, const xub_StrLen nLen )
490 {
491 	xub_StrLen nTmp = nLen;
492 	if ( nTmp == STRING_LEN )	// schon initialisiert?
493 		nTmp = rTxt.Len();
494 	Font aOldFont( ChgPhysFont((OutputDevice *)pOut) );
495 	Size aTxtSize;
496 	if( IsCapital() && rTxt.Len() )
497 	{
498 		aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp );
499 	}
500 	else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp);
501 	((OutputDevice *)pOut)->SetFont( aOldFont );
502 	return aTxtSize;
503 }
504 
505 /*************************************************************************
506  *					  SvxFont::DrawText()
507  *************************************************************************/
508 
DrawText(OutputDevice * pOut,const Point & rPos,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen) const509 void SvxFont::DrawText( OutputDevice *pOut,
510 			   const Point &rPos, const XubString &rTxt,
511 			   const xub_StrLen nIdx, const xub_StrLen nLen ) const
512 {
513 	if( !nLen || !rTxt.Len() )	return;
514 	xub_StrLen nTmp = nLen;
515 	if ( nTmp == STRING_LEN )	// schon initialisiert?
516 		nTmp = rTxt.Len();
517 	Point aPos( rPos );
518 	if ( nEsc )
519 	{
520 		Size aSize = (this->GetSize());
521 		aPos.Y() -= ((nEsc*long(aSize.Height()))/ 100L);
522 	}
523 	Font aOldFont( ChgPhysFont( pOut ) );
524 
525 	if ( IsCapital() )
526 		DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
527 	else
528 	{
529 		Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nTmp );
530 
531 		if ( !IsCaseMap() )
532 			pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
533 		else
534 			pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ),
535 								   nIdx, nTmp );
536 	}
537 	pOut->SetFont(aOldFont);
538 }
539 
QuickDrawText(OutputDevice * pOut,const Point & rPos,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen,const sal_Int32 * pDXArray) const540 void SvxFont::QuickDrawText( OutputDevice *pOut,
541 	const Point &rPos, const XubString &rTxt,
542 	const xub_StrLen nIdx, const xub_StrLen nLen, const sal_Int32* pDXArray ) const
543 {
544 	// Font muss ins OutputDevice selektiert sein...
545 	if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
546 	{
547 		pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen );
548 		return;
549 	}
550 
551 	Point aPos( rPos );
552 
553     if ( nEsc )
554     {
555         long nDiff = GetSize().Height();
556         nDiff *= nEsc;
557         nDiff /= 100;
558 
559         if ( !IsVertical() )
560 		    aPos.Y() -= nDiff;
561         else
562             aPos.X() += nDiff;
563     }
564 
565 	if( IsCapital() )
566 	{
567 		DBG_ASSERT( !pDXArray, "DrawCapital nicht fuer TextArray!" );
568 		DrawCapital( pOut, aPos, rTxt, nIdx, nLen );
569 	}
570 	else
571 	{
572 		if ( IsKern() && !pDXArray )
573 		{
574 			Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen );
575 
576 			if ( !IsCaseMap() )
577 				pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen );
578 			else
579 				pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen );
580 		}
581 		else
582 		{
583 			if ( !IsCaseMap() )
584 				pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen );
585 			else
586 				pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
587 		}
588 	}
589 }
590 
591 // -----------------------------------------------------------------------
592 
DrawPrev(OutputDevice * pOut,Printer * pPrinter,const Point & rPos,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen) const593 void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter,
594 						const Point &rPos, const XubString &rTxt,
595 						const xub_StrLen nIdx, const xub_StrLen nLen ) const
596 {
597 	if ( !nLen || !rTxt.Len() )
598 		return;
599 	xub_StrLen nTmp = nLen;
600 
601 	if ( nTmp == STRING_LEN )	// schon initialisiert?
602 		nTmp = rTxt.Len();
603 	Point aPos( rPos );
604 
605 	if ( nEsc )
606 	{
607 		short nTmpEsc;
608 		if( DFLT_ESC_AUTO_SUPER == nEsc )
609 			nTmpEsc = 33;
610 		else if( DFLT_ESC_AUTO_SUB == nEsc )
611 			nTmpEsc = -20;
612 		else
613 			nTmpEsc = nEsc;
614 		Size aSize = ( this->GetSize() );
615 		aPos.Y() -= ( ( nTmpEsc * long( aSize.Height() ) ) / 100L );
616 	}
617 	Font aOldFont( ChgPhysFont( pOut ) );
618 	Font aOldPrnFont( ChgPhysFont( pPrinter ) );
619 
620 	if ( IsCapital() )
621 		DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
622 	else
623 	{
624 		Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp );
625 
626 		if ( !IsCaseMap() )
627 			pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
628 		else
629 		{
630 			// #108210#
631 			const XubString aNewText = CalcCaseMap(rTxt);
632 			sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
633 
634 			if(bCaseMapLengthDiffers)
635 			{
636 				// If strings differ work preparing the necessary snippet to address that
637 				// potential difference
638 				const XubString aSnippet(rTxt, nIdx, nTmp);
639                 XubString _aNewText = CalcCaseMap(aSnippet);
640 
641                 pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.Len() );
642 			}
643 			else
644 			{
645 				pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp );
646 			}
647 		}
648 	}
649 	pOut->SetFont(aOldFont);
650 	pPrinter->SetFont( aOldPrnFont );
651 }
652 
653 // -----------------------------------------------------------------------
654 
operator =(const Font & rFont)655 SvxFont& SvxFont::operator=( const Font& rFont )
656 {
657 	Font::operator=( rFont );
658 	return *this;
659 }
660 
operator =(const SvxFont & rFont)661 SvxFont& SvxFont::operator=( const SvxFont& rFont )
662 {
663 	Font::operator=( rFont );
664 	eLang = rFont.eLang;
665 	eCaseMap = rFont.eCaseMap;
666 	nEsc = rFont.nEsc;
667 	nPropr = rFont.nPropr;
668 	nKern = rFont.nKern;
669 	return *this;
670 }
671 
672 
673 /*************************************************************************
674  *					  class SvxDoGetCapitalSize
675  * wird von SvxFont::GetCapitalSize() zur Berechnung der TxtSize bei
676  * eingestellten Kapitaelchen benutzt.
677  *************************************************************************/
678 
679 class SvxDoGetCapitalSize : public SvxDoCapitals
680 {
681 protected:
682 	SvxFont*	pFont;
683 	Size 		aTxtSize;
684 	short    	nKern;
685 public:
SvxDoGetCapitalSize(SvxFont * _pFnt,const OutputDevice * _pOut,const XubString & _rTxt,const xub_StrLen _nIdx,const xub_StrLen _nLen,const short _nKrn)686       SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut,
687                            const XubString &_rTxt, const xub_StrLen _nIdx,
688                            const xub_StrLen _nLen, const short _nKrn )
689             : SvxDoCapitals( (OutputDevice*)_pOut, _rTxt, _nIdx, _nLen ),
690               pFont( _pFnt ),
691               nKern( _nKrn )
692 			{ }
693 
694 	virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
695 					 const xub_StrLen nLen, const sal_Bool bUpper );
696 
GetSize() const697 	inline const Size &GetSize() const { return aTxtSize; };
698 };
699 
Do(const XubString & _rTxt,const xub_StrLen _nIdx,const xub_StrLen _nLen,const sal_Bool bUpper)700 void SvxDoGetCapitalSize::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
701                               const xub_StrLen _nLen, const sal_Bool bUpper )
702 {
703 	Size aPartSize;
704 	if ( !bUpper )
705 	{
706 		sal_uInt8 nProp = pFont->GetPropr();
707 		pFont->SetProprRel( KAPITAELCHENPROP );
708 		pFont->SetPhysFont( pOut );
709         aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
710 		aPartSize.setHeight( pOut->GetTextHeight() );
711 		aTxtSize.Height() = aPartSize.Height();
712 		pFont->SetPropr( nProp );
713 		pFont->SetPhysFont( pOut );
714 	}
715 	else
716 	{
717         aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
718 		aPartSize.setHeight( pOut->GetTextHeight() );
719 	}
720 	aTxtSize.Width() += aPartSize.Width();
721     aTxtSize.Width() += ( _nLen * long( nKern ) );
722 }
723 
724 /*************************************************************************
725  *					  SvxFont::GetCapitalSize()
726  * berechnet TxtSize, wenn Kapitaelchen eingestellt sind.
727  *************************************************************************/
728 
GetCapitalSize(const OutputDevice * pOut,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen) const729 Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const XubString &rTxt,
730 							 const xub_StrLen nIdx, const xub_StrLen nLen) const
731 {
732 	// Start:
733 	SvxDoGetCapitalSize aDo( (SvxFont *)this, pOut, rTxt, nIdx, nLen, nKern );
734 	DoOnCapitals( aDo );
735 	Size aTxtSize( aDo.GetSize() );
736 
737 	// End:
738 	if( !aTxtSize.Height() )
739 	{
740 		aTxtSize.setWidth( 0 );
741 		aTxtSize.setHeight( pOut->GetTextHeight() );
742 	}
743 	return aTxtSize;
744 }
745 
746 /*************************************************************************
747  *					   class SvxDoDrawCapital
748  * wird von SvxFont::DrawCapital zur Ausgabe von Kapitaelchen benutzt.
749  *************************************************************************/
750 
751 class SvxDoDrawCapital : public SvxDoCapitals
752 {
753 protected:
754 	SvxFont *pFont;
755 	Point aPos;
756 	Point aSpacePos;
757 	short nKern;
758 public:
SvxDoDrawCapital(SvxFont * pFnt,OutputDevice * _pOut,const XubString & _rTxt,const xub_StrLen _nIdx,const xub_StrLen _nLen,const Point & rPos,const short nKrn)759     SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const XubString &_rTxt,
760                       const xub_StrLen _nIdx, const xub_StrLen _nLen,
761                       const Point &rPos, const short nKrn )
762         : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ),
763 		  pFont( pFnt ),
764 		  aPos( rPos ),
765 		  aSpacePos( rPos ),
766 		  nKern( nKrn )
767 		{ }
768 	virtual void DoSpace( const sal_Bool bDraw );
769 	virtual void SetSpace();
770 	virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
771 					 const xub_StrLen nLen, const sal_Bool bUpper );
772 };
773 
DoSpace(const sal_Bool bDraw)774 void SvxDoDrawCapital::DoSpace( const sal_Bool bDraw )
775 {
776 	if ( bDraw || pFont->IsWordLineMode() )
777 	{
778 		sal_uInt16 nDiff = (sal_uInt16)(aPos.X() - aSpacePos.X());
779 		if ( nDiff )
780 		{
781 			sal_Bool bWordWise = pFont->IsWordLineMode();
782 			sal_Bool bTrans = pFont->IsTransparent();
783 			pFont->SetWordLineMode( sal_False );
784 			pFont->SetTransparent( sal_True );
785 			pFont->SetPhysFont( pOut );
786 			pOut->DrawStretchText( aSpacePos, nDiff, XubString( sDoubleSpace,
787 							RTL_TEXTENCODING_MS_1252 ), 0, 2 );
788 			pFont->SetWordLineMode( bWordWise );
789 			pFont->SetTransparent( bTrans );
790 			pFont->SetPhysFont( pOut );
791 		}
792 	}
793 }
794 
SetSpace()795 void SvxDoDrawCapital::SetSpace()
796 {
797 	if ( pFont->IsWordLineMode() )
798 		aSpacePos.X() = aPos.X();
799 }
800 
Do(const XubString & _rTxt,const xub_StrLen _nIdx,const xub_StrLen _nLen,const sal_Bool bUpper)801 void SvxDoDrawCapital::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
802                            const xub_StrLen _nLen, const sal_Bool bUpper)
803 {
804 	sal_uInt8 nProp = 0;
805 	Size aPartSize;
806 
807 	// Einstellen der gewuenschten Fonts
808 	FontUnderline eUnder = pFont->GetUnderline();
809 	FontStrikeout eStrike = pFont->GetStrikeout();
810 	pFont->SetUnderline( UNDERLINE_NONE );
811 	pFont->SetStrikeout( STRIKEOUT_NONE );
812 	if ( !bUpper )
813 	{
814 		nProp = pFont->GetPropr();
815 		pFont->SetProprRel( KAPITAELCHENPROP );
816 	}
817 	pFont->SetPhysFont( pOut );
818 
819     aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
820 	aPartSize.setHeight( pOut->GetTextHeight() );
821 	long nWidth = aPartSize.Width();
822 	if ( nKern )
823 	{
824 		aPos.X() += (nKern/2);
825         if ( _nLen ) nWidth += (_nLen*long(nKern));
826 	}
827     pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen);
828 
829 	// Font restaurieren
830 	pFont->SetUnderline( eUnder );
831 	pFont->SetStrikeout( eStrike );
832 	if ( !bUpper )
833 		pFont->SetPropr( nProp );
834 	pFont->SetPhysFont( pOut );
835 
836 	aPos.X() += nWidth-(nKern/2);
837 }
838 
839 /*************************************************************************
840  * SvxFont::DrawCapital() gibt Kapitaelchen aus.
841  *************************************************************************/
842 
DrawCapital(OutputDevice * pOut,const Point & rPos,const XubString & rTxt,const xub_StrLen nIdx,const xub_StrLen nLen) const843 void SvxFont::DrawCapital( OutputDevice *pOut,
844 			   const Point &rPos, const XubString &rTxt,
845 			   const xub_StrLen nIdx, const xub_StrLen nLen ) const
846 {
847 	SvxDoDrawCapital aDo( (SvxFont *)this,pOut,rTxt,nIdx,nLen,rPos,nKern );
848 	DoOnCapitals( aDo );
849 }
850 
851 #endif // !REDUCEDSVXFONT
852 
853 
854