/* -*- 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 "atrhndl.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Attribute to Stack Mapping * * Attributes applied to a text are pushed on different stacks. For each * stack, the top most attribute on the stack is valid. Because some * kinds of attributes have to be pushed to the same stacks we map their * ids to stack ids * Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx ) * are stored in the defaultitem-cache, if you add one, you have to increase * NUM_DEFAULT_VALUES. * Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx. */ const sal_uInt8 StackPos[ RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN + 1 ] = { 0, // // 0 1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN // 1 0, // RES_CHRATR_CHARSETCOLOR, // 2 2, // RES_CHRATR_COLOR, // 3 3, // RES_CHRATR_CONTOUR, // 4 4, // RES_CHRATR_CROSSEDOUT, // 5 5, // RES_CHRATR_ESCAPEMENT, // 6 6, // RES_CHRATR_FONT, // 7 7, // RES_CHRATR_FONTSIZE, // 8 8, // RES_CHRATR_KERNING, // 9 9, // RES_CHRATR_LANGUAGE, // 10 10, // RES_CHRATR_POSTURE, // 11 0, // RES_CHRATR_UNUSED1, // 12 11, // RES_CHRATR_SHADOWED, // 13 12, // RES_CHRATR_UNDERLINE, // 14 13, // RES_CHRATR_WEIGHT, // 15 14, // RES_CHRATR_WORDLINEMODE, // 16 15, // RES_CHRATR_AUTOKERN, // 17 16, // RES_CHRATR_BLINK, // 18 17, // RES_CHRATR_NOHYPHEN, // 19 0, // RES_CHRATR_UNUSED2, // 20 18, // RES_CHRATR_BACKGROUND, // 21 19, // RES_CHRATR_CJK_FONT, // 22 20, // RES_CHRATR_CJK_FONTSIZE, // 23 21, // RES_CHRATR_CJK_LANGUAGE, // 24 22, // RES_CHRATR_CJK_POSTURE, // 25 23, // RES_CHRATR_CJK_WEIGHT, // 26 24, // RES_CHRATR_CTL_FONT, // 27 25, // RES_CHRATR_CTL_FONTSIZE, // 28 26, // RES_CHRATR_CTL_LANGUAGE, // 29 27, // RES_CHRATR_CTL_POSTURE, // 30 28, // RES_CHRATR_CTL_WEIGHT, // 31 29, // RES_CHRATR_ROTATE, // 32 30, // RES_CHRATR_EMPHASIS_MARK, // 33 31, // RES_CHRATR_TWO_LINES, // 34 32, // RES_CHRATR_SCALEW, // 35 33, // RES_CHRATR_RELIEF, // 36 34, // RES_CHRATR_HIDDEN, // 37 35, // RES_CHRATR_OVERLINE, // 38 0, // RES_CHRATR_RSID, // 39 36, // RES_CHRATR_BOX, // 40 37, // RES_CHRATR_SHADOW, // 41 38, // RES_CHRATR_HIGHLIGHT, // 42 0, // RES_CHRATR_GRABBAG, // 43 0, // RES_CHRATR_BIDIRTL, // 44 0, // RES_CHRATR_IDCTHINT, // 45 39, // RES_TXTATR_REFMARK, // 46 40, // RES_TXTATR_TOXMARK, // 47 41, // RES_TXTATR_META, // 48 41, // RES_TXTATR_METAFIELD, // 49 0, // RES_TXTATR_AUTOFMT, // 50 0, // RES_TXTATR_INETFMT // 51 0, // RES_TXTATR_CHARFMT, // 52 42, // RES_TXTATR_CJK_RUBY, // 53 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 54 43, // RES_TXTATR_INPUTFIELD // 55 }; namespace CharFormat { /// Returns the item set associated with a character/inet/auto style const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr ) { const SfxItemSet* pSet = nullptr; if ( RES_TXTATR_AUTOFMT == rAttr.Which() ) { pSet = static_cast(rAttr).GetStyleHandle().get(); } else { // Get the attributes from the template const SwCharFormat* pFormat = RES_TXTATR_INETFMT == rAttr.Which() ? static_cast(rAttr).GetTextINetFormat()->GetCharFormat() : static_cast(rAttr).GetCharFormat(); if( pFormat ) { pSet = &pFormat->GetAttrSet(); } } return pSet; } /// Extracts pool item of type nWhich from rAttr const SfxPoolItem* GetItem( const SwTextAttr& rAttr, sal_uInt16 nWhich ) { if ( RES_TXTATR_INETFMT == rAttr.Which() || RES_TXTATR_CHARFMT == rAttr.Which() || RES_TXTATR_AUTOFMT == rAttr.Which() ) { const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() ); if ( !pSet ) return nullptr; bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which(); const SfxPoolItem* pItem; bool bRet = SfxItemState::SET == pSet->GetItemState( nWhich, bInParent, &pItem ); return bRet ? pItem : nullptr; } return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : nullptr; } /// Checks if item is included in character/inet/auto style bool IsItemIncluded( const sal_uInt16 nWhich, const SwTextAttr *pAttr ) { bool bRet = false; const SfxItemSet* pItemSet = CharFormat::GetItemSet( pAttr->GetAttr() ); if ( pItemSet ) bRet = SfxItemState::SET == pItemSet->GetItemState( nWhich ); return bRet; } } /** * The color of hyperlinks is taken from the associated character attribute, * depending on its 'visited' state. There are actually two cases, which * should override the colors from the character attribute: * 1. We never take the 'visited' color during printing/pdf export/preview * 2. The user has chosen to override these colors in the view options */ static bool lcl_ChgHyperLinkColor( const SwTextAttr& rAttr, const SfxPoolItem& rItem, const SwViewShell* pShell, Color* pColor ) { if ( !pShell || RES_TXTATR_INETFMT != rAttr.Which() || RES_CHRATR_COLOR != rItem.Which() ) return false; // #i15455# // 1. case: // We do not want to show visited links: // (printing, pdf export, page preview) SwTextINetFormat & rINetAttr(const_cast( static_txtattr_cast(rAttr))); if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER || pShell->GetViewOptions()->IsPDFExport() || pShell->GetViewOptions()->IsPagePreview() ) { if (rINetAttr.IsVisited()) { if ( pColor ) { // take color from character format 'unvisited link' rINetAttr.SetVisited(false); const SwCharFormat* pTmpFormat = rINetAttr.GetCharFormat(); const SfxPoolItem* pItem; if (SfxItemState::SET == pTmpFormat->GetItemState(RES_CHRATR_COLOR, true, &pItem)) *pColor = static_cast(pItem)->GetValue(); rINetAttr.SetVisited(true); } return true; } return false; } // 2. case: // We do not want to apply the color set in the hyperlink // attribute, instead we take the colors from the view options: if ( pShell->GetWin() && ( (rINetAttr.IsVisited() && SwViewOption::IsVisitedLinks()) || (!rINetAttr.IsVisited() && SwViewOption::IsLinks()) ) ) { if ( pColor ) { if (rINetAttr.IsVisited()) { // take color from view option 'visited link color' *pColor = SwViewOption::GetVisitedLinksColor(); } else { // take color from view option 'unvisited link color' *pColor = SwViewOption::GetLinksColor(); } } return true; } return false; } SwAttrHandler::SwAttrHandler() : m_pIDocumentSettingAccess(nullptr) , m_pShell(nullptr) , m_bVertLayout(false) , m_bVertLayoutLRBT(false) { memset( m_pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) ); } SwAttrHandler::~SwAttrHandler() { } void SwAttrHandler::Init( const SwAttrSet& rAttrSet, const IDocumentSettingAccess& rIDocumentSettingAcces ) { m_pIDocumentSettingAccess = &rIDocumentSettingAcces; m_pShell = nullptr; for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ ) m_pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i ); } void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS, const IDocumentSettingAccess& rIDocumentSettingAcces, const SwViewShell* pSh, SwFont& rFnt, bool bVL, bool bVertLayoutLRBT ) { // initialize default array memcpy( m_pDefaultArray, pPoolItem, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) ); m_pIDocumentSettingAccess = &rIDocumentSettingAcces; m_pShell = pSh; // do we have to apply additional paragraph attributes? m_bVertLayout = bVL; m_bVertLayoutLRBT = bVertLayoutLRBT; if ( pAS && pAS->Count() ) { SfxItemIter aIter( *pAS ); sal_uInt16 nWhich; const SfxPoolItem* pItem = aIter.GetCurItem(); do { nWhich = pItem->Which(); if (isCHRATR(nWhich)) { m_pDefaultArray[ StackPos[ nWhich ] ] = pItem; FontChg( *pItem, rFnt, true ); } pItem = aIter.NextItem(); } while (pItem); } // It is possible, that Init is called more than once, e.g., in a // SwTextFrame::FormatOnceMore situation or (since sw_redlinehide) // from SwAttrIter::Seek(); in the latter case SwTextSizeInfo::m_pFnt // is an alias of m_pFnt so it must not be deleted! if (m_pFnt) { *m_pFnt = rFnt; } else { m_pFnt.reset(new SwFont(rFnt)); } } void SwAttrHandler::Reset( ) { for (auto& i : m_aAttrStack) i.clear(); } void SwAttrHandler::PushAndChg( const SwTextAttr& rAttr, SwFont& rFnt ) { // these special attributes in fact represent a collection of attributes // they have to be pushed to each stack they belong to if ( RES_TXTATR_INETFMT == rAttr.Which() || RES_TXTATR_CHARFMT == rAttr.Which() || RES_TXTATR_AUTOFMT == rAttr.Which() ) { const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() ); if ( !pSet ) return; for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++) { const SfxPoolItem* pItem; bool bRet = SfxItemState::SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem ); if ( bRet ) { // we push rAttr onto the appropriate stack if ( Push( rAttr, *pItem ) ) { // we let pItem change rFnt Color aColor; if (lcl_ChgHyperLinkColor(rAttr, *pItem, m_pShell, &aColor)) { SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR ); FontChg( aItemNext, rFnt, true ); } else FontChg( *pItem, rFnt, true ); } } } } // this is the usual case, we have a basic attribute, push it onto the // stack and change the font else { if ( Push( rAttr, rAttr.GetAttr() ) ) // we let pItem change rFnt FontChg( rAttr.GetAttr(), rFnt, true ); } } const SwTextAttr* SwAttrHandler::GetTop(sal_uInt16 nStack) { return m_aAttrStack[nStack].empty() ? nullptr : m_aAttrStack[nStack].back(); } bool SwAttrHandler::Push( const SwTextAttr& rAttr, const SfxPoolItem& rItem ) { OSL_ENSURE( rItem.Which() < RES_TXTATR_WITHEND_END, "I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); // robust if ( RES_TXTATR_WITHEND_END <= rItem.Which() ) return false; const sal_uInt16 nStack = StackPos[ rItem.Which() ]; // attributes originating from redlining have highest priority // second priority are hyperlink attributes, which have a color replacement const SwTextAttr* pTopAttr = GetTop(nStack); if ( !pTopAttr || rAttr.IsPriorityAttr() || ( !pTopAttr->IsPriorityAttr() && !lcl_ChgHyperLinkColor(*pTopAttr, rItem, m_pShell, nullptr))) { m_aAttrStack[nStack].push_back(&rAttr); return true; } const auto it = m_aAttrStack[nStack].end() - 1; m_aAttrStack[nStack].insert(it, &rAttr); return false; } void SwAttrHandler::RemoveFromStack(sal_uInt16 nWhich, const SwTextAttr& rAttr) { auto& rStack = m_aAttrStack[StackPos[nWhich]]; const auto it = std::find(rStack.begin(), rStack.end(), &rAttr); if (it != rStack.end()) rStack.erase(it); } void SwAttrHandler::PopAndChg( const SwTextAttr& rAttr, SwFont& rFnt ) { if ( RES_TXTATR_WITHEND_END <= rAttr.Which() ) return; // robust // these special attributes in fact represent a collection of attributes // they have to be removed from each stack they belong to if ( RES_TXTATR_INETFMT == rAttr.Which() || RES_TXTATR_CHARFMT == rAttr.Which() || RES_TXTATR_AUTOFMT == rAttr.Which() ) { const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() ); if ( !pSet ) return; for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++) { const SfxPoolItem* pItem; bool bRet = SfxItemState::SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem ); if ( bRet ) { // we remove rAttr from the appropriate stack RemoveFromStack(i, rAttr); // reset font according to attribute on top of stack // or default value ActivateTop( rFnt, i ); } } } // this is the usual case, we have a basic attribute, remove it from the // stack and reset the font else { RemoveFromStack(rAttr.Which(), rAttr); // reset font according to attribute on top of stack // or default value ActivateTop( rFnt, rAttr.Which() ); } } /// Only used during redlining void SwAttrHandler::Pop( const SwTextAttr& rAttr ) { OSL_ENSURE( rAttr.Which() < RES_TXTATR_WITHEND_END, "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); if ( rAttr.Which() < RES_TXTATR_WITHEND_END ) { RemoveFromStack(rAttr.Which(), rAttr); } } void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr ) { OSL_ENSURE( nAttr < RES_TXTATR_WITHEND_END, "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" ); const sal_uInt16 nStackPos = StackPos[ nAttr ]; const SwTextAttr* pTopAt = GetTop(nStackPos); if ( pTopAt ) { const SfxPoolItem* pItemNext(nullptr); // check if top attribute is collection of attributes if ( RES_TXTATR_INETFMT == pTopAt->Which() || RES_TXTATR_CHARFMT == pTopAt->Which() || RES_TXTATR_AUTOFMT == pTopAt->Which() ) { const SfxItemSet* pSet = CharFormat::GetItemSet( pTopAt->GetAttr() ); if (pSet) pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext ); } if (pItemNext) { Color aColor; if (lcl_ChgHyperLinkColor(*pTopAt, *pItemNext, m_pShell, &aColor)) { SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR ); FontChg( aItemNext, rFnt, false ); } else FontChg( *pItemNext, rFnt, false ); } else FontChg( pTopAt->GetAttr(), rFnt, false ); } // default value has to be set, we only have default values for char attribs else if ( nStackPos < NUM_DEFAULT_VALUES ) FontChg( *m_pDefaultArray[ nStackPos ], rFnt, false ); else if ( RES_TXTATR_REFMARK == nAttr ) rFnt.GetRef()--; else if ( RES_TXTATR_TOXMARK == nAttr ) rFnt.GetTox()--; else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) ) { rFnt.GetMeta()--; } else if ( RES_TXTATR_CJK_RUBY == nAttr ) { // ruby stack has no more attributes // check, if a rotation attribute has to be applied const sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; bool bTwoLineAct = false; const SwTextAttr* pTwoLineAttr = GetTop(nTwoLineStack); if ( pTwoLineAttr ) { const SfxPoolItem* pTwoLineItem = CharFormat::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); bTwoLineAct = static_cast(pTwoLineItem)->GetValue(); } else bTwoLineAct = static_cast(m_pDefaultArray[ nTwoLineStack ])->GetValue(); if ( bTwoLineAct ) return; // eventually, a rotate attribute has to be activated const sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; const SwTextAttr* pRotateAttr = GetTop(nRotateStack); if ( pRotateAttr ) { const SfxPoolItem* pRotateItem = CharFormat::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); rFnt.SetVertical( static_cast(pRotateItem)->GetValue(), m_bVertLayout ); } else rFnt.SetVertical( static_cast(m_pDefaultArray[ nRotateStack ])->GetValue(), m_bVertLayout ); } else if ( RES_TXTATR_INPUTFIELD == nAttr ) rFnt.GetInputField()--; } /** * When popping an attribute from the stack, the top more remaining * attribute in the stack becomes valid. The following function change * a font depending on the stack id. */ void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, bool bPush ) { switch ( rItem.Which() ) { case RES_CHRATR_CASEMAP : rFnt.SetCaseMap( static_cast(rItem).GetCaseMap() ); break; case RES_CHRATR_COLOR : rFnt.SetColor( static_cast(rItem).GetValue() ); break; case RES_CHRATR_CONTOUR : rFnt.SetOutline( static_cast(rItem).GetValue() ); break; case RES_CHRATR_CROSSEDOUT : rFnt.SetStrikeout( static_cast(rItem).GetStrikeout() ); break; case RES_CHRATR_ESCAPEMENT : rFnt.SetEscapement( static_cast(rItem).GetEsc() ); rFnt.SetProportion( static_cast(rItem).GetProportionalHeight() ); break; case RES_CHRATR_FONT : rFnt.SetName( static_cast(rItem).GetFamilyName(), SwFontScript::Latin ); rFnt.SetStyleName( static_cast(rItem).GetStyleName(), SwFontScript::Latin ); rFnt.SetFamily( static_cast(rItem).GetFamily(), SwFontScript::Latin ); rFnt.SetPitch( static_cast(rItem).GetPitch(), SwFontScript::Latin ); rFnt.SetCharSet( static_cast(rItem).GetCharSet(), SwFontScript::Latin ); break; case RES_CHRATR_FONTSIZE : rFnt.SetSize(Size(0,static_cast(rItem).GetHeight() ), SwFontScript::Latin ); break; case RES_CHRATR_KERNING : rFnt.SetFixKerning( static_cast(rItem).GetValue() ); break; case RES_CHRATR_LANGUAGE : rFnt.SetLanguage( static_cast(rItem).GetLanguage(), SwFontScript::Latin ); break; case RES_CHRATR_POSTURE : rFnt.SetItalic( static_cast(rItem).GetPosture(), SwFontScript::Latin ); break; case RES_CHRATR_SHADOWED : rFnt.SetShadow( static_cast(rItem).GetValue() ); break; case RES_CHRATR_UNDERLINE : { const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ]; const SwTextAttr* pTopAt = GetTop(nStackPos); const SfxPoolItem* pTmpItem = pTopAt ? CharFormat::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) : m_pDefaultArray[ nStackPos ]; if ((m_pShell && !m_pShell->GetWin()) || (pTmpItem && !static_cast(pTmpItem)->GetValue()) ) { rFnt.SetUnderline( static_cast(rItem).GetLineStyle() ); rFnt.SetUnderColor( static_cast(rItem).GetColor() ); } break; } case RES_CHRATR_BOX: { const SvxBoxItem& aBoxItem = static_cast(rItem); rFnt.SetTopBorder( aBoxItem.GetTop() ); rFnt.SetBottomBorder( aBoxItem.GetBottom() ); rFnt.SetRightBorder( aBoxItem.GetRight() ); rFnt.SetLeftBorder( aBoxItem.GetLeft() ); rFnt.SetTopBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::TOP) ); rFnt.SetBottomBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::BOTTOM) ); rFnt.SetRightBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::RIGHT) ); rFnt.SetLeftBorderDist( aBoxItem.GetDistance(SvxBoxItemLine::LEFT) ); break; } case RES_CHRATR_SHADOW: { const SvxShadowItem& aShadowItem = static_cast(rItem); rFnt.SetShadowColor( aShadowItem.GetColor() ); rFnt.SetShadowWidth( aShadowItem.GetWidth() ); rFnt.SetShadowLocation( aShadowItem.GetLocation() ); break; } case RES_CHRATR_OVERLINE : rFnt.SetOverline( static_cast(rItem).GetLineStyle() ); rFnt.SetOverColor( static_cast(rItem).GetColor() ); break; case RES_CHRATR_WEIGHT : rFnt.SetWeight( static_cast(rItem).GetWeight(), SwFontScript::Latin ); break; case RES_CHRATR_WORDLINEMODE : rFnt.SetWordLineMode( static_cast(rItem).GetValue() ); break; case RES_CHRATR_AUTOKERN : if( static_cast(rItem).GetValue() ) { rFnt.SetAutoKern( (!m_pIDocumentSettingAccess || !m_pIDocumentSettingAccess->get(DocumentSettingId::KERN_ASIAN_PUNCTUATION)) ? FontKerning::FontSpecific : FontKerning::Asian ); } else rFnt.SetAutoKern( FontKerning::NONE ); break; case RES_CHRATR_BLINK : rFnt.SetBlink( static_cast(rItem).GetValue() ); break; case RES_CHRATR_BACKGROUND : rFnt.SetBackColor(new Color( static_cast(rItem).GetColor() ) ); break; case RES_CHRATR_HIGHLIGHT : rFnt.SetHighlightColor( static_cast(rItem).GetColor() ); break; case RES_CHRATR_CJK_FONT : rFnt.SetName( static_cast(rItem).GetFamilyName(), SwFontScript::CJK ); rFnt.SetStyleName( static_cast(rItem).GetStyleName(), SwFontScript::CJK ); rFnt.SetFamily( static_cast(rItem).GetFamily(), SwFontScript::CJK ); rFnt.SetPitch( static_cast(rItem).GetPitch(), SwFontScript::CJK ); rFnt.SetCharSet( static_cast(rItem).GetCharSet(), SwFontScript::CJK ); break; case RES_CHRATR_CJK_FONTSIZE : rFnt.SetSize(Size( 0, static_cast(rItem).GetHeight()), SwFontScript::CJK); break; case RES_CHRATR_CJK_LANGUAGE : rFnt.SetLanguage( static_cast(rItem).GetLanguage(), SwFontScript::CJK ); break; case RES_CHRATR_CJK_POSTURE : rFnt.SetItalic( static_cast(rItem).GetPosture(), SwFontScript::CJK ); break; case RES_CHRATR_CJK_WEIGHT : rFnt.SetWeight( static_cast(rItem).GetWeight(), SwFontScript::CJK ); break; case RES_CHRATR_CTL_FONT : rFnt.SetName( static_cast(rItem).GetFamilyName(), SwFontScript::CTL ); rFnt.SetStyleName( static_cast(rItem).GetStyleName(), SwFontScript::CTL ); rFnt.SetFamily( static_cast(rItem).GetFamily(), SwFontScript::CTL ); rFnt.SetPitch( static_cast(rItem).GetPitch(), SwFontScript::CTL ); rFnt.SetCharSet( static_cast(rItem).GetCharSet(), SwFontScript::CTL ); break; case RES_CHRATR_CTL_FONTSIZE : rFnt.SetSize(Size(0, static_cast(rItem).GetHeight() ), SwFontScript::CTL); break; case RES_CHRATR_CTL_LANGUAGE : rFnt.SetLanguage( static_cast(rItem).GetLanguage(), SwFontScript::CTL ); break; case RES_CHRATR_CTL_POSTURE : rFnt.SetItalic( static_cast(rItem).GetPosture(), SwFontScript::CTL ); break; case RES_CHRATR_CTL_WEIGHT : rFnt.SetWeight( static_cast(rItem).GetWeight(), SwFontScript::CTL ); break; case RES_CHRATR_EMPHASIS_MARK : rFnt.SetEmphasisMark( static_cast(rItem).GetEmphasisMark() ); break; case RES_CHRATR_SCALEW : rFnt.SetPropWidth( static_cast(rItem).GetValue() ); break; case RES_CHRATR_RELIEF : rFnt.SetRelief( static_cast(rItem).GetValue() ); break; case RES_CHRATR_HIDDEN : if (m_pShell && m_pShell->GetWin()) { if ( static_cast(rItem).GetValue() ) rFnt.SetUnderline( LINESTYLE_DOTTED ); else ActivateTop( rFnt, RES_CHRATR_UNDERLINE ); } break; case RES_CHRATR_ROTATE : { // rotate attribute is applied, when: // 1. ruby stack is empty and // 2. top of two line stack ( or default attribute )is an // deactivated two line attribute const bool bRuby = 0 != m_aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].size(); if ( bRuby ) break; const sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ]; bool bTwoLineAct = false; const SwTextAttr* pTwoLineAttr = GetTop(nTwoLineStack); if ( pTwoLineAttr ) { const SfxPoolItem* pTwoLineItem = CharFormat::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES ); bTwoLineAct = static_cast(pTwoLineItem)->GetValue(); } else bTwoLineAct = static_cast(m_pDefaultArray[ nTwoLineStack ])->GetValue(); if ( !bTwoLineAct ) rFnt.SetVertical( static_cast(rItem).GetValue(), m_bVertLayout, m_bVertLayoutLRBT ); break; } case RES_CHRATR_TWO_LINES : { bool bRuby = 0 != m_aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].size(); // two line is activated, if // 1. no ruby attribute is set and // 2. attribute is active if ( !bRuby && static_cast(rItem).GetValue() ) { rFnt.SetVertical( 0, m_bVertLayout ); break; } // a deactivating two line attribute is on top of stack, // check if rotate attribute has to be enabled if ( bRuby ) break; const sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ]; const SwTextAttr* pRotateAttr = GetTop(nRotateStack); if ( pRotateAttr ) { const SfxPoolItem* pRotateItem = CharFormat::GetItem( *pRotateAttr, RES_CHRATR_ROTATE ); rFnt.SetVertical( static_cast(pRotateItem)->GetValue(), m_bVertLayout ); } else rFnt.SetVertical( static_cast(m_pDefaultArray[ nRotateStack ])->GetValue(), m_bVertLayout ); break; } case RES_TXTATR_CJK_RUBY : rFnt.SetVertical( 0, m_bVertLayout ); break; case RES_TXTATR_REFMARK : if ( bPush ) rFnt.GetRef()++; else rFnt.GetRef()--; break; case RES_TXTATR_TOXMARK : if ( bPush ) rFnt.GetTox()++; else rFnt.GetTox()--; break; case RES_TXTATR_META: case RES_TXTATR_METAFIELD: if ( bPush ) rFnt.GetMeta()++; else rFnt.GetMeta()--; break; case RES_TXTATR_INPUTFIELD : if ( bPush ) rFnt.GetInputField()++; else rFnt.GetInputField()--; break; } } /// Takes the default font and calculated the ascent and height void SwAttrHandler::GetDefaultAscentAndHeight( SwViewShell const * pShell, OutputDevice const & rOut, sal_uInt16& nAscent, sal_uInt16& nHeight ) const { OSL_ENSURE(m_pFnt, "No font available for GetDefaultAscentAndHeight"); if (m_pFnt) { SwFont aFont( *m_pFnt ); nHeight = aFont.GetHeight( pShell, rOut ); nAscent = aFont.GetAscent( pShell, rOut ); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */