xref: /AOO41X/main/editeng/source/items/svxfont.cxx (revision 190118d08a3be86671f4129b3e9a490e144719cd)
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(!this, "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