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