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