summaryrefslogtreecommitdiffstats
path: root/sw/source/core/txtnode/swfont.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/txtnode/swfont.cxx')
-rw-r--r--sw/source/core/txtnode/swfont.cxx1469
1 files changed, 1469 insertions, 0 deletions
diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx
new file mode 100644
index 000000000..0ed7baf87
--- /dev/null
+++ b/sw/source/core/txtnode/swfont.cxx
@@ -0,0 +1,1469 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <hintids.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <vcl/outdev.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/autokernitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/emphasismarkitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <charatr.hxx>
+#include <viewsh.hxx>
+#include <swfont.hxx>
+#include <fntcache.hxx>
+#include <txtfrm.hxx>
+#include <scriptinfo.hxx>
+
+#ifdef DBG_UTIL
+// global Variable
+SvStatistics g_SvStat;
+#endif
+
+using namespace ::com::sun::star;
+
+// set background brush, depending on character formatting
+void SwFont::SetBackColor( std::optional<Color> xNewColor )
+{
+ mxBackColor = xNewColor;
+ m_bFontChg = true;
+ m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
+}
+
+void SwFont::SetTopBorder( const editeng::SvxBorderLine* pTopBorder )
+{
+ if( pTopBorder )
+ m_aTopBorder = *pTopBorder;
+ else
+ {
+ m_aTopBorder.reset();
+ m_nTopBorderDist = 0;
+ }
+ m_bFontChg = true;
+ m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
+}
+
+void SwFont::SetBottomBorder( const editeng::SvxBorderLine* pBottomBorder )
+{
+ if( pBottomBorder )
+ m_aBottomBorder = *pBottomBorder;
+ else
+ {
+ m_aBottomBorder.reset();
+ m_nBottomBorderDist = 0;
+ }
+ m_bFontChg = true;
+ m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
+}
+
+void SwFont::SetRightBorder( const editeng::SvxBorderLine* pRightBorder )
+{
+ if( pRightBorder )
+ m_aRightBorder = *pRightBorder;
+ else
+ {
+ m_aRightBorder.reset();
+ m_nRightBorderDist = 0;
+ }
+ m_bFontChg = true;
+ m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
+}
+
+void SwFont::SetLeftBorder( const editeng::SvxBorderLine* pLeftBorder )
+{
+ if( pLeftBorder )
+ m_aLeftBorder = *pLeftBorder;
+ else
+ {
+ m_aLeftBorder.reset();
+ m_nLeftBorderDist = 0;
+ }
+ m_bFontChg = true;
+ m_aSub[SwFontScript::Latin].m_nFontCacheId = m_aSub[SwFontScript::CJK].m_nFontCacheId = m_aSub[SwFontScript::CTL].m_nFontCacheId = nullptr;
+}
+
+const std::optional<editeng::SvxBorderLine>&
+SwFont::GetAbsTopBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
+{
+ switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
+ {
+ case 0 :
+ return m_aTopBorder;
+ case 900 :
+ return m_aRightBorder;
+ case 1800 :
+ return m_aBottomBorder;
+ case 2700 :
+ return m_aLeftBorder;
+ default :
+ assert(false);
+ return m_aTopBorder;
+ }
+}
+
+const std::optional<editeng::SvxBorderLine>&
+SwFont::GetAbsBottomBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
+{
+ switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
+ {
+ case 0 :
+ return m_aBottomBorder;
+ case 900 :
+ return m_aLeftBorder;
+ case 1800 :
+ return m_aTopBorder;
+ case 2700 :
+ return m_aRightBorder;
+ default :
+ assert(false);
+ return m_aBottomBorder;
+ }
+}
+
+const std::optional<editeng::SvxBorderLine>&
+SwFont::GetAbsLeftBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
+{
+ switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
+ {
+ case 0 :
+ return m_aLeftBorder;
+ case 900 :
+ return m_aTopBorder;
+ case 1800 :
+ return m_aRightBorder;
+ case 2700 :
+ return m_aBottomBorder;
+ default :
+ assert(false);
+ return m_aLeftBorder;
+ }
+}
+
+const std::optional<editeng::SvxBorderLine>&
+SwFont::GetAbsRightBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const
+{
+ switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
+ {
+ case 0 :
+ return m_aRightBorder;
+ case 900 :
+ return m_aBottomBorder;
+ case 1800 :
+ return m_aLeftBorder;
+ case 2700 :
+ return m_aTopBorder;
+ default :
+ assert(false);
+ return m_aRightBorder;
+ }
+}
+
+SvxShadowLocation SwFont::GetAbsShadowLocation(const bool bVertLayout,
+ const bool bVertLayoutLRBT) const
+{
+ SvxShadowLocation aLocation = SvxShadowLocation::NONE;
+ switch (GetOrientation(bVertLayout, bVertLayoutLRBT).get())
+ {
+ case 0:
+ aLocation = m_aShadowLocation;
+ break;
+
+ case 900:
+ switch ( m_aShadowLocation )
+ {
+ case SvxShadowLocation::TopLeft:
+ aLocation = SvxShadowLocation::BottomLeft;
+ break;
+ case SvxShadowLocation::TopRight:
+ aLocation = SvxShadowLocation::TopLeft;
+ break;
+ case SvxShadowLocation::BottomLeft:
+ aLocation = SvxShadowLocation::BottomRight;
+ break;
+ case SvxShadowLocation::BottomRight:
+ aLocation = SvxShadowLocation::TopRight;
+ break;
+ case SvxShadowLocation::NONE:
+ case SvxShadowLocation::End:
+ aLocation = m_aShadowLocation;
+ break;
+ }
+ break;
+
+ case 1800:
+ switch ( m_aShadowLocation )
+ {
+ case SvxShadowLocation::TopLeft:
+ aLocation = SvxShadowLocation::BottomRight;
+ break;
+ case SvxShadowLocation::TopRight:
+ aLocation = SvxShadowLocation::BottomLeft;
+ break;
+ case SvxShadowLocation::BottomLeft:
+ aLocation = SvxShadowLocation::TopRight;
+ break;
+ case SvxShadowLocation::BottomRight:
+ aLocation = SvxShadowLocation::TopLeft;
+ break;
+ case SvxShadowLocation::NONE:
+ case SvxShadowLocation::End:
+ aLocation = m_aShadowLocation;
+ break;
+ }
+ break;
+
+ case 2700:
+ switch ( m_aShadowLocation )
+ {
+ case SvxShadowLocation::TopLeft:
+ aLocation = SvxShadowLocation::TopRight;
+ break;
+ case SvxShadowLocation::TopRight:
+ aLocation = SvxShadowLocation::BottomRight;
+ break;
+ case SvxShadowLocation::BottomLeft:
+ aLocation = SvxShadowLocation::TopLeft;
+ break;
+ case SvxShadowLocation::BottomRight:
+ aLocation = SvxShadowLocation::BottomLeft;
+ break;
+ case SvxShadowLocation::NONE:
+ case SvxShadowLocation::End:
+ aLocation = m_aShadowLocation;
+ break;
+ }
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+ return aLocation;
+}
+
+sal_uInt16 SwFont::CalcShadowSpace(const SvxShadowItemSide nShadow, const bool bVertLayout,
+ const bool bVertLayoutLRBT, const bool bSkipLeft,
+ const bool bSkipRight) const
+{
+ sal_uInt16 nSpace = 0;
+ const Degree10 nOrient = GetOrientation(bVertLayout, bVertLayoutLRBT);
+ const SvxShadowLocation aLoc = GetAbsShadowLocation(bVertLayout, bVertLayoutLRBT);
+ switch( nShadow )
+ {
+ case SvxShadowItemSide::TOP:
+ if(( aLoc == SvxShadowLocation::TopLeft ||
+ aLoc == SvxShadowLocation::TopRight ) &&
+ ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
+ ( nOrient == 900_deg10 && !bSkipRight ) ||
+ ( nOrient == 2700_deg10 && !bSkipLeft )))
+ {
+ nSpace = m_nShadowWidth;
+ }
+ break;
+
+ case SvxShadowItemSide::BOTTOM:
+ if(( aLoc == SvxShadowLocation::BottomLeft ||
+ aLoc == SvxShadowLocation::BottomRight ) &&
+ ( nOrient == 0_deg10 || nOrient == 1800_deg10 ||
+ ( nOrient == 900_deg10 && !bSkipLeft ) ||
+ ( nOrient == 2700_deg10 && !bSkipRight )))
+ {
+ nSpace = m_nShadowWidth;
+ }
+ break;
+
+ case SvxShadowItemSide::LEFT:
+ if(( aLoc == SvxShadowLocation::TopLeft ||
+ aLoc == SvxShadowLocation::BottomLeft ) &&
+ ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
+ ( nOrient == 0_deg10 && !bSkipLeft ) ||
+ ( nOrient == 1800_deg10 && !bSkipRight )))
+ {
+ nSpace = m_nShadowWidth;
+ }
+ break;
+
+ case SvxShadowItemSide::RIGHT:
+ if(( aLoc == SvxShadowLocation::TopRight ||
+ aLoc == SvxShadowLocation::BottomRight ) &&
+ ( nOrient == 900_deg10 || nOrient == 2700_deg10 ||
+ ( nOrient == 0_deg10 && !bSkipRight ) ||
+ ( nOrient == 1800_deg10 && !bSkipLeft )))
+ {
+ nSpace = m_nShadowWidth;
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ return nSpace;
+}
+
+// maps directions for vertical layout
+static Degree10 MapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
+{
+ if ( bVertFormat )
+ {
+ switch ( nDir.get() )
+ {
+ case 0 :
+ if (bVertFormatLRBT)
+ nDir = 900_deg10;
+ else
+ nDir = 2700_deg10;
+ break;
+ case 900 :
+ nDir = 0_deg10;
+ break;
+ case 2700 :
+ nDir = 1800_deg10;
+ break;
+#if OSL_DEBUG_LEVEL > 0
+ default :
+ OSL_FAIL( "Unsupported direction" );
+ break;
+#endif
+ }
+ }
+ return nDir;
+}
+
+// maps the absolute direction set at the font to its logical counterpart
+// in the rotated environment
+Degree10 UnMapDirection(Degree10 nDir, const bool bVertFormat, const bool bVertFormatLRBT)
+{
+ if (bVertFormatLRBT)
+ {
+ switch (nDir.get())
+ {
+ case 900:
+ nDir = 0_deg10;
+ break;
+ default:
+ SAL_WARN("sw.core", "unsupported direction for VertLRBT");
+ break;
+ }
+ return nDir;
+ }
+
+ if ( bVertFormat )
+ {
+ switch ( nDir.get() )
+ {
+ case 0 :
+ nDir = 900_deg10;
+ break;
+ case 1800 :
+ nDir = 2700_deg10;
+ break;
+ case 2700 :
+ nDir = 0_deg10;
+ break;
+#if OSL_DEBUG_LEVEL > 0
+ default :
+ OSL_FAIL( "Unsupported direction" );
+ break;
+#endif
+ }
+ }
+ return nDir;
+}
+
+Degree10 SwFont::GetOrientation(const bool bVertFormat, const bool bVertFormatLRBT) const
+{
+ return UnMapDirection(m_aSub[m_nActual].GetOrientation(), bVertFormat, bVertFormatLRBT);
+}
+
+void SwFont::SetVertical(Degree10 nDir, const bool bVertFormat, const bool bVertLayoutLRBT)
+{
+ // map direction if frame has vertical layout
+ nDir = MapDirection(nDir, bVertFormat, bVertLayoutLRBT);
+
+ if( nDir != m_aSub[SwFontScript::Latin].GetOrientation() )
+ {
+ m_bFontChg = true;
+ bool bVertical = bVertFormat && !bVertLayoutLRBT;
+ m_aSub[SwFontScript::Latin].SetVertical(nDir, bVertical);
+ m_aSub[SwFontScript::CJK].SetVertical(nDir, bVertical);
+ m_aSub[SwFontScript::CTL].SetVertical(nDir, bVertical);
+ }
+}
+
+/*
+ Escapement:
+ frEsc: Fraction, ratio of Escapements
+ Esc = resulting Escapement
+ A1 = original Ascent (nOrgAscent)
+ A2 = shrunk Ascent (nEscAscent)
+ Ax = resulting Ascent (GetAscent())
+ H1 = original Height (nOrgHeight)
+ H2 = shrunk Height (nEscHeight)
+ Hx = resulting Height (GetHeight())
+ Bx = resulting Baseline for Text (CalcPos())
+ (Attention: Y - A1!)
+
+ Escapement:
+ Esc = H1 * frEsc;
+
+ Superscript:
+ Ax = A2 + Esc;
+ Hx = H2 + Esc;
+ Bx = A1 - Esc;
+
+ Subscript:
+ Ax = A1;
+ Hx = A1 + Esc + (H2 - A2);
+ Bx = A1 + Esc;
+*/
+
+// nEsc is the percentage
+sal_uInt16 SwSubFont::CalcEscAscent( const sal_uInt16 nOldAscent ) const
+{
+ if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
+ DFLT_ESC_AUTO_SUB != GetEscapement() )
+ {
+ const tools::Long nAscent = nOldAscent +
+ ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
+ if ( nAscent>0 )
+ return std::max<sal_uInt16>( nAscent, m_nOrgAscent );
+ }
+ return m_nOrgAscent;
+}
+
+void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet,
+ const IDocumentSettingAccess *pIDocumentSettingAccess )
+{
+ mxBackColor.reset();
+
+ if( pAttrSet )
+ {
+
+ if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_FONT ) )
+ {
+ m_aSub[SwFontScript::Latin].SetFamily( pFont->GetFamily() );
+ m_aSub[SwFontScript::Latin].Font::SetFamilyName( pFont->GetFamilyName() );
+ m_aSub[SwFontScript::Latin].Font::SetStyleName( pFont->GetStyleName() );
+ m_aSub[SwFontScript::Latin].Font::SetPitch( pFont->GetPitch() );
+ m_aSub[SwFontScript::Latin].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( const SvxFontHeightItem *pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_FONTSIZE ) )
+ {
+ m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 );
+ m_aSub[SwFontScript::Latin].m_aSize = m_aSub[SwFontScript::Latin].Font::GetFontSize();
+ Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
+ aTmpSize.setHeight( pHeight->GetHeight() );
+ m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
+ }
+ if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_POSTURE ) )
+ m_aSub[SwFontScript::Latin].Font::SetItalic( pItem->GetPosture() );
+ if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WEIGHT ) )
+ m_aSub[SwFontScript::Latin].Font::SetWeight( pItem->GetWeight() );
+ if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_LANGUAGE ) )
+ m_aSub[SwFontScript::Latin].SetLanguage( pItem->GetLanguage() );
+
+ if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_FONT ) )
+ {
+ m_aSub[SwFontScript::CJK].SetFamily( pFont->GetFamily() );
+ m_aSub[SwFontScript::CJK].Font::SetFamilyName( pFont->GetFamilyName() );
+ m_aSub[SwFontScript::CJK].Font::SetStyleName( pFont->GetStyleName() );
+ m_aSub[SwFontScript::CJK].Font::SetPitch( pFont->GetPitch() );
+ m_aSub[SwFontScript::CJK].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( const SvxFontHeightItem* pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_FONTSIZE) )
+ {
+ m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 );
+ m_aSub[SwFontScript::CJK].m_aSize = m_aSub[SwFontScript::CJK].Font::GetFontSize();
+ Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
+ aTmpSize.setHeight( pHeight->GetHeight() );
+ m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
+ }
+ if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_POSTURE ) )
+ m_aSub[SwFontScript::CJK].Font::SetItalic( pItem->GetPosture() );
+ if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_WEIGHT ) )
+ m_aSub[SwFontScript::CJK].Font::SetWeight( pItem->GetWeight() );
+ if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_LANGUAGE ) )
+ {
+ LanguageType eNewLang = pItem->GetLanguage();
+ m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
+ m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
+ m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
+ m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
+ }
+
+ if( const SvxFontItem* pFont = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_FONT ) )
+ {
+ m_aSub[SwFontScript::CTL].SetFamily( pFont->GetFamily() );
+ m_aSub[SwFontScript::CTL].Font::SetFamilyName( pFont->GetFamilyName() );
+ m_aSub[SwFontScript::CTL].Font::SetStyleName( pFont->GetStyleName() );
+ m_aSub[SwFontScript::CTL].Font::SetPitch( pFont->GetPitch() );
+ m_aSub[SwFontScript::CTL].Font::SetCharSet( pFont->GetCharSet() );
+ }
+ if( const SvxFontHeightItem* pHeight = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_FONTSIZE ) )
+ {
+ m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 );
+ m_aSub[SwFontScript::CTL].m_aSize = m_aSub[SwFontScript::CTL].Font::GetFontSize();
+ Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
+ aTmpSize.setHeight( pHeight->GetHeight() );
+ m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
+ }
+ if( const SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_POSTURE ) )
+ m_aSub[SwFontScript::CTL].Font::SetItalic(pItem->GetPosture() );
+ if( const SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_WEIGHT ) )
+ m_aSub[SwFontScript::CTL].Font::SetWeight( pItem->GetWeight() );
+ if( const SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_LANGUAGE ) )
+ m_aSub[SwFontScript::CTL].SetLanguage( pItem->GetLanguage() );
+
+ if( const SvxUnderlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_UNDERLINE ) )
+ {
+ SetUnderline( pItem->GetLineStyle() );
+ SetUnderColor( pItem->GetColor() );
+ }
+ if( const SvxOverlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_OVERLINE ) )
+ {
+ SetOverline( pItem->GetLineStyle() );
+ SetOverColor( pItem->GetColor() );
+ }
+ if( const SvxCrossedOutItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CROSSEDOUT ) )
+ SetStrikeout( pItem->GetStrikeout() );
+ if( const SvxColorItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_COLOR ) )
+ SetColor( pItem->GetValue() );
+ if( const SvxEmphasisMarkItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_EMPHASIS_MARK ))
+ SetEmphasisMark( pItem->GetEmphasisMark() );
+
+ SetTransparent( true );
+ SetAlign( ALIGN_BASELINE );
+ if( const SvxContourItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CONTOUR ) )
+ SetOutline( pItem->GetValue() );
+ if( const SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ) )
+ SetShadow( pItem->GetValue() );
+ if( const SvxCharReliefItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_RELIEF ) )
+ SetRelief( pItem->GetValue() );
+ if( const SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ))
+ SetPropWidth( pItem->GetValue() ? 50 : 100 );
+ if( const SvxAutoKernItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_AUTOKERN ) )
+ {
+ if( pItem->GetValue() )
+ {
+ SetAutoKern( ( !pIDocumentSettingAccess ||
+ !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
+ FontKerning::FontSpecific :
+ FontKerning::Asian );
+ }
+ else
+ SetAutoKern( FontKerning::NONE );
+ }
+ if( const SvxWordLineModeItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WORDLINEMODE ) )
+ SetWordLineMode( pItem->GetValue() );
+
+ if( const SvxEscapementItem* pEsc = pAttrSet->GetItemIfSet( RES_CHRATR_ESCAPEMENT ) )
+ {
+ SetEscapement( pEsc->GetEsc() );
+ if( m_aSub[SwFontScript::Latin].IsEsc() )
+ SetProportion( pEsc->GetProportionalHeight() );
+ }
+ if( const SvxCaseMapItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CASEMAP ) )
+ SetCaseMap( pItem->GetCaseMap() );
+ if( const SvxKerningItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_KERNING ) )
+ SetFixKerning( pItem->GetValue() );
+ if( const SvxCharRotateItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_ROTATE ) )
+ SetVertical( pItem->GetValue() );
+ if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
+ mxBackColor = pItem->GetColor();
+ if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
+ SetHighlightColor(pItem->GetColor());
+ if( const SvxBoxItem* pBoxItem = pAttrSet->GetItemIfSet( RES_CHRATR_BOX ) )
+ {
+ SetTopBorder(pBoxItem->GetTop());
+ SetBottomBorder(pBoxItem->GetBottom());
+ SetRightBorder(pBoxItem->GetRight());
+ SetLeftBorder(pBoxItem->GetLeft());
+ SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
+ SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
+ SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
+ SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
+ }
+ if( const SvxShadowItem* pShadowItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOW ) )
+ {
+ SetShadowColor(pShadowItem->GetColor());
+ SetShadowWidth(pShadowItem->GetWidth());
+ SetShadowLocation(pShadowItem->GetLocation());
+ }
+ const SvxTwoLinesItem* pTwoLinesItem = pAttrSet->GetItemIfSet( RES_CHRATR_TWO_LINES );
+ if( pTwoLinesItem && pTwoLinesItem->GetValue() )
+ SetVertical( 0_deg10 );
+ }
+ else
+ {
+ Invalidate();
+ }
+ m_bPaintBlank = false;
+ OSL_ENSURE( m_aSub[SwFontScript::Latin].IsTransparent(), "SwFont: Transparent revolution" );
+}
+
+SwFont::SwFont( const SwFont &rFont )
+ : m_aSub(rFont.m_aSub)
+{
+ m_nActual = rFont.m_nActual;
+ mxBackColor = rFont.mxBackColor;
+ m_aHighlightColor = rFont.m_aHighlightColor;
+ m_aTopBorder = rFont.m_aTopBorder;
+ m_aBottomBorder = rFont.m_aBottomBorder;
+ m_aRightBorder = rFont.m_aRightBorder;
+ m_aLeftBorder = rFont.m_aLeftBorder;
+ m_nTopBorderDist = rFont.m_nTopBorderDist;
+ m_nBottomBorderDist = rFont.m_nBottomBorderDist;
+ m_nRightBorderDist = rFont.m_nRightBorderDist;
+ m_nLeftBorderDist = rFont.m_nLeftBorderDist;
+ m_aShadowColor = rFont.m_aShadowColor;
+ m_nShadowWidth = rFont.m_nShadowWidth;
+ m_aShadowLocation = rFont.m_aShadowLocation;
+ m_aUnderColor = rFont.GetUnderColor();
+ m_aOverColor = rFont.GetOverColor();
+ m_nToxCount = 0;
+ m_nRefCount = 0;
+ m_nMetaCount = 0;
+ m_nContentControlCount = 0;
+ m_nInputFieldCount = 0;
+ m_bFontChg = rFont.m_bFontChg;
+ m_bOrgChg = rFont.m_bOrgChg;
+ m_bPaintBlank = rFont.m_bPaintBlank;
+ m_bGreyWave = rFont.m_bGreyWave;
+}
+
+SwFont::SwFont( const SwAttrSet* pAttrSet,
+ const IDocumentSettingAccess* pIDocumentSettingAccess )
+ : m_aSub()
+{
+ m_nActual = SwFontScript::Latin;
+ m_nToxCount = 0;
+ m_nRefCount = 0;
+ m_nMetaCount = 0;
+ m_nContentControlCount = 0;
+ m_nInputFieldCount = 0;
+ m_bPaintBlank = false;
+ m_bGreyWave = false;
+ m_bOrgChg = true;
+ {
+ const SvxFontItem& rFont = pAttrSet->GetFont();
+ m_aSub[SwFontScript::Latin].SetFamily( rFont.GetFamily() );
+ m_aSub[SwFontScript::Latin].SetFamilyName( rFont.GetFamilyName() );
+ m_aSub[SwFontScript::Latin].SetStyleName( rFont.GetStyleName() );
+ m_aSub[SwFontScript::Latin].SetPitch( rFont.GetPitch() );
+ m_aSub[SwFontScript::Latin].SetCharSet( rFont.GetCharSet() );
+ m_aSub[SwFontScript::Latin].SvxFont::SetPropr( 100 ); // 100% of FontSize
+ Size aTmpSize = m_aSub[SwFontScript::Latin].m_aSize;
+ aTmpSize.setHeight( pAttrSet->GetSize().GetHeight() );
+ m_aSub[SwFontScript::Latin].SetSize( aTmpSize );
+ m_aSub[SwFontScript::Latin].SetItalic( pAttrSet->GetPosture().GetPosture() );
+ m_aSub[SwFontScript::Latin].SetWeight( pAttrSet->GetWeight().GetWeight() );
+ m_aSub[SwFontScript::Latin].SetLanguage( pAttrSet->GetLanguage().GetLanguage() );
+ }
+
+ {
+ const SvxFontItem& rFont = pAttrSet->GetCJKFont();
+ m_aSub[SwFontScript::CJK].SetFamily( rFont.GetFamily() );
+ m_aSub[SwFontScript::CJK].SetFamilyName( rFont.GetFamilyName() );
+ m_aSub[SwFontScript::CJK].SetStyleName( rFont.GetStyleName() );
+ m_aSub[SwFontScript::CJK].SetPitch( rFont.GetPitch() );
+ m_aSub[SwFontScript::CJK].SetCharSet( rFont.GetCharSet() );
+ m_aSub[SwFontScript::CJK].SvxFont::SetPropr( 100 ); // 100% of FontSize
+ Size aTmpSize = m_aSub[SwFontScript::CJK].m_aSize;
+ aTmpSize.setHeight( pAttrSet->GetCJKSize().GetHeight() );
+ m_aSub[SwFontScript::CJK].SetSize( aTmpSize );
+ m_aSub[SwFontScript::CJK].SetItalic( pAttrSet->GetCJKPosture().GetPosture() );
+ m_aSub[SwFontScript::CJK].SetWeight( pAttrSet->GetCJKWeight().GetWeight() );
+ LanguageType eNewLang = pAttrSet->GetCJKLanguage().GetLanguage();
+ m_aSub[SwFontScript::CJK].SetLanguage( eNewLang );
+ m_aSub[SwFontScript::Latin].SetCJKContextLanguage( eNewLang );
+ m_aSub[SwFontScript::CJK].SetCJKContextLanguage( eNewLang );
+ m_aSub[SwFontScript::CTL].SetCJKContextLanguage( eNewLang );
+ }
+
+ {
+ const SvxFontItem& rFont = pAttrSet->GetCTLFont();
+ m_aSub[SwFontScript::CTL].SetFamily( rFont.GetFamily() );
+ m_aSub[SwFontScript::CTL].SetFamilyName( rFont.GetFamilyName() );
+ m_aSub[SwFontScript::CTL].SetStyleName( rFont.GetStyleName() );
+ m_aSub[SwFontScript::CTL].SetPitch( rFont.GetPitch() );
+ m_aSub[SwFontScript::CTL].SetCharSet( rFont.GetCharSet() );
+ m_aSub[SwFontScript::CTL].SvxFont::SetPropr( 100 ); // 100% of FontSize
+ Size aTmpSize = m_aSub[SwFontScript::CTL].m_aSize;
+ aTmpSize.setHeight( pAttrSet->GetCTLSize().GetHeight() );
+ m_aSub[SwFontScript::CTL].SetSize( aTmpSize );
+ m_aSub[SwFontScript::CTL].SetItalic( pAttrSet->GetCTLPosture().GetPosture() );
+ m_aSub[SwFontScript::CTL].SetWeight( pAttrSet->GetCTLWeight().GetWeight() );
+ m_aSub[SwFontScript::CTL].SetLanguage( pAttrSet->GetCTLLanguage().GetLanguage() );
+ }
+ if ( pAttrSet->GetCharHidden().GetValue() )
+ SetUnderline( LINESTYLE_DOTTED );
+ else
+ SetUnderline( pAttrSet->GetUnderline().GetLineStyle() );
+ SetUnderColor( pAttrSet->GetUnderline().GetColor() );
+ SetOverline( pAttrSet->GetOverline().GetLineStyle() );
+ SetOverColor( pAttrSet->GetOverline().GetColor() );
+ SetEmphasisMark( pAttrSet->GetEmphasisMark().GetEmphasisMark() );
+ SetStrikeout( pAttrSet->GetCrossedOut().GetStrikeout() );
+ SetColor( pAttrSet->GetColor().GetValue() );
+ SetTransparent( true );
+ SetAlign( ALIGN_BASELINE );
+ SetOutline( pAttrSet->GetContour().GetValue() );
+ SetShadow( pAttrSet->GetShadowed().GetValue() );
+ SetPropWidth( pAttrSet->GetCharScaleW().GetValue() );
+ SetRelief( pAttrSet->GetCharRelief().GetValue() );
+ if( pAttrSet->GetAutoKern().GetValue() )
+ {
+ SetAutoKern( ( !pIDocumentSettingAccess ||
+ !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ?
+ FontKerning::FontSpecific :
+ FontKerning::Asian );
+ }
+ else
+ SetAutoKern( FontKerning::NONE );
+ SetWordLineMode( pAttrSet->GetWordLineMode().GetValue() );
+ const SvxEscapementItem &rEsc = pAttrSet->GetEscapement();
+ SetEscapement( rEsc.GetEsc() );
+ if( m_aSub[SwFontScript::Latin].IsEsc() )
+ SetProportion( rEsc.GetProportionalHeight() );
+ SetCaseMap( pAttrSet->GetCaseMap().GetCaseMap() );
+ SetFixKerning( pAttrSet->GetKerning().GetValue() );
+ if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
+ mxBackColor = pItem->GetColor();
+ if( const SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
+ SetHighlightColor(pItem->GetColor());
+ else
+ SetHighlightColor(COL_TRANSPARENT);
+ if( const SvxBoxItem* pBoxItem = pAttrSet->GetItemIfSet( RES_CHRATR_BOX ) )
+ {
+ SetTopBorder(pBoxItem->GetTop());
+ SetBottomBorder(pBoxItem->GetBottom());
+ SetRightBorder(pBoxItem->GetRight());
+ SetLeftBorder(pBoxItem->GetLeft());
+ SetTopBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::TOP));
+ SetBottomBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::BOTTOM));
+ SetRightBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::RIGHT));
+ SetLeftBorderDist(pBoxItem->GetDistance(SvxBoxItemLine::LEFT));
+ }
+ else
+ {
+ SetTopBorder(nullptr);
+ SetBottomBorder(nullptr);
+ SetRightBorder(nullptr);
+ SetLeftBorder(nullptr);
+ SetTopBorderDist(0);
+ SetBottomBorderDist(0);
+ SetRightBorderDist(0);
+ SetLeftBorderDist(0);
+ }
+
+ if( const SvxShadowItem* pShadowItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOW ) )
+ {
+ SetShadowColor(pShadowItem->GetColor());
+ SetShadowWidth(pShadowItem->GetWidth());
+ SetShadowLocation(pShadowItem->GetLocation());
+ }
+ else
+ {
+ SetShadowColor(COL_TRANSPARENT);
+ SetShadowWidth(0);
+ SetShadowLocation(SvxShadowLocation::NONE);
+ }
+
+ const SvxTwoLinesItem& rTwoLinesItem = pAttrSet->Get2Lines();
+ if ( ! rTwoLinesItem.GetValue() )
+ SetVertical( pAttrSet->GetCharRotate().GetValue() );
+ else
+ SetVertical( 0_deg10 );
+ if( pIDocumentSettingAccess && pIDocumentSettingAccess->get( DocumentSettingId::SMALL_CAPS_PERCENTAGE_66 ))
+ {
+ m_aSub[ SwFontScript::Latin ].m_bSmallCapsPercentage66 = true;
+ m_aSub[ SwFontScript::CJK ].m_bSmallCapsPercentage66 = true;
+ m_aSub[ SwFontScript::CTL ].m_bSmallCapsPercentage66 = true;
+ }
+}
+
+SwFont::~SwFont()
+{
+}
+
+SwFont& SwFont::operator=( const SwFont &rFont )
+{
+ if (this != &rFont)
+ {
+ m_aSub[SwFontScript::Latin] = rFont.m_aSub[SwFontScript::Latin];
+ m_aSub[SwFontScript::CJK] = rFont.m_aSub[SwFontScript::CJK];
+ m_aSub[SwFontScript::CTL] = rFont.m_aSub[SwFontScript::CTL];
+ m_nActual = rFont.m_nActual;
+ mxBackColor = rFont.mxBackColor;
+ m_aHighlightColor = rFont.m_aHighlightColor;
+ m_aTopBorder = rFont.m_aTopBorder;
+ m_aBottomBorder = rFont.m_aBottomBorder;
+ m_aRightBorder = rFont.m_aRightBorder;
+ m_aLeftBorder = rFont.m_aLeftBorder;
+ m_nTopBorderDist = rFont.m_nTopBorderDist;
+ m_nBottomBorderDist = rFont.m_nBottomBorderDist;
+ m_nRightBorderDist = rFont.m_nRightBorderDist;
+ m_nLeftBorderDist = rFont.m_nLeftBorderDist;
+ m_aShadowColor = rFont.m_aShadowColor;
+ m_nShadowWidth = rFont.m_nShadowWidth;
+ m_aShadowLocation = rFont.m_aShadowLocation;
+ m_aUnderColor = rFont.GetUnderColor();
+ m_aOverColor = rFont.GetOverColor();
+ m_nToxCount = 0;
+ m_nRefCount = 0;
+ m_nMetaCount = 0;
+ m_nContentControlCount = 0;
+ m_nInputFieldCount = 0;
+ m_bFontChg = rFont.m_bFontChg;
+ m_bOrgChg = rFont.m_bOrgChg;
+ m_bPaintBlank = rFont.m_bPaintBlank;
+ m_bGreyWave = rFont.m_bGreyWave;
+ }
+ return *this;
+}
+
+void SwFont::AllocFontCacheId( SwViewShell const *pSh, SwFontScript nWhich )
+{
+ SwFntAccess aFntAccess( m_aSub[nWhich].m_nFontCacheId, m_aSub[nWhich].m_nFontIndex,
+ &m_aSub[nWhich], pSh, true );
+}
+
+bool SwSubFont::IsSymbol( SwViewShell const *pSh )
+{
+ SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, false );
+ return aFntAccess.Get()->IsSymbol();
+}
+
+bool SwSubFont::ChgFnt( SwViewShell const *pSh, OutputDevice& rOut )
+{
+ if ( pLastFont )
+ pLastFont->Unlock();
+ SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh, true );
+ SV_STAT( nChangeFont );
+
+ pLastFont = aFntAccess.Get();
+
+ pLastFont->SetDevFont( pSh, rOut );
+
+ pLastFont->Lock();
+ return LINESTYLE_NONE != GetUnderline() ||
+ LINESTYLE_NONE != GetOverline() ||
+ STRIKEOUT_NONE != GetStrikeout();
+}
+
+void SwFont::ChgPhysFnt( SwViewShell const *pSh, OutputDevice& rOut )
+{
+ if( m_bOrgChg && m_aSub[m_nActual].IsEsc() )
+ {
+ const sal_uInt8 nOldProp = m_aSub[m_nActual].GetPropr();
+ SetProportion( 100 );
+ ChgFnt( pSh, rOut );
+ SwFntAccess aFntAccess( m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex,
+ &m_aSub[m_nActual], pSh );
+ m_aSub[m_nActual].m_nOrgHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
+ m_aSub[m_nActual].m_nOrgAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ SetProportion( nOldProp );
+ m_bOrgChg = false;
+ }
+
+ if( m_bFontChg )
+ {
+ ChgFnt( pSh, rOut );
+ m_bFontChg = m_bOrgChg;
+ }
+ if( rOut.GetTextLineColor() != m_aUnderColor )
+ rOut.SetTextLineColor( m_aUnderColor );
+ if( rOut.GetOverlineColor() != m_aOverColor )
+ rOut.SetOverlineColor( m_aOverColor );
+}
+
+// Height = MaxAscent + MaxDescent
+// MaxAscent = Max (T1_ascent, T2_ascent + (Esc * T1_height) );
+// MaxDescent = Max (T1_height-T1_ascent,
+// T2_height-T2_ascent - (Esc * T1_height)
+sal_uInt16 SwSubFont::CalcEscHeight( const sal_uInt16 nOldHeight,
+ const sal_uInt16 nOldAscent ) const
+{
+ if( DFLT_ESC_AUTO_SUPER != GetEscapement() &&
+ DFLT_ESC_AUTO_SUB != GetEscapement() )
+ {
+ tools::Long nDescent = nOldHeight - nOldAscent -
+ ( static_cast<tools::Long>(m_nOrgHeight) * GetEscapement() ) / 100;
+ const sal_uInt16 nDesc = nDescent>0
+ ? std::max<sal_uInt16>( nDescent, m_nOrgHeight - m_nOrgAscent)
+ : m_nOrgHeight - m_nOrgAscent;
+ return ( nDesc + CalcEscAscent( nOldAscent ) );
+ }
+ return m_nOrgHeight;
+}
+
+short SwSubFont::CheckKerning_( )
+{
+ short nKernx = - short( Font::GetFontSize().Height() / 6 );
+
+ if ( nKernx < GetFixKerning() )
+ return GetFixKerning();
+ return nKernx;
+}
+
+sal_uInt16 SwSubFont::GetAscent( SwViewShell const *pSh, const OutputDevice& rOut )
+{
+ SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
+ const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ return GetEscapement() ? CalcEscAscent( nAscent ) : nAscent;
+}
+
+sal_uInt16 SwSubFont::GetHeight( SwViewShell const *pSh, const OutputDevice& rOut )
+{
+ SV_STAT( nGetTextSize );
+ SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
+ const sal_uInt16 nHeight = aFntAccess.Get()->GetFontHeight( pSh, rOut );
+ if ( GetEscapement() )
+ {
+ const sal_uInt16 nAscent = aFntAccess.Get()->GetFontAscent( pSh, rOut );
+ return CalcEscHeight( nHeight, nAscent ); // + nLeading;
+ }
+ return nHeight; // + nLeading;
+}
+
+sal_uInt16 SwSubFont::GetHangingBaseline( SwViewShell const *pSh, const OutputDevice& rOut )
+{
+ SwFntAccess aFntAccess( m_nFontCacheId, m_nFontIndex, this, pSh );
+ return aFntAccess.Get()->GetFontHangingBaseline( pSh, rOut );
+}
+
+Size SwSubFont::GetTextSize_( SwDrawTextInfo& rInf )
+{
+ // Robust: the font is supposed to be set already, but better safe than
+ // sorry...
+ if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId ||
+ !IsSameInstance( rInf.GetpOut()->GetFont() ) )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ Size aTextSize;
+ TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
+ ? TextFrameIndex(rInf.GetText().getLength())
+ : rInf.GetLen();
+ rInf.SetLen( nLn );
+ if( IsCapital() && nLn )
+ aTextSize = GetCapitalSize( rInf );
+ else
+ {
+ SV_STAT( nGetTextSize );
+ tools::Long nOldKern = rInf.GetKern();
+ const OUString oldText = rInf.GetText();
+ rInf.SetKern( CheckKerning() );
+ if ( !IsCaseMap() )
+ aTextSize = pLastFont->GetTextSize( rInf );
+ else
+ {
+ const OUString aTmp = CalcCaseMap( rInf.GetText() );
+ const OUString oldStr = rInf.GetText();
+ bool bCaseMapLengthDiffers(aTmp.getLength() != oldStr.getLength());
+
+ if(bCaseMapLengthDiffers && rInf.GetLen())
+ {
+ // If the length of the original string and the CaseMapped one
+ // are different, it is necessary to handle the given text part as
+ // a single snippet since its size may differ, too.
+ TextFrameIndex const nOldIdx(rInf.GetIdx());
+ TextFrameIndex const nOldLen(rInf.GetLen());
+ const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
+ const OUString aNewText(CalcCaseMap(aSnippet));
+
+ rInf.SetText( aNewText );
+ rInf.SetIdx( TextFrameIndex(0) );
+ rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
+
+ aTextSize = pLastFont->GetTextSize( rInf );
+
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else
+ {
+ rInf.SetText( aTmp );
+ aTextSize = pLastFont->GetTextSize( rInf );
+ }
+
+ rInf.SetText(oldStr);
+ }
+ rInf.SetKern( nOldKern );
+ rInf.SetText(oldText);
+ // A word that's longer than one line, with escapement at the line
+ // break, must report its effective height.
+ if( GetEscapement() )
+ {
+ const sal_uInt16 nAscent = pLastFont->GetFontAscent( rInf.GetShell(),
+ rInf.GetOut() );
+ aTextSize.setHeight(
+ static_cast<tools::Long>(CalcEscHeight( o3tl::narrowing<sal_uInt16>(aTextSize.Height()), nAscent)) );
+ }
+ }
+
+ if (TextFrameIndex(1) == rInf.GetLen()
+ && CH_TXT_ATR_FIELDSTART == rInf.GetText()[sal_Int32(rInf.GetIdx())])
+ {
+ assert(!"this is presumably dead code");
+ TextFrameIndex const nOldIdx(rInf.GetIdx());
+ TextFrameIndex const nOldLen(rInf.GetLen());
+ const OUString aNewText(CH_TXT_ATR_SUBST_FIELDSTART);
+ rInf.SetText( aNewText );
+ rInf.SetIdx( TextFrameIndex(0) );
+ rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
+ aTextSize = pLastFont->GetTextSize( rInf );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else if (TextFrameIndex(1) == rInf.GetLen()
+ && CH_TXT_ATR_FIELDEND == rInf.GetText()[sal_Int32(rInf.GetIdx())])
+ {
+ assert(!"this is presumably dead code");
+ TextFrameIndex const nOldIdx(rInf.GetIdx());
+ TextFrameIndex const nOldLen(rInf.GetLen());
+ const OUString aNewText(CH_TXT_ATR_SUBST_FIELDEND);
+ rInf.SetText( aNewText );
+ rInf.SetIdx( TextFrameIndex(0) );
+ rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
+ aTextSize = pLastFont->GetTextSize( rInf );
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+
+ return aTextSize;
+}
+
+void SwSubFont::DrawText_( SwDrawTextInfo &rInf, const bool bGrey )
+{
+ rInf.SetGreyWave( bGrey );
+ TextFrameIndex const nLn(rInf.GetText().getLength());
+ if( !rInf.GetLen() || !nLn )
+ return;
+ if (TextFrameIndex(COMPLETE_STRING) == rInf.GetLen())
+ rInf.SetLen( nLn );
+
+ FontLineStyle nOldUnder = LINESTYLE_NONE;
+ SwUnderlineFont* pUnderFnt = nullptr;
+
+ if( rInf.GetUnderFnt() )
+ {
+ nOldUnder = GetUnderline();
+ SetUnderline( LINESTYLE_NONE );
+ pUnderFnt = rInf.GetUnderFnt();
+ }
+
+ if( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ const Point aOldPos(rInf.GetPos());
+ Point aPos( rInf.GetPos() );
+
+ if( GetEscapement() )
+ CalcEsc( rInf, aPos );
+
+ rInf.SetPos( aPos );
+ rInf.SetKern( CheckKerning() + rInf.GetCharacterSpacing() / SPACING_PRECISION_FACTOR );
+
+ if( IsCapital() )
+ DrawCapital( rInf );
+ else
+ {
+ SV_STAT( nDrawText );
+ if ( !IsCaseMap() )
+ pLastFont->DrawText( rInf );
+ else
+ {
+ const OUString oldStr = rInf.GetText();
+ const OUString aString( CalcCaseMap(oldStr) );
+ bool bCaseMapLengthDiffers(aString.getLength() != oldStr.getLength());
+
+ if(bCaseMapLengthDiffers && rInf.GetLen())
+ {
+ // If the length of the original string and the CaseMapped one
+ // are different, it is necessary to handle the given text part as
+ // a single snippet since its size may differ, too.
+ TextFrameIndex const nOldIdx(rInf.GetIdx());
+ TextFrameIndex const nOldLen(rInf.GetLen());
+ const OUString aSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldLen)));
+ const OUString aNewText = CalcCaseMap(aSnippet);
+
+ rInf.SetText( aNewText );
+ rInf.SetIdx( TextFrameIndex(0) );
+ rInf.SetLen( TextFrameIndex(aNewText.getLength()) );
+
+ pLastFont->DrawText( rInf );
+
+ rInf.SetIdx( nOldIdx );
+ rInf.SetLen( nOldLen );
+ }
+ else
+ {
+ rInf.SetText( aString );
+ pLastFont->DrawText( rInf );
+ }
+
+ rInf.SetText(oldStr);
+ }
+ }
+
+ if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
+ {
+ Size aFontSize = GetTextSize_( rInf );
+ const OUString oldStr = rInf.GetText();
+
+ TextFrameIndex const nOldIdx = rInf.GetIdx();
+ TextFrameIndex const nOldLen = rInf.GetLen();
+ tools::Long nSpace = 0;
+ if( rInf.GetSpace() )
+ {
+ TextFrameIndex nTmpEnd = nOldIdx + nOldLen;
+ if (nTmpEnd > TextFrameIndex(oldStr.getLength()))
+ nTmpEnd = TextFrameIndex(oldStr.getLength());
+
+ const SwScriptInfo* pSI = rInf.GetScriptInfo();
+
+ const bool bAsianFont =
+ ( rInf.GetFont() && SwFontScript::CJK == rInf.GetFont()->GetActual() );
+ for (TextFrameIndex nTmp = nOldIdx; nTmp < nTmpEnd; ++nTmp)
+ {
+ if (CH_BLANK == oldStr[sal_Int32(nTmp)] || bAsianFont ||
+ (nTmp + TextFrameIndex(1) < TextFrameIndex(oldStr.getLength())
+ && pSI
+ && i18n::ScriptType::ASIAN == pSI->ScriptType(nTmp + TextFrameIndex(1))))
+ {
+ ++nSpace;
+ }
+ }
+
+ // if next portion if a hole portion we do not consider any
+ // extra space added because the last character was ASIAN
+ if ( nSpace && rInf.IsSpaceStop() && bAsianFont )
+ --nSpace;
+
+ nSpace *= rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ }
+
+ rInf.SetWidth( sal_uInt16(aFontSize.Width() + nSpace) );
+ rInf.SetTextIdxLen( " ", TextFrameIndex(0), TextFrameIndex(2) );
+ SetUnderline( nOldUnder );
+ rInf.SetUnderFnt( nullptr );
+
+ // set position for underline font
+ rInf.SetPos( pUnderFnt->GetPos() );
+
+ pUnderFnt->GetFont().DrawStretchText_( rInf );
+
+ rInf.SetUnderFnt( pUnderFnt );
+ rInf.SetTextIdxLen(oldStr, nOldIdx, nOldLen);
+ }
+
+ rInf.SetPos(aOldPos);
+}
+
+void SwSubFont::DrawStretchText_( SwDrawTextInfo &rInf )
+{
+ if( !rInf.GetLen() || !rInf.GetText().getLength() )
+ return;
+
+ FontLineStyle nOldUnder = LINESTYLE_NONE;
+ SwUnderlineFont* pUnderFnt = nullptr;
+
+ if( rInf.GetUnderFnt() )
+ {
+ nOldUnder = GetUnderline();
+ SetUnderline( LINESTYLE_NONE );
+ pUnderFnt = rInf.GetUnderFnt();
+ }
+
+ if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ rInf.ApplyAutoColor();
+
+ const Point aOldPos(rInf.GetPos());
+ Point aPos( rInf.GetPos() );
+
+ if( GetEscapement() )
+ CalcEsc( rInf, aPos );
+
+ rInf.SetKern( CheckKerning() + rInf.GetCharacterSpacing() / SPACING_PRECISION_FACTOR );
+ rInf.SetPos( aPos );
+
+ if( IsCapital() )
+ DrawStretchCapital( rInf );
+ else
+ {
+ SV_STAT( nDrawStretchText );
+
+ if ( rInf.GetFrame() )
+ {
+ if ( rInf.GetFrame()->IsRightToLeft() )
+ rInf.GetFrame()->SwitchLTRtoRTL( aPos );
+
+ if ( rInf.GetFrame()->IsVertical() )
+ rInf.GetFrame()->SwitchHorizontalToVertical( aPos );
+
+ rInf.SetPos( aPos );
+ }
+
+ if ( !IsCaseMap() )
+ rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
+ rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+ else
+ rInf.GetOut().DrawStretchText( aPos, rInf.GetWidth(),
+ CalcCaseMap(rInf.GetText()),
+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+ }
+
+ if( pUnderFnt && nOldUnder != LINESTYLE_NONE )
+ {
+ const OUString oldStr = rInf.GetText();
+ TextFrameIndex const nOldIdx = rInf.GetIdx();
+ TextFrameIndex const nOldLen = rInf.GetLen();
+ rInf.SetTextIdxLen( " ", TextFrameIndex(0), TextFrameIndex(2) );
+ SetUnderline( nOldUnder );
+ rInf.SetUnderFnt( nullptr );
+
+ // set position for underline font
+ rInf.SetPos( pUnderFnt->GetPos() );
+
+ pUnderFnt->GetFont().DrawStretchText_( rInf );
+
+ rInf.SetUnderFnt( pUnderFnt );
+ rInf.SetTextIdxLen(oldStr, nOldIdx, nOldLen);
+ }
+
+ rInf.SetPos(aOldPos);
+}
+
+TextFrameIndex SwSubFont::GetModelPositionForViewPoint_( SwDrawTextInfo& rInf )
+{
+ if ( !pLastFont || pLastFont->GetOwner() != m_nFontCacheId )
+ ChgFnt( rInf.GetShell(), rInf.GetOut() );
+
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
+ TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
+ ? TextFrameIndex(rInf.GetText().getLength())
+ : rInf.GetLen();
+ rInf.SetLen( nLn );
+ TextFrameIndex nCursor(0);
+ if( IsCapital() && nLn )
+ nCursor = GetCapitalCursorOfst( rInf );
+ else
+ {
+ const OUString oldText = rInf.GetText();
+ tools::Long nOldKern = rInf.GetKern();
+ rInf.SetKern( CheckKerning() );
+ SV_STAT( nGetTextSize );
+ if ( !IsCaseMap() )
+ nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
+ else
+ {
+ rInf.SetText( CalcCaseMap( rInf.GetText() ) );
+ nCursor = pLastFont->GetModelPositionForViewPoint( rInf );
+ }
+ rInf.SetKern( nOldKern );
+ rInf.SetText(oldText);
+ }
+ return nCursor;
+}
+
+void SwSubFont::CalcEsc( SwDrawTextInfo const & rInf, Point& rPos )
+{
+ tools::Long nOfst;
+
+ bool bVert = false;
+ bool bVertLRBT = false;
+ if (rInf.GetFrame())
+ {
+ bVert = rInf.GetFrame()->IsVertical();
+ bVertLRBT = rInf.GetFrame()->IsVertLRBT();
+ }
+ const Degree10 nDir = UnMapDirection(GetOrientation(), bVert, bVertLRBT);
+
+ switch ( GetEscapement() )
+ {
+ case DFLT_ESC_AUTO_SUB :
+ nOfst = m_nOrgHeight - m_nOrgAscent -
+ pLastFont->GetFontHeight( rInf.GetShell(), rInf.GetOut() ) +
+ pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() );
+
+ switch ( nDir.get() )
+ {
+ case 0 :
+ rPos.AdjustY(nOfst );
+ break;
+ case 900 :
+ rPos.AdjustX(nOfst );
+ break;
+ case 2700 :
+ rPos.AdjustX( -nOfst );
+ break;
+ }
+
+ break;
+ case DFLT_ESC_AUTO_SUPER :
+ nOfst = pLastFont->GetFontAscent( rInf.GetShell(), rInf.GetOut() ) -
+ m_nOrgAscent;
+
+ switch ( nDir.get() )
+ {
+ case 0 :
+ rPos.AdjustY(nOfst );
+ break;
+ case 900 :
+ rPos.AdjustX(nOfst );
+ break;
+ case 2700 :
+ rPos.AdjustX( -nOfst );
+ break;
+ }
+
+ break;
+ default :
+ nOfst = (static_cast<tools::Long>(m_nOrgHeight) * GetEscapement()) / 100;
+
+ switch ( nDir.get() )
+ {
+ case 0 :
+ rPos.AdjustY( -nOfst );
+ break;
+ case 900 :
+ rPos.AdjustX( -nOfst );
+ break;
+ case 2700 :
+ rPos.AdjustX(nOfst );
+ break;
+ }
+ }
+}
+
+// used during painting of small capitals
+void SwDrawTextInfo::Shift( Degree10 nDir )
+{
+#ifdef DBG_UTIL
+ OSL_ENSURE( m_bPos, "DrawTextInfo: Undefined Position" );
+ OSL_ENSURE( m_bSize, "DrawTextInfo: Undefined Width" );
+#endif
+
+ const bool bBidiPor = ( GetFrame() && GetFrame()->IsRightToLeft() ) !=
+ ( vcl::text::ComplexTextLayoutFlags::Default != ( vcl::text::ComplexTextLayoutFlags::BiDiRtl & GetpOut()->GetLayoutMode() ) );
+
+ bool bVert = false;
+ bool bVertLRBT = false;
+ if (GetFrame())
+ {
+ bVert = GetFrame()->IsVertical();
+ bVertLRBT = GetFrame()->IsVertLRBT();
+ }
+ nDir = bBidiPor ? 1800_deg10 : UnMapDirection(nDir, bVert, bVertLRBT);
+
+ switch ( nDir.get() )
+ {
+ case 0 :
+ m_aPos.AdjustX(GetSize().Width() );
+ break;
+ case 900 :
+ OSL_ENSURE( m_aPos.Y() >= GetSize().Width(), "Going underground" );
+ m_aPos.AdjustY( -(GetSize().Width()) );
+ break;
+ case 1800 :
+ m_aPos.AdjustX( -(GetSize().Width()) );
+ break;
+ case 2700 :
+ m_aPos.AdjustY(GetSize().Width() );
+ break;
+ }
+}
+
+/**
+ * @note Used for the "continuous underline" feature.
+ **/
+SwUnderlineFont::SwUnderlineFont(SwFont& rFnt, TextFrameIndex const nEnd, const Point& rPoint)
+ : m_aPos( rPoint ), m_nEnd( nEnd ), m_pFont( &rFnt )
+{
+};
+
+SwUnderlineFont::~SwUnderlineFont()
+{
+}
+
+/// Helper for filters to find true lineheight of a font
+tools::Long AttrSetToLineHeight( const IDocumentSettingAccess& rIDocumentSettingAccess,
+ const SwAttrSet &rSet,
+ const vcl::RenderContext &rOut, sal_Int16 nScript)
+{
+ SwFont aFont(&rSet, &rIDocumentSettingAccess);
+ SwFontScript nActual;
+ switch (nScript)
+ {
+ default:
+ case i18n::ScriptType::LATIN:
+ nActual = SwFontScript::Latin;
+ break;
+ case i18n::ScriptType::ASIAN:
+ nActual = SwFontScript::CJK;
+ break;
+ case i18n::ScriptType::COMPLEX:
+ nActual = SwFontScript::CTL;
+ break;
+ }
+ aFont.SetActual(nActual);
+
+ vcl::RenderContext &rMutableOut = const_cast<vcl::RenderContext &>(rOut);
+ const vcl::Font aOldFont(rMutableOut.GetFont());
+
+ rMutableOut.SetFont(aFont.GetActualFont());
+ tools::Long nHeight = rMutableOut.GetTextHeight();
+
+ rMutableOut.SetFont(aOldFont);
+ return nHeight;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */