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 <com/sun/star/uno/Sequence.h>
21 : #include <unotools/linguprops.hxx>
22 : #include <unotools/lingucfg.hxx>
23 : #include <hintids.hxx>
24 : #include <svl/ctloptions.hxx>
25 : #include <sfx2/printer.hxx>
26 : #include <editeng/hyphenzoneitem.hxx>
27 : #include <editeng/escapementitem.hxx>
28 : #include <editeng/hngpnctitem.hxx>
29 : #include <editeng/scriptspaceitem.hxx>
30 : #include <editeng/brushitem.hxx>
31 : #include <editeng/splwrap.hxx>
32 : #include <editeng/pgrditem.hxx>
33 : #include <editeng/tstpitem.hxx>
34 : #include <editeng/shaditem.hxx>
35 :
36 : #include <SwSmartTagMgr.hxx>
37 : #include <linguistic/lngprops.hxx>
38 : #include <editeng/unolingu.hxx>
39 : #include <breakit.hxx>
40 : #include <editeng/forbiddenruleitem.hxx>
41 : #include <txatbase.hxx>
42 : #include <fmtinfmt.hxx>
43 : #include <swmodule.hxx>
44 : #include <vcl/svapp.hxx>
45 : #include <vcl/wrkwin.hxx>
46 : #include <viewsh.hxx>
47 : #include <viewopt.hxx>
48 : #include <frmtool.hxx>
49 : #include <IDocumentSettingAccess.hxx>
50 : #include <IDocumentDeviceAccess.hxx>
51 : #include <paratr.hxx>
52 : #include <rootfrm.hxx>
53 : #include <inftxt.hxx>
54 : #include <blink.hxx>
55 : #include <noteurl.hxx>
56 : #include <porftn.hxx>
57 : #include <porrst.hxx>
58 : #include <itratr.hxx>
59 : #include <accessibilityoptions.hxx>
60 : #include <wrong.hxx>
61 : #include <doc.hxx>
62 : #include <pam.hxx>
63 : #include <SwGrammarMarkUp.hxx>
64 : #include "numrule.hxx"
65 : #include <EnhancedPDFExportHelper.hxx>
66 : #include <docufld.hxx>
67 :
68 : //UUUU
69 : #include <frmfmt.hxx>
70 :
71 : #include <unomid.h>
72 :
73 : using namespace ::com::sun::star;
74 : using namespace ::com::sun::star::linguistic2;
75 : using namespace ::com::sun::star::uno;
76 : using namespace ::com::sun::star::beans;
77 :
78 : #define CHAR_UNDERSCORE ((sal_Unicode)0x005F)
79 : #define CHAR_LEFT_ARROW ((sal_Unicode)0x25C0)
80 : #define CHAR_RIGHT_ARROW ((sal_Unicode)0x25B6)
81 : #define CHAR_TAB ((sal_Unicode)0x2192)
82 : #define CHAR_TAB_RTL ((sal_Unicode)0x2190)
83 : #define CHAR_LINEBREAK ((sal_Unicode)0x21B5)
84 : #define CHAR_LINEBREAK_RTL ((sal_Unicode)0x21B3)
85 :
86 : #define DRAW_SPECIAL_OPTIONS_CENTER 1
87 : #define DRAW_SPECIAL_OPTIONS_ROTATE 2
88 :
89 : #ifdef DBG_UTIL
90 : bool SwTextSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); }
91 : #endif
92 :
93 184833 : SwLineInfo::SwLineInfo()
94 : : pRuler( 0 ),
95 : pSpace( 0 ),
96 : nVertAlign( 0 ),
97 : nDefTabStop( 0 ),
98 : bListTabStopIncluded( false ),
99 184833 : nListTabStopPosition( 0 )
100 : {
101 184833 : }
102 :
103 184833 : SwLineInfo::~SwLineInfo()
104 : {
105 184833 : delete pRuler;
106 184833 : }
107 184833 : void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
108 : const SwTextNode& rTextNode )
109 : {
110 184833 : delete pRuler;
111 184833 : pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
112 184833 : if ( rTextNode.GetListTabStopPosition( nListTabStopPosition ) )
113 : {
114 11899 : bListTabStopIncluded = true;
115 :
116 : // insert the list tab stop into SvxTabItem instance <pRuler>
117 : const SvxTabStop aListTabStop( nListTabStopPosition,
118 11899 : SVX_TAB_ADJUST_LEFT );
119 11899 : pRuler->Insert( aListTabStop );
120 :
121 : // remove default tab stops, which are before the inserted list tab stop
122 34063 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
123 : {
124 23049 : if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
125 885 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
126 : {
127 190 : pRuler->Remove(i);
128 190 : continue;
129 : }
130 : }
131 : }
132 :
133 184833 : if ( !rTextNode.getIDocumentSettingAccess()->get(DocumentSettingId::TABS_RELATIVE_TO_INDENT) )
134 : {
135 : // remove default tab stop at position 0
136 275906 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
137 : {
138 162570 : if ( (*pRuler)[i].GetTabPos() == 0 &&
139 9819 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
140 : {
141 0 : pRuler->Remove(i);
142 0 : break;
143 : }
144 : }
145 : }
146 :
147 184833 : pSpace = &rAttrSet.GetLineSpacing();
148 184833 : nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
149 184833 : nDefTabStop = USHRT_MAX;
150 184833 : }
151 :
152 184833 : void SwTextInfo::CtorInitTextInfo( SwTextFrm *pFrm )
153 : {
154 184833 : m_pPara = pFrm->GetPara();
155 184833 : m_nTextStart = pFrm->GetOfst();
156 184833 : if (!m_pPara)
157 : {
158 : SAL_WARN("sw.core", "+SwTextInfo::CTOR: missing paragraph information");
159 0 : pFrm->Format();
160 0 : m_pPara = pFrm->GetPara();
161 : }
162 184833 : }
163 :
164 126479 : SwTextInfo::SwTextInfo( const SwTextInfo &rInf )
165 126479 : : m_pPara( const_cast<SwTextInfo&>(rInf).GetParaPortion() )
166 126479 : , m_nTextStart( rInf.GetTextStart() )
167 126479 : { }
168 :
169 : #if OSL_DEBUG_LEVEL > 0
170 :
171 : void ChkOutDev( const SwTextSizeInfo &rInf )
172 : {
173 : if ( !rInf.GetVsh() )
174 : return;
175 :
176 : const OutputDevice* pOut = rInf.GetOut();
177 : const OutputDevice* pRef = rInf.GetRefDev();
178 : OSL_ENSURE( pOut && pRef, "ChkOutDev: invalid output devices" );
179 : }
180 : #endif
181 :
182 253892 : inline sal_Int32 GetMinLen( const SwTextSizeInfo &rInf )
183 : {
184 253892 : const sal_Int32 nTextLen = rInf.GetText().getLength();
185 253892 : if (rInf.GetLen() == COMPLETE_STRING)
186 253892 : return nTextLen;
187 0 : const sal_Int32 nInfLen = rInf.GetIdx() + rInf.GetLen();
188 0 : return std::min(nTextLen, nInfLen);
189 : }
190 :
191 57202 : SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew )
192 : : SwTextInfo( rNew ),
193 57202 : m_pKanaComp(rNew.GetpKanaComp()),
194 57202 : m_pVsh(const_cast<SwTextSizeInfo&>(rNew).GetVsh()),
195 : m_pOut(const_cast<SwTextSizeInfo&>(rNew).GetOut()),
196 : m_pRef(const_cast<SwTextSizeInfo&>(rNew).GetRefDev()),
197 57202 : m_pFnt(const_cast<SwTextSizeInfo&>(rNew).GetFont()),
198 57202 : m_pUnderFnt(rNew.GetUnderFnt()),
199 : m_pFrm(rNew.m_pFrm),
200 57202 : m_pOpt(&rNew.GetOpt()),
201 57202 : m_pText(&rNew.GetText()),
202 57202 : m_nIdx(rNew.GetIdx()),
203 57202 : m_nLen(rNew.GetLen()),
204 57202 : m_nKanaIdx( rNew.GetKanaIdx() ),
205 57202 : m_bOnWin( rNew.OnWin() ),
206 57202 : m_bNotEOL( rNew.NotEOL() ),
207 57202 : m_bURLNotify( rNew.URLNotify() ),
208 57202 : m_bStopUnderflow( rNew.StopUnderflow() ),
209 57202 : m_bFootnoteInside( rNew.IsFootnoteInside() ),
210 57202 : m_bOtherThanFootnoteInside( rNew.IsOtherThanFootnoteInside() ),
211 57202 : m_bMulti( rNew.IsMulti() ),
212 57202 : m_bFirstMulti( rNew.IsFirstMulti() ),
213 57202 : m_bRuby( rNew.IsRuby() ),
214 57202 : m_bHanging( rNew.IsHanging() ),
215 57202 : m_bScriptSpace( rNew.HasScriptSpace() ),
216 57202 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
217 57202 : m_bSnapToGrid( rNew.SnapToGrid() ),
218 1315646 : m_nDirection( rNew.GetDirection() )
219 : {
220 : #if OSL_DEBUG_LEVEL > 0
221 : ChkOutDev( *this );
222 : #endif
223 57202 : }
224 :
225 184615 : void SwTextSizeInfo::CtorInitTextSizeInfo( SwTextFrm *pFrame, SwFont *pNewFnt,
226 : const sal_Int32 nNewIdx, const sal_Int32 nNewLen )
227 : {
228 184615 : m_pKanaComp = NULL;
229 184615 : m_nKanaIdx = 0;
230 184615 : m_pFrm = pFrame;
231 184615 : CtorInitTextInfo( m_pFrm );
232 184615 : const SwTextNode *pNd = m_pFrm->GetTextNode();
233 184615 : m_pVsh = m_pFrm->getRootFrm()->GetCurrShell();
234 :
235 : // Get the output and reference device
236 184615 : if ( m_pVsh )
237 : {
238 184615 : m_pOut = m_pVsh->GetOut();
239 184615 : m_pRef = &m_pVsh->GetRefDev();
240 184615 : m_bOnWin = m_pVsh->GetWin() || OUTDEV_WINDOW == m_pOut->GetOutDevType();
241 : }
242 : else
243 : {
244 : // Access via StarONE. We do not need a Shell or an active one.
245 0 : if ( pNd->getIDocumentSettingAccess()->get(DocumentSettingId::HTML_MODE) )
246 : {
247 : // We can only pick the AppWin here? (there's nothing better to pick?)
248 0 : m_pOut = Application::GetDefaultDevice();
249 : }
250 : else
251 0 : m_pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false );
252 :
253 0 : m_pRef = m_pOut;
254 : }
255 :
256 : #if OSL_DEBUG_LEVEL > 0
257 : ChkOutDev( *this );
258 : #endif
259 :
260 : // Set default layout mode ( LTR or RTL ).
261 184615 : if ( m_pFrm->IsRightToLeft() )
262 : {
263 296 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
264 296 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
265 296 : m_nDirection = DIR_RIGHT2LEFT;
266 : }
267 : else
268 : {
269 184319 : m_pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
270 184319 : m_pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
271 184319 : m_nDirection = DIR_LEFT2RIGHT;
272 : }
273 :
274 : // The Options
275 :
276 : m_pOpt = m_pVsh ?
277 184615 : m_pVsh->GetViewOptions() :
278 369230 : SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(DocumentSettingId::HTML_MODE) ); // Options from Module, due to StarONE
279 :
280 : // bURLNotify is set if MakeGraphic prepares it
281 : // TODO: Unwind
282 184615 : m_bURLNotify = pNoteURL && !m_bOnWin;
283 :
284 368944 : SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
285 368944 : m_pFrm->IsInDocBody() );
286 :
287 184615 : m_pFnt = pNewFnt;
288 184615 : m_pUnderFnt = 0;
289 184615 : m_pText = &pNd->GetText();
290 :
291 184615 : m_nIdx = nNewIdx;
292 184615 : m_nLen = nNewLen;
293 184615 : m_bNotEOL = false;
294 184615 : m_bStopUnderflow = m_bFootnoteInside = m_bOtherThanFootnoteInside = false;
295 : m_bMulti = m_bFirstMulti = m_bRuby = m_bHanging = m_bScriptSpace =
296 184615 : m_bForbiddenChars = false;
297 :
298 184615 : SetLen( GetMinLen( *this ) );
299 184615 : }
300 :
301 69277 : SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew, const OUString* pText,
302 : const sal_Int32 nIndex, const sal_Int32 nLength )
303 : : SwTextInfo( rNew ),
304 69277 : m_pKanaComp(rNew.GetpKanaComp()),
305 69277 : m_pVsh(const_cast<SwTextSizeInfo&>(rNew).GetVsh()),
306 : m_pOut(const_cast<SwTextSizeInfo&>(rNew).GetOut()),
307 : m_pRef(const_cast<SwTextSizeInfo&>(rNew).GetRefDev()),
308 69277 : m_pFnt(const_cast<SwTextSizeInfo&>(rNew).GetFont()),
309 69277 : m_pUnderFnt(rNew.GetUnderFnt()),
310 : m_pFrm( rNew.m_pFrm ),
311 69277 : m_pOpt(&rNew.GetOpt()),
312 : m_pText(pText),
313 : m_nIdx(nIndex),
314 : m_nLen(nLength),
315 69277 : m_nKanaIdx( rNew.GetKanaIdx() ),
316 69277 : m_bOnWin( rNew.OnWin() ),
317 69277 : m_bNotEOL( rNew.NotEOL() ),
318 69277 : m_bURLNotify( rNew.URLNotify() ),
319 69277 : m_bStopUnderflow( rNew.StopUnderflow() ),
320 69277 : m_bFootnoteInside( rNew.IsFootnoteInside() ),
321 69277 : m_bOtherThanFootnoteInside( rNew.IsOtherThanFootnoteInside() ),
322 69277 : m_bMulti( rNew.IsMulti() ),
323 69277 : m_bFirstMulti( rNew.IsFirstMulti() ),
324 69277 : m_bRuby( rNew.IsRuby() ),
325 69277 : m_bHanging( rNew.IsHanging() ),
326 69277 : m_bScriptSpace( rNew.HasScriptSpace() ),
327 69277 : m_bForbiddenChars( rNew.HasForbiddenChars() ),
328 69277 : m_bSnapToGrid( rNew.SnapToGrid() ),
329 1385540 : m_nDirection( rNew.GetDirection() )
330 : {
331 : #if OSL_DEBUG_LEVEL > 0
332 : ChkOutDev( *this );
333 : #endif
334 69277 : SetLen( GetMinLen( *this ) );
335 69277 : }
336 :
337 1457 : void SwTextSizeInfo::SelectFont()
338 : {
339 : // The path needs to go via ChgPhysFnt or the FontMetricCache gets confused.
340 : // In this case pLastMet has it's old value.
341 : // Wrong: GetOut()->SetFont( GetFont()->GetFnt() );
342 1457 : GetFont()->Invalidate();
343 1457 : GetFont()->ChgPhysFnt( m_pVsh, *GetOut() );
344 1457 : }
345 :
346 0 : void SwTextSizeInfo::NoteAnimation() const
347 : {
348 0 : if( OnWin() )
349 0 : SwRootFrm::FlushVout();
350 :
351 : OSL_ENSURE( m_pOut == m_pVsh->GetOut(),
352 : "SwTextSizeInfo::NoteAnimation() changed m_pOut" );
353 0 : }
354 :
355 568 : SwPosSize SwTextSizeInfo::GetTextSize( OutputDevice* pOutDev,
356 : const SwScriptInfo* pSI,
357 : const OUString& rText,
358 : const sal_Int32 nIndex,
359 : const sal_Int32 nLength,
360 : const sal_uInt16 nComp) const
361 : {
362 568 : SwDrawTextInfo aDrawInf( m_pVsh, *pOutDev, pSI, rText, nIndex, nLength );
363 568 : aDrawInf.SetFrm( m_pFrm );
364 568 : aDrawInf.SetFont( m_pFnt );
365 568 : aDrawInf.SetSnapToGrid( SnapToGrid() );
366 568 : aDrawInf.SetKanaComp( nComp );
367 568 : return m_pFnt->_GetTextSize( aDrawInf );
368 : }
369 :
370 3995 : SwPosSize SwTextSizeInfo::GetTextSize() const
371 : {
372 : const SwScriptInfo& rSI =
373 3995 : const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo();
374 :
375 : // in some cases, compression is not allowed or suppressed for
376 : // performance reasons
377 3995 : sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
378 0 : rSI.CountCompChg() &&
379 0 : ! IsMulti() ) ?
380 : GetKanaComp() :
381 3995 : 0 ;
382 :
383 3995 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rSI, *m_pText, m_nIdx, m_nLen );
384 3995 : aDrawInf.SetFrm( m_pFrm );
385 3995 : aDrawInf.SetFont( m_pFnt );
386 3995 : aDrawInf.SetSnapToGrid( SnapToGrid() );
387 3995 : aDrawInf.SetKanaComp( nComp );
388 3995 : return m_pFnt->_GetTextSize( aDrawInf );
389 : }
390 :
391 98799 : void SwTextSizeInfo::GetTextSize( const SwScriptInfo* pSI, const sal_Int32 nIndex,
392 : const sal_Int32 nLength, const sal_uInt16 nComp,
393 : sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff,
394 : vcl::TextLayoutCache const*const pCache) const
395 : {
396 98799 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pText, nIndex, nLength,
397 197598 : 0, false, pCache);
398 98799 : aDrawInf.SetFrm( m_pFrm );
399 98799 : aDrawInf.SetFont( m_pFnt );
400 98799 : aDrawInf.SetSnapToGrid( SnapToGrid() );
401 98799 : aDrawInf.SetKanaComp( nComp );
402 98799 : SwPosSize aSize = m_pFnt->_GetTextSize( aDrawInf );
403 98799 : nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
404 98799 : nMinSize = aSize.Width();
405 98799 : }
406 :
407 40313 : sal_Int32 SwTextSizeInfo::GetTextBreak( const long nLineWidth,
408 : const sal_Int32 nMaxLen,
409 : const sal_uInt16 nComp,
410 : vcl::TextLayoutCache const*const pCache) const
411 : {
412 : const SwScriptInfo& rScriptInfo =
413 40313 : const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo();
414 :
415 : OSL_ENSURE( m_pRef == m_pOut, "GetTextBreak is supposed to use the RefDev" );
416 40313 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo,
417 80626 : *m_pText, GetIdx(), nMaxLen, 0, false, pCache );
418 40313 : aDrawInf.SetFrm( m_pFrm );
419 40313 : aDrawInf.SetFont( m_pFnt );
420 40313 : aDrawInf.SetSnapToGrid( SnapToGrid() );
421 40313 : aDrawInf.SetKanaComp( nComp );
422 40313 : aDrawInf.SetHyphPos( 0 );
423 :
424 40313 : return m_pFnt->GetTextBreak( aDrawInf, nLineWidth );
425 : }
426 :
427 0 : sal_Int32 SwTextSizeInfo::GetTextBreak( const long nLineWidth,
428 : const sal_Int32 nMaxLen,
429 : const sal_uInt16 nComp,
430 : sal_Int32& rExtraCharPos,
431 : vcl::TextLayoutCache const*const pCache) const
432 : {
433 : const SwScriptInfo& rScriptInfo =
434 0 : const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo();
435 :
436 : OSL_ENSURE( m_pRef == m_pOut, "GetTextBreak is supposed to use the RefDev" );
437 0 : SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo,
438 0 : *m_pText, GetIdx(), nMaxLen, 0, false, pCache );
439 0 : aDrawInf.SetFrm( m_pFrm );
440 0 : aDrawInf.SetFont( m_pFnt );
441 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
442 0 : aDrawInf.SetKanaComp( nComp );
443 0 : aDrawInf.SetHyphPos( &rExtraCharPos );
444 :
445 0 : return m_pFnt->GetTextBreak( aDrawInf, nLineWidth );
446 : }
447 :
448 7991 : bool SwTextSizeInfo::_HasHint( const SwTextNode* pTextNode, sal_Int32 nPos )
449 : {
450 7991 : return pTextNode->GetTextAttrForCharAt(nPos);
451 : }
452 :
453 69633 : void SwTextPaintInfo::CtorInitTextPaintInfo( SwTextFrm *pFrame, const SwRect &rPaint )
454 : {
455 69633 : CtorInitTextSizeInfo( pFrame );
456 69633 : aTextFly.CtorInitTextFly( pFrame ),
457 69633 : aPaintRect = rPaint;
458 69633 : nSpaceIdx = 0;
459 69633 : pSpaceAdd = NULL;
460 69633 : pWrongList = NULL;
461 69633 : pGrammarCheckList = NULL;
462 69633 : pSmartTags = NULL;
463 :
464 : #if OSL_DEBUG_LEVEL > 1
465 : pBrushItem = reinterpret_cast<SvxBrushItem*>(-1);
466 : #else
467 69633 : pBrushItem = 0;
468 : #endif
469 69633 : }
470 :
471 0 : SwTextPaintInfo::SwTextPaintInfo( const SwTextPaintInfo &rInf, const OUString* pText )
472 : : SwTextSizeInfo( rInf, pText ),
473 0 : pWrongList( rInf.GetpWrongList() ),
474 0 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
475 0 : pSmartTags( rInf.GetSmartTags() ),
476 0 : pSpaceAdd( rInf.GetpSpaceAdd() ),
477 0 : pBrushItem( rInf.GetBrushItem() ),
478 0 : aTextFly( rInf.GetTextFly() ),
479 0 : aPos( rInf.GetPos() ),
480 0 : aPaintRect( rInf.GetPaintRect() ),
481 0 : nSpaceIdx( rInf.GetSpaceIdx() )
482 0 : { }
483 :
484 57202 : SwTextPaintInfo::SwTextPaintInfo( const SwTextPaintInfo &rInf )
485 : : SwTextSizeInfo( rInf ),
486 57202 : pWrongList( rInf.GetpWrongList() ),
487 57202 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
488 57202 : pSmartTags( rInf.GetSmartTags() ),
489 57202 : pSpaceAdd( rInf.GetpSpaceAdd() ),
490 57202 : pBrushItem( rInf.GetBrushItem() ),
491 57202 : aTextFly( rInf.GetTextFly() ),
492 57202 : aPos( rInf.GetPos() ),
493 57202 : aPaintRect( rInf.GetPaintRect() ),
494 514818 : nSpaceIdx( rInf.GetSpaceIdx() )
495 57202 : { }
496 :
497 : extern Color aGlobalRetoucheColor;
498 :
499 : /// Returns if the current background color is dark.
500 1892 : static bool lcl_IsDarkBackground( const SwTextPaintInfo& rInf )
501 : {
502 1892 : const Color* pCol = rInf.GetFont()->GetBackColor();
503 1892 : if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
504 : {
505 : const SvxBrushItem* pItem;
506 1892 : SwRect aOrigBackRect;
507 :
508 : //UUUU
509 1892 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
510 :
511 : // Consider, that [GetBackgroundBrush(...)] can set <pCol>
512 : // See implementation in /core/layout/paintfrm.cxx
513 : // There is a background color, if there is a background brush and
514 : // its color is *not* "no fill"/"auto fill".
515 1892 : if( rInf.GetTextFrm()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false ) )
516 : {
517 178 : if ( !pCol )
518 178 : pCol = &pItem->GetColor();
519 :
520 : // Determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
521 178 : if ( pCol->GetColor() == COL_TRANSPARENT)
522 174 : pCol = NULL;
523 : }
524 : else
525 1714 : pCol = NULL;
526 : }
527 :
528 1892 : if( !pCol )
529 1888 : pCol = &aGlobalRetoucheColor;
530 :
531 1892 : return pCol->IsDark();
532 : }
533 :
534 20449 : void SwTextPaintInfo::_DrawText( const OUString &rText, const SwLinePortion &rPor,
535 : const sal_Int32 nStart, const sal_Int32 nLength,
536 : const bool bKern, const bool bWrong,
537 : const bool bSmartTag,
538 : const bool bGrammarCheck )
539 : {
540 20449 : if( !nLength )
541 0 : return;
542 :
543 20449 : if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
544 : {
545 : // check if accessibility options allow blinking portions:
546 58 : const SwViewShell* pSh = GetTextFrm()->getRootFrm()->GetCurrShell();
547 116 : if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
548 58 : ! pSh->IsPreview() )
549 : {
550 58 : if( !pBlink )
551 1 : pBlink = new SwBlink();
552 :
553 58 : Point aPoint( aPos );
554 :
555 58 : if ( GetTextFrm()->IsRightToLeft() )
556 0 : GetTextFrm()->SwitchLTRtoRTL( aPoint );
557 :
558 58 : if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
559 26 : aPoint.X() -= rPor.Width();
560 :
561 58 : if ( GetTextFrm()->IsVertical() )
562 0 : GetTextFrm()->SwitchHorizontalToVertical( aPoint );
563 :
564 58 : pBlink->Insert( aPoint, &rPor, GetTextFrm(), m_pFnt->GetOrientation() );
565 :
566 58 : if( !pBlink->IsVisible() )
567 0 : return;
568 : }
569 : else
570 : {
571 0 : delete pBlink;
572 0 : pBlink = NULL;
573 : }
574 : }
575 :
576 : // The SwScriptInfo is useless if we are inside a field portion
577 20449 : SwScriptInfo* pSI = 0;
578 20449 : if ( ! rPor.InFieldGrp() )
579 18426 : pSI = &GetParaPortion()->GetScriptInfo();
580 :
581 : // in some cases, kana compression is not allowed or suppressed for
582 : // performance reasons
583 20449 : sal_uInt16 nComp = 0;
584 20449 : if ( ! IsMulti() )
585 20449 : nComp = GetKanaComp();
586 :
587 20449 : bool bCfgIsAutoGrammar = false;
588 20449 : SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bCfgIsAutoGrammar;
589 20449 : const bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
590 20449 : const bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
591 20449 : const bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
592 20449 : const bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled();
593 :
594 : OSL_ENSURE( GetParaPortion(), "No paragraph!");
595 20449 : SwDrawTextInfo aDrawInf( m_pFrm->getRootFrm()->GetCurrShell(), *m_pOut, pSI, rText, nStart, nLength,
596 40898 : rPor.Width(), bBullet );
597 :
598 20449 : aDrawInf.SetLeft( GetPaintRect().Left() );
599 20449 : aDrawInf.SetRight( GetPaintRect().Right());
600 :
601 20449 : aDrawInf.SetUnderFnt( m_pUnderFnt );
602 :
603 60941 : const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
604 60258 : rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
605 20449 : if ( nSpaceAdd )
606 : {
607 951 : sal_Int32 nCharCnt = 0;
608 : // #i41860# Thai justified alignment needs some
609 : // additional information:
610 951 : aDrawInf.SetNumberOfBlanks( rPor.InTextGrp() ?
611 951 : static_cast<const SwTextPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
612 1902 : 0 );
613 : }
614 :
615 20449 : aDrawInf.SetSpace( nSpaceAdd );
616 20449 : aDrawInf.SetKanaComp( nComp );
617 :
618 : // the font is used to identify the current script via nActual
619 20449 : aDrawInf.SetFont( m_pFnt );
620 : // the frame is used to identify the orientation
621 20449 : aDrawInf.SetFrm( GetTextFrm() );
622 : // we have to know if the paragraph should snap to grid
623 20449 : aDrawInf.SetSnapToGrid( SnapToGrid() );
624 : // for underlining we must know when not to add extra space behind
625 : // a character in justified mode
626 26782 : aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
627 26070 : rPor.GetPortion()->InFixMargGrp() ||
628 26070 : rPor.GetPortion()->IsHolePortion() );
629 :
630 : // Draw text next to the left border
631 20449 : Point aFontPos(aPos);
632 20449 : if( m_pFnt->GetLeftBorder() && !static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithPrev() )
633 : {
634 8 : const sal_uInt16 nLeftBorderSpace = m_pFnt->GetLeftBorderSpace();
635 8 : if ( GetTextFrm()->IsRightToLeft() )
636 : {
637 0 : aFontPos.X() -= nLeftBorderSpace;
638 : }
639 : else
640 : {
641 8 : switch( m_pFnt->GetOrientation(GetTextFrm()->IsVertical()) )
642 : {
643 : case 0 :
644 8 : aFontPos.X() += nLeftBorderSpace;
645 8 : break;
646 : case 900 :
647 0 : aFontPos.Y() -= nLeftBorderSpace;
648 0 : break;
649 : case 1800 :
650 0 : aFontPos.X() -= nLeftBorderSpace;
651 0 : break;
652 : case 2700 :
653 0 : aFontPos.Y() += nLeftBorderSpace;
654 0 : break;
655 : }
656 : }
657 8 : if( aFontPos.X() < 0 )
658 0 : aFontPos.X() = 0;
659 8 : if( aFontPos.X() < 0 )
660 0 : aFontPos.X() = 0;
661 : }
662 :
663 20449 : if( GetTextFly().IsOn() )
664 : {
665 : // aPos needs to be the TopLeft, because we cannot calculate the
666 : // ClipRects otherwise
667 280 : const Point aPoint( aFontPos.X(), aFontPos.Y() - rPor.GetAscent() );
668 280 : const Size aSize( rPor.Width(), rPor.Height() );
669 280 : aDrawInf.SetPos( aPoint );
670 280 : aDrawInf.SetSize( aSize );
671 280 : aDrawInf.SetAscent( rPor.GetAscent() );
672 280 : aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
673 280 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
674 280 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
675 280 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
676 280 : GetTextFly().DrawTextOpaque( aDrawInf );
677 : }
678 : else
679 : {
680 20169 : aDrawInf.SetPos( aFontPos );
681 20169 : if( bKern )
682 78 : m_pFnt->_DrawStretchText( aDrawInf );
683 : else
684 : {
685 20091 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
686 20091 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
687 20091 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL );
688 20091 : m_pFnt->_DrawText( aDrawInf );
689 : }
690 20449 : }
691 : }
692 :
693 64592 : void SwTextPaintInfo::CalcRect( const SwLinePortion& rPor,
694 : SwRect* pRect, SwRect* pIntersect,
695 : const bool bInsideBox ) const
696 : {
697 64592 : Size aSize( rPor.Width(), rPor.Height() );
698 64592 : if( rPor.IsHangingPortion() )
699 0 : aSize.Width() = static_cast<const SwHangingPortion&>(rPor).GetInnerWidth();
700 64592 : if( rPor.InSpaceGrp() && GetSpaceAdd() )
701 : {
702 2865 : SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
703 2865 : if( rPor.InFieldGrp() && GetSpaceAdd() < 0 && nAdd )
704 0 : nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
705 2865 : aSize.Width() += nAdd;
706 : }
707 :
708 64592 : Point aPoint;
709 :
710 64592 : if( IsRotated() )
711 : {
712 3 : long nTmp = aSize.Width();
713 3 : aSize.Width() = aSize.Height();
714 3 : aSize.Height() = nTmp;
715 3 : if ( 1 == GetDirection() )
716 : {
717 3 : aPoint.A() = X() - rPor.GetAscent();
718 3 : aPoint.B() = Y() - aSize.Height();
719 : }
720 : else
721 : {
722 0 : aPoint.A() = X() - rPor.Height() + rPor.GetAscent();
723 0 : aPoint.B() = Y();
724 : }
725 : }
726 : else
727 : {
728 64589 : aPoint.A() = X();
729 64589 : if ( GetTextFrm()->IsVertLR() )
730 0 : aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
731 : else
732 64589 : aPoint.B() = Y() - rPor.GetAscent();
733 : }
734 :
735 : // Adjust x coordinate if we are inside a bidi portion
736 64592 : const bool bFrmDir = GetTextFrm()->IsRightToLeft();
737 64619 : const bool bCounterDir = ( !bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
738 64619 : ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
739 :
740 64592 : if ( bCounterDir )
741 27 : aPoint.A() -= aSize.Width();
742 :
743 64592 : SwRect aRect( aPoint, aSize );
744 :
745 64592 : if ( GetTextFrm()->IsRightToLeft() )
746 27 : GetTextFrm()->SwitchLTRtoRTL( aRect );
747 :
748 64592 : if ( GetTextFrm()->IsVertical() )
749 0 : GetTextFrm()->SwitchHorizontalToVertical( aRect );
750 :
751 64592 : if( bInsideBox && rPor.InTextGrp() )
752 : {
753 : const bool bJoinWithPrev =
754 42711 : static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithPrev();
755 : const bool bJoinWithNext =
756 42711 : static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithNext();
757 42711 : const bool bIsVert = GetTextFrm()->IsVertical();
758 42711 : aRect.Top(aRect.Top() + GetFont()->CalcShadowSpace(SvxShadowItemSide::TOP, bIsVert, bJoinWithPrev, bJoinWithNext ));
759 42711 : aRect.Bottom(aRect.Bottom() - GetFont()->CalcShadowSpace(SvxShadowItemSide::BOTTOM, bIsVert, bJoinWithPrev, bJoinWithNext ));
760 42711 : aRect.Left(aRect.Left() + GetFont()->CalcShadowSpace(SvxShadowItemSide::LEFT, bIsVert, bJoinWithPrev, bJoinWithNext ));
761 42711 : aRect.Right(aRect.Right() - GetFont()->CalcShadowSpace(SvxShadowItemSide::RIGHT, bIsVert, bJoinWithPrev, bJoinWithNext ));
762 : }
763 :
764 64592 : if ( pRect )
765 41691 : *pRect = aRect;
766 :
767 64592 : if( aRect.HasArea() && pIntersect )
768 : {
769 22901 : ::SwAlignRect( aRect, GetVsh() );
770 :
771 22901 : if ( GetOut()->IsClipRegion() )
772 : {
773 8769 : SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
774 8769 : aRect.Intersection( aClip );
775 : }
776 :
777 22901 : *pIntersect = aRect;
778 : }
779 64592 : }
780 :
781 : /**
782 : * Draws a special portion
783 : * E.g.: line break portion, tab portion
784 : *
785 : * @param rPor The portion
786 : * @param rRect The rectangle surrounding the character
787 : * @param rCol Specify a color for the character
788 : * @param bCenter Draw the character centered, otherwise left aligned
789 : * @param bRotate Rotate the character if character rotation is set
790 : */
791 6 : static void lcl_DrawSpecial( const SwTextPaintInfo& rInf, const SwLinePortion& rPor,
792 : SwRect& rRect, const Color& rCol, sal_Unicode cChar,
793 : sal_uInt8 nOptions )
794 : {
795 6 : bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
796 6 : bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
797 :
798 : // rRect is given in absolute coordinates
799 6 : if ( rInf.GetTextFrm()->IsRightToLeft() )
800 0 : rInf.GetTextFrm()->SwitchRTLtoLTR( rRect );
801 6 : if ( rInf.GetTextFrm()->IsVertical() )
802 0 : rInf.GetTextFrm()->SwitchVerticalToHorizontal( rRect );
803 :
804 6 : const SwFont* pOldFnt = rInf.GetFont();
805 :
806 : // Font is generated only once:
807 : static SwFont* m_pFnt = 0;
808 6 : if ( ! m_pFnt )
809 : {
810 1 : m_pFnt = new SwFont( *pOldFnt );
811 1 : m_pFnt->SetFamily( FAMILY_DONTKNOW, m_pFnt->GetActual() );
812 1 : m_pFnt->SetName( numfunc::GetDefBulletFontname(), m_pFnt->GetActual() );
813 1 : m_pFnt->SetStyleName( aEmptyOUStr, m_pFnt->GetActual() );
814 1 : m_pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, m_pFnt->GetActual() );
815 : }
816 :
817 : // Some of the current values are set at the font:
818 6 : if ( ! bRotate )
819 6 : m_pFnt->SetVertical( 0, rInf.GetTextFrm()->IsVertical() );
820 : else
821 0 : m_pFnt->SetVertical( pOldFnt->GetOrientation() );
822 :
823 6 : m_pFnt->SetColor(rCol);
824 :
825 6 : Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
826 6 : m_pFnt->SetSize( aFontSize, m_pFnt->GetActual() );
827 :
828 6 : const_cast<SwTextPaintInfo&>(rInf).SetFont( m_pFnt );
829 :
830 : // The maximum width depends on the current orientation
831 6 : const sal_uInt16 nDir = m_pFnt->GetOrientation( rInf.GetTextFrm()->IsVertical() );
832 : SwTwips nMaxWidth;
833 6 : if (nDir == 900 || nDir == 2700)
834 0 : nMaxWidth = rRect.Height();
835 : else
836 : {
837 : assert(nDir == 0); //Unknown direction set at font
838 6 : nMaxWidth = rRect.Width();
839 : }
840 :
841 : // check if char fits into rectangle
842 6 : const OUString aTmp( cChar );
843 6 : aFontSize = rInf.GetTextSize( aTmp ).SvLSize();
844 12 : while ( aFontSize.Width() > nMaxWidth )
845 : {
846 0 : SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth;
847 0 : const SwTwips nOldWidth = aFontSize.Width();
848 :
849 : // new height for font
850 0 : const sal_uInt8 nAct = m_pFnt->GetActual();
851 0 : aFontSize.Height() = ( 100 * m_pFnt->GetSize( nAct ).Height() ) / nFactor;
852 0 : aFontSize.Width() = ( 100 * m_pFnt->GetSize( nAct).Width() ) / nFactor;
853 :
854 0 : if ( !aFontSize.Width() && !aFontSize.Height() )
855 0 : break;
856 :
857 0 : m_pFnt->SetSize( aFontSize, nAct );
858 :
859 0 : aFontSize = rInf.GetTextSize( aTmp ).SvLSize();
860 :
861 0 : if ( aFontSize.Width() >= nOldWidth )
862 0 : break;
863 : }
864 :
865 6 : const Point aOldPos( rInf.GetPos() );
866 :
867 : // adjust values so that tab is vertically and horizontally centered
868 6 : SwTwips nX = rRect.Left();
869 6 : SwTwips nY = rRect.Top();
870 6 : switch ( nDir )
871 : {
872 : case 0 :
873 6 : if ( bCenter )
874 0 : nX += ( rRect.Width() - aFontSize.Width() ) / 2;
875 6 : nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
876 6 : break;
877 : case 900 :
878 0 : if ( bCenter )
879 0 : nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent();
880 0 : nY += ( rRect.Height() + aFontSize.Width() ) / 2;
881 0 : break;
882 : case 2700 :
883 0 : if ( bCenter )
884 0 : nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent();
885 0 : nY += ( rRect.Height() - aFontSize.Width() ) / 2;
886 0 : break;
887 : }
888 :
889 6 : Point aTmpPos( nX, nY );
890 6 : const_cast<SwTextPaintInfo&>(rInf).SetPos( aTmpPos );
891 6 : sal_uInt16 nOldWidth = rPor.Width();
892 6 : const_cast<SwLinePortion&>(rPor).Width( (sal_uInt16)aFontSize.Width() );
893 6 : rInf.DrawText( aTmp, rPor );
894 6 : const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
895 6 : const_cast<SwTextPaintInfo&>(rInf).SetFont( const_cast<SwFont*>(pOldFnt) );
896 6 : const_cast<SwTextPaintInfo&>(rInf).SetPos( aOldPos );
897 6 : }
898 :
899 2228 : void SwTextPaintInfo::DrawRect( const SwRect &rRect, bool bNoGraphic,
900 : bool bRetouche ) const
901 : {
902 2228 : if ( OnWin() || !bRetouche )
903 : {
904 2228 : if( aTextFly.IsOn() )
905 30 : const_cast<SwTextPaintInfo*>(this)->GetTextFly().
906 60 : DrawFlyRect( m_pOut, rRect, *this, bNoGraphic );
907 2198 : else if ( bNoGraphic )
908 2198 : m_pOut->DrawRect( rRect.SVRect() );
909 : else
910 : {
911 0 : if(pBrushItem != reinterpret_cast<SvxBrushItem*>(-1))
912 : {
913 0 : ::DrawGraphic( pBrushItem, m_pOut, aItemRect, rRect );
914 : }
915 : else
916 : {
917 : OSL_ENSURE(false, "DrawRect: Uninitialized BrushItem!" );
918 : }
919 : }
920 : }
921 2228 : }
922 :
923 0 : void SwTextPaintInfo::DrawTab( const SwLinePortion &rPor ) const
924 : {
925 0 : if( OnWin() )
926 : {
927 0 : SwRect aRect;
928 0 : CalcRect( rPor, &aRect );
929 :
930 0 : if ( ! aRect.HasArea() )
931 0 : return;
932 :
933 0 : const sal_Unicode cChar = GetTextFrm()->IsRightToLeft() ? CHAR_TAB_RTL : CHAR_TAB;
934 0 : const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER | DRAW_SPECIAL_OPTIONS_ROTATE;
935 :
936 0 : lcl_DrawSpecial( *this, rPor, aRect, Color(NON_PRINTING_CHARACTER_COLOR), cChar, nOptions );
937 : }
938 : }
939 :
940 0 : void SwTextPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
941 : {
942 0 : if( OnWin() )
943 : {
944 0 : sal_uInt16 nOldWidth = rPor.Width();
945 0 : const_cast<SwLinePortion&>(rPor).Width( LINE_BREAK_WIDTH );
946 :
947 0 : SwRect aRect;
948 0 : CalcRect( rPor, &aRect );
949 :
950 0 : if( aRect.HasArea() )
951 : {
952 0 : const sal_Unicode cChar = GetTextFrm()->IsRightToLeft() ?
953 0 : CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
954 0 : const sal_uInt8 nOptions = 0;
955 :
956 0 : lcl_DrawSpecial( *this, rPor, aRect, Color(NON_PRINTING_CHARACTER_COLOR), cChar, nOptions );
957 : }
958 :
959 0 : const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
960 : }
961 0 : }
962 :
963 6 : void SwTextPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
964 : {
965 6 : Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
966 6 : SwRect aRect( static_cast<const SwArrowPortion&>(rPor).GetPos(), aSize );
967 : sal_Unicode cChar;
968 6 : if( static_cast<const SwArrowPortion&>(rPor).IsLeft() )
969 : {
970 0 : aRect.Pos().Y() += 20 - GetAscent();
971 0 : aRect.Pos().X() += 20;
972 0 : if( aSize.Height() > rPor.Height() )
973 0 : aRect.Height( rPor.Height() );
974 0 : cChar = CHAR_LEFT_ARROW;
975 : }
976 : else
977 : {
978 6 : if( aSize.Height() > rPor.Height() )
979 0 : aRect.Height( rPor.Height() );
980 6 : aRect.Pos().Y() -= aRect.Height() + 20;
981 6 : aRect.Pos().X() -= aRect.Width() + 20;
982 6 : cChar = CHAR_RIGHT_ARROW;
983 : }
984 :
985 6 : if ( GetTextFrm()->IsVertical() )
986 0 : GetTextFrm()->SwitchHorizontalToVertical( aRect );
987 :
988 6 : Color aCol( COL_LIGHTRED );
989 :
990 6 : if( aRect.HasArea() )
991 : {
992 6 : const sal_uInt8 nOptions = 0;
993 6 : lcl_DrawSpecial( *this, rPor, aRect, aCol, cChar, nOptions );
994 : }
995 6 : }
996 :
997 24 : void SwTextPaintInfo::DrawPostIts( const SwLinePortion&, bool bScript ) const
998 : {
999 24 : if( OnWin() && m_pOpt->IsPostIts() )
1000 : {
1001 24 : Size aSize;
1002 24 : Point aTmp;
1003 :
1004 24 : const sal_uInt16 nPostItsWidth = SwViewOption::GetPostItsWidth( GetOut() );
1005 24 : const sal_uInt16 nFontHeight = m_pFnt->GetHeight( m_pVsh, *GetOut() );
1006 24 : const sal_uInt16 nFontAscent = m_pFnt->GetAscent( m_pVsh, *GetOut() );
1007 :
1008 24 : switch ( m_pFnt->GetOrientation( GetTextFrm()->IsVertical() ) )
1009 : {
1010 : case 0 :
1011 24 : aSize.Width() = nPostItsWidth;
1012 24 : aSize.Height() = nFontHeight;
1013 24 : aTmp.X() = aPos.X();
1014 24 : aTmp.Y() = aPos.Y() - nFontAscent;
1015 24 : break;
1016 : case 900 :
1017 0 : aSize.Height() = nPostItsWidth;
1018 0 : aSize.Width() = nFontHeight;
1019 0 : aTmp.X() = aPos.X() - nFontAscent;
1020 0 : aTmp.Y() = aPos.Y();
1021 0 : break;
1022 : case 2700 :
1023 0 : aSize.Height() = nPostItsWidth;
1024 0 : aSize.Width() = nFontHeight;
1025 0 : aTmp.X() = aPos.X() - nFontHeight +
1026 0 : nFontAscent;
1027 0 : aTmp.Y() = aPos.Y();
1028 0 : break;
1029 : }
1030 :
1031 24 : SwRect aTmpRect( aTmp, aSize );
1032 :
1033 24 : if ( GetTextFrm()->IsRightToLeft() )
1034 0 : GetTextFrm()->SwitchLTRtoRTL( aTmpRect );
1035 :
1036 24 : if ( GetTextFrm()->IsVertical() )
1037 0 : GetTextFrm()->SwitchHorizontalToVertical( aTmpRect );
1038 :
1039 24 : const Rectangle aRect( aTmpRect.SVRect() );
1040 24 : SwViewOption::PaintPostIts( const_cast<OutputDevice*>(GetOut()), aRect, bScript );
1041 : }
1042 24 : }
1043 :
1044 2 : void SwTextPaintInfo::DrawCheckBox(const SwFieldFormCheckboxPortion &rPor, bool bChecked) const
1045 : {
1046 2 : SwRect aIntersect;
1047 2 : CalcRect( rPor, &aIntersect, 0 );
1048 2 : if ( aIntersect.HasArea() )
1049 : {
1050 4 : if (OnWin() && SwViewOption::IsFieldShadings() &&
1051 2 : !GetOpt().IsPagePreview())
1052 : {
1053 2 : OutputDevice* pOut = const_cast<OutputDevice*>(GetOut());
1054 2 : pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1055 2 : pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1056 2 : pOut->SetLineColor();
1057 2 : pOut->DrawRect( aIntersect.SVRect() );
1058 2 : pOut->Pop();
1059 : }
1060 2 : const int delta=10;
1061 2 : Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
1062 2 : m_pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1063 2 : m_pOut->SetLineColor( Color(0, 0, 0));
1064 2 : m_pOut->SetFillColor();
1065 2 : m_pOut->DrawRect( r );
1066 2 : if (bChecked)
1067 : {
1068 1 : m_pOut->DrawLine(r.TopLeft(), r.BottomRight());
1069 1 : m_pOut->DrawLine(r.TopRight(), r.BottomLeft());
1070 : }
1071 2 : m_pOut->Pop();
1072 : }
1073 2 : }
1074 :
1075 1983 : void SwTextPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
1076 : {
1077 : OSL_ENSURE( OnWin(), "SwTextPaintInfo::DrawBackground: printer pollution ?" );
1078 :
1079 1983 : SwRect aIntersect;
1080 1983 : CalcRect( rPor, 0, &aIntersect, true );
1081 :
1082 1983 : if ( aIntersect.HasArea() )
1083 : {
1084 1892 : OutputDevice* pOut = const_cast<OutputDevice*>(GetOut());
1085 1892 : pOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1086 :
1087 : // For dark background we do not want to have a filled rectangle
1088 1892 : if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
1089 : {
1090 0 : pOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
1091 : }
1092 : else
1093 : {
1094 1892 : pOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1095 1892 : pOut->SetLineColor();
1096 : }
1097 :
1098 1892 : DrawRect( aIntersect, true );
1099 1892 : pOut->Pop();
1100 : }
1101 1983 : }
1102 :
1103 20918 : void SwTextPaintInfo::DrawBackBrush( const SwLinePortion &rPor ) const
1104 : {
1105 : {
1106 20918 : SwRect aIntersect;
1107 20918 : CalcRect( rPor, &aIntersect, 0, true );
1108 20918 : if(aIntersect.HasArea())
1109 : {
1110 20918 : SwTextNode *pNd = m_pFrm->GetTextNode();
1111 20918 : const ::sw::mark::IMark* pFieldmark = NULL;
1112 20918 : if(pNd)
1113 : {
1114 20918 : const SwDoc *doc=pNd->GetDoc();
1115 20918 : if(doc)
1116 : {
1117 20918 : SwIndex aIndex(pNd, GetIdx());
1118 41836 : SwPosition aPosition(*pNd, aIndex);
1119 41836 : pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
1120 : }
1121 : }
1122 20918 : bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetText()[GetIdx()]);
1123 20918 : if(pFieldmark) {
1124 : OSL_TRACE("Found Fieldmark");
1125 : SAL_INFO("sw.core", pFieldmark->ToString() << "\n");
1126 : }
1127 : if(bIsStartMark) OSL_TRACE("Found StartMark");
1128 62313 : if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
1129 20926 : SwViewOption::IsFieldShadings() &&
1130 4 : !GetOpt().IsPagePreview())
1131 : {
1132 4 : OutputDevice* pOutDev = const_cast<OutputDevice*>(GetOut());
1133 4 : pOutDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1134 4 : pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1135 4 : pOutDev->SetLineColor( );
1136 4 : pOutDev->DrawRect( aIntersect.SVRect() );
1137 4 : pOutDev->Pop();
1138 : }
1139 : }
1140 : }
1141 :
1142 20918 : SwRect aIntersect;
1143 20918 : CalcRect( rPor, 0, &aIntersect, true );
1144 :
1145 20918 : if ( aIntersect.HasArea() )
1146 : {
1147 19807 : OutputDevice* pTmpOut = const_cast<OutputDevice*>(GetOut());
1148 :
1149 : // #i16816# tagged pdf support
1150 19807 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
1151 :
1152 19807 : Color aFillColor;
1153 :
1154 19807 : if( m_pFnt->GetHighlightColor() != COL_TRANSPARENT )
1155 : {
1156 80 : aFillColor = m_pFnt->GetHighlightColor();
1157 : }
1158 : else
1159 : {
1160 19727 : if( !m_pFnt->GetBackColor() )
1161 40389 : return;
1162 256 : aFillColor = *m_pFnt->GetBackColor();
1163 : }
1164 :
1165 336 : pTmpOut->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
1166 :
1167 336 : pTmpOut->SetFillColor(aFillColor);
1168 336 : pTmpOut->SetLineColor();
1169 :
1170 336 : DrawRect( aIntersect, true, false );
1171 :
1172 336 : pTmpOut->Pop();
1173 : }
1174 : }
1175 :
1176 20770 : void SwTextPaintInfo::DrawBorder( const SwLinePortion &rPor ) const
1177 : {
1178 20770 : SwRect aDrawArea;
1179 20770 : CalcRect( rPor, &aDrawArea );
1180 20770 : if ( aDrawArea.HasArea() )
1181 : {
1182 : PaintCharacterBorder(
1183 20770 : *m_pFnt, aDrawArea, GetTextFrm()->IsVertical(),
1184 41540 : rPor.GetJoinBorderWithPrev(), rPor.GetJoinBorderWithNext());
1185 : }
1186 20770 : }
1187 :
1188 2719 : void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
1189 : const sal_uInt16 nWhich ) const
1190 : {
1191 2719 : if( OnWin() && !IsMulti() )
1192 : {
1193 2612 : bool bDraw = false;
1194 2612 : switch( nWhich )
1195 : {
1196 : case POR_FTN:
1197 : case POR_QUOVADIS:
1198 : case POR_NUMBER:
1199 : case POR_FLD:
1200 : case POR_URL:
1201 : case POR_HIDDEN:
1202 : case POR_TOX:
1203 : case POR_REF:
1204 : case POR_META:
1205 : case POR_CONTROLCHAR:
1206 4812 : if ( !GetOpt().IsPagePreview()
1207 2406 : && !GetOpt().IsReadonly()
1208 2406 : && SwViewOption::IsFieldShadings()
1209 6589 : && ( POR_NUMBER != nWhich
1210 629 : || m_pFrm->GetTextNode()->HasMarkedLabel())) // #i27615#
1211 : {
1212 1777 : bDraw = true;
1213 : }
1214 2406 : break;
1215 : case POR_INPUTFLD:
1216 : // input field shading also in read-only mode
1217 22 : if ( !GetOpt().IsPagePreview()
1218 11 : && SwViewOption::IsFieldShadings() )
1219 : {
1220 11 : bDraw = true;
1221 : }
1222 11 : break;
1223 0 : case POR_TAB: if ( GetOpt().IsTab() ) bDraw = true; break;
1224 0 : case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = true; break;
1225 195 : case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = true; break;
1226 : default:
1227 : {
1228 : OSL_ENSURE( false, "SwTextPaintInfo::DrawViewOpt: don't know how to draw this" );
1229 0 : break;
1230 : }
1231 : }
1232 2612 : if ( bDraw )
1233 1983 : DrawBackground( rPor );
1234 : }
1235 2719 : }
1236 :
1237 0 : void SwTextPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
1238 : {
1239 : OSL_ENSURE( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
1240 :
1241 0 : SwRect aIntersect;
1242 0 : CalcRect( rPor, 0, &aIntersect );
1243 :
1244 0 : if( aIntersect.HasArea() )
1245 : {
1246 0 : SwTextNode *pNd = const_cast<SwTextNode*>(GetTextFrm()->GetTextNode());
1247 : SwTextAttr *const pAttr =
1248 0 : pNd->GetTextAttrAt(GetIdx(), RES_TXTATR_INETFMT);
1249 0 : if( pAttr )
1250 : {
1251 0 : const SwFormatINetFormat& rFormat = pAttr->GetINetFormat();
1252 0 : pNoteURL->InsertURLNote( rFormat.GetValue(), rFormat.GetTargetFrame(),
1253 0 : aIntersect );
1254 : }
1255 : }
1256 0 : }
1257 :
1258 42 : static void lcl_InitHyphValues( PropertyValues &rVals,
1259 : sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
1260 : {
1261 42 : sal_Int32 nLen = rVals.getLength();
1262 :
1263 42 : if (0 == nLen) // yet to be initialized?
1264 : {
1265 42 : rVals.realloc( 2 );
1266 42 : PropertyValue *pVal = rVals.getArray();
1267 :
1268 42 : pVal[0].Name = UPN_HYPH_MIN_LEADING;
1269 42 : pVal[0].Handle = UPH_HYPH_MIN_LEADING;
1270 42 : pVal[0].Value <<= nMinLeading;
1271 :
1272 42 : pVal[1].Name = UPN_HYPH_MIN_TRAILING;
1273 42 : pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
1274 42 : pVal[1].Value <<= nMinTrailing;
1275 : }
1276 0 : else if (2 == nLen) // already initialized once?
1277 : {
1278 0 : PropertyValue *pVal = rVals.getArray();
1279 0 : pVal[0].Value <<= nMinLeading;
1280 0 : pVal[1].Value <<= nMinTrailing;
1281 : }
1282 : else {
1283 : OSL_FAIL( "unexpected size of sequence" );
1284 : }
1285 42 : }
1286 :
1287 0 : const PropertyValues & SwTextFormatInfo::GetHyphValues() const
1288 : {
1289 : OSL_ENSURE( 2 == aHyphVals.getLength(),
1290 : "hyphenation values not yet initialized" );
1291 0 : return aHyphVals;
1292 : }
1293 :
1294 55817 : bool SwTextFormatInfo::InitHyph( const bool bAutoHyphen )
1295 : {
1296 55817 : const SwAttrSet& rAttrSet = GetTextFrm()->GetTextNode()->GetSwAttrSet();
1297 55817 : SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
1298 55817 : SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
1299 55817 : SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
1300 55817 : const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
1301 55817 : MaxHyph() = rAttr.GetMaxHyphens();
1302 55817 : const bool bAuto = bAutoHyphen || rAttr.IsHyphen();
1303 55817 : if( bAuto || bInterHyph )
1304 : {
1305 42 : const sal_Int16 nMinimalLeading = std::max(rAttr.GetMinLead(), sal_uInt8(2));
1306 42 : const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
1307 42 : lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
1308 : }
1309 55817 : return bAuto;
1310 : }
1311 :
1312 55817 : void SwTextFormatInfo::CtorInitTextFormatInfo( SwTextFrm *pNewFrm, const bool bNewInterHyph,
1313 : const bool bNewQuick, const bool bTst )
1314 : {
1315 55817 : CtorInitTextPaintInfo( pNewFrm, SwRect() );
1316 :
1317 55817 : bQuick = bNewQuick;
1318 55817 : bInterHyph = bNewInterHyph;
1319 :
1320 : //! needs to be done in this order
1321 55817 : nMinLeading = 2;
1322 55817 : nMinTrailing = 2;
1323 55817 : nMinWordLength = 0;
1324 55817 : bAutoHyph = InitHyph();
1325 :
1326 55817 : bIgnoreFly = false;
1327 55817 : bFakeLineStart = false;
1328 55817 : bShift = false;
1329 55817 : bDropInit = false;
1330 55817 : bTestFormat = bTst;
1331 55817 : nLeft = 0;
1332 55817 : nRight = 0;
1333 55817 : nFirst = 0;
1334 55817 : nRealWidth = 0;
1335 55817 : nForcedLeftMargin = 0;
1336 55817 : pRest = 0;
1337 55817 : nLineHeight = 0;
1338 55817 : nLineNetHeight = 0;
1339 55817 : SetLineStart(0);
1340 :
1341 : SvtCTLOptions::TextNumerals const nTextNumerals(
1342 55817 : SW_MOD()->GetCTLOptions().GetCTLTextNumerals());
1343 : // cannot cache for NUMERALS_CONTEXT because we need to know the string
1344 : // for the whole paragraph now
1345 55817 : if (nTextNumerals != SvtCTLOptions::NUMERALS_CONTEXT)
1346 : {
1347 : // set digit mode to what will be used later to get same results
1348 55817 : SwDigitModeModifier const m(*m_pRef, LANGUAGE_NONE /*dummy*/);
1349 : assert(m_pRef->GetDigitLanguage() != LANGUAGE_NONE);
1350 55817 : SetCachedVclData(m_pRef->CreateTextLayoutCache(*m_pText));
1351 : }
1352 :
1353 55817 : Init();
1354 55817 : }
1355 :
1356 : /**
1357 : * If the Hyphenator returns ERROR or the language is set to NOLANGUAGE
1358 : * we do not hyphenate.
1359 : * Else, we always hyphenate if we do interactive hyphenation.
1360 : * If we do not do interactive hyphenation, we only hyphenate if ParaFormat is
1361 : * set to automatic hyphenation.
1362 : */
1363 40313 : bool SwTextFormatInfo::IsHyphenate() const
1364 : {
1365 40313 : if( !bInterHyph && !bAutoHyph )
1366 40301 : return false;
1367 :
1368 12 : LanguageType eTmp = GetFont()->GetLanguage();
1369 12 : if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
1370 0 : return false;
1371 :
1372 12 : uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
1373 12 : if (!xHyph.is())
1374 0 : return false;
1375 :
1376 12 : if (bInterHyph)
1377 0 : SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
1378 :
1379 12 : return xHyph->hasLocale( g_pBreakIt->GetLocale(eTmp) );
1380 : }
1381 :
1382 55817 : const SwFormatDrop *SwTextFormatInfo::GetDropFormat() const
1383 : {
1384 55817 : const SwFormatDrop *pDrop = &GetTextFrm()->GetTextNode()->GetSwAttrSet().GetDrop();
1385 111634 : if( 1 >= pDrop->GetLines() ||
1386 6 : ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
1387 55811 : pDrop = 0;
1388 55817 : return pDrop;
1389 : }
1390 :
1391 140481 : void SwTextFormatInfo::Init()
1392 : {
1393 : // Not initialized: pRest, nLeft, nRight, nFirst, nRealWidth
1394 140481 : X(0);
1395 : bArrowDone = bFull = bFootnoteDone = bErgoDone = bNumDone = bNoEndHyph =
1396 140481 : bNoMidHyph = bStop = bNewLine = bUnderflow = bTabOverflow = false;
1397 :
1398 : // generally we do not allow number portions in follows, except...
1399 140481 : if ( GetTextFrm()->IsFollow() )
1400 : {
1401 16923 : const SwTextFrm* pMaster = GetTextFrm()->FindMaster();
1402 : OSL_ENSURE(pMaster, "pTextFrm without Master");
1403 16923 : const SwLinePortion* pTmpPara = pMaster ? pMaster->GetPara() : NULL;
1404 :
1405 : // there is a master for this follow and the master does not have
1406 : // any contents (especially it does not have a number portion)
1407 33846 : bNumDone = ! pTmpPara ||
1408 33846 : ! static_cast<const SwParaPortion*>(pTmpPara)->GetFirstPortion()->IsFlyPortion();
1409 : }
1410 :
1411 140481 : pRoot = 0;
1412 140481 : pLast = 0;
1413 140481 : pFly = 0;
1414 140481 : pLastField = 0;
1415 140481 : pLastTab = 0;
1416 140481 : pUnderflow = 0;
1417 140481 : cTabDecimal = 0;
1418 140481 : nWidth = nRealWidth;
1419 140481 : nForcedLeftMargin = 0;
1420 140481 : nSoftHyphPos = 0;
1421 140481 : nUnderScorePos = COMPLETE_STRING;
1422 140481 : cHookChar = 0;
1423 140481 : SetIdx(0);
1424 140481 : SetLen( GetText().getLength() );
1425 140481 : SetPaintOfst(0);
1426 140481 : }
1427 :
1428 : /**
1429 : * There are a few differences between a copy constructor
1430 : * and the following constructor for multi-line formatting.
1431 : * The root is the first line inside the multi-portion,
1432 : * the line start is the actual position in the text,
1433 : * the line width is the rest width from the surrounding line
1434 : * and the bMulti and bFirstMulti-flag has to be set correctly.
1435 : */
1436 423 : SwTextFormatInfo::SwTextFormatInfo( const SwTextFormatInfo& rInf,
1437 : SwLineLayout& rLay, SwTwips nActWidth ) : SwTextPaintInfo( rInf ),
1438 423 : bTabOverflow( false )
1439 : {
1440 423 : pRoot = &rLay;
1441 423 : pLast = &rLay;
1442 423 : pFly = NULL;
1443 423 : pLastField = NULL;
1444 423 : pUnderflow = NULL;
1445 423 : pRest = NULL;
1446 423 : pLastTab = NULL;
1447 :
1448 423 : nSoftHyphPos = 0;
1449 423 : nUnderScorePos = COMPLETE_STRING;
1450 423 : nLineStart = rInf.GetIdx();
1451 423 : nLeft = rInf.nLeft;
1452 423 : nRight = rInf.nRight;
1453 423 : nFirst = rInf.nLeft;
1454 423 : nRealWidth = sal_uInt16(nActWidth);
1455 423 : nWidth = nRealWidth;
1456 423 : nLineHeight = 0;
1457 423 : nLineNetHeight = 0;
1458 423 : nForcedLeftMargin = 0;
1459 :
1460 423 : nMinLeading = 0;
1461 423 : nMinTrailing = 0;
1462 423 : nMinWordLength = 0;
1463 423 : bFull = false;
1464 423 : bFootnoteDone = true;
1465 423 : bErgoDone = true;
1466 423 : bNumDone = true;
1467 423 : bArrowDone = true;
1468 423 : bStop = false;
1469 423 : bNewLine = true;
1470 423 : bShift = false;
1471 423 : bUnderflow = false;
1472 423 : bInterHyph = false;
1473 423 : bAutoHyph = false;
1474 423 : bDropInit = false;
1475 423 : bQuick = rInf.bQuick;
1476 423 : bNoEndHyph = false;
1477 423 : bNoMidHyph = false;
1478 423 : bIgnoreFly = false;
1479 423 : bFakeLineStart = false;
1480 :
1481 423 : cTabDecimal = 0;
1482 423 : cHookChar = 0;
1483 423 : nMaxHyph = 0;
1484 423 : bTestFormat = rInf.bTestFormat;
1485 423 : SetMulti( true );
1486 423 : SetFirstMulti( rInf.IsFirstMulti() );
1487 423 : }
1488 :
1489 109 : bool SwTextFormatInfo::_CheckFootnotePortion( SwLineLayout* pCurr )
1490 : {
1491 109 : const sal_uInt16 nHeight = pCurr->GetRealHeight();
1492 361 : for( SwLinePortion *pPor = pCurr->GetPortion(); pPor; pPor = pPor->GetPortion() )
1493 : {
1494 261 : if( pPor->IsFootnotePortion() && nHeight > static_cast<SwFootnotePortion*>(pPor)->Orig() )
1495 : {
1496 9 : SetLineHeight( nHeight );
1497 9 : SetLineNetHeight( pCurr->Height() );
1498 9 : return true;
1499 : }
1500 : }
1501 100 : return false;
1502 : }
1503 :
1504 95379 : sal_Int32 SwTextFormatInfo::ScanPortionEnd( const sal_Int32 nStart,
1505 : const sal_Int32 nEnd )
1506 : {
1507 95379 : cHookChar = 0;
1508 95379 : sal_Int32 i = nStart;
1509 :
1510 : // Used for decimal tab handling:
1511 95379 : const sal_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
1512 95379 : const sal_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
1513 :
1514 : // #i45951# German (Switzerland) uses ' as thousand separator
1515 95379 : const sal_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
1516 :
1517 95379 : bool bNumFound = false;
1518 95379 : const bool bTabCompat = GetTextFrm()->GetTextNode()->getIDocumentSettingAccess()->get(DocumentSettingId::TAB_COMPAT);
1519 :
1520 3902172 : for( ; i < nEnd; ++i )
1521 : {
1522 3820808 : const sal_Unicode cPos = GetChar( i );
1523 3820808 : switch( cPos )
1524 : {
1525 : case CH_TXTATR_BREAKWORD:
1526 : case CH_TXTATR_INWORD:
1527 0 : if( !HasHint( i ))
1528 0 : break;
1529 : // no break;
1530 :
1531 : case CHAR_SOFTHYPHEN:
1532 : case CHAR_HARDHYPHEN:
1533 : case CHAR_HARDBLANK:
1534 : case CH_TAB:
1535 : case CH_BREAK:
1536 : case CHAR_ZWSP :
1537 : case CHAR_ZWNBSP :
1538 14012 : cHookChar = cPos;
1539 14012 : return i;
1540 :
1541 : case CHAR_UNDERSCORE:
1542 5993 : if ( COMPLETE_STRING == nUnderScorePos )
1543 395 : nUnderScorePos = i;
1544 5993 : break;
1545 :
1546 : default:
1547 3800803 : if ( cTabDec )
1548 : {
1549 37 : if( cTabDec == cPos )
1550 : {
1551 : OSL_ENSURE( cPos, "Unexpected end of string" );
1552 2 : if( cPos ) // robust
1553 : {
1554 2 : cHookChar = cPos;
1555 2 : return i;
1556 : }
1557 : }
1558 :
1559 : // Compatibility: First non-digit character behind a
1560 : // a digit character becomes the hook character
1561 35 : if ( bTabCompat )
1562 : {
1563 35 : if ( ( 0x2F < cPos && cPos < 0x3A ) ||
1564 1 : ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
1565 : {
1566 3 : bNumFound = true;
1567 : }
1568 : else
1569 : {
1570 32 : if ( bNumFound )
1571 : {
1572 1 : cHookChar = cPos;
1573 1 : SetTabDecimal( cPos );
1574 1 : return i;
1575 : }
1576 : }
1577 : }
1578 : }
1579 : }
1580 : }
1581 :
1582 : // Check if character *behind* the portion has
1583 : // to become the hook:
1584 81364 : if ( i == nEnd && i < GetText().getLength() && bNumFound )
1585 : {
1586 1 : const sal_Unicode cPos = GetChar( i );
1587 1 : if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
1588 : {
1589 1 : cHookChar = GetChar( i );
1590 1 : SetTabDecimal( cHookChar );
1591 : }
1592 : }
1593 :
1594 81364 : return i;
1595 : }
1596 :
1597 82706 : bool SwTextFormatInfo::LastKernPortion()
1598 : {
1599 82706 : if( GetLast() )
1600 : {
1601 82706 : if( GetLast()->IsKernPortion() )
1602 255 : return true;
1603 86841 : if( GetLast()->Width() || ( GetLast()->GetLen() &&
1604 4390 : !GetLast()->IsHolePortion() ) )
1605 65628 : return false;
1606 : }
1607 16823 : SwLinePortion* pPor = GetRoot();
1608 16823 : SwLinePortion *pKern = NULL;
1609 65513 : while( pPor )
1610 : {
1611 31867 : if( pPor->IsKernPortion() )
1612 15 : pKern = pPor;
1613 31852 : else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
1614 13060 : pKern = NULL;
1615 31867 : pPor = pPor->GetPortion();
1616 : }
1617 16823 : if( pKern )
1618 : {
1619 6 : SetLast( pKern );
1620 6 : return true;
1621 : }
1622 16817 : return false;
1623 : }
1624 :
1625 3038 : SwTextSlot::SwTextSlot(
1626 : const SwTextSizeInfo *pNew,
1627 : const SwLinePortion *pPor,
1628 : bool bTextLen,
1629 : bool bExgLists,
1630 : OUString const & rCh )
1631 : : pOldText(0)
1632 : , pOldSmartTagList(0)
1633 : , pOldGrammarCheckList(0)
1634 : , pTempList(0)
1635 : , nIdx(0)
1636 : , nLen(0)
1637 3038 : , pInf(NULL)
1638 : {
1639 3038 : if( rCh.isEmpty() )
1640 : {
1641 3036 : bOn = pPor->GetExpText( *pNew, aText );
1642 : }
1643 : else
1644 : {
1645 2 : aText = rCh;
1646 2 : bOn = true;
1647 : }
1648 :
1649 : // The text is replaced ...
1650 3038 : if( bOn )
1651 : {
1652 3022 : pInf = const_cast<SwTextSizeInfo*>(pNew);
1653 3022 : nIdx = pInf->GetIdx();
1654 3022 : nLen = pInf->GetLen();
1655 3022 : pOldText = &(pInf->GetText());
1656 3022 : m_pOldCachedVclData = pInf->GetCachedVclData();
1657 3022 : pInf->SetText( aText );
1658 3022 : pInf->SetIdx( 0 );
1659 3022 : pInf->SetLen( bTextLen ? pInf->GetText().getLength() : pPor->GetLen() );
1660 3022 : pInf->SetCachedVclData(nullptr);
1661 :
1662 : // ST2
1663 3022 : if ( bExgLists )
1664 : {
1665 2272 : pOldSmartTagList = static_cast<SwTextPaintInfo*>(pInf)->GetSmartTags();
1666 2272 : if ( pOldSmartTagList )
1667 : {
1668 0 : const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
1669 0 : const sal_Int32 nListPos = pOldSmartTagList->Pos(nPos);
1670 0 : if( nListPos == nIdx )
1671 0 : static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
1672 0 : else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && !aText.isEmpty() )
1673 : {
1674 0 : pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
1675 0 : pTempList->Insert( OUString(), 0, 0, aText.getLength(), 0 );
1676 0 : static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pTempList );
1677 : }
1678 : else
1679 0 : static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( 0);
1680 : }
1681 2272 : pOldGrammarCheckList = static_cast<SwTextPaintInfo*>(pInf)->GetGrammarCheckList();
1682 2272 : if ( pOldGrammarCheckList )
1683 : {
1684 0 : const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
1685 0 : const sal_Int32 nListPos = pOldGrammarCheckList->Pos(nPos);
1686 0 : if( nListPos == nIdx )
1687 0 : static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
1688 0 : else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && !aText.isEmpty() )
1689 : {
1690 0 : pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
1691 0 : pTempList->Insert( OUString(), 0, 0, aText.getLength(), 0 );
1692 0 : static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pTempList );
1693 : }
1694 : else
1695 0 : static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( 0);
1696 : }
1697 : }
1698 : }
1699 3038 : }
1700 :
1701 6076 : SwTextSlot::~SwTextSlot()
1702 : {
1703 3038 : if( bOn )
1704 : {
1705 3022 : pInf->SetCachedVclData(m_pOldCachedVclData);
1706 3022 : pInf->SetText( *pOldText );
1707 3022 : pInf->SetIdx( nIdx );
1708 3022 : pInf->SetLen( nLen );
1709 :
1710 : // ST2
1711 : // Restore old smart tag list
1712 3022 : if ( pOldSmartTagList )
1713 0 : static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pOldSmartTagList );
1714 3022 : if ( pOldGrammarCheckList )
1715 0 : static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pOldGrammarCheckList );
1716 3022 : delete pTempList;
1717 : }
1718 3038 : }
1719 :
1720 38996 : SwFontSave::SwFontSave(const SwTextSizeInfo &rInf, SwFont *pNew,
1721 : SwAttrIter* pItr)
1722 : : pInf(NULL)
1723 : , pFnt(pNew ? const_cast<SwTextSizeInfo&>(rInf).GetFont() : NULL)
1724 38996 : , pIter(NULL)
1725 : {
1726 38996 : if( pFnt )
1727 : {
1728 32998 : pInf = &const_cast<SwTextSizeInfo&>(rInf);
1729 : // In these cases we temporarily switch to the new font:
1730 : // 1. the fonts have a different magic number
1731 : // 2. they have different script types
1732 : // 3. their background colors differ (this is not covered by 1.)
1733 80639 : if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
1734 27062 : pNew->GetActual() != pFnt->GetActual() ||
1735 37232 : ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
1736 78404 : ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
1737 12415 : ( pNew->GetBackColor() && pFnt->GetBackColor() &&
1738 7 : ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
1739 : {
1740 20597 : pNew->SetTransparent( true );
1741 20597 : pNew->SetAlign( ALIGN_BASELINE );
1742 20597 : pInf->SetFont( pNew );
1743 : }
1744 : else
1745 12401 : pFnt = 0;
1746 32998 : pNew->Invalidate();
1747 32998 : pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1748 32998 : if( pItr && pItr->GetFnt() == pFnt )
1749 : {
1750 10 : pIter = pItr;
1751 10 : pIter->SetFnt( pNew );
1752 : }
1753 : }
1754 38996 : }
1755 :
1756 38996 : SwFontSave::~SwFontSave()
1757 : {
1758 38996 : if( pFnt )
1759 : {
1760 : // Reset SwFont
1761 20597 : pFnt->Invalidate();
1762 20597 : pInf->SetFont( pFnt );
1763 20597 : if( pIter )
1764 : {
1765 10 : pIter->SetFnt( pFnt );
1766 10 : pIter->nPos = COMPLETE_STRING;
1767 : }
1768 : }
1769 38996 : }
1770 :
1771 0 : bool SwTextFormatInfo::ChgHyph( const bool bNew )
1772 : {
1773 0 : const bool bOld = bAutoHyph;
1774 0 : if( bAutoHyph != bNew )
1775 : {
1776 0 : bAutoHyph = bNew;
1777 0 : InitHyph( bNew );
1778 : // Set language in the Hyphenator
1779 0 : if( m_pFnt )
1780 0 : m_pFnt->ChgPhysFnt( m_pVsh, *m_pOut );
1781 : }
1782 0 : return bOld;
1783 177 : }
1784 :
1785 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|