/* -*- 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 <unotools/localedatawrapper.hxx>
#include <editeng/unolingu.hxx>
#include <editeng/brushitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/blinkitem.hxx>
#include <editeng/nhypitem.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 <vcl/window.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( Color* pNewColor )
{
m_pBackColor.reset( pNewColor );
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 = boost::none;
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 = boost::none;
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 = boost::none;
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 = boost::none;
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 boost::optional<editeng::SvxBorderLine>&
SwFont::GetAbsTopBorder( const bool bVertLayout ) const
{
switch( GetOrientation( bVertLayout ) )
{
case 0 :
return m_aTopBorder;
break;
case 900 :
return m_aRightBorder;
break;
case 1800 :
return m_aBottomBorder;
break;
case 2700 :
return m_aLeftBorder;
break;
default :
assert(false);
return m_aTopBorder;
break;
}
}
const boost::optional<editeng::SvxBorderLine>&
SwFont::GetAbsBottomBorder( const bool bVertLayout ) const
{
switch( GetOrientation( bVertLayout ) )
{
case 0 :
return m_aBottomBorder;
break;
case 900 :
return m_aLeftBorder;
break;
case 1800 :
return m_aTopBorder;
break;
case 2700 :
return m_aRightBorder;
break;
default :
assert(false);
return m_aBottomBorder;
break;
}
}
const boost::optional<editeng::SvxBorderLine>&
SwFont::GetAbsLeftBorder( const bool bVertLayout ) const
{
switch( GetOrientation( bVertLayout ) )
{
case 0 :
return m_aLeftBorder;
break;
case 900 :
return m_aTopBorder;
break;
case 1800 :
return m_aRightBorder;
break;
case 2700 :
return m_aBottomBorder;
break;
default :
assert(false);
return m_aLeftBorder;
break;
}
}
const boost::optional<editeng::SvxBorderLine>&
SwFont::GetAbsRightBorder( const bool bVertLayout ) const
{
switch( GetOrientation( bVertLayout ) )
{
case 0 :
return m_aRightBorder;
break;
case 900 :
return m_aBottomBorder;
break;
case 1800 :
return m_aLeftBorder;
break;
case 2700 :
return m_aTopBorder;
break;
default :
assert(false);
return m_aRightBorder;
break;
}
}
SvxShadowLocation SwFont::GetAbsShadowLocation( const bool bVertLayout ) const
{
SvxShadowLocation aLocation = SvxShadowLocation::NONE;
switch( GetOrientation( bVertLayout ) )
{
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 bSkipLeft, const bool bSkipRight ) const
{
sal_uInt16 nSpace = 0;
const sal_uInt16 nOrient = GetOrientation( bVertLayout );
const SvxShadowLocation aLoc = GetAbsShadowLocation( bVertLayout );
switch( nShadow )
{
case SvxShadowItemSide::TOP:
if(( aLoc == SvxShadowLocation::TopLeft ||
aLoc == SvxShadowLocation::TopRight ) &&
( nOrient == 0 || nOrient == 1800 ||
( nOrient == 900 && !bSkipRight ) ||
( nOrient == 2700 && !bSkipLeft )))
{
nSpace = m_nShadowWidth;
}
break;
case SvxShadowItemSide::BOTTOM:
if(( aLoc == SvxShadowLocation::BottomLeft ||
aLoc == SvxShadowLocation::BottomRight ) &&
( nOrient == 0 || nOrient == 1800 ||
( nOrient == 900 && !bSkipLeft ) ||
( nOrient == 2700 && !bSkipRight )))
{
nSpace = m_nShadowWidth;
}
break;
case SvxShadowItemSide::LEFT:
if(( aLoc == SvxShadowLocation::TopLeft ||
aLoc == SvxShadowLocation::BottomLeft ) &&
( nOrient == 900 || nOrient == 2700 ||
( nOrient == 0 && !bSkipLeft ) ||
( nOrient == 1800 && !bSkipRight )))
{
nSpace = m_nShadowWidth;
}
break;
case SvxShadowItemSide::RIGHT:
if(( aLoc == SvxShadowLocation::TopRight ||
aLoc == SvxShadowLocation::BottomRight ) &&
( nOrient == 900 || nOrient == 2700 ||
( nOrient == 0 && !bSkipRight ) ||
( nOrient == 1800 && !bSkipLeft )))
{
nSpace = m_nShadowWidth;
}
break;
default:
assert(false);
break;
}
return nSpace;
}
// maps directions for vertical layout
sal_uInt16 MapDirection( sal_uInt16 nDir, const bool bVertFormat )
{
if ( bVertFormat )
{
switch ( nDir )
{
case 0 :
nDir = 2700;
break;
case 900 :
nDir = 0;
break;
case 2700 :
nDir = 1800;
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
sal_uInt16 UnMapDirection( sal_uInt16 nDir, const bool bVertFormat )
{
if ( bVertFormat )
{
switch ( nDir )
{
case 0 :
nDir = 900;
break;
case 1800 :
nDir = 2700;
break;
case 2700 :
nDir = 0;
break;
#if OSL_DEBUG_LEVEL > 0
default :
OSL_FAIL( "Unsupported direction" );
break;
#endif
}
}
return nDir;
}
sal_uInt16 SwFont::GetOrientation( const bool bVertFormat ) const
{
return UnMapDirection( m_aSub[m_nActual].GetOrientation(), bVertFormat );
}
void SwFont::SetVertical( sal_uInt16 nDir, const bool bVertFormat )
{
// map direction if frame has vertical layout
nDir = MapDirection( nDir, bVertFormat );
if( nDir != m_aSub[SwFontScript::Latin].GetOrientation() )
{
m_bFontChg = true;
m_aSub[SwFontScript::Latin].SetVertical( nDir, bVertFormat );
m_aSub[SwFontScript::CJK].SetVertical( nDir, bVertFormat );
m_aSub[SwFontScript::CTL].SetVertical( nDir, bVertFormat );
}
}
/*
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 long nAscent = nOldAscent +
( static_cast<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 )
{
m_pBackColor.reset();
if( pAttrSet )
{
const SfxPoolItem* pItem;
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_FONT,
true, &pItem ))
{
const SvxFontItem *pFont = static_cast<const SvxFontItem *>(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<const SvxFontHeightItem *>(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<const SvxPostureItem*>(pItem)->GetPosture() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_WEIGHT,
true, &pItem ))
m_aSub[SwFontScript::Latin].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_LANGUAGE,
true, &pItem ))
m_aSub[SwFontScript::Latin].SetLanguage( static_cast<const SvxLanguageItem*>(pItem)->GetLanguage() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_FONT,
true, &pItem ))
{
const SvxFontItem *pFont = static_cast<const SvxFontItem *>(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<const SvxFontHeightItem *>(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<const SvxPostureItem*>(pItem)->GetPosture() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_WEIGHT,
true, &pItem ))
m_aSub[SwFontScript::CJK].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CJK_LANGUAGE,
true, &pItem ))
{
LanguageType eNewLang = static_cast<const SvxLanguageItem*>(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<const SvxFontItem *>(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<const SvxFontHeightItem *>(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<const SvxPostureItem*>(pItem)->GetPosture() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_WEIGHT,
true, &pItem ))
m_aSub[SwFontScript::CTL].Font::SetWeight( static_cast<const SvxWeightItem*>(pItem)->GetWeight() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CTL_LANGUAGE,
true, &pItem ))
m_aSub[SwFontScript::CTL].SetLanguage( static_cast<const SvxLanguageItem*>(pItem)->GetLanguage() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_UNDERLINE,
true, &pItem ))
{
SetUnderline( static_cast<const SvxUnderlineItem*>(pItem)->GetLineStyle() );
SetUnderColor( static_cast<const SvxUnderlineItem*>(pItem)->GetColor() );
}
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_OVERLINE,
true, &pItem ))
{
SetOverline( static_cast<const SvxOverlineItem*>(pItem)->GetLineStyle() );
SetOverColor( static_cast<const SvxOverlineItem*>(pItem)->GetColor() );
}
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CROSSEDOUT,
true, &pItem ))
SetStrikeout( static_cast<const SvxCrossedOutItem*>(pItem)->GetStrikeout() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_COLOR,
true, &pItem ))
SetColor( static_cast<const SvxColorItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_EMPHASIS_MARK,
true, &pItem ))
SetEmphasisMark( static_cast<const SvxEmphasisMarkItem*>(pItem)->GetEmphasisMark() );
SetTransparent( true );
SetAlign( ALIGN_BASELINE );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_CONTOUR,
true, &pItem ))
SetOutline( static_cast<const SvxContourItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
true, &pItem ))
SetShadow( static_cast<const SvxShadowedItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_RELIEF,
true, &pItem ))
SetRelief( static_cast<const SvxCharReliefItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_SHADOWED,
true, &pItem ))
SetPropWidth(static_cast<const SvxShadowedItem*>(pItem)->GetValue() ? 50 : 100 );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_AUTOKERN,
true, &pItem ))
{
if( static_cast<const SvxAutoKernItem*>(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<const SvxWordLineModeItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ESCAPEMENT,
true, &pItem ))
{
const SvxEscapementItem *pEsc = static_cast<const SvxEscapementItem *>(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<const SvxCaseMapItem*>(pItem)->GetCaseMap() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_KERNING,
true, &pItem ))
SetFixKerning( static_cast<const SvxKerningItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BLINK,
true, &pItem ))
SetBlink( static_cast<const SvxBlinkItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_ROTATE,
true, &pItem ))
SetVertical( static_cast<const SvxCharRotateItem*>(pItem)->GetValue() );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BACKGROUND,
true, &pItem ))
m_pBackColor.reset( new Color( static_cast<const SvxBrushItem*>(pItem)->GetColor() ) );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT,
true, &pItem ))
SetHighlightColor(static_cast<const SvxBrushItem*>(pItem)->GetColor());
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX,
true, &pItem ))
{
const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(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<const SvxShadowItem*>(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<const SvxTwoLinesItem*>(pTwoLinesItem)->GetValue() )
SetVertical( 0 );
}
else
{
Invalidate();
m_bBlink = false;
}
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;
m_pBackColor.reset( rFont.m_pBackColor ? new Color( *rFont.m_pBackColor ) : nullptr );
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;
m_bBlink = rFont.m_bBlink;
}
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_bBlink = pAttrSet->GetBlink().GetValue();
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 ))
m_pBackColor.reset( new Color( static_cast<const SvxBrushItem*>(pItem)->GetColor() ) );
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_HIGHLIGHT,
true, &pItem ))
SetHighlightColor(static_cast<const SvxBrushItem*>(pItem)->GetColor());
else
SetHighlightColor(COL_TRANSPARENT);
if( SfxItemState::SET == pAttrSet->GetItemState( RES_CHRATR_BOX,
true, &pItem ))
{
const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(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<const SvxShadowItem*>(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 );
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 )
{
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;
m_pBackColor.reset( rFont.m_pBackColor ? new Color( *rFont.m_pBackColor ) : nullptr );
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;
m_bBlink = rFont.m_bBlink;
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() )
{
long nDescent = nOldHeight - nOldAscent -
( static_cast<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;
}
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<const void*>(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 );
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<long>(CalcEscHeight( static_cast<sal_uInt16>(aTextSize.Height()), nAscent)) );
}
}
if (TextFrameIndex(1) == rInf.GetLen()
&& CH_TXT_ATR_FIELDSTART == rInf.GetText()[sal_Int32(rInf.GetIdx())])
{
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())])
{
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<const void*>(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();
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<const void*>(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::GetCursorOfst_( SwDrawTextInfo& rInf )
{
if ( !pLastFont || pLastFont->GetOwner() != reinterpret_cast<const void*>(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();
long nOldKern = rInf.GetKern();
rInf.SetKern( CheckKerning() );
SV_STAT( nGetTextSize );
if ( !IsCaseMap() )
nCursor = pLastFont->GetCursorOfst( rInf );
else
{
rInf.SetText( CalcCaseMap( rInf.GetText() ) );
nCursor = pLastFont->GetCursorOfst( rInf );
}
rInf.SetKern( nOldKern );
rInf.SetText(oldText);
}
return nCursor;
}
void SwSubFont::CalcEsc( SwDrawTextInfo const & rInf, Point& rPos )
{
long nOfst;
const sal_uInt16 nDir = UnMapDirection(
GetOrientation(), rInf.GetFrame() && rInf.GetFrame()->IsVertical() );
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 )
{
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 )
{
case 0 :
rPos.AdjustY(nOfst );
break;
case 900 :
rPos.AdjustX(nOfst );
break;
case 2700 :
rPos.AdjustX( -nOfst );
break;
}
break;
default :
nOfst = (static_cast<long>(m_nOrgHeight) * GetEscapement()) / 100;
switch ( nDir )
{
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( sal_uInt16 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() ) );
nDir = bBidiPor ?
1800 :
UnMapDirection( nDir, GetFrame() && GetFrame()->IsVertical() );
switch ( nDir )
{
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
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());
long nHeight = rMutableOut.GetTextHeight();
rMutableOut.SetFont(aOldFont);
return nHeight;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V794 The assignment operator should be protected from the case of 'this == &rFont'.