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 <hintids.hxx>
21 : #include <editeng/cmapitem.hxx>
22 : #include <editeng/svxfont.hxx>
23 :
24 : #include <vcl/outdev.hxx>
25 : #include <com/sun/star/i18n/CharType.hpp>
26 : #include <com/sun/star/i18n/WordType.hpp>
27 :
28 : #include <vcl/print.hxx>
29 : #include <fntcache.hxx>
30 : #include <swfont.hxx>
31 : #include <breakit.hxx>
32 : #include <txtfrm.hxx>
33 : #include <scriptinfo.hxx>
34 : #include <fntcap.hxx>
35 :
36 : using namespace ::com::sun::star::i18n;
37 :
38 : // The information encapsulated in SwCapitalInfo is required
39 : // by the ::Do functions. They contain the information about
40 : // the original string, whereas rDo.GetInf() contains information
41 : // about the display string.
42 : class SwCapitalInfo
43 : {
44 : public:
45 440 : explicit SwCapitalInfo( const OUString& rOrigText ) :
46 440 : rString( rOrigText ), nIdx( 0 ), nLen( 0 ) {};
47 : const OUString& rString;
48 : sal_Int32 nIdx;
49 : sal_Int32 nLen;
50 : };
51 :
52 : // rFnt: required for CalcCaseMap
53 : // rOrigString: The original string
54 : // nOfst: Position of the substring in rOrigString
55 : // nLen: Length if the substring in rOrigString
56 : // nIdx: Referes to a position in the display string and should be mapped
57 : // to a position in rOrigString
58 0 : sal_Int32 sw_CalcCaseMap( const SwFont& rFnt,
59 : const OUString& rOrigString,
60 : sal_Int32 nOfst,
61 : sal_Int32 nLen,
62 : sal_Int32 nIdx )
63 : {
64 0 : int j = 0;
65 0 : const sal_Int32 nEnd = nOfst + nLen;
66 : OSL_ENSURE( nEnd <= rOrigString.getLength(), "sw_CalcCaseMap: Wrong parameters" );
67 :
68 : // special case for title case:
69 0 : const bool bTitle = SVX_CASEMAP_TITEL == rFnt.GetCaseMap() &&
70 0 : g_pBreakIt->GetBreakIter().is();
71 0 : for ( sal_Int32 i = nOfst; i < nEnd; ++i )
72 : {
73 0 : OUString aTmp(rOrigString.copy(i, 1));
74 :
75 0 : if ( !bTitle ||
76 0 : g_pBreakIt->GetBreakIter()->isBeginWord(
77 : rOrigString, i,
78 0 : g_pBreakIt->GetLocale( rFnt.GetLanguage() ),
79 0 : WordType::ANYWORD_IGNOREWHITESPACES ) )
80 0 : aTmp = rFnt.GetActualFont().CalcCaseMap( aTmp );
81 :
82 0 : j += aTmp.getLength();
83 :
84 0 : if ( j > nIdx )
85 0 : return i;
86 0 : }
87 :
88 0 : return nOfst + nLen;
89 : }
90 :
91 : class SwDoCapitals
92 : {
93 : protected:
94 : SwDrawTextInfo &rInf;
95 : SwCapitalInfo* pCapInf; // referes to additional information
96 : // required by the ::Do function
97 440 : SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { }
98 440 : ~SwDoCapitals() {}
99 : public:
100 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
101 : virtual void Do() = 0;
102 4296 : inline OutputDevice& GetOut() { return rInf.GetOut(); }
103 40058 : inline SwDrawTextInfo& GetInf() { return rInf; }
104 4 : inline SwCapitalInfo* GetCapInf() const { return pCapInf; }
105 0 : inline void SetCapInf( SwCapitalInfo& rNew ) { pCapInf = &rNew; }
106 : };
107 :
108 : class SwDoGetCapitalSize : public SwDoCapitals
109 : {
110 : protected:
111 : Size aTxtSize;
112 : public:
113 322 : SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
114 322 : virtual ~SwDoGetCapitalSize() {}
115 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
116 : virtual void Do() SAL_OVERRIDE;
117 322 : const Size &GetSize() const { return aTxtSize; }
118 : };
119 :
120 322 : void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
121 : {
122 322 : aTxtSize.Height() = 0;
123 322 : aTxtSize.Width() = 0;
124 322 : }
125 :
126 2306 : void SwDoGetCapitalSize::Do()
127 : {
128 2306 : aTxtSize.Width() += rInf.GetSize().Width();
129 2306 : if( rInf.GetUpper() )
130 1254 : aTxtSize.Height() = rInf.GetSize().Height();
131 2306 : }
132 :
133 322 : Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf )
134 : {
135 : // Start:
136 322 : const long nOldKern = rInf.GetKern();
137 322 : rInf.SetKern( CheckKerning() );
138 322 : Point aPos;
139 322 : rInf.SetPos( aPos );
140 322 : rInf.SetSpace( 0 );
141 322 : rInf.SetDrawSpace( false );
142 322 : SwDoGetCapitalSize aDo( rInf );
143 322 : DoOnCapitals( aDo );
144 322 : Size aTxtSize( aDo.GetSize() );
145 :
146 : // End:
147 322 : if( !aTxtSize.Height() )
148 : {
149 : SV_STAT( nGetTextSize );
150 26 : aTxtSize.Height() = short ( rInf.GetpOut()->GetTextHeight() );
151 : }
152 322 : rInf.SetKern( nOldKern );
153 322 : return aTxtSize;
154 : }
155 :
156 : class SwDoGetCapitalBreak : public SwDoCapitals
157 : {
158 : protected:
159 : long nTxtWidth;
160 : sal_Int32 m_nBreak;
161 : public:
162 4 : SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long const nWidth)
163 : : SwDoCapitals ( rInfo )
164 : , nTxtWidth( nWidth )
165 4 : , m_nBreak( -1 )
166 4 : { }
167 4 : virtual ~SwDoGetCapitalBreak() {}
168 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
169 : virtual void Do() SAL_OVERRIDE;
170 4 : sal_Int32 getBreak() const { return m_nBreak; }
171 : };
172 :
173 4 : void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
174 : {
175 4 : }
176 :
177 12 : void SwDoGetCapitalBreak::Do()
178 : {
179 12 : if ( nTxtWidth )
180 : {
181 12 : if ( rInf.GetSize().Width() < nTxtWidth )
182 8 : nTxtWidth -= rInf.GetSize().Width();
183 : else
184 : {
185 4 : sal_Int32 nEnd = rInf.GetEnd();
186 4 : m_nBreak = GetOut().GetTextBreak( rInf.GetText(), nTxtWidth,
187 8 : rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() );
188 :
189 4 : if (m_nBreak > nEnd || m_nBreak < 0)
190 0 : m_nBreak = nEnd;
191 :
192 : // m_nBreak may be relative to the display string. It has to be
193 : // calculated relative to the original string:
194 4 : if ( GetCapInf() )
195 : {
196 0 : if ( GetCapInf()->nLen != rInf.GetLen() )
197 0 : m_nBreak = sw_CalcCaseMap( *rInf.GetFont(),
198 0 : GetCapInf()->rString,
199 0 : GetCapInf()->nIdx,
200 0 : GetCapInf()->nLen, m_nBreak );
201 : else
202 0 : m_nBreak = m_nBreak + GetCapInf()->nIdx;
203 : }
204 :
205 4 : nTxtWidth = 0;
206 : }
207 : }
208 12 : }
209 :
210 4 : sal_Int32 SwFont::GetCapitalBreak( SwViewShell const * pSh, const OutputDevice* pOut,
211 : const SwScriptInfo* pScript, const OUString& rTxt, long const nTextWidth,
212 : const sal_Int32 nIdx, const sal_Int32 nLen )
213 : {
214 : // Start:
215 4 : Point aPos( 0, 0 );
216 : SwDrawTextInfo aInfo(pSh, *(OutputDevice*)pOut, pScript, rTxt, nIdx, nLen,
217 4 : 0, false);
218 4 : aInfo.SetPos( aPos );
219 4 : aInfo.SetSpace( 0 );
220 4 : aInfo.SetWrong( NULL );
221 4 : aInfo.SetGrammarCheck( NULL );
222 4 : aInfo.SetSmartTags( NULL );
223 4 : aInfo.SetDrawSpace( false );
224 4 : aInfo.SetKern( CheckKerning() );
225 4 : aInfo.SetKanaComp( pScript ? 0 : 100 );
226 4 : aInfo.SetFont( this );
227 :
228 8 : SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
229 4 : DoOnCapitals( aDo );
230 8 : return aDo.getBreak();
231 : }
232 :
233 : class SwDoDrawCapital : public SwDoCapitals
234 : {
235 : protected:
236 : SwFntObj *pUpperFnt;
237 : SwFntObj *pLowerFnt;
238 : public:
239 114 : SwDoDrawCapital( SwDrawTextInfo &rInfo ) :
240 114 : SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0)
241 114 : { }
242 114 : virtual ~SwDoDrawCapital() {}
243 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
244 : virtual void Do() SAL_OVERRIDE;
245 : void DrawSpace( Point &rPos );
246 : };
247 :
248 114 : void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
249 : {
250 114 : pUpperFnt = pUpperFont;
251 114 : pLowerFnt = pLowerFont;
252 114 : }
253 :
254 1014 : void SwDoDrawCapital::Do()
255 : {
256 : SV_STAT( nDrawText );
257 1014 : const sal_uInt16 nOrgWidth = rInf.GetWidth();
258 1014 : rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) );
259 1014 : if ( rInf.GetUpper() )
260 552 : pUpperFnt->DrawText( rInf );
261 : else
262 : {
263 462 : bool bOldBullet = rInf.GetBullet();
264 462 : rInf.SetBullet( false );
265 462 : pLowerFnt->DrawText( rInf );
266 462 : rInf.SetBullet( bOldBullet );
267 : }
268 :
269 : OSL_ENSURE( pUpperFnt, "No upper font, dying soon!");
270 1014 : rInf.Shift( pUpperFnt->GetFont().GetOrientation() );
271 1014 : rInf.SetWidth( nOrgWidth );
272 1014 : }
273 :
274 6 : void SwDoDrawCapital::DrawSpace( Point &rPos )
275 : {
276 6 : long nDiff = rInf.GetPos().X() - rPos.X();
277 :
278 6 : Point aPos( rPos );
279 6 : const bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
280 6 : ! rInf.IsIgnoreFrmRTL();
281 :
282 6 : if ( bSwitchL2R )
283 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
284 :
285 6 : const ComplexTextLayoutMode nMode = rInf.GetpOut()->GetLayoutMode();
286 6 : const bool bBidiPor = ( bSwitchL2R !=
287 6 : ( TEXT_LAYOUT_DEFAULT != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
288 :
289 6 : if ( bBidiPor )
290 0 : nDiff = -nDiff;
291 :
292 6 : if ( rInf.GetFrm()->IsVertical() )
293 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
294 :
295 6 : if ( nDiff )
296 : {
297 6 : rInf.ApplyAutoColor();
298 6 : GetOut().DrawStretchText( aPos, nDiff,
299 12 : OUString(" "), 0, 2 );
300 : }
301 6 : rPos.X() = rInf.GetPos().X() + rInf.GetWidth();
302 6 : }
303 :
304 114 : void SwSubFont::DrawCapital( SwDrawTextInfo &rInf )
305 : {
306 : // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
307 : // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
308 222 : rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
309 222 : GetOverline() != UNDERLINE_NONE ||
310 222 : GetStrikeout() != STRIKEOUT_NONE );
311 114 : SwDoDrawCapital aDo( rInf );
312 114 : DoOnCapitals( aDo );
313 114 : }
314 :
315 : class SwDoCapitalCrsrOfst : public SwDoCapitals
316 : {
317 : protected:
318 : SwFntObj *pUpperFnt;
319 : SwFntObj *pLowerFnt;
320 : sal_Int32 nCrsr;
321 : sal_uInt16 nOfst;
322 : public:
323 0 : SwDoCapitalCrsrOfst( SwDrawTextInfo &rInfo, const sal_uInt16 nOfs ) :
324 0 : SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0), nCrsr( 0 ), nOfst( nOfs )
325 0 : { }
326 0 : virtual ~SwDoCapitalCrsrOfst() {}
327 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
328 : virtual void Do() SAL_OVERRIDE;
329 :
330 0 : inline sal_Int32 GetCrsr(){ return nCrsr; }
331 : };
332 :
333 0 : void SwDoCapitalCrsrOfst::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
334 : {
335 0 : pUpperFnt = pUpperFont;
336 0 : pLowerFnt = pLowerFont;
337 0 : }
338 :
339 0 : void SwDoCapitalCrsrOfst::Do()
340 : {
341 0 : if ( nOfst )
342 : {
343 0 : if ( static_cast<long>(nOfst) > rInf.GetSize().Width() )
344 : {
345 0 : nOfst -= rInf.GetSize().Width();
346 0 : nCrsr = nCrsr + rInf.GetLen();
347 : }
348 : else
349 : {
350 0 : SwDrawTextInfo aDrawInf( rInf.GetShell(), *rInf.GetpOut(),
351 : rInf.GetScriptInfo(),
352 0 : rInf.GetText(),
353 : rInf.GetIdx(),
354 0 : rInf.GetLen(), 0, false );
355 0 : aDrawInf.SetOfst( nOfst );
356 0 : aDrawInf.SetKern( rInf.GetKern() );
357 0 : aDrawInf.SetKanaComp( rInf.GetKanaComp() );
358 0 : aDrawInf.SetFrm( rInf.GetFrm() );
359 0 : aDrawInf.SetFont( rInf.GetFont() );
360 :
361 0 : if ( rInf.GetUpper() )
362 : {
363 0 : aDrawInf.SetSpace( 0 );
364 0 : nCrsr = nCrsr + pUpperFnt->GetCrsrOfst( aDrawInf );
365 : }
366 : else
367 : {
368 0 : aDrawInf.SetSpace( rInf.GetSpace() );
369 0 : nCrsr = nCrsr + pLowerFnt->GetCrsrOfst( aDrawInf );
370 : }
371 0 : nOfst = 0;
372 : }
373 : }
374 0 : }
375 :
376 0 : sal_Int32 SwSubFont::GetCapitalCrsrOfst( SwDrawTextInfo& rInf )
377 : {
378 0 : const long nOldKern = rInf.GetKern();
379 0 : rInf.SetKern( CheckKerning() );
380 0 : SwDoCapitalCrsrOfst aDo( rInf, rInf.GetOfst() );
381 0 : Point aPos;
382 0 : rInf.SetPos( aPos );
383 0 : rInf.SetDrawSpace( false );
384 0 : DoOnCapitals( aDo );
385 0 : rInf.SetKern( nOldKern );
386 0 : return aDo.GetCrsr();
387 : }
388 :
389 : class SwDoDrawStretchCapital : public SwDoDrawCapital
390 : {
391 : const sal_Int32 nStrLen;
392 : const sal_uInt16 nCapWidth;
393 : const sal_uInt16 nOrgWidth;
394 : public:
395 : virtual void Do() SAL_OVERRIDE;
396 :
397 0 : SwDoDrawStretchCapital( SwDrawTextInfo &rInfo, const sal_uInt16 nCapitalWidth )
398 : : SwDoDrawCapital( rInfo ),
399 0 : nStrLen( rInfo.GetLen() ),
400 : nCapWidth( nCapitalWidth ),
401 0 : nOrgWidth( rInfo.GetWidth() )
402 0 : { }
403 :
404 0 : virtual ~SwDoDrawStretchCapital() {}
405 : };
406 :
407 0 : void SwDoDrawStretchCapital::Do()
408 : {
409 : SV_STAT( nDrawStretchText );
410 0 : long nPartWidth = rInf.GetSize().Width();
411 :
412 0 : if( rInf.GetLen() )
413 : {
414 : // 4023: Kapitaelchen und Kerning.
415 0 : long nDiff = long(nOrgWidth) - long(nCapWidth);
416 0 : if( nDiff )
417 : {
418 0 : nDiff *= rInf.GetLen();
419 0 : nDiff /= nStrLen;
420 0 : nDiff += nPartWidth;
421 0 : if( 0 < nDiff )
422 0 : nPartWidth = nDiff;
423 : }
424 :
425 0 : rInf.ApplyAutoColor();
426 :
427 0 : Point aPos( rInf.GetPos() );
428 0 : const bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
429 0 : ! rInf.IsIgnoreFrmRTL();
430 :
431 0 : if ( bSwitchL2R )
432 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
433 :
434 0 : if ( rInf.GetFrm()->IsVertical() )
435 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
436 :
437 : // Optimierung:
438 0 : if( 1 >= rInf.GetLen() )
439 0 : GetOut().DrawText( aPos, rInf.GetText(), rInf.GetIdx(),
440 0 : rInf.GetLen() );
441 : else
442 0 : GetOut().DrawStretchText( aPos, nPartWidth,
443 0 : rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
444 : }
445 0 : ((Point&)rInf.GetPos()).X() += nPartWidth;
446 0 : }
447 :
448 0 : void SwSubFont::DrawStretchCapital( SwDrawTextInfo &rInf )
449 : {
450 : // Es wird vorausgesetzt, dass rPos bereits kalkuliert ist!
451 : // hochgezogen in SwFont: const Point aPos( CalcPos(rPos) );
452 :
453 0 : if( rInf.GetLen() == COMPLETE_STRING )
454 0 : rInf.SetLen( rInf.GetText().getLength() );
455 :
456 0 : const Point aOldPos = rInf.GetPos();
457 0 : const sal_uInt16 nCapWidth = (sal_uInt16)( GetCapitalSize( rInf ).Width() );
458 0 : rInf.SetPos(aOldPos);
459 :
460 0 : rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
461 0 : GetOverline() != UNDERLINE_NONE ||
462 0 : GetStrikeout() != STRIKEOUT_NONE );
463 0 : SwDoDrawStretchCapital aDo( rInf, nCapWidth );
464 0 : DoOnCapitals( aDo );
465 0 : }
466 :
467 440 : void SwSubFont::DoOnCapitals( SwDoCapitals &rDo )
468 : {
469 : OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
470 :
471 440 : long nKana = 0;
472 440 : const OUString aTxt( CalcCaseMap( rDo.GetInf().GetText() ) );
473 440 : sal_Int32 nMaxPos = std::min( rDo.GetInf().GetText().getLength() - rDo.GetInf().GetIdx(),
474 880 : rDo.GetInf().GetLen() );
475 440 : rDo.GetInf().SetLen( nMaxPos );
476 :
477 880 : const OUString oldText = rDo.GetInf().GetText();
478 440 : rDo.GetInf().SetText( aTxt );
479 440 : sal_Int32 nPos = rDo.GetInf().GetIdx();
480 440 : sal_Int32 nOldPos = nPos;
481 440 : nMaxPos = nMaxPos + nPos;
482 :
483 : // #107816#
484 : // Look if the length of the original text and the ToUpper-converted
485 : // text is different. If yes, do special handling.
486 880 : OUString aNewText;
487 440 : SwCapitalInfo aCapInf(oldText);
488 440 : bool bCaseMapLengthDiffers(aTxt.getLength() != oldText.getLength());
489 440 : if ( bCaseMapLengthDiffers )
490 0 : rDo.SetCapInf( aCapInf );
491 :
492 440 : SwFntObj *pOldLast = pLastFont;
493 440 : SwFntAccess *pBigFontAccess = NULL;
494 : SwFntObj *pBigFont;
495 440 : SwFntAccess *pSpaceFontAccess = NULL;
496 440 : SwFntObj *pSpaceFont = NULL;
497 :
498 440 : const void *pMagic2 = NULL;
499 440 : sal_uInt16 nIndex2 = 0;
500 880 : SwSubFont aFont( *this );
501 440 : Point aStartPos( rDo.GetInf().GetPos() );
502 :
503 440 : const bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE
504 298 : || aFont.GetOverline() != UNDERLINE_NONE
505 738 : || aFont.GetStrikeout() != STRIKEOUT_NONE;
506 440 : const bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
507 440 : rDo.GetInf().GetDrawSpace();
508 440 : const long nTmpKern = rDo.GetInf().GetKern();
509 :
510 440 : if ( bTextLines )
511 : {
512 142 : if ( bWordWise )
513 : {
514 0 : aFont.SetWordLineMode( false );
515 : pSpaceFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
516 0 : rDo.GetInf().GetShell() );
517 0 : pSpaceFont = pSpaceFontAccess->Get();
518 : }
519 : else
520 142 : pSpaceFont = pLastFont;
521 :
522 : // Wir basteln uns einen Font fuer die Grossbuchstaben:
523 142 : aFont.SetUnderline( UNDERLINE_NONE );
524 142 : aFont.SetOverline( UNDERLINE_NONE );
525 142 : aFont.SetStrikeout( STRIKEOUT_NONE );
526 142 : pMagic2 = NULL;
527 142 : nIndex2 = 0;
528 : pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
529 142 : rDo.GetInf().GetShell() );
530 142 : pBigFont = pBigFontAccess->Get();
531 : }
532 : else
533 298 : pBigFont = pLastFont;
534 :
535 : // Older LO versions had 66 as the small caps percentage size, later changed to 80,
536 : // therefore a backwards compatibility option is kept (otherwise layout is changed).
537 : // NOTE: There are more uses of SMALL_CAPS_PERCENTAGE in editeng, but it seems they
538 : // do not matter for Writer (and if they did it'd be pretty ugly to propagate
539 : // the option there).
540 440 : int smallCapsPercentage = smallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE;
541 440 : aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 );
542 440 : pMagic2 = NULL;
543 440 : nIndex2 = 0;
544 : SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
545 440 : rDo.GetInf().GetShell() );
546 440 : SwFntObj *pSmallFont = pSmallFontAccess->Get();
547 :
548 440 : rDo.Init( pBigFont, pSmallFont );
549 440 : OutputDevice* pOutSize = pSmallFont->GetPrt();
550 440 : if( !pOutSize )
551 68 : pOutSize = &rDo.GetOut();
552 440 : OutputDevice* pOldOut = &rDo.GetOut();
553 :
554 440 : const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
555 440 : ? LANGUAGE_SYSTEM : GetLanguage();
556 :
557 440 : if( nPos < nMaxPos )
558 : {
559 880 : nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
560 : oldText, nPos,
561 440 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
562 440 : if (nPos < 0)
563 400 : nPos = nOldPos;
564 40 : else if( nPos > nMaxPos )
565 12 : nPos = nMaxPos;
566 : }
567 :
568 2802 : while( nOldPos < nMaxPos )
569 : {
570 :
571 : // The lower ones...
572 1922 : if( nOldPos != nPos )
573 : {
574 : SV_STAT( nGetTextSize );
575 1522 : pLastFont = pSmallFont;
576 1522 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
577 :
578 : // #107816#, #i14820#
579 1522 : if( bCaseMapLengthDiffers )
580 : {
581 : // Build an own 'changed' string for the given part of the
582 : // source string and use it. That new string may differ in length
583 : // from the source string.
584 0 : const OUString aSnippet(oldText.copy(nOldPos, nPos - nOldPos));
585 0 : aNewText = CalcCaseMap( aSnippet );
586 0 : aCapInf.nIdx = nOldPos;
587 0 : aCapInf.nLen = nPos - nOldPos;
588 0 : rDo.GetInf().SetIdx( 0 );
589 0 : rDo.GetInf().SetLen( aNewText.getLength() );
590 0 : rDo.GetInf().SetText( aNewText );
591 : }
592 : else
593 : {
594 1522 : rDo.GetInf().SetIdx( nOldPos );
595 1522 : rDo.GetInf().SetLen( nPos - nOldPos );
596 : }
597 :
598 1522 : rDo.GetInf().SetUpper( false );
599 1522 : rDo.GetInf().SetOut( *pOutSize );
600 1522 : Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
601 1522 : nKana += rDo.GetInf().GetKanaDiff();
602 1522 : rDo.GetInf().SetOut( *pOldOut );
603 1522 : if( nTmpKern && nPos < nMaxPos )
604 18 : aPartSize.Width() += nTmpKern;
605 1522 : rDo.GetInf().SetSize( aPartSize );
606 1522 : rDo.Do();
607 1522 : nOldPos = nPos;
608 : }
609 3844 : nPos = g_pBreakIt->GetBreakIter()->nextCharBlock(
610 : oldText, nPos,
611 1922 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
612 1922 : if (nPos < 0 || nPos > nMaxPos)
613 436 : nPos = nMaxPos;
614 : OSL_ENSURE( nPos, "nextCharBlock not implemented?" );
615 : #if OSL_DEBUG_LEVEL > 1
616 : if( !nPos )
617 : nPos = nMaxPos;
618 : #endif
619 : // The upper ones...
620 1922 : if( nOldPos != nPos )
621 : {
622 1810 : const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
623 :
624 1810 : do
625 : {
626 1810 : rDo.GetInf().SetUpper( true );
627 1810 : pLastFont = pBigFont;
628 1810 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
629 : sal_Int32 nTmp;
630 1810 : if( bWordWise )
631 : {
632 0 : nTmp = nOldPos;
633 0 : while (nTmp < nPos && CH_BLANK == oldText[nTmp])
634 0 : ++nTmp;
635 0 : if( nOldPos < nTmp )
636 : {
637 0 : pLastFont = pSpaceFont;
638 0 : pLastFont->SetDevFont( rDo.GetInf().GetShell(),
639 0 : rDo.GetOut() );
640 0 : ((SwDoDrawCapital&)rDo).DrawSpace( aStartPos );
641 0 : pLastFont = pBigFont;
642 0 : pLastFont->SetDevFont( rDo.GetInf().GetShell(),
643 0 : rDo.GetOut() );
644 :
645 : // #107816#, #i14820#
646 0 : if( bCaseMapLengthDiffers )
647 : {
648 : // Build an own 'changed' string for the given part of the
649 : // source string and use it. That new string may differ in length
650 : // from the source string.
651 0 : const OUString aSnippet(oldText.copy(nOldPos, nTmp - nOldPos));
652 0 : aNewText = CalcCaseMap( aSnippet );
653 0 : aCapInf.nIdx = nOldPos;
654 0 : aCapInf.nLen = nTmp - nOldPos;
655 0 : rDo.GetInf().SetIdx( 0 );
656 0 : rDo.GetInf().SetLen( aNewText.getLength() );
657 0 : rDo.GetInf().SetText( aNewText );
658 : }
659 : else
660 : {
661 0 : rDo.GetInf().SetIdx( nOldPos );
662 0 : rDo.GetInf().SetLen( nTmp - nOldPos );
663 : }
664 :
665 0 : rDo.GetInf().SetOut( *pOutSize );
666 0 : Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
667 0 : nKana += rDo.GetInf().GetKanaDiff();
668 0 : rDo.GetInf().SetOut( *pOldOut );
669 0 : if( nSpaceAdd )
670 0 : aPartSize.Width() += nSpaceAdd * ( nTmp - nOldPos );
671 0 : if( nTmpKern && nPos < nMaxPos )
672 0 : aPartSize.Width() += nTmpKern;
673 0 : rDo.GetInf().SetSize( aPartSize );
674 0 : rDo.Do();
675 0 : aStartPos = rDo.GetInf().GetPos();
676 0 : nOldPos = nTmp;
677 : }
678 :
679 0 : while (nTmp < nPos && CH_BLANK != oldText[nTmp])
680 0 : ++nTmp;
681 : }
682 : else
683 1810 : nTmp = nPos;
684 1810 : if( nTmp > nOldPos )
685 : {
686 : // #107816#, #i14820#
687 1810 : if( bCaseMapLengthDiffers )
688 : {
689 : // Build an own 'changed' string for the given part of the
690 : // source string and use it. That new string may differ in length
691 : // from the source string.
692 0 : const OUString aSnippet(oldText.copy(nOldPos, nTmp - nOldPos));
693 0 : aNewText = CalcCaseMap( aSnippet );
694 0 : aCapInf.nIdx = nOldPos;
695 0 : aCapInf.nLen = nTmp - nOldPos;
696 0 : rDo.GetInf().SetIdx( 0 );
697 0 : rDo.GetInf().SetLen( aNewText.getLength() );
698 0 : rDo.GetInf().SetText( aNewText );
699 : }
700 : else
701 : {
702 1810 : rDo.GetInf().SetIdx( nOldPos );
703 1810 : rDo.GetInf().SetLen( nTmp - nOldPos );
704 : }
705 :
706 1810 : rDo.GetInf().SetOut( *pOutSize );
707 1810 : Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
708 1810 : nKana += rDo.GetInf().GetKanaDiff();
709 1810 : rDo.GetInf().SetOut( *pOldOut );
710 1810 : if( !bWordWise && rDo.GetInf().GetSpace() )
711 : {
712 0 : for( sal_Int32 nI = nOldPos; nI < nPos; ++nI )
713 : {
714 0 : if (CH_BLANK == oldText[nI])
715 0 : aPartSize.Width() += nSpaceAdd;
716 : }
717 : }
718 1810 : if( nTmpKern && nPos < nMaxPos )
719 24 : aPartSize.Width() += nTmpKern;
720 1810 : rDo.GetInf().SetSize( aPartSize );
721 1810 : rDo.Do();
722 1810 : nOldPos = nTmp;
723 : }
724 : } while( nOldPos != nPos );
725 : }
726 3844 : nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
727 : oldText, nPos,
728 1922 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
729 1922 : if (nPos < 0 || nPos > nMaxPos)
730 444 : nPos = nMaxPos;
731 : OSL_ENSURE( nPos, "endOfCharBlock not implemented?" );
732 : #if OSL_DEBUG_LEVEL > 1
733 : if( !nPos )
734 : nPos = nMaxPos;
735 : #endif
736 : }
737 :
738 : // Aufraeumen:
739 440 : if( pBigFont != pOldLast )
740 142 : delete pBigFontAccess;
741 :
742 440 : if( bTextLines )
743 : {
744 142 : if( rDo.GetInf().GetDrawSpace() )
745 : {
746 6 : pLastFont = pSpaceFont;
747 6 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
748 6 : ( (SwDoDrawCapital&) rDo ).DrawSpace( aStartPos );
749 : }
750 142 : if ( bWordWise )
751 0 : delete pSpaceFontAccess;
752 : }
753 440 : pLastFont = pOldLast;
754 440 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
755 :
756 440 : delete pSmallFontAccess;
757 440 : rDo.GetInf().SetText(oldText);
758 880 : rDo.GetInf().SetKanaDiff( nKana );
759 710 : }
760 :
761 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|