Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <vcl/outdev.hxx>
22 : #include <vcl/print.hxx>
23 : #include <tools/poly.hxx>
24 : #include <unotools/charclass.hxx>
25 : #include <editeng/unolingu.hxx>
26 : #include <com/sun/star/i18n/KCharacterType.hpp>
27 : #include <editeng/svxfont.hxx>
28 : #include <editeng/escpitem.hxx>
29 :
30 : // Minimum: Percentage of kernel
31 : #define MINKERNPERCENT 5
32 :
33 : #ifndef REDUCEDSVXFONT
34 : const sal_Unicode CH_BLANK = sal_Unicode(' '); // ' ' Space character
35 : static sal_Char const sDoubleSpace[] = " ";
36 : #endif
37 :
38 :
39 86671 : SvxFont::SvxFont()
40 : {
41 86671 : nKern = nEsc = 0;
42 86671 : nPropr = 100;
43 86671 : eCaseMap = SVX_CASEMAP_NOT_MAPPED;
44 86671 : eLang = LANGUAGE_SYSTEM;
45 86671 : }
46 :
47 36 : SvxFont::SvxFont( const Font &rFont )
48 36 : : Font( rFont )
49 : {
50 36 : nKern = nEsc = 0;
51 36 : nPropr = 100;
52 36 : eCaseMap = SVX_CASEMAP_NOT_MAPPED;
53 36 : eLang = LANGUAGE_SYSTEM;
54 36 : }
55 :
56 7204 : SvxFont::SvxFont( const SvxFont &rFont )
57 7204 : : Font( rFont )
58 : {
59 7204 : nKern = rFont.GetFixKerning();
60 7204 : nEsc = rFont.GetEscapement();
61 7204 : nPropr = rFont.GetPropr();
62 7204 : eCaseMap = rFont.GetCaseMap();
63 7204 : eLang = rFont.GetLanguage();
64 7204 : }
65 :
66 :
67 0 : void SvxFont::DrawArrow( OutputDevice &rOut, const Rectangle& rRect,
68 : const Size& rSize, const Color& rCol, sal_Bool bLeft )
69 : {
70 0 : long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2;
71 0 : long nRight = nLeft + rSize.Width();
72 0 : long nMid = ( rRect.Top() + rRect.Bottom() ) / 2;
73 0 : long nTop = nMid - rSize.Height() / 2;
74 0 : long nBottom = nTop + rSize.Height();
75 0 : if( nLeft < rRect.Left() )
76 : {
77 0 : nLeft = rRect.Left();
78 0 : nRight = rRect.Right();
79 : }
80 0 : if( nTop < rRect.Top() )
81 : {
82 0 : nTop = rRect.Top();
83 0 : nBottom = rRect.Bottom();
84 : }
85 0 : Polygon aPoly;
86 0 : Point aTmp( bLeft ? nLeft : nRight, nMid );
87 0 : Point aNxt( bLeft ? nRight : nLeft, nTop );
88 0 : aPoly.Insert( 0, aTmp );
89 0 : aPoly.Insert( 0, aNxt );
90 0 : aNxt.Y() = nBottom;
91 0 : aPoly.Insert( 0, aNxt );
92 0 : aPoly.Insert( 0, aTmp );
93 0 : Color aOldLineColor = rOut.GetLineColor();
94 0 : Color aOldFillColor = rOut.GetFillColor();
95 0 : rOut.SetFillColor( rCol );
96 0 : rOut.SetLineColor( Color( COL_BLACK ) );
97 0 : rOut.DrawPolygon( aPoly );
98 0 : rOut.DrawLine( aTmp, aNxt );
99 0 : rOut.SetLineColor( aOldLineColor );
100 0 : rOut.SetFillColor( aOldFillColor );
101 0 : }
102 :
103 :
104 3 : OUString SvxFont::CalcCaseMap(const OUString &rTxt) const
105 : {
106 3 : if (!IsCaseMap() || rTxt.isEmpty())
107 0 : return rTxt;
108 3 : OUString aTxt(rTxt);
109 : // I still have to get the language
110 : const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
111 3 : ? LANGUAGE_SYSTEM : eLang;
112 :
113 3 : LanguageTag aLanguageTag( eLng);
114 3 : CharClass aCharClass( aLanguageTag );
115 :
116 3 : switch( eCaseMap )
117 : {
118 : case SVX_CASEMAP_KAPITAELCHEN:
119 : case SVX_CASEMAP_VERSALIEN:
120 : {
121 3 : aTxt = aCharClass.uppercase( aTxt );
122 3 : break;
123 : }
124 :
125 : case SVX_CASEMAP_GEMEINE:
126 : {
127 0 : aTxt = aCharClass.lowercase( aTxt );
128 0 : break;
129 : }
130 : case SVX_CASEMAP_TITEL:
131 : {
132 : // Every beginning of a word is capitalized, the rest of the word
133 : // is taken over as is.
134 : // Bug: if the attribute starts in the middle of the word.
135 0 : bool bBlank = true;
136 :
137 0 : for (sal_Int32 i = 0; i < aTxt.getLength(); ++i)
138 : {
139 0 : if( aTxt[i] == ' ' || aTxt[i] == '\t')
140 0 : bBlank = true;
141 : else
142 : {
143 0 : if (bBlank)
144 : {
145 0 : OUString sTitle(aCharClass.uppercase(OUString(aTxt[i])));
146 0 : aTxt = aTxt.replaceAt(i, 1, sTitle);
147 : }
148 0 : bBlank = false;
149 : }
150 : }
151 0 : break;
152 : }
153 : default:
154 : {
155 : DBG_ASSERT(!this, "SvxFont::CaseMapTxt: unknown casemap");
156 0 : break;
157 : }
158 : }
159 3 : return aTxt;
160 : }
161 :
162 : /*************************************************************************
163 : * class SvxDoCapitals
164 : * The virtual Method Do si called by SvxFont::DoOnCapitals alternately
165 : * the uppercase and lowercase parts. The derivate of SvxDoCapitals fills
166 : * this method with life.
167 : *************************************************************************/
168 :
169 : class SvxDoCapitals
170 : {
171 : protected:
172 : OutputDevice *pOut;
173 : const XubString &rTxt;
174 : const xub_StrLen nIdx;
175 : const xub_StrLen nLen;
176 :
177 : public:
178 0 : SvxDoCapitals( OutputDevice *_pOut, const XubString &_rTxt,
179 : const xub_StrLen _nIdx, const xub_StrLen _nLen )
180 0 : : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen)
181 0 : { }
182 :
183 0 : virtual ~SvxDoCapitals() {}
184 :
185 : virtual void DoSpace( const sal_Bool bDraw );
186 : virtual void SetSpace();
187 : virtual void Do( const XubString &rTxt,
188 : const xub_StrLen nIdx, const xub_StrLen nLen,
189 : const sal_Bool bUpper ) = 0;
190 :
191 : inline OutputDevice *GetOut() { return pOut; }
192 0 : inline const XubString &GetTxt() const { return rTxt; }
193 0 : xub_StrLen GetIdx() const { return nIdx; }
194 0 : xub_StrLen GetLen() const { return nLen; }
195 : };
196 :
197 0 : void SvxDoCapitals::DoSpace( const sal_Bool /*bDraw*/ ) { }
198 :
199 0 : void SvxDoCapitals::SetSpace() { }
200 :
201 : /*************************************************************************
202 : * SvxFont::DoOnCapitals() const
203 : * Decomposes the String into uppercase and lowercase letters and then
204 : * calls the method SvxDoCapitals::Do( ).
205 : *************************************************************************/
206 :
207 0 : void SvxFont::DoOnCapitals(SvxDoCapitals &rDo, const xub_StrLen nPartLen) const
208 : {
209 0 : const XubString &rTxt = rDo.GetTxt();
210 0 : const xub_StrLen nIdx = rDo.GetIdx();
211 0 : const xub_StrLen nLen = STRING_LEN == nPartLen ? rDo.GetLen() : nPartLen;
212 :
213 0 : const XubString aTxt( CalcCaseMap( rTxt ) );
214 0 : const sal_uInt16 nTxtLen = Min( rTxt.Len(), nLen );
215 0 : sal_uInt16 nPos = 0;
216 0 : sal_uInt16 nOldPos = nPos;
217 :
218 : // #108210#
219 : // Test if string length differ between original and CaseMapped
220 0 : sal_Bool bCaseMapLengthDiffers(aTxt.Len() != rTxt.Len());
221 :
222 : const LanguageType eLng = LANGUAGE_DONTKNOW == eLang
223 0 : ? LANGUAGE_SYSTEM : eLang;
224 :
225 0 : LanguageTag aLanguageTag( eLng );
226 0 : CharClass aCharClass( aLanguageTag );
227 0 : String aCharString;
228 :
229 0 : while( nPos < nTxtLen )
230 : {
231 : // first in turn are teh uppercase letters
232 :
233 : // There are characters that are both upper- and lower-case L (eg blank)
234 : // Such ambiguities lead to chaos, this is why these characters are
235 : // allocated to the lowercase characters!
236 :
237 0 : while( nPos < nTxtLen )
238 : {
239 0 : aCharString = rTxt.GetChar( nPos + nIdx );
240 0 : sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
241 0 : if ( nCharacterType & ::com::sun::star::i18n::KCharacterType::LOWER )
242 0 : break;
243 0 : if ( ! ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
244 0 : break;
245 0 : ++nPos;
246 : }
247 0 : if( nOldPos != nPos )
248 : {
249 0 : if(bCaseMapLengthDiffers)
250 : {
251 : // #108210#
252 : // If strings differ work preparing the necessary snippet to address that
253 : // potential difference
254 0 : const XubString aSnippet(rTxt, nIdx + nOldPos, nPos-nOldPos);
255 0 : XubString aNewText = CalcCaseMap(aSnippet);
256 :
257 0 : rDo.Do( aNewText, 0, aNewText.Len(), sal_True );
258 : }
259 : else
260 : {
261 0 : rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_True );
262 : }
263 :
264 0 : nOldPos = nPos;
265 : }
266 : // Now the lowercase are processed (without blanks)
267 0 : while( nPos < nTxtLen )
268 : {
269 0 : sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 );
270 0 : if ( ( nCharacterType & ::com::sun::star::i18n::KCharacterType::UPPER ) )
271 0 : break;
272 0 : if ( comphelper::string::equals(aCharString, CH_BLANK) )
273 0 : break;
274 0 : if( ++nPos < nTxtLen )
275 0 : aCharString = rTxt.GetChar( nPos + nIdx );
276 : }
277 0 : if( nOldPos != nPos )
278 : {
279 0 : if(bCaseMapLengthDiffers)
280 : {
281 : // #108210#
282 : // If strings differ work preparing the necessary snippet to address that
283 : // potential difference
284 0 : const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
285 0 : XubString aNewText = CalcCaseMap(aSnippet);
286 :
287 0 : rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
288 : }
289 : else
290 : {
291 0 : rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, sal_False );
292 : }
293 :
294 0 : nOldPos = nPos;
295 : }
296 : // Now the blanks are<processed
297 0 : while( nPos < nTxtLen && comphelper::string::equals(aCharString, CH_BLANK) && ++nPos < nTxtLen )
298 0 : aCharString = rTxt.GetChar( nPos + nIdx );
299 :
300 0 : if( nOldPos != nPos )
301 : {
302 0 : rDo.DoSpace( sal_False );
303 :
304 0 : if(bCaseMapLengthDiffers)
305 : {
306 : // #108210#
307 : // If strings differ work preparing the necessary snippet to address that
308 : // potential difference
309 0 : const XubString aSnippet(rTxt, nIdx + nOldPos, nPos - nOldPos);
310 0 : XubString aNewText = CalcCaseMap(aSnippet);
311 :
312 0 : rDo.Do( aNewText, 0, aNewText.Len(), sal_False );
313 : }
314 : else
315 : {
316 0 : rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, sal_False );
317 : }
318 :
319 0 : nOldPos = nPos;
320 0 : rDo.SetSpace();
321 : }
322 : }
323 0 : rDo.DoSpace( sal_True );
324 0 : }
325 :
326 :
327 41311 : void SvxFont::SetPhysFont( OutputDevice *pOut ) const
328 : {
329 41311 : const Font& rCurrentFont = pOut->GetFont();
330 41311 : if ( nPropr == 100 )
331 : {
332 41097 : if ( !rCurrentFont.IsSameInstance( *this ) )
333 28887 : pOut->SetFont( *this );
334 : }
335 : else
336 : {
337 214 : Font aNewFont( *this );
338 214 : Size aSize( aNewFont.GetSize() );
339 214 : aNewFont.SetSize( Size( aSize.Width() * nPropr / 100L,
340 428 : aSize.Height() * nPropr / 100L ) );
341 214 : if ( !rCurrentFont.IsSameInstance( aNewFont ) )
342 214 : pOut->SetFont( aNewFont );
343 : }
344 41311 : }
345 :
346 :
347 0 : Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const
348 : {
349 0 : Font aOldFont( pOut->GetFont() );
350 0 : SetPhysFont( pOut );
351 0 : return aOldFont;
352 : }
353 :
354 :
355 0 : Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt,
356 : const xub_StrLen nIdx, const xub_StrLen nLen ) const
357 : {
358 0 : if ( !IsCaseMap() && !IsKern() )
359 : return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ),
360 0 : pOut->GetTextHeight() );
361 :
362 0 : Size aTxtSize;
363 0 : aTxtSize.setHeight( pOut->GetTextHeight() );
364 0 : if ( !IsCaseMap() )
365 0 : aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) );
366 : else
367 : {
368 : // #108210#
369 0 : const XubString aNewText = CalcCaseMap(rTxt);
370 0 : sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
371 0 : sal_Int32 nWidth(0L);
372 :
373 0 : if(bCaseMapLengthDiffers)
374 : {
375 : // If strings differ work preparing the necessary snippet to address that
376 : // potential difference
377 0 : const XubString aSnippet(rTxt, nIdx, nLen);
378 0 : XubString _aNewText = CalcCaseMap(aSnippet);
379 0 : nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.Len() );
380 : }
381 : else
382 : {
383 0 : nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen );
384 : }
385 :
386 0 : aTxtSize.setWidth(nWidth);
387 : }
388 :
389 0 : if( IsKern() && ( nLen > 1 ) )
390 0 : aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
391 :
392 0 : return aTxtSize;
393 : }
394 :
395 18036 : Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const XubString &rTxt )
396 : {
397 18036 : if ( !IsCaseMap() && !IsKern() )
398 18036 : return Size( pOut->GetTextWidth( rTxt ), pOut->GetTextHeight() );
399 :
400 0 : Size aTxtSize;
401 0 : aTxtSize.setHeight( pOut->GetTextHeight() );
402 0 : if ( !IsCaseMap() )
403 0 : aTxtSize.setWidth( pOut->GetTextWidth( rTxt ) );
404 : else
405 0 : aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( rTxt ) ) );
406 :
407 0 : if( IsKern() && ( rTxt.Len() > 1 ) )
408 0 : aTxtSize.Width() += ( ( rTxt.Len()-1 ) * long( nKern ) );
409 :
410 0 : return aTxtSize;
411 : }
412 :
413 11473 : Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const XubString &rTxt,
414 : const sal_uInt16 nIdx, const sal_uInt16 nLen, sal_Int32* pDXArray ) const
415 : {
416 11473 : if ( !IsCaseMap() && !IsKern() )
417 : return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ),
418 11473 : pOut->GetTextHeight() );
419 :
420 0 : Size aTxtSize;
421 0 : aTxtSize.setHeight( pOut->GetTextHeight() );
422 0 : if ( !IsCaseMap() )
423 0 : aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) );
424 : else
425 : aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ),
426 0 : pDXArray, nIdx, nLen ) );
427 :
428 0 : if( IsKern() && ( nLen > 1 ) )
429 : {
430 0 : aTxtSize.Width() += ( ( nLen-1 ) * long( nKern ) );
431 :
432 0 : if ( pDXArray )
433 : {
434 0 : for ( xub_StrLen i = 0; i < nLen; i++ )
435 0 : pDXArray[i] += ( (i+1) * long( nKern ) );
436 : // The last one is a nKern too big:
437 0 : pDXArray[nLen-1] -= nKern;
438 : }
439 : }
440 0 : return aTxtSize;
441 : }
442 :
443 :
444 0 : Size SvxFont::GetTxtSize( const OutputDevice *pOut, const XubString &rTxt,
445 : const xub_StrLen nIdx, const xub_StrLen nLen ) const
446 : {
447 0 : xub_StrLen nTmp = nLen;
448 0 : if ( nTmp == STRING_LEN ) // already initialized?
449 0 : nTmp = rTxt.Len();
450 0 : Font aOldFont( ChgPhysFont((OutputDevice *)pOut) );
451 0 : Size aTxtSize;
452 0 : if( IsCapital() && rTxt.Len() )
453 : {
454 0 : aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp );
455 : }
456 0 : else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp);
457 0 : ((OutputDevice *)pOut)->SetFont( aOldFont );
458 0 : return aTxtSize;
459 : }
460 :
461 :
462 31 : void SvxFont::QuickDrawText( OutputDevice *pOut,
463 : const Point &rPos, const XubString &rTxt,
464 : const xub_StrLen nIdx, const xub_StrLen nLen, const sal_Int32* pDXArray ) const
465 : {
466 : // Font has to be selected in OutputDevice...
467 31 : if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
468 : {
469 31 : pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen );
470 31 : return;
471 : }
472 :
473 0 : Point aPos( rPos );
474 :
475 0 : if ( nEsc )
476 : {
477 0 : long nDiff = GetSize().Height();
478 0 : nDiff *= nEsc;
479 0 : nDiff /= 100;
480 :
481 0 : if ( !IsVertical() )
482 0 : aPos.Y() -= nDiff;
483 : else
484 0 : aPos.X() += nDiff;
485 : }
486 :
487 0 : if( IsCapital() )
488 : {
489 : DBG_ASSERT( !pDXArray, "DrawCapital not for TextArray!" );
490 0 : DrawCapital( pOut, aPos, rTxt, nIdx, nLen );
491 : }
492 : else
493 : {
494 0 : if ( IsKern() && !pDXArray )
495 : {
496 0 : Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen );
497 :
498 0 : if ( !IsCaseMap() )
499 0 : pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen );
500 : else
501 0 : pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen );
502 : }
503 : else
504 : {
505 0 : if ( !IsCaseMap() )
506 0 : pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen );
507 : else
508 0 : pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
509 : }
510 : }
511 : }
512 :
513 :
514 0 : void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter,
515 : const Point &rPos, const XubString &rTxt,
516 : const xub_StrLen nIdx, const xub_StrLen nLen ) const
517 : {
518 0 : if ( !nLen || !rTxt.Len() )
519 0 : return;
520 0 : xub_StrLen nTmp = nLen;
521 :
522 0 : if ( nTmp == STRING_LEN ) // already initialized?
523 0 : nTmp = rTxt.Len();
524 0 : Point aPos( rPos );
525 :
526 0 : if ( nEsc )
527 : {
528 : short nTmpEsc;
529 0 : if( DFLT_ESC_AUTO_SUPER == nEsc )
530 0 : nTmpEsc = 33;
531 0 : else if( DFLT_ESC_AUTO_SUB == nEsc )
532 0 : nTmpEsc = -20;
533 : else
534 0 : nTmpEsc = nEsc;
535 0 : Size aSize = ( this->GetSize() );
536 0 : aPos.Y() -= ( ( nTmpEsc * long( aSize.Height() ) ) / 100L );
537 : }
538 0 : Font aOldFont( ChgPhysFont( pOut ) );
539 0 : Font aOldPrnFont( ChgPhysFont( pPrinter ) );
540 :
541 0 : if ( IsCapital() )
542 0 : DrawCapital( pOut, aPos, rTxt, nIdx, nTmp );
543 : else
544 : {
545 0 : Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp );
546 :
547 0 : if ( !IsCaseMap() )
548 0 : pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp );
549 : else
550 : {
551 : // #108210#
552 0 : const XubString aNewText = CalcCaseMap(rTxt);
553 0 : sal_Bool bCaseMapLengthDiffers(aNewText.Len() != rTxt.Len());
554 :
555 0 : if(bCaseMapLengthDiffers)
556 : {
557 : // If strings differ work preparing the necessary snippet to address that
558 : // potential difference
559 0 : const XubString aSnippet(rTxt, nIdx, nTmp);
560 0 : XubString _aNewText = CalcCaseMap(aSnippet);
561 :
562 0 : pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.Len() );
563 : }
564 : else
565 : {
566 0 : pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp );
567 0 : }
568 : }
569 : }
570 0 : pOut->SetFont(aOldFont);
571 0 : pPrinter->SetFont( aOldPrnFont );
572 : }
573 :
574 :
575 75063 : SvxFont& SvxFont::operator=( const Font& rFont )
576 : {
577 75063 : Font::operator=( rFont );
578 75063 : return *this;
579 : }
580 :
581 91078 : SvxFont& SvxFont::operator=( const SvxFont& rFont )
582 : {
583 91078 : Font::operator=( rFont );
584 91078 : eLang = rFont.eLang;
585 91078 : eCaseMap = rFont.eCaseMap;
586 91078 : nEsc = rFont.nEsc;
587 91078 : nPropr = rFont.nPropr;
588 91078 : nKern = rFont.nKern;
589 91078 : return *this;
590 : }
591 :
592 : class SvxDoGetCapitalSize : public SvxDoCapitals
593 : {
594 : protected:
595 : SvxFont* pFont;
596 : Size aTxtSize;
597 : short nKern;
598 : public:
599 0 : SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut,
600 : const XubString &_rTxt, const xub_StrLen _nIdx,
601 : const xub_StrLen _nLen, const short _nKrn )
602 : : SvxDoCapitals( (OutputDevice*)_pOut, _rTxt, _nIdx, _nLen ),
603 : pFont( _pFnt ),
604 0 : nKern( _nKrn )
605 0 : { }
606 :
607 0 : virtual ~SvxDoGetCapitalSize() {}
608 :
609 : virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
610 : const xub_StrLen nLen, const sal_Bool bUpper );
611 :
612 0 : inline const Size &GetSize() const { return aTxtSize; };
613 : };
614 :
615 0 : void SvxDoGetCapitalSize::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
616 : const xub_StrLen _nLen, const sal_Bool bUpper )
617 : {
618 0 : Size aPartSize;
619 0 : if ( !bUpper )
620 : {
621 0 : sal_uInt8 nProp = pFont->GetPropr();
622 0 : pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
623 0 : pFont->SetPhysFont( pOut );
624 0 : aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
625 0 : aPartSize.setHeight( pOut->GetTextHeight() );
626 0 : aTxtSize.Height() = aPartSize.Height();
627 0 : pFont->SetPropr( nProp );
628 0 : pFont->SetPhysFont( pOut );
629 : }
630 : else
631 : {
632 0 : aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
633 0 : aPartSize.setHeight( pOut->GetTextHeight() );
634 : }
635 0 : aTxtSize.Width() += aPartSize.Width();
636 0 : aTxtSize.Width() += ( _nLen * long( nKern ) );
637 0 : }
638 :
639 0 : Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const XubString &rTxt,
640 : const xub_StrLen nIdx, const xub_StrLen nLen) const
641 : {
642 : // Start:
643 0 : SvxDoGetCapitalSize aDo( (SvxFont *)this, pOut, rTxt, nIdx, nLen, nKern );
644 0 : DoOnCapitals( aDo );
645 0 : Size aTxtSize( aDo.GetSize() );
646 :
647 : // End:
648 0 : if( !aTxtSize.Height() )
649 : {
650 0 : aTxtSize.setWidth( 0 );
651 0 : aTxtSize.setHeight( pOut->GetTextHeight() );
652 : }
653 0 : return aTxtSize;
654 : }
655 :
656 : class SvxDoDrawCapital : public SvxDoCapitals
657 : {
658 : protected:
659 : SvxFont *pFont;
660 : Point aPos;
661 : Point aSpacePos;
662 : short nKern;
663 : public:
664 0 : SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const XubString &_rTxt,
665 : const xub_StrLen _nIdx, const xub_StrLen _nLen,
666 : const Point &rPos, const short nKrn )
667 : : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ),
668 : pFont( pFnt ),
669 : aPos( rPos ),
670 : aSpacePos( rPos ),
671 0 : nKern( nKrn )
672 0 : { }
673 0 : virtual ~SvxDoDrawCapital() {}
674 : virtual void DoSpace( const sal_Bool bDraw );
675 : virtual void SetSpace();
676 : virtual void Do( const XubString &rTxt, const xub_StrLen nIdx,
677 : const xub_StrLen nLen, const sal_Bool bUpper );
678 : };
679 :
680 0 : void SvxDoDrawCapital::DoSpace( const sal_Bool bDraw )
681 : {
682 0 : if ( bDraw || pFont->IsWordLineMode() )
683 : {
684 0 : sal_uInt16 nDiff = (sal_uInt16)(aPos.X() - aSpacePos.X());
685 0 : if ( nDiff )
686 : {
687 0 : sal_Bool bWordWise = pFont->IsWordLineMode();
688 0 : sal_Bool bTrans = pFont->IsTransparent();
689 0 : pFont->SetWordLineMode( sal_False );
690 0 : pFont->SetTransparent( sal_True );
691 0 : pFont->SetPhysFont( pOut );
692 : pOut->DrawStretchText( aSpacePos, nDiff, XubString( sDoubleSpace,
693 0 : RTL_TEXTENCODING_MS_1252 ), 0, 2 );
694 0 : pFont->SetWordLineMode( bWordWise );
695 0 : pFont->SetTransparent( bTrans );
696 0 : pFont->SetPhysFont( pOut );
697 : }
698 : }
699 0 : }
700 :
701 0 : void SvxDoDrawCapital::SetSpace()
702 : {
703 0 : if ( pFont->IsWordLineMode() )
704 0 : aSpacePos.X() = aPos.X();
705 0 : }
706 :
707 0 : void SvxDoDrawCapital::Do( const XubString &_rTxt, const xub_StrLen _nIdx,
708 : const xub_StrLen _nLen, const sal_Bool bUpper)
709 : {
710 0 : sal_uInt8 nProp = 0;
711 0 : Size aPartSize;
712 :
713 : // Set the desired font
714 0 : FontUnderline eUnder = pFont->GetUnderline();
715 0 : FontStrikeout eStrike = pFont->GetStrikeout();
716 0 : pFont->SetUnderline( UNDERLINE_NONE );
717 0 : pFont->SetStrikeout( STRIKEOUT_NONE );
718 0 : if ( !bUpper )
719 : {
720 0 : nProp = pFont->GetPropr();
721 0 : pFont->SetProprRel( SMALL_CAPS_PERCENTAGE );
722 : }
723 0 : pFont->SetPhysFont( pOut );
724 :
725 0 : aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) );
726 0 : aPartSize.setHeight( pOut->GetTextHeight() );
727 0 : long nWidth = aPartSize.Width();
728 0 : if ( nKern )
729 : {
730 0 : aPos.X() += (nKern/2);
731 0 : if ( _nLen ) nWidth += (_nLen*long(nKern));
732 : }
733 0 : pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen);
734 :
735 : // Restore Font
736 0 : pFont->SetUnderline( eUnder );
737 0 : pFont->SetStrikeout( eStrike );
738 0 : if ( !bUpper )
739 0 : pFont->SetPropr( nProp );
740 0 : pFont->SetPhysFont( pOut );
741 :
742 0 : aPos.X() += nWidth-(nKern/2);
743 0 : }
744 :
745 : /*************************************************************************
746 : * SvxFont::DrawCapital() draws the uppercase letter.
747 : *************************************************************************/
748 :
749 0 : void SvxFont::DrawCapital( OutputDevice *pOut,
750 : const Point &rPos, const XubString &rTxt,
751 : const xub_StrLen nIdx, const xub_StrLen nLen ) const
752 : {
753 0 : SvxDoDrawCapital aDo( (SvxFont *)this,pOut,rTxt,nIdx,nLen,rPos,nKern );
754 0 : DoOnCapitals( aDo );
755 0 : }
756 :
757 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|