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