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