Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / txtnode / swfont.cxx
blobc6d9c3ace26e283f1e834da1251f5eb1451f9036
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 #include <vcl/outdev.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/wrlmitem.hxx>
26 #include <editeng/kernitem.hxx>
27 #include <editeng/cmapitem.hxx>
28 #include <editeng/langitem.hxx>
29 #include <editeng/escapementitem.hxx>
30 #include <editeng/autokernitem.hxx>
31 #include <editeng/shdditem.hxx>
32 #include <editeng/charreliefitem.hxx>
33 #include <editeng/contouritem.hxx>
34 #include <editeng/colritem.hxx>
35 #include <editeng/crossedoutitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/wghtitem.hxx>
38 #include <editeng/postitem.hxx>
39 #include <editeng/fhgtitem.hxx>
40 #include <editeng/fontitem.hxx>
41 #include <editeng/emphasismarkitem.hxx>
42 #include <editeng/charscaleitem.hxx>
43 #include <editeng/charrotateitem.hxx>
44 #include <editeng/twolinesitem.hxx>
45 #include <editeng/charhiddenitem.hxx>
46 #include <editeng/boxitem.hxx>
47 #include <editeng/shaditem.hxx>
48 #include <IDocumentSettingAccess.hxx>
49 #include <charatr.hxx>
50 #include <viewsh.hxx>
51 #include <swfont.hxx>
52 #include <fntcache.hxx>
53 #include <txtfrm.hxx>
54 #include <scriptinfo.hxx>
56 #ifdef DBG_UTIL
57 // global Variable
58 SvStatistics g_SvStat;
59 #endif
61 using namespace ::com::sun::star;
63 // set background brush, depending on character formatting
64 void SwFont::SetBackColor( std::optional<Color> xNewColor )
66 mxBackColor = xNewColor;
67 m_bFontChg = true;
68 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
71 void SwFont::SetTopBorder( const editeng::SvxBorderLine* pTopBorder )
73 if( pTopBorder )
74 m_aTopBorder = *pTopBorder;
75 else
77 m_aTopBorder.reset();
78 m_nTopBorderDist = 0;
80 m_bFontChg = true;
81 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
84 void SwFont::SetBottomBorder( const editeng::SvxBorderLine* pBottomBorder )
86 if( pBottomBorder )
87 m_aBottomBorder = *pBottomBorder;
88 else
90 m_aBottomBorder.reset();
91 m_nBottomBorderDist = 0;
93 m_bFontChg = true;
94 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
97 void SwFont::SetRightBorder( const editeng::SvxBorderLine* pRightBorder )
99 if( pRightBorder )
100 m_aRightBorder = *pRightBorder;
101 else
103 m_aRightBorder.reset();
104 m_nRightBorderDist = 0;
106 m_bFontChg = true;
107 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
110 void SwFont::SetLeftBorder( const editeng::SvxBorderLine* pLeftBorder )
112 if( pLeftBorder )
113 m_aLeftBorder = *pLeftBorder;
114 else
116 m_aLeftBorder.reset();
117 m_nLeftBorderDist = 0;
119 m_bFontChg = true;
120 m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
123 const std::optional<editeng::SvxBorderLine>&
124 SwFont::GetAbsTopBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
126 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
128 case 0 :
129 return m_aTopBorder;
130 case 900 :
131 return m_aRightBorder;
132 case 1800 :
133 return m_aBottomBorder;
134 case 2700 :
135 return m_aLeftBorder;
136 default :
137 assert(false);
138 return m_aTopBorder;
142 const std::optional<editeng::SvxBorderLine>&
143 SwFont::GetAbsBottomBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
145 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
147 case 0 :
148 return m_aBottomBorder;
149 case 900 :
150 return m_aLeftBorder;
151 case 1800 :
152 return m_aTopBorder;
153 case 2700 :
154 return m_aRightBorder;
155 default :
156 assert(false);
157 return m_aBottomBorder;
161 const std::optional<editeng::SvxBorderLine>&
162 SwFont::GetAbsLeftBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
164 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
166 case 0 :
167 return m_aLeftBorder;
168 case 900 :
169 return m_aTopBorder;
170 case 1800 :
171 return m_aRightBorder;
172 case 2700 :
173 return m_aBottomBorder;
174 default :
175 assert(false);
176 return m_aLeftBorder;
180 const std::optional<editeng::SvxBorderLine>&
181 SwFont::GetAbsRightBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
183 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
185 case 0 :
186 return m_aRightBorder;
187 case 900 :
188 return m_aBottomBorder;
189 case 1800 :
190 return m_aLeftBorder;
191 case 2700 :
192 return m_aTopBorder;
193 default :
194 assert(false);
195 return m_aRightBorder;
199 SvxShadowLocation SwFont::GetAbsShadowLocation(const bool bVertLayout,
200 const bool bVertLayoutLRBT) const
202 SvxShadowLocation aLocation = SvxShadowLocation::NONE;
203 switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
205 case 0:
206 aLocation = m_aShadowLocation;
207 break;
209 case 900:
210 switch ( m_aShadowLocation )
212 case SvxShadowLocation::TopLeft:
213 aLocation = SvxShadowLocation::BottomLeft;
214 break;
215 case SvxShadowLocation::TopRight:
216 aLocation = SvxShadowLocation::TopLeft;
217 break;
218 case SvxShadowLocation::BottomLeft:
219 aLocation = SvxShadowLocation::BottomRight;
220 break;
221 case SvxShadowLocation::BottomRight:
222 aLocation = SvxShadowLocation::TopRight;
223 break;
224 case SvxShadowLocation::NONE:
225 case SvxShadowLocation::End:
226 aLocation = m_aShadowLocation;
227 break;
229 break;
231 case 1800:
232 switch ( m_aShadowLocation )
234 case SvxShadowLocation::TopLeft:
235 aLocation = SvxShadowLocation::BottomRight;
236 break;
237 case SvxShadowLocation::TopRight:
238 aLocation = SvxShadowLocation::BottomLeft;
239 break;
240 case SvxShadowLocation::BottomLeft:
241 aLocation = SvxShadowLocation::TopRight;
242 break;
243 case SvxShadowLocation::BottomRight:
244 aLocation = SvxShadowLocation::TopLeft;
245 break;
246 case SvxShadowLocation::NONE:
247 case SvxShadowLocation::End:
248 aLocation = m_aShadowLocation;
249 break;
251 break;
253 case 2700:
254 switch ( m_aShadowLocation )
256 case SvxShadowLocation::TopLeft:
257 aLocation = SvxShadowLocation::TopRight;
258 break;
259 case SvxShadowLocation::TopRight:
260 aLocation = SvxShadowLocation::BottomRight;
261 break;
262 case SvxShadowLocation::BottomLeft:
263 aLocation = SvxShadowLocation::TopLeft;
264 break;
265 case SvxShadowLocation::BottomRight:
266 aLocation = SvxShadowLocation::BottomLeft;
267 break;
268 case SvxShadowLocation::NONE:
269 case SvxShadowLocation::End:
270 aLocation = m_aShadowLocation;
271 break;
273 break;
275 default:
276 assert(false);
277 break;
279 return aLocation;
282 sal_uInt16 SwFont::CalcShadowSpace(const SvxShadowItemSide nShadow, const bool bVertLayout,
283 const bool bVertLayoutLRBT, const bool bSkipLeft,
284 const bool bSkipRight) const
286 sal_uInt16 nSpace = 0;
287 const Degree10 nOrient = GetOrientation(bVertLayout, bVertLayoutLRBT);
288 const SvxShadowLocation aLoc = GetAbsShadowLocation(bVertLayout, bVertLayoutLRBT);
289 switch( nShadow )
291 case SvxShadowItemSide::TOP:
292 if(( aLoc == SvxShadowLocation::TopLeft ||
293 aLoc == SvxShadowLocation::TopRight ) &&
294 ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
295 ( nOrient == 900_deg10 && !bSkipRight ) ||
296 ( nOrient == 2700_deg10 && !bSkipLeft )))
298 nSpace = m_nShadowWidth;
300 break;
302 case SvxShadowItemSide::BOTTOM:
303 if(( aLoc == SvxShadowLocation::BottomLeft ||
304 aLoc == SvxShadowLocation::BottomRight ) &&
305 ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
306 ( nOrient == 900_deg10 && !bSkipLeft ) ||
307 ( nOrient == 2700_deg10 && !bSkipRight )))
309 nSpace = m_nShadowWidth;
311 break;
313 case SvxShadowItemSide::LEFT:
314 if(( aLoc == SvxShadowLocation::TopLeft ||
315 aLoc == SvxShadowLocation::BottomLeft ) &&
316 ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
317 ( nOrient == 0_deg10 && !bSkipLeft ) ||
318 ( nOrient == 1800_deg10 && !bSkipRight )))
320 nSpace = m_nShadowWidth;
322 break;
324 case SvxShadowItemSide::RIGHT:
325 if(( aLoc == SvxShadowLocation::TopRight ||
326 aLoc == SvxShadowLocation::BottomRight ) &&
327 ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
328 ( nOrient == 0_deg10 && !bSkipRight ) ||
329 ( nOrient == 1800_deg10 && !bSkipLeft )))
331 nSpace = m_nShadowWidth;
333 break;
334 default:
335 assert(false);
336 break;
339 return nSpace;
342 // maps directions for vertical layout
343 static Degree10 MapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
345 if ( bVertFormat )
347 switch ( nDir.get() )
349 case 0 :
350 if (bVertFormatLRBT)
351 nDir = 900_deg10;
352 else
353 nDir = 2700_deg10;
354 break;
355 case 900 :
356 nDir = 0_deg10;
357 break;
358 case 2700 :
359 nDir = 1800_deg10;
360 break;
361 #if OSL_DEBUG_LEVEL > 0
362 default :
363 OSL_FAIL( "Unsupported direction" );
364 break;
365 #endif
368 return nDir;
371 // maps the absolute direction set at the font to its logical counterpart
372 // in the rotated environment
373 Degree10 UnMapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
375 if (bVertFormatLRBT)
377 switch (nDir.get())
379 case 900:
380 nDir = 0_deg10;
381 break;
382 default:
383 SAL_WARN("sw.core", "unsupported direction for VertLRBT");
384 break;
386 return nDir;
389 if ( bVertFormat )
391 switch ( nDir.get() )
393 case 0 :
394 nDir = 900_deg10;
395 break;
396 case 1800 :
397 nDir = 2700_deg10;
398 break;
399 case 2700 :
400 nDir = 0_deg10;
401 break;
402 #if OSL_DEBUG_LEVEL > 0
403 default :
404 OSL_FAIL( "Unsupported direction" );
405 break;
406 #endif
409 return nDir;
412 Degree10 SwFont::GetOrientation(const bool bVertFormat, const bool bVertFormatLRBT) const
414 return UnMapDirection(m_aSub[m_nActual].GetOrientation(), bVertFormat, bVertFormatLRBT);
417 void SwFont::SetVertical(Degree10 nDir, const bool bVertFormat, const bool bVertLayoutLRBT)
419 // map direction if frame has vertical layout
420 nDir = MapDirection(nDir, bVertFormat, bVertLayoutLRBT);
422 if( nDir != m_aSub[SwFontScript::Latin].GetOrientation() )
424 m_bFontChg = true;
425 bool bVertical = bVertFormat && !bVertLayoutLRBT;
426 m_aSub[SwFontScript::Latin].SetVertical(nDir, bVertical);
427 m_aSub[SwFontScript::CJK].SetVertical(nDir, bVertical);
428 m_aSub[SwFontScript::CTL].SetVertical(nDir, bVertical);
433 Escapement:
434 frEsc: Fraction, ratio of Escapements
435 Esc = resulting Escapement
436 A1 = original Ascent (nOrgAscent)
437 A2 = shrunk Ascent (nEscAscent)
438 Ax = resulting Ascent (GetAscent())
439 H1 = original Height (nOrgHeight)
440 H2 = shrunk Height (nEscHeight)
441 Hx = resulting Height (GetHeight())
442 Bx = resulting Baseline for Text (CalcPos())
443 (Attention: Y - A1!)
445 Escapement:
446 Esc = H1 * frEsc;
448 Superscript:
449 Ax = A2 + Esc;
450 Hx = H2 + Esc;
451 Bx = A1 - Esc;
453 Subscript:
454 Ax = A1;
455 Hx = A1 + Esc + (H2 - A2);
456 Bx = A1 + Esc;
459 // nEsc is the percentage
460 sal_uInt16 SwSubFont::CalcEscAscent( const sal_uInt16 nOldAscent ) const
462 if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
463 DFLT_ESC_AUTO_SUB != GetEscapement() )
465 const tools::Long nAscent = nOldAscent +
466 ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
467 if ( nAscent>0 )
468 return std::max<sal_uInt16>( nAscent, m_nOrgAscent );
470 return m_nOrgAscent;
473 void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet,
474 const IDocumentSettingAccess *pIDocumentSettingAccess )
476 mxBackColor.reset();
478 if( pAttrSet )
481 if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_FONT ) )
483 m_aSub[SwFontScript::Latin].SetFamily( pFont->GetFamily() );
484 m_aSub[SwFontScript::Latin].Font::SetFamilyName( pFont->GetFamilyName() );
485 m_aSub[SwFontScript::Latin].Font::SetStyleName( pFont->GetStyleName() );
486 m_aSub[SwFontScript::Latin].Font::SetPitch( pFont->GetPitch() );
487 m_aSub[SwFontScript::Latin].Font::SetCharSet( pFont->GetCharSet() );
489 if( const SvxFontHeightItem *pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_FONTSIZE ) )
491 m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 );
492 m_aSub[SwFontScript::Latin].m_aSize = m_aSub[SwFontScript::Latin].Font::GetFontSize();
493 Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
494 aTmpSize.setHeight( pHeight->GetHeight() );
495 m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
497 if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_POSTURE ) )
498 m_aSub[SwFontScript::Latin].Font::SetItalic( pItem->GetPosture() );
499 if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WEIGHT ) )
500 m_aSub[SwFontScript::Latin].Font::SetWeight( pItem->GetWeight() );
501 if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_LANGUAGE ) )
502 m_aSub[SwFontScript::Latin].SetLanguage( pItem->GetLanguage() );
504 if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_FONT ) )
506 m_aSub[SwFontScript::CJK].SetFamily( pFont->GetFamily() );
507 m_aSub[SwFontScript::CJK].Font::SetFamilyName( pFont->GetFamilyName() );
508 m_aSub[SwFontScript::CJK].Font::SetStyleName( pFont->GetStyleName() );
509 m_aSub[SwFontScript::CJK].Font::SetPitch( pFont->GetPitch() );
510 m_aSub[SwFontScript::CJK].Font::SetCharSet( pFont->GetCharSet() );
512 if( const SvxFontHeightItem* pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_FONTSIZE) )
514 m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 );
515 m_aSub[SwFontScript::CJK].m_aSize = m_aSub[SwFontScript::CJK].Font::GetFontSize();
516 Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
517 aTmpSize.setHeight( pHeight->GetHeight() );
518 m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
520 if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_POSTURE ) )
521 m_aSub[SwFontScript::CJK].Font::SetItalic( pItem->GetPosture() );
522 if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_WEIGHT ) )
523 m_aSub[SwFontScript::CJK].Font::SetWeight( pItem->GetWeight() );
524 if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_LANGUAGE ) )
526 LanguageType eNewLang = pItem->GetLanguage();
527 m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
528 m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
529 m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
530 m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
533 if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_FONT ) )
535 m_aSub[SwFontScript::CTL].SetFamily( pFont->GetFamily() );
536 m_aSub[SwFontScript::CTL].Font::SetFamilyName( pFont->GetFamilyName() );
537 m_aSub[SwFontScript::CTL].Font::SetStyleName( pFont->GetStyleName() );
538 m_aSub[SwFontScript::CTL].Font::SetPitch( pFont->GetPitch() );
539 m_aSub[SwFontScript::CTL].Font::SetCharSet( pFont->GetCharSet() );
541 if( const SvxFontHeightItem* pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_FONTSIZE ) )
543 m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 );
544 m_aSub[SwFontScript::CTL].m_aSize = m_aSub[SwFontScript::CTL].Font::GetFontSize();
545 Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
546 aTmpSize.setHeight( pHeight->GetHeight() );
547 m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
549 if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_POSTURE ) )
550 m_aSub[SwFontScript::CTL].Font::SetItalic(pItem->GetPosture() );
551 if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_WEIGHT ) )
552 m_aSub[SwFontScript::CTL].Font::SetWeight( pItem->GetWeight() );
553 if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_LANGUAGE ) )
554 m_aSub[SwFontScript::CTL].SetLanguage( pItem->GetLanguage() );
556 if( const SvxUnderlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_UNDERLINE ) )
558 SetUnderline( pItem->GetLineStyle() );
559 SetUnderColor( pItem->GetColor() );
561 if( const SvxOverlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_OVERLINE ) )
563 SetOverline( pItem->GetLineStyle() );
564 SetOverColor( pItem->GetColor() );
566 if( const SvxCrossedOutItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CROSSEDOUT ) )
567 SetStrikeout( pItem->GetStrikeout() );
568 if( const SvxColorItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_COLOR ) )
569 SetColor( pItem->GetValue() );
570 if( const SvxEmphasisMarkItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_EMPHASIS_MARK ))
571 SetEmphasisMark( pItem->GetEmphasisMark() );
573 SetTransparent( true );
574 SetAlign( ALIGN_BASELINE );
575 if( const SvxContourItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CONTOUR ) )
576 SetOutline( pItem->GetValue() );
577 if( const SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ) )
578 SetShadow( pItem->GetValue() );
579 if( const SvxCharReliefItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_RELIEF ) )
580 SetRelief( pItem->GetValue() );
581 if( const SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ))
582 SetPropWidth( pItem->GetValue() ? 50 : 100 );
583 if( const SvxAutoKernItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_AUTOKERN ) )
585 if( pItem->GetValue() )
587 SetAutoKern( ( !pIDocumentSettingAccess ||
588 !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
589 FontKerning::FontSpecific :
590 FontKerning::Asian );
592 else
593 SetAutoKern( FontKerning::NONE );
595 if( const SvxWordLineModeItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WORDLINEMODE ) )
596 SetWordLineMode( pItem->GetValue() );
598 if( const SvxEscapementItem* pEsc = pAttrSet->GetItemIfSet( RES_CHRATR_ESCAPEMENT ) )
600 SetEscapement( pEsc->GetEsc() );
601 if( m_aSub[SwFontScript::Latin].IsEsc() )
602 SetProportion( pEsc->GetProportionalHeight() );
604 if( const SvxCaseMapItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CASEMAP ) )
605 SetCaseMap( pItem->GetCaseMap() );
606 if( const SvxKerningItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_KERNING ) )
607 SetFixKerning( pItem->GetValue() );
608 if( const SvxCharRotateItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_ROTATE ) )
609 SetVertical( pItem->GetValue() );
610 if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
611 mxBackColor = pItem->GetColor();
612 if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
613 SetHighlightColor(pItem->GetColor());
614 if( const SvxBoxItem* pBoxItem = pAttrSet->GetItemIfSet( RES_CHRATR_BOX ) )
616 SetTopBorder(pBoxItem->GetTop());
617 SetBottomBorder(pBoxItem->GetBottom());
618 SetRightBorder(pBoxItem->GetRight());
619 SetLeftBorder(pBoxItem->GetLeft());
620 SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
621 SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
622 SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
623 SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
625 if( const SvxShadowItem* pShadowItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOW ) )
627 SetShadowColor(pShadowItem->GetColor());
628 SetShadowWidth(pShadowItem->GetWidth());
629 SetShadowLocation(pShadowItem->GetLocation());
631 const SvxTwoLinesItem* pTwoLinesItem = pAttrSet->GetItemIfSet( RES_CHRATR_TWO_LINES );
632 if( pTwoLinesItem && pTwoLinesItem->GetValue() )
633 SetVertical( 0_deg10 );
635 else
637 Invalidate();
639 m_bPaintBlank = false;
640 OSL_ENSURE( m_aSub[SwFontScript::Latin].IsTransparent(), "SwFont: Transparent revolution" );
643 SwFont::SwFont( const SwFont &rFont )
644 : m_aSub(rFont.m_aSub)
646 m_nActual = rFont.m_nActual;
647 mxBackColor = rFont.mxBackColor;
648 m_aHighlightColor = rFont.m_aHighlightColor;
649 m_aTopBorder = rFont.m_aTopBorder;
650 m_aBottomBorder = rFont.m_aBottomBorder;
651 m_aRightBorder = rFont.m_aRightBorder;
652 m_aLeftBorder = rFont.m_aLeftBorder;
653 m_nTopBorderDist = rFont.m_nTopBorderDist;
654 m_nBottomBorderDist = rFont.m_nBottomBorderDist;
655 m_nRightBorderDist = rFont.m_nRightBorderDist;
656 m_nLeftBorderDist = rFont.m_nLeftBorderDist;
657 m_aShadowColor = rFont.m_aShadowColor;
658 m_nShadowWidth = rFont.m_nShadowWidth;
659 m_aShadowLocation = rFont.m_aShadowLocation;
660 m_aUnderColor = rFont.GetUnderColor();
661 m_aOverColor = rFont.GetOverColor();
662 m_nToxCount = 0;
663 m_nRefCount = 0;
664 m_nMetaCount = 0;
665 m_nContentControlCount = 0;
666 m_nInputFieldCount = 0;
667 m_bFontChg = rFont.m_bFontChg;
668 m_bOrgChg = rFont.m_bOrgChg;
669 m_bPaintBlank = rFont.m_bPaintBlank;
670 m_bGreyWave = rFont.m_bGreyWave;
673 SwFont::SwFont( const SwAttrSet* pAttrSet,
674 const IDocumentSettingAccess* pIDocumentSettingAccess )
675 : m_aSub()
677 m_nActual = SwFontScript::Latin;
678 m_nToxCount = 0;
679 m_nRefCount = 0;
680 m_nMetaCount = 0;
681 m_nContentControlCount = 0;
682 m_nInputFieldCount = 0;
683 m_bPaintBlank = false;
684 m_bGreyWave = false;
685 m_bOrgChg = true;
687 const SvxFontItem& rFont = pAttrSet->GetFont();
688 m_aSub[SwFontScript::Latin].SetFamily( rFont.GetFamily() );
689 m_aSub[SwFontScript::Latin].SetFamilyName( rFont.GetFamilyName() );
690 m_aSub[SwFontScript::Latin].SetStyleName( rFont.GetStyleName() );
691 m_aSub[SwFontScript::Latin].SetPitch( rFont.GetPitch() );
692 m_aSub[SwFontScript::Latin].SetCharSet( rFont.GetCharSet() );
693 m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 ); // 100% of FontSize
694 Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
695 aTmpSize.setHeight( pAttrSet->GetSize().GetHeight() );
696 m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
697 m_aSub[SwFontScript::Latin].SetItalic( pAttrSet->GetPosture().GetPosture() );
698 m_aSub[SwFontScript::Latin].SetWeight( pAttrSet->GetWeight().GetWeight() );
699 m_aSub[SwFontScript::Latin].SetLanguage( pAttrSet->GetLanguage().GetLanguage() );
703 const SvxFontItem& rFont = pAttrSet->GetCJKFont();
704 m_aSub[SwFontScript::CJK].SetFamily( rFont.GetFamily() );
705 m_aSub[SwFontScript::CJK].SetFamilyName( rFont.GetFamilyName() );
706 m_aSub[SwFontScript::CJK].SetStyleName( rFont.GetStyleName() );
707 m_aSub[SwFontScript::CJK].SetPitch( rFont.GetPitch() );
708 m_aSub[SwFontScript::CJK].SetCharSet( rFont.GetCharSet() );
709 m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 ); // 100% of FontSize
710 Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
711 aTmpSize.setHeight( pAttrSet->GetCJKSize().GetHeight() );
712 m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
713 m_aSub[SwFontScript::CJK].SetItalic( pAttrSet->GetCJKPosture().GetPosture() );
714 m_aSub[SwFontScript::CJK].SetWeight( pAttrSet->GetCJKWeight().GetWeight() );
715 LanguageType eNewLang = pAttrSet->GetCJKLanguage().GetLanguage();
716 m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
717 m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
718 m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
719 m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
723 const SvxFontItem& rFont = pAttrSet->GetCTLFont();
724 m_aSub[SwFontScript::CTL].SetFamily( rFont.GetFamily() );
725 m_aSub[SwFontScript::CTL].SetFamilyName( rFont.GetFamilyName() );
726 m_aSub[SwFontScript::CTL].SetStyleName( rFont.GetStyleName() );
727 m_aSub[SwFontScript::CTL].SetPitch( rFont.GetPitch() );
728 m_aSub[SwFontScript::CTL].SetCharSet( rFont.GetCharSet() );
729 m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 ); // 100% of FontSize
730 Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
731 aTmpSize.setHeight( pAttrSet->GetCTLSize().GetHeight() );
732 m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
733 m_aSub[SwFontScript::CTL].SetItalic( pAttrSet->GetCTLPosture().GetPosture() );
734 m_aSub[SwFontScript::CTL].SetWeight( pAttrSet->GetCTLWeight().GetWeight() );
735 m_aSub[SwFontScript::CTL].SetLanguage( pAttrSet->GetCTLLanguage().GetLanguage() );
737 if ( pAttrSet->GetCharHidden().GetValue() )
738 SetUnderline( LINESTYLE_DOTTED );
739 else
740 SetUnderline( pAttrSet->GetUnderline().GetLineStyle() );
741 SetUnderColor( pAttrSet->GetUnderline().GetColor() );
742 SetOverline( pAttrSet->GetOverline().GetLineStyle() );
743 SetOverColor( pAttrSet->GetOverline().GetColor() );
744 SetEmphasisMark( pAttrSet->GetEmphasisMark().GetEmphasisMark() );
745 SetStrikeout( pAttrSet->GetCrossedOut().GetStrikeout() );
746 SetColor( pAttrSet->GetColor().GetValue() );
747 SetTransparent( true );
748 SetAlign( ALIGN_BASELINE );
749 SetOutline( pAttrSet->GetContour().GetValue() );
750 SetShadow( pAttrSet->GetShadowed().GetValue() );
751 SetPropWidth( pAttrSet->GetCharScaleW().GetValue() );
752 SetRelief( pAttrSet->GetCharRelief().GetValue() );
753 if( pAttrSet->GetAutoKern().GetValue() )
755 SetAutoKern( ( !pIDocumentSettingAccess ||
756 !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
757 FontKerning::FontSpecific :
758 FontKerning::Asian );
760 else
761 SetAutoKern( FontKerning::NONE );
762 SetWordLineMode( pAttrSet->GetWordLineMode().GetValue() );
763 const SvxEscapementItem &rEsc = pAttrSet->GetEscapement();
764 SetEscapement( rEsc.GetEsc() );
765 if( m_aSub[SwFontScript::Latin].IsEsc() )
766 SetProportion( rEsc.GetProportionalHeight() );
767 SetCaseMap( pAttrSet->GetCaseMap().GetCaseMap() );
768 SetFixKerning( pAttrSet->GetKerning().GetValue() );
769 if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
770 mxBackColor = pItem->GetColor();
771 if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
772 SetHighlightColor(pItem->GetColor());
773 else
774 SetHighlightColor(COL_TRANSPARENT);
775 if( const SvxBoxItem* pBoxItem = pAttrSet->GetItemIfSet( RES_CHRATR_BOX ) )
777 SetTopBorder(pBoxItem->GetTop());
778 SetBottomBorder(pBoxItem->GetBottom());
779 SetRightBorder(pBoxItem->GetRight());
780 SetLeftBorder(pBoxItem->GetLeft());
781 SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
782 SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
783 SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
784 SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
786 else
788 SetTopBorder(nullptr);
789 SetBottomBorder(nullptr);
790 SetRightBorder(nullptr);
791 SetLeftBorder(nullptr);
792 SetTopBorderDist(0);
793 SetBottomBorderDist(0);
794 SetRightBorderDist(0);
795 SetLeftBorderDist(0);
798 if( const SvxShadowItem* pShadowItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOW ) )
800 SetShadowColor(pShadowItem->GetColor());
801 SetShadowWidth(pShadowItem->GetWidth());
802 SetShadowLocation(pShadowItem->GetLocation());
804 else
806 SetShadowColor(COL_TRANSPARENT);
807 SetShadowWidth(0);
808 SetShadowLocation(SvxShadowLocation::NONE);
811 const SvxTwoLinesItem& rTwoLinesItem = pAttrSet->Get2Lines();
812 if ( ! rTwoLinesItem.GetValue() )
813 SetVertical( pAttrSet->GetCharRotate().GetValue() );
814 else
815 SetVertical( 0_deg10 );
816 if( pIDocumentSettingAccess && pIDocumentSettingAccess->get( DocumentSettingId::SMALL_CAPS_PERCENTAGE_66 ))
818 m_aSub[ SwFontScript::Latin ].m_bSmallCapsPercentage66 = true;
819 m_aSub[ SwFontScript::CJK ].m_bSmallCapsPercentage66 = true;
820 m_aSub[ SwFontScript::CTL ].m_bSmallCapsPercentage66 = true;
824 SwFont::~SwFont()
828 SwFont& SwFont::operator=( const SwFont &rFont )
830 if (this != &rFont)
832 m_aSub[SwFontScript::Latin] = rFont.m_aSub[SwFontScript::Latin];
833 m_aSub[SwFontScript::CJK] = rFont.m_aSub[SwFontScript::CJK];
834 m_aSub[SwFontScript::CTL] = rFont.m_aSub[SwFontScript::CTL];
835 m_nActual = rFont.m_nActual;
836 mxBackColor = rFont.mxBackColor;
837 m_aHighlightColor = rFont.m_aHighlightColor;
838 m_aTopBorder = rFont.m_aTopBorder;
839 m_aBottomBorder = rFont.m_aBottomBorder;
840 m_aRightBorder = rFont.m_aRightBorder;
841 m_aLeftBorder = rFont.m_aLeftBorder;
842 m_nTopBorderDist = rFont.m_nTopBorderDist;
843 m_nBottomBorderDist = rFont.m_nBottomBorderDist;
844 m_nRightBorderDist = rFont.m_nRightBorderDist;
845 m_nLeftBorderDist = rFont.m_nLeftBorderDist;
846 m_aShadowColor = rFont.m_aShadowColor;
847 m_nShadowWidth = rFont.m_nShadowWidth;
848 m_aShadowLocation = rFont.m_aShadowLocation;
849 m_aUnderColor = rFont.GetUnderColor();
850 m_aOverColor = rFont.GetOverColor();
851 m_nToxCount = 0;
852 m_nRefCount = 0;
853 m_nMetaCount = 0;
854 m_nContentControlCount = 0;
855 m_nInputFieldCount = 0;
856 m_bFontChg = rFont.m_bFontChg;
857 m_bOrgChg = rFont.m_bOrgChg;
858 m_bPaintBlank = rFont.m_bPaintBlank;
859 m_bGreyWave = rFont.m_bGreyWave;
861 return *this;
864 void SwFont::AllocFontCacheId( SwViewShell const *pSh, SwFontScript nWhich )
866 SwFntAccess aFntAccess( m_aSub[nWhich].m_nFontCacheId, m_aSub[nWhich].m_nFontIndex,
867 &m_aSub[nWhich], pSh, true );
870 bool SwSubFont::IsSymbol( SwViewShell const *pSh )
872 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, false );
873 return aFntAccess.Get()->IsSymbol();
876 bool SwSubFont::ChgFnt( SwViewShell const *pSh, OutputDevice& rOut )
878 if ( pLastFont )
879 pLastFont->Unlock();
880 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, true );
881 SV_STAT( nChangeFont );
883 pLastFont = aFntAccess.Get();
885 pLastFont->SetDevFont( pSh, rOut );
887 pLastFont->Lock();
888 return LINESTYLE_NONE != GetUnderline() ||
889 LINESTYLE_NONE != GetOverline() ||
890 STRIKEOUT_NONE != GetStrikeout();
893 void SwFont::ChgPhysFnt( SwViewShell const *pSh, OutputDevice& rOut )
895 if( m_bOrgChg && m_aSub[m_nActual].IsEsc() )
897 const sal_uInt8 nOldProp = m_aSub[m_nActual].GetPropr();
898 SetProportion( 100 );
899 ChgFnt( pSh, rOut );
900 SwFntAccess aFntAccess( m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex,
901 &m_aSub[m_nActual], pSh );
902 m_aSub[m_nActual].m_nOrgHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
903 m_aSub[m_nActual].m_nOrgAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
904 SetProportion( nOldProp );
905 m_bOrgChg = false;
908 if( m_bFontChg )
910 ChgFnt( pSh, rOut );
911 m_bFontChg = m_bOrgChg;
913 if( rOut.GetTextLineColor() != m_aUnderColor )
914 rOut.SetTextLineColor( m_aUnderColor );
915 if( rOut.GetOverlineColor() != m_aOverColor )
916 rOut.SetOverlineColor( m_aOverColor );
919 // Height = MaxAscent + MaxDescent
920 // MaxAscent = Max (T1_ascent, T2_ascent + (Esc * T1_height) );
921 // MaxDescent = Max (T1_height-T1_ascent,
922 // T2_height-T2_ascent - (Esc * T1_height)
923 sal_uInt16 SwSubFont::CalcEscHeight( const sal_uInt16 nOldHeight,
924 const sal_uInt16 nOldAscent ) const
926 if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
927 DFLT_ESC_AUTO_SUB != GetEscapement() )
929 tools::Long nDescent = nOldHeight - nOldAscent -
930 ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
931 const sal_uInt16 nDesc = nDescent>0
932 ? std::max<sal_uInt16>( nDescent, m_nOrgHeight - m_nOrgAscent)
933 : m_nOrgHeight - m_nOrgAscent;
934 return ( nDesc + CalcEscAscent( nOldAscent ) );
936 return m_nOrgHeight;
939 short SwSubFont::CheckKerning_( )
941 short nKernx = - short( Font::GetFontSize().Height() / 6 );
943 if ( nKernx < GetFixKerning() )
944 return GetFixKerning();
945 return nKernx;
948 sal_uInt16 SwSubFont::GetAscent( SwViewShell const *pSh, const OutputDevice& rOut )
950 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
951 const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
952 return GetEscapement() ? CalcEscAscent( nAscent ) : nAscent;
955 sal_uInt16 SwSubFont::GetHeight( SwViewShell const *pSh, const OutputDevice& rOut )
957 SV_STAT( nGetTextSize );
958 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
959 const sal_uInt16 nHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
960 if ( GetEscapement() )
962 const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
963 return CalcEscHeight( nHeight, nAscent ); // + nLeading;
965 return nHeight; // + nLeading;
968 sal_uInt16 SwSubFont::GetHangingBaseline( SwViewShell const *pSh, const OutputDevice& rOut )
970 SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
971 return aFntAccess.Get()->GetFontHangingBaseline( pSh, rOut );
974 Size SwSubFont::GetTextSize_( SwDrawTextInfo& rInf )
976 // Robust: the font is supposed to be set already, but better safe than
977 // sorry...
978 if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId ||
979 !IsSameInstance( rInf.GetpOut()->GetFont() ) )
980 ChgFnt( rInf.GetShell(), rInf.GetOut() );
982 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
984 Size aTextSize;
985 TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
986 ? TextFrameIndex(rInf.GetText().getLength())
987 : rInf.GetLen();
988 rInf.SetLen( nLn );
990 if( IsCapital() && nLn )
992 if (rInf.GetMeasureLen() != TextFrameIndex(COMPLETE_STRING))
994 rInf.SetLen(rInf.GetMeasureLen());
995 rInf.SetMeasureLen(TextFrameIndex(COMPLETE_STRING));
997 aTextSize = GetCapitalSize( rInf );
999 else
1001 SV_STAT( nGetTextSize );
1002 tools::Long nOldKern = rInf.GetKern();
1003 const OUString oldText = rInf.GetText();
1004 rInf.SetKern( CheckKerning() );
1005 if ( !IsCaseMap() )
1006 aTextSize = pLastFont->GetTextSize( rInf );
1007 else
1009 const OUString aTmp = CalcCaseMap( rInf.GetText() );
1010 const OUString oldStr = rInf.GetText();
1011 bool bCaseMapLengthDiffers(aTmp.getLength() != oldStr.getLength());
1013 if(bCaseMapLengthDiffers && rInf.GetLen())
1015 // If the length of the original string and the CaseMapped one
1016 // are different, it is necessary to handle the given text part as
1017 // a single snippet since its size may differ, too.
1018 TextFrameIndex const nOldIdx(rInf.GetIdx());
1019 TextFrameIndex const nOldLen(rInf.GetLen());
1020 TextFrameIndex const nOldMeasureLen(rInf.GetMeasureLen());
1021 const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
1022 const OUString aNewText(CalcCaseMap(aSnippet));
1024 rInf.SetText( aNewText );
1025 rInf.SetIdx( TextFrameIndex(0) );
1026 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1027 if (nOldMeasureLen != TextFrameIndex(COMPLETE_STRING))
1029 const OUString aMeasureSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldMeasureLen)));
1030 const OUString aNewMeasureText(CalcCaseMap(aMeasureSnippet));
1031 rInf.SetMeasureLen(TextFrameIndex(aNewMeasureText.getLength()));
1034 aTextSize = pLastFont->GetTextSize( rInf );
1036 rInf.SetIdx( nOldIdx );
1037 rInf.SetLen( nOldLen );
1038 rInf.SetMeasureLen(nOldMeasureLen);
1040 else
1042 rInf.SetText( aTmp );
1043 aTextSize = pLastFont->GetTextSize( rInf );
1046 rInf.SetText(oldStr);
1048 rInf.SetKern( nOldKern );
1049 rInf.SetText(oldText);
1050 // A word that's longer than one line, with escapement at the line
1051 // break, must report its effective height.
1052 if( GetEscapement() )
1054 const sal_uInt16 nAscent = pLastFont->GetFontAscent( rInf.GetShell(),
1055 rInf.GetOut() );
1056 aTextSize.setHeight(
1057 static_cast<tools::Long>(CalcEscHeight( o3tl::narrowing<sal_uInt16>(aTextSize.Height()), nAscent)) );
1061 if (TextFrameIndex(1) == rInf.GetLen()
1062 && CH_TXT_ATR_FIELDSTART == rInf.GetText()[sal_Int32(rInf.GetIdx())])
1064 SAL_WARN("sw", "this is meant to be dead code");
1065 TextFrameIndex const nOldIdx(rInf.GetIdx());
1066 TextFrameIndex const nOldLen(rInf.GetLen());
1067 OUString aOldText(rInf.GetText());
1068 const OUString aNewText(CH_TXT_ATR_SUBST_FIELDSTART);
1069 rInf.SetTextIdxLen(aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
1070 aTextSize = pLastFont->GetTextSize( rInf );
1071 rInf.SetTextIdxLen(aOldText, nOldIdx, nOldLen);
1073 else if (TextFrameIndex(1) == rInf.GetLen()
1074 && CH_TXT_ATR_FIELDEND == rInf.GetText()[sal_Int32(rInf.GetIdx())])
1076 SAL_WARN("sw", "this is meant to be dead code");
1077 TextFrameIndex const nOldIdx(rInf.GetIdx());
1078 TextFrameIndex const nOldLen(rInf.GetLen());
1079 OUString aOldText(rInf.GetText());
1080 const OUString aNewText(CH_TXT_ATR_SUBST_FIELDEND);
1081 rInf.SetTextIdxLen(aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
1082 aTextSize = pLastFont->GetTextSize( rInf );
1083 rInf.SetTextIdxLen(aOldText, nOldIdx, nOldLen);
1086 return aTextSize;
1089 void SwSubFont::DrawText_( SwDrawTextInfo &rInf, const bool bGrey )
1091 rInf.SetGreyWave( bGrey );
1092 TextFrameIndex const nLn(rInf.GetText().getLength());
1093 if( !rInf.GetLen() || !nLn )
1094 return;
1095 if (TextFrameIndex(COMPLETE_STRING) == rInf.GetLen())
1096 rInf.SetLen( nLn );
1098 FontLineStyle nOldUnder = LINESTYLE_NONE;
1099 SwUnderlineFont* pUnderFnt = nullptr;
1101 if( rInf.GetUnderFnt() )
1103 nOldUnder = GetUnderline();
1104 SetUnderline( LINESTYLE_NONE );
1105 pUnderFnt = rInf.GetUnderFnt();
1108 if( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
1109 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1111 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1113 const Point aOldPos(rInf.GetPos());
1114 Point aPos( rInf.GetPos() );
1116 if( GetEscapement() )
1117 CalcEsc( rInf, aPos );
1119 rInf.SetPos( aPos );
1120 rInf.SetKern( CheckKerning() + rInf.GetCharacterSpacing() / SPACING_PRECISION_FACTOR );
1122 if( IsCapital() )
1123 DrawCapital( rInf );
1124 else
1126 SV_STAT( nDrawText );
1127 if ( !IsCaseMap() )
1128 pLastFont->DrawText( rInf );
1129 else
1131 const OUString oldStr = rInf.GetText();
1132 const OUString aString( CalcCaseMap(oldStr) );
1133 bool bCaseMapLengthDiffers(aString.getLength() != oldStr.getLength());
1135 if(bCaseMapLengthDiffers && rInf.GetLen())
1137 // If the length of the original string and the CaseMapped one
1138 // are different, it is necessary to handle the given text part as
1139 // a single snippet since its size may differ, too.
1140 TextFrameIndex const nOldIdx(rInf.GetIdx());
1141 TextFrameIndex const nOldLen(rInf.GetLen());
1142 const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
1143 const OUString aNewText = CalcCaseMap(aSnippet);
1145 rInf.SetText( aNewText );
1146 rInf.SetIdx( TextFrameIndex(0) );
1147 rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
1149 pLastFont->DrawText( rInf );
1151 rInf.SetIdx( nOldIdx );
1152 rInf.SetLen( nOldLen );
1154 else
1156 rInf.SetText( aString );
1157 pLastFont->DrawText( rInf );
1160 rInf.SetText(oldStr);
1164 if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
1166 Size aFontSize = GetTextSize_( rInf );
1167 const OUString oldStr = rInf.GetText();
1169 TextFrameIndex const nOldIdx = rInf.GetIdx();
1170 TextFrameIndex const nOldLen = rInf.GetLen();
1171 tools::Long nSpace = 0;
1172 if( rInf.GetSpace() )
1174 TextFrameIndex nTmpEnd = nOldIdx + nOldLen;
1175 if (nTmpEnd > TextFrameIndex(oldStr.getLength()))
1176 nTmpEnd = TextFrameIndex(oldStr.getLength());
1178 const SwScriptInfo* pSI = rInf.GetScriptInfo();
1180 const bool bAsianFont =
1181 ( rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() );
1182 for (TextFrameIndex nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp)
1184 if (CH_BLANK == oldStr[sal_Int32(nTmp)] || bAsianFont ||
1185 (nTmp + TextFrameIndex(1) < TextFrameIndex(oldStr.getLength())
1186 && pSI
1187 && i18n::ScriptType::ASIAN == pSI->ScriptType(nTmp + TextFrameIndex(1))))
1189 ++nSpace;
1193 // if next portion if a hole portion we do not consider any
1194 // extra space added because the last character was ASIAN
1195 if ( nSpace && rInf.IsSpaceStop() && bAsianFont )
1196 --nSpace;
1198 nSpace *= rInf.GetSpace() / SPACING_PRECISION_FACTOR;
1201 rInf.SetWidth( sal_uInt16(aFontSize.Width() + nSpace) );
1202 rInf.SetTextIdxLen( " ", TextFrameIndex(0), TextFrameIndex(2) );
1203 SetUnderline( nOldUnder );
1204 rInf.SetUnderFnt( nullptr );
1206 // set position for underline font
1207 rInf.SetPos( pUnderFnt->GetPos() );
1209 pUnderFnt->GetFont().DrawStretchText_( rInf );
1211 rInf.SetUnderFnt( pUnderFnt );
1212 rInf.SetTextIdxLen(oldStr, nOldIdx, nOldLen);
1215 rInf.SetPos(aOldPos);
1218 void SwSubFont::DrawStretchText_( SwDrawTextInfo &rInf )
1220 if( !rInf.GetLen() || !rInf.GetText().getLength() )
1221 return;
1223 FontLineStyle nOldUnder = LINESTYLE_NONE;
1224 SwUnderlineFont* pUnderFnt = nullptr;
1226 if( rInf.GetUnderFnt() )
1228 nOldUnder = GetUnderline();
1229 SetUnderline( LINESTYLE_NONE );
1230 pUnderFnt = rInf.GetUnderFnt();
1233 if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
1234 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1236 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1238 rInf.ApplyAutoColor();
1240 const Point aOldPos(rInf.GetPos());
1241 Point aPos( rInf.GetPos() );
1243 if( GetEscapement() )
1244 CalcEsc( rInf, aPos );
1246 rInf.SetKern( CheckKerning() + rInf.GetCharacterSpacing() / SPACING_PRECISION_FACTOR );
1247 rInf.SetPos( aPos );
1249 if( IsCapital() )
1250 DrawStretchCapital( rInf );
1251 else
1253 SV_STAT( nDrawStretchText );
1255 if ( rInf.GetFrame() )
1257 if ( rInf.GetFrame()->IsRightToLeft() )
1258 rInf.GetFrame()->SwitchLTRtoRTL( aPos );
1260 if ( rInf.GetFrame()->IsVertical() )
1261 rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
1263 rInf.SetPos( aPos );
1266 if ( !IsCaseMap() )
1267 rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
1268 rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
1269 else
1270 rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
1271 CalcCaseMap(rInf.GetText()),
1272 sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
1275 if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
1277 const OUString oldStr = rInf.GetText();
1278 TextFrameIndex const nOldIdx = rInf.GetIdx();
1279 TextFrameIndex const nOldLen = rInf.GetLen();
1280 rInf.SetTextIdxLen( " ", TextFrameIndex(0), TextFrameIndex(2) );
1281 SetUnderline( nOldUnder );
1282 rInf.SetUnderFnt( nullptr );
1284 // set position for underline font
1285 rInf.SetPos( pUnderFnt->GetPos() );
1287 pUnderFnt->GetFont().DrawStretchText_( rInf );
1289 rInf.SetUnderFnt( pUnderFnt );
1290 rInf.SetTextIdxLen(oldStr, nOldIdx, nOldLen);
1293 rInf.SetPos(aOldPos);
1296 TextFrameIndex SwSubFont::GetModelPositionForViewPoint_( SwDrawTextInfo& rInf )
1298 if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
1299 ChgFnt( rInf.GetShell(), rInf.GetOut() );
1301 SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
1303 TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
1304 ? TextFrameIndex(rInf.GetText().getLength())
1305 : rInf.GetLen();
1306 rInf.SetLen( nLn );
1307 TextFrameIndex nCursor(0);
1308 if( IsCapital() && nLn )
1309 nCursor = GetCapitalCursorOfst( rInf );
1310 else
1312 const OUString oldText = rInf.GetText();
1313 tools::Long nOldKern = rInf.GetKern();
1314 rInf.SetKern( CheckKerning() );
1315 SV_STAT( nGetTextSize );
1316 if ( !IsCaseMap() )
1317 nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
1318 else
1320 rInf.SetText( CalcCaseMap( rInf.GetText() ) );
1321 nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
1323 rInf.SetKern( nOldKern );
1324 rInf.SetText(oldText);
1326 return nCursor;
1329 void SwSubFont::CalcEsc( SwDrawTextInfo const & rInf, Point& rPos )
1331 tools::Long nOfst;
1333 bool bVert = false;
1334 bool bVertLRBT = false;
1335 if (rInf.GetFrame())
1337 bVert = rInf.GetFrame()->IsVertical();
1338 bVertLRBT = rInf.GetFrame()->IsVertLRBT();
1340 const Degree10 nDir = UnMapDirection(GetOrientation(), bVert, bVertLRBT);
1342 switch ( GetEscapement() )
1344 case DFLT_ESC_AUTO_SUB :
1345 nOfst = m_nOrgHeight - m_nOrgAscent -
1346 pLastFont->GetFontHeight( rInf.GetShell(), rInf.GetOut() ) +
1347 pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() );
1349 switch ( nDir.get() )
1351 case 0 :
1352 rPos.AdjustY(nOfst );
1353 break;
1354 case 900 :
1355 rPos.AdjustX(nOfst );
1356 break;
1357 case 2700 :
1358 rPos.AdjustX( -nOfst );
1359 break;
1362 break;
1363 case DFLT_ESC_AUTO_SUPER :
1364 nOfst = pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() ) -
1365 m_nOrgAscent;
1367 switch ( nDir.get() )
1369 case 0 :
1370 rPos.AdjustY(nOfst );
1371 break;
1372 case 900 :
1373 rPos.AdjustX(nOfst );
1374 break;
1375 case 2700 :
1376 rPos.AdjustX( -nOfst );
1377 break;
1380 break;
1381 default :
1382 nOfst = (static_cast<tools::Long>(m_nOrgHeight) * GetEscapement()) / 100;
1384 switch ( nDir.get() )
1386 case 0 :
1387 rPos.AdjustY( -nOfst );
1388 break;
1389 case 900 :
1390 rPos.AdjustX( -nOfst );
1391 break;
1392 case 2700 :
1393 rPos.AdjustX(nOfst );
1394 break;
1399 // used during painting of small capitals
1400 void SwDrawTextInfo::Shift( Degree10 nDir )
1402 #ifdef DBG_UTIL
1403 OSL_ENSURE( m_bPos, "DrawTextInfo: Undefined Position" );
1404 OSL_ENSURE( m_bSize, "DrawTextInfo: Undefined Width" );
1405 #endif
1407 const bool bBidiPor = ( GetFrame() && GetFrame()->IsRightToLeft() ) !=
1408 ( vcl::text::ComplexTextLayoutFlags::Default != ( vcl::text::ComplexTextLayoutFlags::BiDiRtl & GetpOut()->GetLayoutMode() ) );
1410 bool bVert = false;
1411 bool bVertLRBT = false;
1412 if (GetFrame())
1414 bVert = GetFrame()->IsVertical();
1415 bVertLRBT = GetFrame()->IsVertLRBT();
1417 nDir = bBidiPor ? 1800_deg10 : UnMapDirection(nDir, bVert, bVertLRBT);
1419 switch ( nDir.get() )
1421 case 0 :
1422 m_aPos.AdjustX(GetSize().Width() );
1423 break;
1424 case 900 :
1425 OSL_ENSURE( m_aPos.Y() >= GetSize().Width(), "Going underground" );
1426 m_aPos.AdjustY( -(GetSize().Width()) );
1427 break;
1428 case 1800 :
1429 m_aPos.AdjustX( -(GetSize().Width()) );
1430 break;
1431 case 2700 :
1432 m_aPos.AdjustY(GetSize().Width() );
1433 break;
1438 * @note Used for the "continuous underline" feature.
1440 SwUnderlineFont::SwUnderlineFont(SwFont& rFnt, TextFrameIndex const nEnd, const Point& rPoint)
1441 : m_aPos( rPoint ), m_nEnd( nEnd ), m_pFont( &rFnt )
1445 SwUnderlineFont::~SwUnderlineFont()
1449 /// Helper for filters to find true lineheight of a font
1450 tools::Long AttrSetToLineHeight( const IDocumentSettingAccess& rIDocumentSettingAccess,
1451 const SwAttrSet &rSet,
1452 const vcl::RenderContext &rOut, sal_Int16 nScript)
1454 SwFont aFont(&rSet, &rIDocumentSettingAccess);
1455 SwFontScript nActual;
1456 switch (nScript)
1458 default:
1459 case i18n::ScriptType::LATIN:
1460 nActual = SwFontScript::Latin;
1461 break;
1462 case i18n::ScriptType::ASIAN:
1463 nActual = SwFontScript::CJK;
1464 break;
1465 case i18n::ScriptType::COMPLEX:
1466 nActual = SwFontScript::CTL;
1467 break;
1469 aFont.SetActual(nActual);
1471 vcl::RenderContext &rMutableOut = const_cast<vcl::RenderContext &>(rOut);
1472 const vcl::Font aOldFont(rMutableOut.GetFont());
1474 rMutableOut.SetFont(aFont.GetActualFont());
1475 tools::Long nHeight = rMutableOut.GetTextHeight();
1477 rMutableOut.SetFont(aOldFont);
1478 return nHeight;
1481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */