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