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 220 : explicit SwCapitalInfo( const OUString& rOrigText ) :
46 220 : 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 220 : explicit SwDoCapitals ( SwDrawTextInfo &rInfo ) : rInf( rInfo ), pCapInf( 0 ) { }
98 220 : ~SwDoCapitals() {}
99 : public:
100 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) = 0;
101 : virtual void Do() = 0;
102 2148 : inline OutputDevice& GetOut() { return rInf.GetOut(); }
103 20029 : inline SwDrawTextInfo& GetInf() { return rInf; }
104 2 : 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 aTextSize;
112 : public:
113 161 : explicit SwDoGetCapitalSize( SwDrawTextInfo &rInfo ) : SwDoCapitals ( rInfo ) { }
114 161 : virtual ~SwDoGetCapitalSize() {}
115 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
116 : virtual void Do() SAL_OVERRIDE;
117 161 : const Size &GetSize() const { return aTextSize; }
118 : };
119 :
120 161 : void SwDoGetCapitalSize::Init( SwFntObj *, SwFntObj * )
121 : {
122 161 : aTextSize.Height() = 0;
123 161 : aTextSize.Width() = 0;
124 161 : }
125 :
126 1153 : void SwDoGetCapitalSize::Do()
127 : {
128 1153 : aTextSize.Width() += rInf.GetSize().Width();
129 1153 : if( rInf.GetUpper() )
130 627 : aTextSize.Height() = rInf.GetSize().Height();
131 1153 : }
132 :
133 161 : Size SwSubFont::GetCapitalSize( SwDrawTextInfo& rInf )
134 : {
135 : // Start:
136 161 : const long nOldKern = rInf.GetKern();
137 161 : rInf.SetKern( CheckKerning() );
138 161 : Point aPos;
139 161 : rInf.SetPos( aPos );
140 161 : rInf.SetSpace( 0 );
141 161 : rInf.SetDrawSpace( false );
142 161 : SwDoGetCapitalSize aDo( rInf );
143 161 : DoOnCapitals( aDo );
144 161 : Size aTextSize( aDo.GetSize() );
145 :
146 : // End:
147 161 : if( !aTextSize.Height() )
148 : {
149 : SV_STAT( nGetTextSize );
150 13 : aTextSize.Height() = short ( rInf.GetpOut()->GetTextHeight() );
151 : }
152 161 : rInf.SetKern( nOldKern );
153 161 : return aTextSize;
154 : }
155 :
156 : class SwDoGetCapitalBreak : public SwDoCapitals
157 : {
158 : protected:
159 : long nTextWidth;
160 : sal_Int32 m_nBreak;
161 : public:
162 2 : SwDoGetCapitalBreak( SwDrawTextInfo &rInfo, long const nWidth)
163 : : SwDoCapitals ( rInfo )
164 : , nTextWidth( nWidth )
165 2 : , m_nBreak( -1 )
166 2 : { }
167 2 : virtual ~SwDoGetCapitalBreak() {}
168 : virtual void Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont ) SAL_OVERRIDE;
169 : virtual void Do() SAL_OVERRIDE;
170 2 : sal_Int32 getBreak() const { return m_nBreak; }
171 : };
172 :
173 2 : void SwDoGetCapitalBreak::Init( SwFntObj *, SwFntObj * )
174 : {
175 2 : }
176 :
177 6 : void SwDoGetCapitalBreak::Do()
178 : {
179 6 : if ( nTextWidth )
180 : {
181 6 : if ( rInf.GetSize().Width() < nTextWidth )
182 4 : nTextWidth -= rInf.GetSize().Width();
183 : else
184 : {
185 2 : sal_Int32 nEnd = rInf.GetEnd();
186 2 : m_nBreak = GetOut().GetTextBreak( rInf.GetText(), nTextWidth,
187 4 : rInf.GetIdx(), rInf.GetLen(), rInf.GetKern() );
188 :
189 2 : 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 2 : 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 2 : nTextWidth = 0;
206 : }
207 : }
208 6 : }
209 :
210 2 : sal_Int32 SwFont::GetCapitalBreak( SwViewShell const * pSh, const OutputDevice* pOut,
211 : const SwScriptInfo* pScript, const OUString& rText, long const nTextWidth,
212 : const sal_Int32 nIdx, const sal_Int32 nLen )
213 : {
214 : // Start:
215 2 : Point aPos( 0, 0 );
216 : SwDrawTextInfo aInfo(pSh, *const_cast<OutputDevice*>(pOut), pScript, rText, nIdx, nLen,
217 2 : 0, false);
218 2 : aInfo.SetPos( aPos );
219 2 : aInfo.SetSpace( 0 );
220 2 : aInfo.SetWrong( NULL );
221 2 : aInfo.SetGrammarCheck( NULL );
222 2 : aInfo.SetSmartTags( NULL );
223 2 : aInfo.SetDrawSpace( false );
224 2 : aInfo.SetKern( CheckKerning() );
225 2 : aInfo.SetKanaComp( pScript ? 0 : 100 );
226 2 : aInfo.SetFont( this );
227 :
228 4 : SwDoGetCapitalBreak aDo(aInfo, nTextWidth);
229 2 : DoOnCapitals( aDo );
230 4 : return aDo.getBreak();
231 : }
232 :
233 : class SwDoDrawCapital : public SwDoCapitals
234 : {
235 : protected:
236 : SwFntObj *pUpperFnt;
237 : SwFntObj *pLowerFnt;
238 : public:
239 57 : explicit SwDoDrawCapital( SwDrawTextInfo &rInfo ) :
240 57 : SwDoCapitals( rInfo ), pUpperFnt(0), pLowerFnt(0)
241 57 : { }
242 57 : 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 57 : void SwDoDrawCapital::Init( SwFntObj *pUpperFont, SwFntObj *pLowerFont )
249 : {
250 57 : pUpperFnt = pUpperFont;
251 57 : pLowerFnt = pLowerFont;
252 57 : }
253 :
254 507 : void SwDoDrawCapital::Do()
255 : {
256 : SV_STAT( nDrawText );
257 507 : const sal_uInt16 nOrgWidth = rInf.GetWidth();
258 507 : rInf.SetWidth( sal_uInt16(rInf.GetSize().Width()) );
259 507 : if ( rInf.GetUpper() )
260 276 : pUpperFnt->DrawText( rInf );
261 : else
262 : {
263 231 : bool bOldBullet = rInf.GetBullet();
264 231 : rInf.SetBullet( false );
265 231 : pLowerFnt->DrawText( rInf );
266 231 : rInf.SetBullet( bOldBullet );
267 : }
268 :
269 : OSL_ENSURE( pUpperFnt, "No upper font, dying soon!");
270 507 : rInf.Shift( pUpperFnt->GetFont().GetOrientation() );
271 507 : rInf.SetWidth( nOrgWidth );
272 507 : }
273 :
274 3 : void SwDoDrawCapital::DrawSpace( Point &rPos )
275 : {
276 3 : long nDiff = rInf.GetPos().X() - rPos.X();
277 :
278 3 : Point aPos( rPos );
279 3 : const bool bSwitchL2R = rInf.GetFrm()->IsRightToLeft() &&
280 3 : ! rInf.IsIgnoreFrmRTL();
281 :
282 3 : if ( bSwitchL2R )
283 0 : rInf.GetFrm()->SwitchLTRtoRTL( aPos );
284 :
285 3 : const ComplexTextLayoutMode nMode = rInf.GetpOut()->GetLayoutMode();
286 3 : const bool bBidiPor = ( bSwitchL2R !=
287 3 : ( TEXT_LAYOUT_DEFAULT != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
288 :
289 3 : if ( bBidiPor )
290 0 : nDiff = -nDiff;
291 :
292 3 : if ( rInf.GetFrm()->IsVertical() )
293 0 : rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
294 :
295 3 : if ( nDiff )
296 : {
297 3 : rInf.ApplyAutoColor();
298 3 : GetOut().DrawStretchText( aPos, nDiff,
299 6 : OUString(" "), 0, 2 );
300 : }
301 3 : rPos.X() = rInf.GetPos().X() + rInf.GetWidth();
302 3 : }
303 :
304 57 : 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 111 : rInf.SetDrawSpace( GetUnderline() != UNDERLINE_NONE ||
309 111 : GetOverline() != UNDERLINE_NONE ||
310 111 : GetStrikeout() != STRIKEOUT_NONE );
311 57 : SwDoDrawCapital aDo( rInf );
312 57 : DoOnCapitals( aDo );
313 57 : }
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 : const_cast<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 220 : void SwSubFont::DoOnCapitals( SwDoCapitals &rDo )
468 : {
469 : OSL_ENSURE( pLastFont, "SwFont::DoOnCapitals: No LastFont?!" );
470 :
471 220 : long nKana = 0;
472 220 : const OUString aText( CalcCaseMap( rDo.GetInf().GetText() ) );
473 220 : sal_Int32 nMaxPos = std::min( rDo.GetInf().GetText().getLength() - rDo.GetInf().GetIdx(),
474 440 : rDo.GetInf().GetLen() );
475 220 : rDo.GetInf().SetLen( nMaxPos );
476 :
477 440 : const OUString oldText = rDo.GetInf().GetText();
478 220 : rDo.GetInf().SetText( aText );
479 220 : sal_Int32 nPos = rDo.GetInf().GetIdx();
480 220 : sal_Int32 nOldPos = nPos;
481 220 : 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 440 : OUString aNewText;
487 220 : SwCapitalInfo aCapInf(oldText);
488 220 : bool bCaseMapLengthDiffers(aText.getLength() != oldText.getLength());
489 220 : if ( bCaseMapLengthDiffers )
490 0 : rDo.SetCapInf( aCapInf );
491 :
492 220 : SwFntObj *pOldLast = pLastFont;
493 220 : SwFntAccess *pBigFontAccess = NULL;
494 : SwFntObj *pBigFont;
495 220 : SwFntAccess *pSpaceFontAccess = NULL;
496 220 : SwFntObj *pSpaceFont = NULL;
497 :
498 220 : const void *pMagic2 = NULL;
499 220 : sal_uInt16 nIndex2 = 0;
500 440 : SwSubFont aFont( *this );
501 220 : Point aStartPos( rDo.GetInf().GetPos() );
502 :
503 220 : const bool bTextLines = aFont.GetUnderline() != UNDERLINE_NONE
504 149 : || aFont.GetOverline() != UNDERLINE_NONE
505 369 : || aFont.GetStrikeout() != STRIKEOUT_NONE;
506 220 : const bool bWordWise = bTextLines && aFont.IsWordLineMode() &&
507 220 : rDo.GetInf().GetDrawSpace();
508 220 : const long nTmpKern = rDo.GetInf().GetKern();
509 :
510 220 : if ( bTextLines )
511 : {
512 71 : 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 71 : pSpaceFont = pLastFont;
521 :
522 : // Wir basteln uns einen Font fuer die Grossbuchstaben:
523 71 : aFont.SetUnderline( UNDERLINE_NONE );
524 71 : aFont.SetOverline( UNDERLINE_NONE );
525 71 : aFont.SetStrikeout( STRIKEOUT_NONE );
526 71 : pMagic2 = NULL;
527 71 : nIndex2 = 0;
528 : pBigFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
529 71 : rDo.GetInf().GetShell() );
530 71 : pBigFont = pBigFontAccess->Get();
531 : }
532 : else
533 149 : 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 220 : int smallCapsPercentage = smallCapsPercentage66 ? 66 : SMALL_CAPS_PERCENTAGE;
541 220 : aFont.SetProportion( (aFont.GetPropr() * smallCapsPercentage ) / 100 );
542 220 : pMagic2 = NULL;
543 220 : nIndex2 = 0;
544 : SwFntAccess *pSmallFontAccess = new SwFntAccess( pMagic2, nIndex2, &aFont,
545 220 : rDo.GetInf().GetShell() );
546 220 : SwFntObj *pSmallFont = pSmallFontAccess->Get();
547 :
548 220 : rDo.Init( pBigFont, pSmallFont );
549 220 : OutputDevice* pOutSize = pSmallFont->GetPrt();
550 220 : if( !pOutSize )
551 34 : pOutSize = &rDo.GetOut();
552 220 : OutputDevice* pOldOut = &rDo.GetOut();
553 :
554 220 : const LanguageType eLng = LANGUAGE_DONTKNOW == GetLanguage()
555 220 : ? LANGUAGE_SYSTEM : GetLanguage();
556 :
557 220 : if( nPos < nMaxPos )
558 : {
559 440 : nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
560 : oldText, nPos,
561 220 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
562 220 : if (nPos < 0)
563 200 : nPos = nOldPos;
564 20 : else if( nPos > nMaxPos )
565 6 : nPos = nMaxPos;
566 : }
567 :
568 1401 : while( nOldPos < nMaxPos )
569 : {
570 :
571 : // The lower ones...
572 961 : if( nOldPos != nPos )
573 : {
574 : SV_STAT( nGetTextSize );
575 761 : pLastFont = pSmallFont;
576 761 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
577 :
578 : // #107816#, #i14820#
579 761 : 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 761 : rDo.GetInf().SetIdx( nOldPos );
595 761 : rDo.GetInf().SetLen( nPos - nOldPos );
596 : }
597 :
598 761 : rDo.GetInf().SetUpper( false );
599 761 : rDo.GetInf().SetOut( *pOutSize );
600 761 : Size aPartSize = pSmallFont->GetTextSize( rDo.GetInf() );
601 761 : nKana += rDo.GetInf().GetKanaDiff();
602 761 : rDo.GetInf().SetOut( *pOldOut );
603 761 : if( nTmpKern && nPos < nMaxPos )
604 9 : aPartSize.Width() += nTmpKern;
605 761 : rDo.GetInf().SetSize( aPartSize );
606 761 : rDo.Do();
607 761 : nOldPos = nPos;
608 : }
609 1922 : nPos = g_pBreakIt->GetBreakIter()->nextCharBlock(
610 : oldText, nPos,
611 961 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
612 961 : if (nPos < 0 || nPos > nMaxPos)
613 218 : 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 961 : if( nOldPos != nPos )
621 : {
622 905 : const long nSpaceAdd = rDo.GetInf().GetSpace() / SPACING_PRECISION_FACTOR;
623 :
624 905 : do
625 : {
626 905 : rDo.GetInf().SetUpper( true );
627 905 : pLastFont = pBigFont;
628 905 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
629 : sal_Int32 nTmp;
630 905 : 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 : static_cast<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 905 : nTmp = nPos;
684 905 : if( nTmp > nOldPos )
685 : {
686 : // #107816#, #i14820#
687 905 : 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 905 : rDo.GetInf().SetIdx( nOldPos );
703 905 : rDo.GetInf().SetLen( nTmp - nOldPos );
704 : }
705 :
706 905 : rDo.GetInf().SetOut( *pOutSize );
707 905 : Size aPartSize = pBigFont->GetTextSize( rDo.GetInf() );
708 905 : nKana += rDo.GetInf().GetKanaDiff();
709 905 : rDo.GetInf().SetOut( *pOldOut );
710 905 : 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 905 : if( nTmpKern && nPos < nMaxPos )
719 12 : aPartSize.Width() += nTmpKern;
720 905 : rDo.GetInf().SetSize( aPartSize );
721 905 : rDo.Do();
722 905 : nOldPos = nTmp;
723 : }
724 : } while( nOldPos != nPos );
725 : }
726 1922 : nPos = g_pBreakIt->GetBreakIter()->endOfCharBlock(
727 : oldText, nPos,
728 961 : g_pBreakIt->GetLocale( eLng ), CharType::LOWERCASE_LETTER);
729 961 : if (nPos < 0 || nPos > nMaxPos)
730 222 : 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 220 : if( pBigFont != pOldLast )
740 71 : delete pBigFontAccess;
741 :
742 220 : if( bTextLines )
743 : {
744 71 : if( rDo.GetInf().GetDrawSpace() )
745 : {
746 3 : pLastFont = pSpaceFont;
747 3 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
748 3 : static_cast<SwDoDrawCapital&>( rDo ).DrawSpace( aStartPos );
749 : }
750 71 : if ( bWordWise )
751 0 : delete pSpaceFontAccess;
752 : }
753 220 : pLastFont = pOldLast;
754 220 : pLastFont->SetDevFont( rDo.GetInf().GetShell(), rDo.GetOut() );
755 :
756 220 : delete pSmallFontAccess;
757 220 : rDo.GetInf().SetText(oldText);
758 440 : rDo.GetInf().SetKanaDiff( nKana );
759 397 : }
760 :
761 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|