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