/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 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& 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& 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& 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& 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(m_nOrgHeight) * GetEscapement() ) / 100; if ( nAscent>0 ) return std::max( nAscent, m_nOrgAscent ); } return m_nOrgAscent; } void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet, const IDocumentSettingAccess *pIDocumentSettingAccess ) { mxBackColor.reset(); if( pAttrSet ) { const SfxPoolItem* pItem; if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_FONT, true, &pItem )) { const SvxFontItem *pFont = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_FONTSIZE, true, &pItem )) { const SvxFontHeightItem *pHeight = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_POSTURE, true, &pItem )) m_aSub[SwFontScript::Latin].Font::SetItalic( static_cast(pItem)->GetPosture() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_WEIGHT, true, &pItem )) m_aSub[SwFontScript::Latin].Font::SetWeight( static_cast(pItem)->GetWeight() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_LANGUAGE, true, &pItem )) m_aSub[SwFontScript::Latin].SetLanguage( static_cast(pItem)->GetLanguage() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONT, true, &pItem )) { const SvxFontItem *pFont = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONTSIZE, true, &pItem )) { const SvxFontHeightItem *pHeight = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_POSTURE, true, &pItem )) m_aSub[SwFontScript::CJK].Font::SetItalic( static_cast(pItem)->GetPosture() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_WEIGHT, true, &pItem )) m_aSub[SwFontScript::CJK].Font::SetWeight( static_cast(pItem)->GetWeight() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_LANGUAGE, true, &pItem )) { LanguageType eNewLang = static_cast(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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONT, true, &pItem )) { const SvxFontItem *pFont = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_FONTSIZE, true, &pItem )) { const SvxFontHeightItem *pHeight = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_POSTURE, true, &pItem )) m_aSub[SwFontScript::CTL].Font::SetItalic( static_cast(pItem)->GetPosture() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_WEIGHT, true, &pItem )) m_aSub[SwFontScript::CTL].Font::SetWeight( static_cast(pItem)->GetWeight() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_LANGUAGE, true, &pItem )) m_aSub[SwFontScript::CTL].SetLanguage( static_cast(pItem)->GetLanguage() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_UNDERLINE, true, &pItem )) { SetUnderline( static_cast(pItem)->GetLineStyle() ); SetUnderColor( static_cast(pItem)->GetColor() ); } if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_OVERLINE, true, &pItem )) { SetOverline( static_cast(pItem)->GetLineStyle() ); SetOverColor( static_cast(pItem)->GetColor() ); } if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CROSSEDOUT, true, &pItem )) SetStrikeout( static_cast(pItem)->GetStrikeout() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_COLOR, true, &pItem )) SetColor( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_EMPHASIS_MARK, true, &pItem )) SetEmphasisMark( static_cast(pItem)->GetEmphasisMark() ); SetTransparent( true ); SetAlign( ALIGN_BASELINE ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CONTOUR, true, &pItem )) SetOutline( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED, true, &pItem )) SetShadow( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_RELIEF, true, &pItem )) SetRelief( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED, true, &pItem )) SetPropWidth(static_cast(pItem)->GetValue() ? 50 : 100 ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_AUTOKERN, true, &pItem )) { if( static_cast(pItem)->GetValue() ) { SetAutoKern( ( !pIDocumentSettingAccess || !pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION) ) ? FontKerning::FontSpecific : FontKerning::Asian ); } else SetAutoKern( FontKerning::NONE ); } if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_WORDLINEMODE, true, &pItem )) SetWordLineMode( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ESCAPEMENT, true, &pItem )) { const SvxEscapementItem *pEsc = static_cast(pItem); SetEscapement( pEsc->GetEsc() ); if( m_aSub[SwFontScript::Latin].IsEsc() ) SetProportion( pEsc->GetProportionalHeight() ); } if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CASEMAP, true, &pItem )) SetCaseMap( static_cast(pItem)->GetCaseMap() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_KERNING, true, &pItem )) SetFixKerning( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ROTATE, true, &pItem )) SetVertical( static_cast(pItem)->GetValue() ); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND, true, &pItem )) mxBackColor = static_cast(pItem)->GetColor(); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT, true, &pItem )) SetHighlightColor(static_cast(pItem)->GetColor()); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX, true, &pItem )) { const SvxBoxItem* pBoxItem = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOW, true, &pItem )) { const SvxShadowItem* pShadowItem = static_cast(pItem); SetShadowColor(pShadowItem->GetColor()); SetShadowWidth(pShadowItem->GetWidth()); SetShadowLocation(pShadowItem->GetLocation()); } const SfxPoolItem* pTwoLinesItem = nullptr; if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_TWO_LINES, true, &pTwoLinesItem )) if ( static_cast(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_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_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() ); const SfxPoolItem* pItem; if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND, true, &pItem )) mxBackColor = static_cast(pItem)->GetColor(); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT, true, &pItem )) SetHighlightColor(static_cast(pItem)->GetColor()); else SetHighlightColor(COL_TRANSPARENT); if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX, true, &pItem )) { const SvxBoxItem* pBoxItem = static_cast(pItem); 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( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOW, true, &pItem )) { const SvxShadowItem* pShadowItem = static_cast(pItem); 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_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(m_nOrgHeight) * GetEscapement() ) / 100; const sal_uInt16 nDesc = nDescent>0 ? std::max( 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; } Size SwSubFont::GetTextSize_( SwDrawTextInfo& rInf ) { // Robust: the font is supposed to be set already, but better safe than // sorry... if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast(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(CalcEscHeight( o3tl::narrowing(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() != reinterpret_cast(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.GetSperren() / 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.SetText( " " ); rInf.SetIdx( TextFrameIndex(0) ); rInf.SetLen( TextFrameIndex(2) ); SetUnderline( nOldUnder ); rInf.SetUnderFnt( nullptr ); // set position for underline font rInf.SetPos( pUnderFnt->GetPos() ); pUnderFnt->GetFont().DrawStretchText_( rInf ); rInf.SetUnderFnt( pUnderFnt ); rInf.SetText(oldStr); rInf.SetIdx( nOldIdx ); rInf.SetLen( 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() != reinterpret_cast(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.GetSperren() / 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.SetText( " " ); rInf.SetIdx( TextFrameIndex(0) ); rInf.SetLen( TextFrameIndex(2) ); SetUnderline( nOldUnder ); rInf.SetUnderFnt( nullptr ); // set position for underline font rInf.SetPos( pUnderFnt->GetPos() ); pUnderFnt->GetFont().DrawStretchText_( rInf ); rInf.SetUnderFnt( pUnderFnt ); rInf.SetText(oldStr); rInf.SetIdx( nOldIdx ); rInf.SetLen( nOldLen ); } rInf.SetPos(aOldPos); } TextFrameIndex SwSubFont::GetModelPositionForViewPoint_( SwDrawTextInfo& rInf ) { if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast(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(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() ) != ( ComplexTextLayoutFlags::Default != ( 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(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: */