Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  swfont.cxx   Sprache: C

 
/* -*- 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 <vcl/metric.hxx>
#include <IDocumentSettingAccess.hxx>
#include <charatr.hxx>
#include <viewsh.hxx>
#include <swfont.hxx>
#include <fntcache.hxx>
#include <txtfrm.hxx>
#include <scriptinfo.hxx>
#include <swmodule.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;
}

SvxFontUnitMetrics SwFont::GetFontUnitMetrics() const
{
    // tdf#36709: Metrics conversion should use em and ic values from the bound fonts.
    // Unfortunately, this currently poses a problem due to font substitution: tests
    // abort when a missing font is set on a device.
    // In the interim, use height for all metrics. This is technically not correct, but
    // should be close enough for common fonts.
    return { /*em*/ static_cast<double>(GetHeight(GetActual())),
             /*ic*/ static_cast<double>(GetHeight(SwFontScript::CJK)) };
}

void SwFont::dumpAsXml(xmlTextWriterPtr writer) const
{
    (void)xmlTextWriterStartElement(writer, BAD_CAST("SwFont"));
    (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("ptr"), "%p"this);
    // do not use Color::AsRGBHexString() as that omits the transparency
    (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("color"), "%08" SAL_PRIxUINT32, sal_uInt32(GetColor()));
    (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("height"), BAD_CAST(OString::number(GetSize(GetActual()).Height()).getStr()));
    (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("width"), BAD_CAST(OString::number(GetSize(GetActual()).Width()).getStr()));
    {
        std::stringstream ss;
        ss << GetWeight();
        (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("weight"), BAD_CAST(ss.str().c_str()));
    }
    (void)xmlTextWriterEndElement(writer);
}

// 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 )
    {

        ifconst 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() );
        }
        ifconst 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 );
        }
        ifconst SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_POSTURE ) )
            m_aSub[SwFontScript::Latin].Font::SetItalic( pItem->GetPosture() );
        ifconst SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WEIGHT ) )
            m_aSub[SwFontScript::Latin].Font::SetWeight( pItem->GetWeight() );
        ifconst SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_LANGUAGE ) )
            m_aSub[SwFontScript::Latin].SetLanguage( pItem->GetLanguage() );

        ifconst 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() );
        }
        ifconst 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 );
        }
        ifconst SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_POSTURE ) )
            m_aSub[SwFontScript::CJK].Font::SetItalic( pItem->GetPosture() );
        ifconst SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CJK_WEIGHT ) )
            m_aSub[SwFontScript::CJK].Font::SetWeight( pItem->GetWeight() );
        ifconst 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 );
        }

        ifconst 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() );
        }
        ifconst 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 );
        }
        ifconst SvxPostureItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_POSTURE ) )
            m_aSub[SwFontScript::CTL].Font::SetItalic(pItem->GetPosture() );
        ifconst SvxWeightItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_WEIGHT ) )
            m_aSub[SwFontScript::CTL].Font::SetWeight( pItem->GetWeight() );
        ifconst SvxLanguageItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CTL_LANGUAGE ) )
            m_aSub[SwFontScript::CTL].SetLanguage( pItem->GetLanguage() );

        ifconst SvxUnderlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_UNDERLINE ) )
        {
            SetUnderline( pItem->GetLineStyle() );
            SetUnderColor( pItem->GetColor() );
        }
        ifconst SvxOverlineItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_OVERLINE ) )
        {
            SetOverline( pItem->GetLineStyle() );
            SetOverColor( pItem->GetColor() );
        }
        ifconst SvxCrossedOutItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CROSSEDOUT ) )
            SetStrikeout( pItem->GetStrikeout() );
        ifconst SvxColorItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_COLOR ) )
            SetColor( pItem->GetValue() );
        ifconst SvxEmphasisMarkItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_EMPHASIS_MARK ))
            SetEmphasisMark( pItem->GetEmphasisMark() );

        SetTransparent( true );
        SetAlign( ALIGN_BASELINE );
        ifconst SvxContourItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CONTOUR ) )
            SetOutline( pItem->GetValue() );
        ifconst SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ) )
            SetShadow( pItem->GetValue() );
        ifconst SvxCharReliefItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_RELIEF ) )
            SetRelief( pItem->GetValue() );
        ifconst SvxShadowedItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_SHADOWED ))
            SetPropWidth( pItem->GetValue() ? 50 : 100 );
        ifconst 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 );
        }
        ifconst SvxWordLineModeItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_WORDLINEMODE ) )
            SetWordLineMode( pItem->GetValue() );

        ifconst SvxEscapementItem* pEsc = pAttrSet->GetItemIfSet( RES_CHRATR_ESCAPEMENT ) )
        {
            SetEscapement( pEsc->GetEsc() );
            if( m_aSub[SwFontScript::Latin].IsEsc() )
                SetProportion( pEsc->GetProportionalHeight() );
        }
        ifconst SvxCaseMapItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_CASEMAP ) )
            SetCaseMap( pItem->GetCaseMap() );
        ifconst SvxKerningItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_KERNING ) )
            SetFixKerning( pItem->GetValue() );
        ifconst SvxCharRotateItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_ROTATE ) )
            SetVertical( pItem->GetValue() );
        ifconst SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
            mxBackColor = pItem->GetColor();
        ifconst SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
            SetHighlightColor(pItem->GetColor());
        ifconst 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));
        }
        ifconst 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;
    m_bURL = rFont.m_bURL;
}

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() );
    ifconst SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_BACKGROUND ) )
        mxBackColor = pItem->GetColor();
    ifconst SvxBrushItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_HIGHLIGHT ) )
        SetHighlightColor(pItem->GetColor());
    else
        SetHighlightColor(COL_TRANSPARENT);
    ifconst 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);
    }

    ifconst 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;
        m_bURL = rFont.m_bURL;
    }
    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&&nbsp;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(),
                                           SwModule::get()->GetCTLTextNumerals());

    Size aTextSize;
    TextFrameIndex const nLn = rInf.GetLen() == TextFrameIndex(COMPLETE_STRING)
            ? TextFrameIndex(rInf.GetText().getLength())
            : rInf.GetLen();
    rInf.SetLen( nLn );

    if( IsCapital() && nLn )
    {
        if (rInf.GetMeasureLen() != TextFrameIndex(COMPLETE_STRING))
        {
            rInf.SetLen(rInf.GetMeasureLen());
            rInf.SetMeasureLen(TextFrameIndex(COMPLETE_STRING));
        }
        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());
                TextFrameIndex const nOldMeasureLen(rInf.GetMeasureLen());
                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()) );
                if (nOldMeasureLen != TextFrameIndex(COMPLETE_STRING))
                {
                    const OUString aMeasureSnippet(oldStr.copy(sal_Int32(nOldIdx), sal_Int32(nOldMeasureLen)));
                    const OUString aNewMeasureText(CalcCaseMap(aMeasureSnippet));
                    rInf.SetMeasureLen(TextFrameIndex(aNewMeasureText.getLength()));
                }

                aTextSize = pLastFont->GetTextSize( rInf );

                rInf.SetIdx( nOldIdx );
                rInf.SetLen( nOldLen );
                rInf.SetMeasureLen(nOldMeasureLen);
            }
            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())])
    {
        SAL_WARN("sw""this is meant to be dead code");
        TextFrameIndex const nOldIdx(rInf.GetIdx());
        TextFrameIndex const nOldLen(rInf.GetLen());
        OUString aOldText(rInf.GetText());
        const OUString aNewText(CH_TXT_ATR_SUBST_FIELDSTART);
        rInf.SetTextIdxLen(aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
        aTextSize = pLastFont->GetTextSize( rInf );
        rInf.SetTextIdxLen(aOldText, nOldIdx, nOldLen);
    }
    else if (TextFrameIndex(1) == rInf.GetLen()
            && CH_TXT_ATR_FIELDEND == rInf.GetText()[sal_Int32(rInf.GetIdx())])
    {
        SAL_WARN("sw""this is meant to be dead code");
        TextFrameIndex const nOldIdx(rInf.GetIdx());
        TextFrameIndex const nOldLen(rInf.GetLen());
        OUString aOldText(rInf.GetText());
        const OUString aNewText(CH_TXT_ATR_SUBST_FIELDEND);
        rInf.SetTextIdxLen(aNewText, TextFrameIndex(0), TextFrameIndex(aNewText.getLength()));
        aTextSize = pLastFont->GetTextSize( rInf );
        rInf.SetTextIdxLen(aOldText, nOldIdx, 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(),
                                           SwModule::get()->GetCTLTextNumerals());

    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( u" "_ustr, 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(),
                                           SwModule::get()->GetCTLTextNumerals());

    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( u" "_ustr, 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(),
                                           SwModule::get()->GetCTLTextNumerals());

    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: */

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge