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