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