diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sc/source/core/data/patattr.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sc/source/core/data/patattr.cxx')
-rw-r--r-- | sc/source/core/data/patattr.cxx | 1422 |
1 files changed, 1422 insertions, 0 deletions
diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx new file mode 100644 index 000000000..8a88e9449 --- /dev/null +++ b/sc/source/core/data/patattr.cxx @@ -0,0 +1,1422 @@ +/* -*- 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 <memory> +#include <utility> +#include <scitems.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/lineitem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/contouritem.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/colritem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/emphasismarkitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/forbiddenruleitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/postitem.hxx> +#include <svx/rotmodit.hxx> +#include <editeng/scriptspaceitem.hxx> +#include <editeng/shaditem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <editeng/justifyitem.hxx> +#include <svl/intitem.hxx> +#include <svl/numformat.hxx> +#include <svl/zforlist.hxx> +#include <vcl/outdev.hxx> +#include <tools/fract.hxx> +#include <tools/UnitConversion.hxx> +#include <osl/diagnose.h> + +#include <attrib.hxx> +#include <patattr.hxx> +#include <docpool.hxx> +#include <stlsheet.hxx> +#include <stlpool.hxx> +#include <document.hxx> +#include <globstr.hrc> +#include <scresid.hxx> +#include <validat.hxx> +#include <scmod.hxx> +#include <fillinfo.hxx> +#include <boost/functional/hash.hpp> + +ScPatternAttr::ScPatternAttr( SfxItemSet&& pItemSet, const OUString& rStyleName ) + : SfxSetItem ( ATTR_PATTERN, std::move(pItemSet) ), + pName ( rStyleName ), + pStyle ( nullptr ), + mnKey(0) +{ +} + +ScPatternAttr::ScPatternAttr( SfxItemSet&& pItemSet ) + : SfxSetItem ( ATTR_PATTERN, std::move(pItemSet) ), + pStyle ( nullptr ), + mnKey(0) +{ +} + +ScPatternAttr::ScPatternAttr( SfxItemPool* pItemPool ) + : SfxSetItem ( ATTR_PATTERN, SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END>( *pItemPool ) ), + pStyle ( nullptr ), + mnKey(0) +{ +} + +ScPatternAttr::ScPatternAttr( const ScPatternAttr& rPatternAttr ) + : SfxSetItem ( rPatternAttr ), + pName ( rPatternAttr.pName ), + pStyle ( rPatternAttr.pStyle ), + mnKey(rPatternAttr.mnKey) +{ +} + +ScPatternAttr* ScPatternAttr::Clone( SfxItemPool *pPool ) const +{ + ScPatternAttr* pPattern = new ScPatternAttr( GetItemSet().CloneAsValue(true, pPool) ); + + pPattern->pStyle = pStyle; + pPattern->pName = pName; + + return pPattern; +} + +static bool StrCmp( const OUString* pStr1, const OUString* pStr2 ) +{ + if (pStr1 == pStr2) + return true; + if (pStr1 && !pStr2) + return false; + if (!pStr1 && pStr2) + return false; + return *pStr1 == *pStr2; +} + +constexpr size_t compareSize = ATTR_PATTERN_END - ATTR_PATTERN_START + 1; + +std::optional<bool> ScPatternAttr::FastEqualPatternSets( const SfxItemSet& rSet1, const SfxItemSet& rSet2 ) +{ + // #i62090# The SfxItemSet in the SfxSetItem base class always has the same ranges + // (single range from ATTR_PATTERN_START to ATTR_PATTERN_END), and the items are pooled, + // so it's enough to compare just the pointers (Count just because it's even faster). + + if ( rSet1.Count() != rSet2.Count() ) + return { false }; + + // Actually test_tdf133629 from UITest_calc_tests9 somehow manages to have + // a different range (and I don't understand enough why), so better be safe and compare fully. + if( rSet1.TotalCount() != compareSize || rSet2.TotalCount() != compareSize ) + return std::nullopt; + + SfxPoolItem const ** pItems1 = rSet1.GetItems_Impl(); // inline method of SfxItemSet + SfxPoolItem const ** pItems2 = rSet2.GetItems_Impl(); + + return { memcmp( pItems1, pItems2, compareSize * sizeof(pItems1[0]) ) == 0 }; +} + +static bool EqualPatternSets( const SfxItemSet& rSet1, const SfxItemSet& rSet2 ) +{ + std::optional<bool> equal = ScPatternAttr::FastEqualPatternSets( rSet1, rSet2 ); + if(equal.has_value()) + return *equal; + return rSet1 == rSet2; +} + +bool ScPatternAttr::operator==( const SfxPoolItem& rCmp ) const +{ + // #i62090# Use quick comparison between ScPatternAttr's ItemSets + + if (!SfxPoolItem::operator==(rCmp) ) + return false; + if (!mxHashCode) + CalcHashCode(); + auto const & rOther = static_cast<const ScPatternAttr&>(rCmp); + if (!rOther.mxHashCode) + rOther.CalcHashCode(); + if (*mxHashCode != *rOther.mxHashCode) + return false; + return EqualPatternSets( GetItemSet(), rOther.GetItemSet() ) && + StrCmp( GetStyleName(), rOther.GetStyleName() ); +} + +SfxPoolItem::lookup_iterator ScPatternAttr::Lookup(lookup_iterator begin, lookup_iterator end ) const +{ + if( !mxHashCode ) + CalcHashCode(); + if( *mxHashCode != 0 ) + { + for( auto it = begin; it != end; ++it) + { + const ScPatternAttr* other = static_cast<const ScPatternAttr*>(*it); + if( !other->mxHashCode ) + other->CalcHashCode(); + if (*mxHashCode == *other->mxHashCode + && EqualPatternSets( GetItemSet(), other->GetItemSet()) + && StrCmp( GetStyleName(), other->GetStyleName())) + { + return it; + } + } + } + return end; +} + +SvxCellOrientation ScPatternAttr::GetCellOrientation( const SfxItemSet& rItemSet, const SfxItemSet* pCondSet ) +{ + SvxCellOrientation eOrient = SvxCellOrientation::Standard; + + if( GetItem( ATTR_STACKED, rItemSet, pCondSet ).GetValue() ) + { + eOrient = SvxCellOrientation::Stacked; + } + else + { + Degree100 nAngle = GetItem( ATTR_ROTATE_VALUE, rItemSet, pCondSet ).GetValue(); + if( nAngle == 9000_deg100 ) + eOrient = SvxCellOrientation::BottomUp; + else if( nAngle == 27000_deg100 ) + eOrient = SvxCellOrientation::TopBottom; + } + + return eOrient; +} + +SvxCellOrientation ScPatternAttr::GetCellOrientation( const SfxItemSet* pCondSet ) const +{ + return GetCellOrientation( GetItemSet(), pCondSet ); +} + +namespace { + +void getFontIDsByScriptType(SvtScriptType nScript, + TypedWhichId<SvxFontItem>& nFontId, + TypedWhichId<SvxFontHeightItem>& nHeightId, + TypedWhichId<SvxWeightItem>& nWeightId, + TypedWhichId<SvxPostureItem>& nPostureId, + TypedWhichId<SvxLanguageItem>& nLangId) +{ + if ( nScript == SvtScriptType::ASIAN ) + { + nFontId = ATTR_CJK_FONT; + nHeightId = ATTR_CJK_FONT_HEIGHT; + nWeightId = ATTR_CJK_FONT_WEIGHT; + nPostureId = ATTR_CJK_FONT_POSTURE; + nLangId = ATTR_CJK_FONT_LANGUAGE; + } + else if ( nScript == SvtScriptType::COMPLEX ) + { + nFontId = ATTR_CTL_FONT; + nHeightId = ATTR_CTL_FONT_HEIGHT; + nWeightId = ATTR_CTL_FONT_WEIGHT; + nPostureId = ATTR_CTL_FONT_POSTURE; + nLangId = ATTR_CTL_FONT_LANGUAGE; + } + else + { + nFontId = ATTR_FONT; + nHeightId = ATTR_FONT_HEIGHT; + nWeightId = ATTR_FONT_WEIGHT; + nPostureId = ATTR_FONT_POSTURE; + nLangId = ATTR_FONT_LANGUAGE; + } +} + +} + +void ScPatternAttr::GetFont( + vcl::Font& rFont, const SfxItemSet& rItemSet, ScAutoFontColorMode eAutoMode, + const OutputDevice* pOutDev, const Fraction* pScale, + const SfxItemSet* pCondSet, SvtScriptType nScript, + const Color* pBackConfigColor, const Color* pTextConfigColor ) +{ + // Read items + + const SvxFontItem* pFontAttr; + sal_uInt32 nFontHeight; + FontWeight eWeight; + FontItalic eItalic; + FontLineStyle eUnder; + FontLineStyle eOver; + bool bWordLine; + FontStrikeout eStrike; + bool bOutline; + bool bShadow; + FontEmphasisMark eEmphasis; + FontRelief eRelief; + Color aColor; + LanguageType eLang; + + TypedWhichId<SvxFontItem> nFontId(0); + TypedWhichId<SvxFontHeightItem> nHeightId(0); + TypedWhichId<SvxWeightItem> nWeightId(0); + TypedWhichId<SvxPostureItem> nPostureId(0); + TypedWhichId<SvxLanguageItem> nLangId(0); + getFontIDsByScriptType(nScript, nFontId, nHeightId, nWeightId, nPostureId, nLangId); + + if ( pCondSet ) + { + pFontAttr = pCondSet->GetItemIfSet( nFontId ); + if ( !pFontAttr ) + pFontAttr = &rItemSet.Get( nFontId ); + + const SvxFontHeightItem* pFontHeightItem = pCondSet->GetItemIfSet( nHeightId ); + if ( !pFontHeightItem ) + pFontHeightItem = &rItemSet.Get( nHeightId ); + nFontHeight = pFontHeightItem->GetHeight(); + + const SvxWeightItem* pFontHWeightItem = pCondSet->GetItemIfSet( nWeightId ); + if ( !pFontHWeightItem ) + pFontHWeightItem = &rItemSet.Get( nWeightId ); + eWeight = pFontHWeightItem->GetValue(); + + const SvxPostureItem* pPostureItem = pCondSet->GetItemIfSet( nPostureId ); + if ( !pPostureItem ) + pPostureItem = &rItemSet.Get( nPostureId ); + eItalic = pPostureItem->GetValue(); + + const SvxUnderlineItem* pUnderlineItem = pCondSet->GetItemIfSet( ATTR_FONT_UNDERLINE ); + if ( !pUnderlineItem ) + pUnderlineItem = &rItemSet.Get( ATTR_FONT_UNDERLINE ); + eUnder = pUnderlineItem->GetValue(); + + const SvxOverlineItem* pOverlineItem = pCondSet->GetItemIfSet( ATTR_FONT_OVERLINE ); + if ( !pOverlineItem ) + pOverlineItem = &rItemSet.Get( ATTR_FONT_OVERLINE ); + eOver = pOverlineItem->GetValue(); + + const SvxWordLineModeItem* pWordlineItem = pCondSet->GetItemIfSet( ATTR_FONT_WORDLINE ); + if ( !pWordlineItem ) + pWordlineItem = &rItemSet.Get( ATTR_FONT_WORDLINE ); + bWordLine = pWordlineItem->GetValue(); + + const SvxCrossedOutItem* pCrossedOutItem = pCondSet->GetItemIfSet( ATTR_FONT_CROSSEDOUT ); + if ( !pCrossedOutItem ) + pCrossedOutItem = &rItemSet.Get( ATTR_FONT_CROSSEDOUT ); + eStrike = pCrossedOutItem->GetValue(); + + const SvxContourItem* pContourItem = pCondSet->GetItemIfSet( ATTR_FONT_CONTOUR ); + if ( !pContourItem ) + pContourItem = &rItemSet.Get( ATTR_FONT_CONTOUR ); + bOutline = pContourItem->GetValue(); + + const SvxShadowedItem* pShadowedItem = pCondSet->GetItemIfSet( ATTR_FONT_SHADOWED ); + if ( !pShadowedItem ) + pShadowedItem = &rItemSet.Get( ATTR_FONT_SHADOWED ); + bShadow = pShadowedItem->GetValue(); + + const SvxEmphasisMarkItem* pEmphasisMarkItem = pCondSet->GetItemIfSet( ATTR_FONT_EMPHASISMARK ); + if ( !pEmphasisMarkItem ) + pEmphasisMarkItem = &rItemSet.Get( ATTR_FONT_EMPHASISMARK ); + eEmphasis = pEmphasisMarkItem->GetEmphasisMark(); + + const SvxCharReliefItem* pCharReliefItem = pCondSet->GetItemIfSet( ATTR_FONT_RELIEF ); + if ( !pCharReliefItem ) + pCharReliefItem = &rItemSet.Get( ATTR_FONT_RELIEF ); + eRelief = pCharReliefItem->GetValue(); + + const SvxColorItem* pColorItem = pCondSet->GetItemIfSet( ATTR_FONT_COLOR ); + if ( !pColorItem ) + pColorItem = &rItemSet.Get( ATTR_FONT_COLOR ); + aColor = pColorItem->GetValue(); + + const SvxLanguageItem* pLanguageItem = pCondSet->GetItemIfSet( nLangId ); + if ( !pLanguageItem ) + pLanguageItem = &rItemSet.Get( nLangId ); + eLang = pLanguageItem->GetLanguage(); + } + else // Everything from rItemSet + { + pFontAttr = &rItemSet.Get( nFontId ); + nFontHeight = rItemSet.Get( nHeightId ).GetHeight(); + eWeight = rItemSet.Get( nWeightId ).GetValue(); + eItalic = rItemSet.Get( nPostureId ).GetValue(); + eUnder = rItemSet.Get( ATTR_FONT_UNDERLINE ).GetValue(); + eOver = rItemSet.Get( ATTR_FONT_OVERLINE ).GetValue(); + bWordLine = rItemSet.Get( ATTR_FONT_WORDLINE ).GetValue(); + eStrike = rItemSet.Get( ATTR_FONT_CROSSEDOUT ).GetValue(); + bOutline = rItemSet.Get( ATTR_FONT_CONTOUR ).GetValue(); + bShadow = rItemSet.Get( ATTR_FONT_SHADOWED ).GetValue(); + eEmphasis = rItemSet.Get( ATTR_FONT_EMPHASISMARK ).GetEmphasisMark(); + eRelief = rItemSet.Get( ATTR_FONT_RELIEF ).GetValue(); + aColor = rItemSet.Get( ATTR_FONT_COLOR ).GetValue(); + // for graphite language features + eLang = rItemSet.Get( nLangId ).GetLanguage(); + } + OSL_ENSURE(pFontAttr,"Oops?"); + + // Evaluate + + // FontItem: + + if (rFont.GetFamilyName() != pFontAttr->GetFamilyName()) + rFont.SetFamilyName( pFontAttr->GetFamilyName() ); + if (rFont.GetStyleName() != pFontAttr->GetStyleName()) + rFont.SetStyleName( pFontAttr->GetStyleName() ); + + rFont.SetFamily( pFontAttr->GetFamily() ); + rFont.SetCharSet( pFontAttr->GetCharSet() ); + rFont.SetPitch( pFontAttr->GetPitch() ); + + rFont.SetLanguage(eLang); + + // Size + + if ( pOutDev != nullptr ) + { + Size aEffSize; + Fraction aFraction( 1,1 ); + if (pScale) + aFraction = *pScale; + Size aSize( 0, static_cast<tools::Long>(nFontHeight) ); + MapMode aDestMode = pOutDev->GetMapMode(); + MapMode aSrcMode( MapUnit::MapTwip, Point(), aFraction, aFraction ); + if (aDestMode.GetMapUnit() == MapUnit::MapPixel && pOutDev->GetDPIX() > 0) + aEffSize = pOutDev->LogicToPixel( aSize, aSrcMode ); + else + { + Fraction aFractOne(1,1); + aDestMode.SetScaleX( aFractOne ); + aDestMode.SetScaleY( aFractOne ); + aEffSize = OutputDevice::LogicToLogic( aSize, aSrcMode, aDestMode ); + } + rFont.SetFontSize( aEffSize ); + } + else /* if pOutDev != NULL */ + { + rFont.SetFontSize( Size( 0, static_cast<tools::Long>(nFontHeight) ) ); + } + + // determine effective font color + + if ( ( aColor == COL_AUTO && eAutoMode != SC_AUTOCOL_RAW ) || + eAutoMode == SC_AUTOCOL_IGNOREFONT || eAutoMode == SC_AUTOCOL_IGNOREALL ) + { + if ( eAutoMode == SC_AUTOCOL_BLACK ) + aColor = COL_BLACK; + else + { + // get background color from conditional or own set + Color aBackColor; + if ( pCondSet ) + { + const SvxBrushItem* pItem = pCondSet->GetItemIfSet( ATTR_BACKGROUND ); + if ( !pItem ) + pItem = &rItemSet.Get( ATTR_BACKGROUND ); + aBackColor = pItem->GetColor(); + } + else + aBackColor = rItemSet.Get( ATTR_BACKGROUND ).GetColor(); + + // if background color attribute is transparent, use window color for brightness comparisons + if ( aBackColor == COL_TRANSPARENT || + eAutoMode == SC_AUTOCOL_IGNOREBACK || eAutoMode == SC_AUTOCOL_IGNOREALL ) + { + if ( eAutoMode == SC_AUTOCOL_PRINT ) + aBackColor = COL_WHITE; + else if ( pBackConfigColor ) + { + // pBackConfigColor can be used to avoid repeated lookup of the configured color + aBackColor = *pBackConfigColor; + } + else + aBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor; + } + + // get system text color for comparison + Color aSysTextColor; + if ( eAutoMode == SC_AUTOCOL_PRINT ) + aSysTextColor = COL_BLACK; + else if ( pTextConfigColor ) + { + // pTextConfigColor can be used to avoid repeated lookup of the configured color + aSysTextColor = *pTextConfigColor; + } + else + aSysTextColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + + // select the resulting color + if ( aBackColor.IsDark() && aSysTextColor.IsDark() ) + { + // use white instead of dark on dark + aColor = COL_WHITE; + } + else if ( aBackColor.IsBright() && aSysTextColor.IsBright() ) + { + // use black instead of bright on bright + aColor = COL_BLACK; + } + else + { + // use aSysTextColor (black for SC_AUTOCOL_PRINT, from style settings otherwise) + aColor = aSysTextColor; + } + } + } + + // set font effects + rFont.SetWeight( eWeight ); + rFont.SetItalic( eItalic ); + rFont.SetUnderline( eUnder ); + rFont.SetOverline( eOver ); + rFont.SetWordLineMode( bWordLine ); + rFont.SetStrikeout( eStrike ); + rFont.SetOutline( bOutline ); + rFont.SetShadow( bShadow ); + rFont.SetEmphasisMark( eEmphasis ); + rFont.SetRelief( eRelief ); + rFont.SetColor( aColor ); + rFont.SetTransparent( true ); +} + +void ScPatternAttr::GetFont( + vcl::Font& rFont, ScAutoFontColorMode eAutoMode, + const OutputDevice* pOutDev, const Fraction* pScale, + const SfxItemSet* pCondSet, SvtScriptType nScript, + const Color* pBackConfigColor, const Color* pTextConfigColor ) const +{ + GetFont( rFont, GetItemSet(), eAutoMode, pOutDev, pScale, pCondSet, nScript, pBackConfigColor, pTextConfigColor ); +} + +ScDxfFont ScPatternAttr::GetDxfFont(const SfxItemSet& rItemSet, SvtScriptType nScript) +{ + TypedWhichId<SvxFontItem> nFontId(0); + TypedWhichId<SvxFontHeightItem> nHeightId(0); + TypedWhichId<SvxWeightItem> nWeightId(0); + TypedWhichId<SvxPostureItem> nPostureId(0); + TypedWhichId<SvxLanguageItem> nLangId(0); + getFontIDsByScriptType(nScript, nFontId, nHeightId, nWeightId, nPostureId, nLangId); + + ScDxfFont aReturn; + + if ( const SvxFontItem* pItem = rItemSet.GetItemIfSet( nFontId ) ) + { + aReturn.pFontAttr = pItem; + } + + if ( const SvxFontHeightItem* pItem = rItemSet.GetItemIfSet( nHeightId ) ) + { + aReturn.nFontHeight = pItem->GetHeight(); + } + + if ( const SvxWeightItem* pItem = rItemSet.GetItemIfSet( nWeightId ) ) + { + aReturn.eWeight = pItem->GetValue(); + } + + if ( const SvxPostureItem* pItem = rItemSet.GetItemIfSet( nPostureId ) ) + { + aReturn.eItalic = pItem->GetValue(); + } + + if ( const SvxUnderlineItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_UNDERLINE ) ) + { + pItem = &rItemSet.Get( ATTR_FONT_UNDERLINE ); + aReturn.eUnder = pItem->GetValue(); + } + + if ( const SvxOverlineItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_OVERLINE ) ) + { + aReturn.eOver = pItem->GetValue(); + } + + if ( const SvxWordLineModeItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_WORDLINE ) ) + { + aReturn.bWordLine = pItem->GetValue(); + } + + if ( const SvxCrossedOutItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_CROSSEDOUT ) ) + { + pItem = &rItemSet.Get( ATTR_FONT_CROSSEDOUT ); + aReturn.eStrike = pItem->GetValue(); + } + + if ( const SvxContourItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_CONTOUR ) ) + { + aReturn.bOutline = pItem->GetValue(); + } + + if ( const SvxShadowedItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_SHADOWED ) ) + { + pItem = &rItemSet.Get( ATTR_FONT_SHADOWED ); + aReturn.bShadow = pItem->GetValue(); + } + + if ( const SvxEmphasisMarkItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_EMPHASISMARK ) ) + { + aReturn.eEmphasis = pItem->GetEmphasisMark(); + } + + if ( const SvxCharReliefItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_RELIEF ) ) + { + aReturn.eRelief = pItem->GetValue(); + } + + if ( const SvxColorItem* pItem = rItemSet.GetItemIfSet( ATTR_FONT_COLOR ) ) + { + aReturn.aColor = pItem->GetValue(); + } + + if ( const SvxLanguageItem* pItem = rItemSet.GetItemIfSet( nLangId ) ) + { + aReturn.eLang = pItem->GetLanguage(); + } + + return aReturn; +} + +template <class T> +static void lcl_populate( std::unique_ptr<T>& rxItem, TypedWhichId<T> nWhich, const SfxItemSet& rSrcSet, const SfxItemSet* pCondSet ) +{ + const T* pItem = pCondSet->GetItemIfSet( nWhich ); + if ( !pItem ) + pItem = &rSrcSet.Get( nWhich ); + rxItem.reset(pItem->Clone()); +} + +void ScPatternAttr::FillToEditItemSet( SfxItemSet& rEditSet, const SfxItemSet& rSrcSet, const SfxItemSet* pCondSet ) +{ + // Read Items + + std::unique_ptr<SvxColorItem> aColorItem(std::make_unique<SvxColorItem>(EE_CHAR_COLOR)); // use item as-is + std::unique_ptr<SvxFontItem> aFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO)); // use item as-is + std::unique_ptr<SvxFontItem> aCjkFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO_CJK)); // use item as-is + std::unique_ptr<SvxFontItem> aCtlFontItem(std::make_unique<SvxFontItem>(EE_CHAR_FONTINFO_CTL)); // use item as-is + tools::Long nTHeight, nCjkTHeight, nCtlTHeight; // Twips + FontWeight eWeight, eCjkWeight, eCtlWeight; + std::unique_ptr<SvxUnderlineItem> aUnderlineItem(std::make_unique<SvxUnderlineItem>(LINESTYLE_NONE, EE_CHAR_UNDERLINE)); + std::unique_ptr<SvxOverlineItem> aOverlineItem(std::make_unique<SvxOverlineItem>(LINESTYLE_NONE, EE_CHAR_OVERLINE)); + bool bWordLine; + FontStrikeout eStrike; + FontItalic eItalic, eCjkItalic, eCtlItalic; + bool bOutline; + bool bShadow; + bool bForbidden; + FontEmphasisMark eEmphasis; + FontRelief eRelief; + LanguageType eLang, eCjkLang, eCtlLang; + bool bHyphenate; + SvxFrameDirection eDirection; + + //TODO: additional parameter to control if language is needed? + + if ( pCondSet ) + { + lcl_populate(aColorItem, ATTR_FONT_COLOR, rSrcSet, pCondSet); + lcl_populate(aFontItem, ATTR_FONT, rSrcSet, pCondSet); + lcl_populate(aCjkFontItem, ATTR_CJK_FONT, rSrcSet, pCondSet); + lcl_populate(aCtlFontItem, ATTR_CTL_FONT, rSrcSet, pCondSet); + + const SvxFontHeightItem* pFontHeightItem = pCondSet->GetItemIfSet( ATTR_FONT_HEIGHT ); + if (!pFontHeightItem) + pFontHeightItem = &rSrcSet.Get( ATTR_FONT_HEIGHT ); + nTHeight = pFontHeightItem->GetHeight(); + pFontHeightItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_HEIGHT ); + if ( !pFontHeightItem ) + pFontHeightItem = &rSrcSet.Get( ATTR_CJK_FONT_HEIGHT ); + nCjkTHeight = pFontHeightItem->GetHeight(); + pFontHeightItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_HEIGHT ); + if ( !pFontHeightItem ) + pFontHeightItem = &rSrcSet.Get( ATTR_CTL_FONT_HEIGHT ); + nCtlTHeight = pFontHeightItem->GetHeight(); + + const SvxWeightItem* pWeightItem = pCondSet->GetItemIfSet( ATTR_FONT_WEIGHT ); + if ( !pWeightItem ) + pWeightItem = &rSrcSet.Get( ATTR_FONT_WEIGHT ); + eWeight = pWeightItem->GetValue(); + pWeightItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_WEIGHT ); + if ( !pWeightItem ) + pWeightItem = &rSrcSet.Get( ATTR_CJK_FONT_WEIGHT ); + eCjkWeight = pWeightItem->GetValue(); + pWeightItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_WEIGHT ); + if ( !pWeightItem ) + pWeightItem = &rSrcSet.Get( ATTR_CTL_FONT_WEIGHT ); + eCtlWeight = pWeightItem->GetValue(); + + const SvxPostureItem* pPostureItem = pCondSet->GetItemIfSet( ATTR_FONT_POSTURE ); + if ( !pPostureItem ) + pPostureItem = &rSrcSet.Get( ATTR_FONT_POSTURE ); + eItalic = pPostureItem->GetValue(); + pPostureItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_POSTURE ); + if ( !pPostureItem ) + pPostureItem = &rSrcSet.Get( ATTR_CJK_FONT_POSTURE ); + eCjkItalic = pPostureItem->GetValue(); + pPostureItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_POSTURE ); + if ( !pPostureItem ) + pPostureItem = &rSrcSet.Get( ATTR_CTL_FONT_POSTURE ); + eCtlItalic = pPostureItem->GetValue(); + + lcl_populate(aUnderlineItem, ATTR_FONT_UNDERLINE, rSrcSet, pCondSet); + lcl_populate(aOverlineItem, ATTR_FONT_OVERLINE, rSrcSet, pCondSet); + + const SvxWordLineModeItem* pWordLineModeItem = pCondSet->GetItemIfSet( ATTR_FONT_WORDLINE ); + if ( !pWordLineModeItem ) + pWordLineModeItem = &rSrcSet.Get( ATTR_FONT_WORDLINE ); + bWordLine = pWordLineModeItem->GetValue(); + + const SvxCrossedOutItem* pCrossedOutItem = pCondSet->GetItemIfSet( ATTR_FONT_CROSSEDOUT ); + if ( !pCrossedOutItem ) + pCrossedOutItem = &rSrcSet.Get( ATTR_FONT_CROSSEDOUT ); + eStrike = pCrossedOutItem->GetValue(); + + const SvxContourItem* pContourItem = pCondSet->GetItemIfSet( ATTR_FONT_CONTOUR ); + if ( !pContourItem ) + pContourItem = &rSrcSet.Get( ATTR_FONT_CONTOUR ); + bOutline = pContourItem->GetValue(); + + const SvxShadowedItem* pShadowedItem = pCondSet->GetItemIfSet( ATTR_FONT_SHADOWED ); + if ( !pShadowedItem ) + pShadowedItem = &rSrcSet.Get( ATTR_FONT_SHADOWED ); + bShadow = pShadowedItem->GetValue(); + + const SvxForbiddenRuleItem* pForbiddenRuleItem = pCondSet->GetItemIfSet( ATTR_FORBIDDEN_RULES ); + if ( !pForbiddenRuleItem ) + pForbiddenRuleItem = &rSrcSet.Get( ATTR_FORBIDDEN_RULES ); + bForbidden = pForbiddenRuleItem->GetValue(); + + const SvxEmphasisMarkItem* pEmphasisMarkItem = pCondSet->GetItemIfSet( ATTR_FONT_EMPHASISMARK ); + if ( !pEmphasisMarkItem ) + pEmphasisMarkItem = &rSrcSet.Get( ATTR_FONT_EMPHASISMARK ); + eEmphasis = pEmphasisMarkItem->GetEmphasisMark(); + const SvxCharReliefItem* pCharReliefItem = pCondSet->GetItemIfSet( ATTR_FONT_RELIEF ); + if ( !pCharReliefItem ) + pCharReliefItem = &rSrcSet.Get( ATTR_FONT_RELIEF ); + eRelief = pCharReliefItem->GetValue(); + + const SvxLanguageItem* pLanguageItem = pCondSet->GetItemIfSet( ATTR_FONT_LANGUAGE ); + if ( !pLanguageItem ) + pLanguageItem = &rSrcSet.Get( ATTR_FONT_LANGUAGE ); + eLang = pLanguageItem->GetLanguage(); + pLanguageItem = pCondSet->GetItemIfSet( ATTR_CJK_FONT_LANGUAGE ); + if ( !pLanguageItem ) + pLanguageItem = &rSrcSet.Get( ATTR_CJK_FONT_LANGUAGE ); + eCjkLang = pLanguageItem->GetLanguage(); + pLanguageItem = pCondSet->GetItemIfSet( ATTR_CTL_FONT_LANGUAGE ); + if ( !pLanguageItem ) + pLanguageItem = &rSrcSet.Get( ATTR_CTL_FONT_LANGUAGE ); + eCtlLang = pLanguageItem->GetLanguage(); + + const ScHyphenateCell* pHyphenateCell = pCondSet->GetItemIfSet( ATTR_HYPHENATE ); + if ( !pHyphenateCell ) + pHyphenateCell = &rSrcSet.Get( ATTR_HYPHENATE ); + bHyphenate = pHyphenateCell->GetValue(); + + const SvxFrameDirectionItem* pFrameDirectionItem = pCondSet->GetItemIfSet( ATTR_WRITINGDIR ); + if ( !pFrameDirectionItem ) + pFrameDirectionItem = &rSrcSet.Get( ATTR_WRITINGDIR ); + eDirection = pFrameDirectionItem->GetValue(); + } + else // Everything directly from Pattern + { + aColorItem.reset(rSrcSet.Get(ATTR_FONT_COLOR).Clone()); + aFontItem.reset(rSrcSet.Get(ATTR_FONT).Clone()); + aCjkFontItem.reset(rSrcSet.Get(ATTR_CJK_FONT).Clone()); + aCtlFontItem.reset(rSrcSet.Get(ATTR_CTL_FONT).Clone()); + nTHeight = rSrcSet.Get( ATTR_FONT_HEIGHT ).GetHeight(); + nCjkTHeight = rSrcSet.Get( ATTR_CJK_FONT_HEIGHT ).GetHeight(); + nCtlTHeight = rSrcSet.Get( ATTR_CTL_FONT_HEIGHT ).GetHeight(); + eWeight = rSrcSet.Get( ATTR_FONT_WEIGHT ).GetValue(); + eCjkWeight = rSrcSet.Get( ATTR_CJK_FONT_WEIGHT ).GetValue(); + eCtlWeight = rSrcSet.Get( ATTR_CTL_FONT_WEIGHT ).GetValue(); + eItalic = rSrcSet.Get( ATTR_FONT_POSTURE ).GetValue(); + eCjkItalic = rSrcSet.Get( ATTR_CJK_FONT_POSTURE ).GetValue(); + eCtlItalic = rSrcSet.Get( ATTR_CTL_FONT_POSTURE ).GetValue(); + aUnderlineItem.reset(rSrcSet.Get(ATTR_FONT_UNDERLINE).Clone()); + aOverlineItem.reset(rSrcSet.Get(ATTR_FONT_OVERLINE).Clone()); + bWordLine = rSrcSet.Get( ATTR_FONT_WORDLINE ).GetValue(); + eStrike = rSrcSet.Get( ATTR_FONT_CROSSEDOUT ).GetValue(); + bOutline = rSrcSet.Get( ATTR_FONT_CONTOUR ).GetValue(); + bShadow = rSrcSet.Get( ATTR_FONT_SHADOWED ).GetValue(); + bForbidden = rSrcSet.Get( ATTR_FORBIDDEN_RULES ).GetValue(); + eEmphasis = rSrcSet.Get( ATTR_FONT_EMPHASISMARK ).GetEmphasisMark(); + eRelief = rSrcSet.Get( ATTR_FONT_RELIEF ).GetValue(); + eLang = rSrcSet.Get( ATTR_FONT_LANGUAGE ).GetLanguage(); + eCjkLang = rSrcSet.Get( ATTR_CJK_FONT_LANGUAGE ).GetLanguage(); + eCtlLang = rSrcSet.Get( ATTR_CTL_FONT_LANGUAGE ).GetLanguage(); + bHyphenate = rSrcSet.Get( ATTR_HYPHENATE ).GetValue(); + eDirection = rSrcSet.Get( ATTR_WRITINGDIR ).GetValue(); + } + + // Expect to be compatible to LogicToLogic, ie. 2540/1440 = 127/72, and round + + tools::Long nHeight = convertTwipToMm100(nTHeight); + tools::Long nCjkHeight = convertTwipToMm100(nCjkTHeight); + tools::Long nCtlHeight = convertTwipToMm100(nCtlTHeight); + + // put items into EditEngine ItemSet + + if ( aColorItem->GetValue() == COL_AUTO ) + { + // When cell attributes are converted to EditEngine paragraph attributes, + // don't create a hard item for automatic color, because that would be converted + // to black when the item's Store method is used in CreateTransferable/WriteBin. + // COL_AUTO is the EditEngine's pool default, so ClearItem will result in automatic + // color, too, without having to store the item. + rEditSet.ClearItem( EE_CHAR_COLOR ); + } + else + { + // tdf#125054 adapt WhichID + rEditSet.Put( std::move(aColorItem), EE_CHAR_COLOR ); + } + + // tdf#125054 adapt WhichID + rEditSet.Put( std::move(aFontItem), EE_CHAR_FONTINFO ); + rEditSet.Put( std::move(aCjkFontItem), EE_CHAR_FONTINFO_CJK ); + rEditSet.Put( std::move(aCtlFontItem), EE_CHAR_FONTINFO_CTL ); + + rEditSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) ); + rEditSet.Put( SvxFontHeightItem( nCjkHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + rEditSet.Put( SvxFontHeightItem( nCtlHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + rEditSet.Put( SvxWeightItem ( eWeight, EE_CHAR_WEIGHT ) ); + rEditSet.Put( SvxWeightItem ( eCjkWeight, EE_CHAR_WEIGHT_CJK ) ); + rEditSet.Put( SvxWeightItem ( eCtlWeight, EE_CHAR_WEIGHT_CTL ) ); + + // tdf#125054 adapt WhichID + rEditSet.Put( std::move(aUnderlineItem), EE_CHAR_UNDERLINE ); + rEditSet.Put( std::move(aOverlineItem), EE_CHAR_OVERLINE ); + + rEditSet.Put( SvxWordLineModeItem( bWordLine, EE_CHAR_WLM ) ); + rEditSet.Put( SvxCrossedOutItem( eStrike, EE_CHAR_STRIKEOUT ) ); + rEditSet.Put( SvxPostureItem ( eItalic, EE_CHAR_ITALIC ) ); + rEditSet.Put( SvxPostureItem ( eCjkItalic, EE_CHAR_ITALIC_CJK ) ); + rEditSet.Put( SvxPostureItem ( eCtlItalic, EE_CHAR_ITALIC_CTL ) ); + rEditSet.Put( SvxContourItem ( bOutline, EE_CHAR_OUTLINE ) ); + rEditSet.Put( SvxShadowedItem ( bShadow, EE_CHAR_SHADOW ) ); + rEditSet.Put( SvxForbiddenRuleItem(bForbidden, EE_PARA_FORBIDDENRULES) ); + rEditSet.Put( SvxEmphasisMarkItem( eEmphasis, EE_CHAR_EMPHASISMARK ) ); + rEditSet.Put( SvxCharReliefItem( eRelief, EE_CHAR_RELIEF ) ); + rEditSet.Put( SvxLanguageItem ( eLang, EE_CHAR_LANGUAGE ) ); + rEditSet.Put( SvxLanguageItem ( eCjkLang, EE_CHAR_LANGUAGE_CJK ) ); + rEditSet.Put( SvxLanguageItem ( eCtlLang, EE_CHAR_LANGUAGE_CTL ) ); + rEditSet.Put( SfxBoolItem ( EE_PARA_HYPHENATE, bHyphenate ) ); + rEditSet.Put( SvxFrameDirectionItem( eDirection, EE_PARA_WRITINGDIR ) ); + + // Script spacing is always off. + // The cell attribute isn't used here as long as there is no UI to set it + // (don't evaluate attributes that can't be changed). + // If a locale-dependent default is needed, it has to go into the cell + // style, like the fonts. + rEditSet.Put( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) ); +} + +void ScPatternAttr::FillEditItemSet( SfxItemSet* pEditSet, const SfxItemSet* pCondSet ) const +{ + if( pEditSet ) + FillToEditItemSet( *pEditSet, GetItemSet(), pCondSet ); +} + +void ScPatternAttr::GetFromEditItemSet( SfxItemSet& rDestSet, const SfxItemSet& rEditSet ) +{ + if (const SvxColorItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_COLOR)) + rDestSet.Put( *pItem, ATTR_FONT_COLOR ); + + if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO)) + rDestSet.Put( *pItem, ATTR_FONT ); + if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO_CJK)) + rDestSet.Put( *pItem, ATTR_CJK_FONT ); + if (const SvxFontItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTINFO_CTL)) + rDestSet.Put( *pItem, ATTR_CTL_FONT ); + + if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT)) + rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100), + 100, ATTR_FONT_HEIGHT ) ); + if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT_CJK)) + rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100), + 100, ATTR_CJK_FONT_HEIGHT ) ); + if (const SvxFontHeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_FONTHEIGHT_CTL)) + rDestSet.Put( SvxFontHeightItem(o3tl::toTwips(pItem->GetHeight(), o3tl::Length::mm100), + 100, ATTR_CTL_FONT_HEIGHT ) ); + + if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT)) + rDestSet.Put( SvxWeightItem( pItem->GetValue(), + ATTR_FONT_WEIGHT) ); + if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT_CJK)) + rDestSet.Put( SvxWeightItem( pItem->GetValue(), + ATTR_CJK_FONT_WEIGHT) ); + if (const SvxWeightItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WEIGHT_CTL)) + rDestSet.Put( SvxWeightItem( pItem->GetValue(), + ATTR_CTL_FONT_WEIGHT) ); + + // SvxTextLineItem contains enum and color + if (const SvxUnderlineItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_UNDERLINE)) + rDestSet.Put( *pItem, ATTR_FONT_UNDERLINE ); + if (const SvxOverlineItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_OVERLINE)) + rDestSet.Put( *pItem, ATTR_FONT_OVERLINE ); + if (const SvxWordLineModeItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_WLM)) + rDestSet.Put( SvxWordLineModeItem( pItem->GetValue(), + ATTR_FONT_WORDLINE) ); + + if (const SvxCrossedOutItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_STRIKEOUT)) + rDestSet.Put( SvxCrossedOutItem( pItem->GetValue(), + ATTR_FONT_CROSSEDOUT) ); + + if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC)) + rDestSet.Put( SvxPostureItem( pItem->GetValue(), + ATTR_FONT_POSTURE) ); + if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC_CJK)) + rDestSet.Put( SvxPostureItem( pItem->GetValue(), + ATTR_CJK_FONT_POSTURE) ); + if (const SvxPostureItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_ITALIC_CTL)) + rDestSet.Put( SvxPostureItem( pItem->GetValue(), + ATTR_CTL_FONT_POSTURE) ); + + if (const SvxContourItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_OUTLINE)) + rDestSet.Put( SvxContourItem( pItem->GetValue(), + ATTR_FONT_CONTOUR) ); + if (const SvxShadowedItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_SHADOW)) + rDestSet.Put( SvxShadowedItem( pItem->GetValue(), + ATTR_FONT_SHADOWED) ); + if (const SvxEmphasisMarkItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_EMPHASISMARK)) + rDestSet.Put( SvxEmphasisMarkItem( pItem->GetEmphasisMark(), + ATTR_FONT_EMPHASISMARK) ); + if (const SvxCharReliefItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_RELIEF)) + rDestSet.Put( SvxCharReliefItem( pItem->GetValue(), + ATTR_FONT_RELIEF) ); + + if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE)) + rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_FONT_LANGUAGE) ); + if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE_CJK)) + rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_CJK_FONT_LANGUAGE) ); + if (const SvxLanguageItem* pItem = rEditSet.GetItemIfSet(EE_CHAR_LANGUAGE_CTL)) + rDestSet.Put( SvxLanguageItem(pItem->GetValue(), ATTR_CTL_FONT_LANGUAGE) ); + + const SvxAdjustItem* pAdjustItem = rEditSet.GetItemIfSet(EE_PARA_JUST); + + if (!pAdjustItem) + return; + + SvxCellHorJustify eVal; + switch ( pAdjustItem->GetAdjust() ) + { + case SvxAdjust::Left: + // EditEngine Default is always set in the GetAttribs() ItemSet ! + // whether left or right, is decided in text / number + eVal = SvxCellHorJustify::Standard; + break; + case SvxAdjust::Right: + eVal = SvxCellHorJustify::Right; + break; + case SvxAdjust::Block: + eVal = SvxCellHorJustify::Block; + break; + case SvxAdjust::Center: + eVal = SvxCellHorJustify::Center; + break; + case SvxAdjust::BlockLine: + eVal = SvxCellHorJustify::Block; + break; + case SvxAdjust::End: + eVal = SvxCellHorJustify::Right; + break; + default: + eVal = SvxCellHorJustify::Standard; + } + if ( eVal != SvxCellHorJustify::Standard ) + rDestSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY) ); +} + +void ScPatternAttr::GetFromEditItemSet( const SfxItemSet* pEditSet ) +{ + if( !pEditSet ) + return; + GetFromEditItemSet( GetItemSet(), *pEditSet ); + mxHashCode.reset(); +} + +void ScPatternAttr::FillEditParaItems( SfxItemSet* pEditSet ) const +{ + // already there in GetFromEditItemSet, but not in FillEditItemSet + // Default horizontal alignment is always implemented as left + + const SfxItemSet& rMySet = GetItemSet(); + + SvxCellHorJustify eHorJust = rMySet.Get(ATTR_HOR_JUSTIFY).GetValue(); + + SvxAdjust eSvxAdjust; + switch (eHorJust) + { + case SvxCellHorJustify::Right: eSvxAdjust = SvxAdjust::Right; break; + case SvxCellHorJustify::Center: eSvxAdjust = SvxAdjust::Center; break; + case SvxCellHorJustify::Block: eSvxAdjust = SvxAdjust::Block; break; + default: eSvxAdjust = SvxAdjust::Left; break; + } + pEditSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); +} + +void ScPatternAttr::DeleteUnchanged( const ScPatternAttr* pOldAttrs ) +{ + SfxItemSet& rThisSet = GetItemSet(); + const SfxItemSet& rOldSet = pOldAttrs->GetItemSet(); + + const SfxPoolItem* pThisItem; + const SfxPoolItem* pOldItem; + + for ( sal_uInt16 nSubWhich=ATTR_PATTERN_START; nSubWhich<=ATTR_PATTERN_END; nSubWhich++ ) + { + // only items that are set are interesting + if ( rThisSet.GetItemState( nSubWhich, false, &pThisItem ) == SfxItemState::SET ) + { + SfxItemState eOldState = rOldSet.GetItemState( nSubWhich, true, &pOldItem ); + if ( eOldState == SfxItemState::SET ) + { + // item is set in OldAttrs (or its parent) -> compare pointers + if ( pThisItem == pOldItem ) + { + rThisSet.ClearItem( nSubWhich ); + mxHashCode.reset(); + } + } + else if ( eOldState != SfxItemState::DONTCARE ) + { + // not set in OldAttrs -> compare item value to default item + if ( *pThisItem == rThisSet.GetPool()->GetDefaultItem( nSubWhich ) ) + { + rThisSet.ClearItem( nSubWhich ); + mxHashCode.reset(); + } + } + } + } +} + +bool ScPatternAttr::HasItemsSet( const sal_uInt16* pWhich ) const +{ + const SfxItemSet& rSet = GetItemSet(); + for (sal_uInt16 i=0; pWhich[i]; i++) + if ( rSet.GetItemState( pWhich[i], false ) == SfxItemState::SET ) + return true; + return false; +} + +void ScPatternAttr::ClearItems( const sal_uInt16* pWhich ) +{ + SfxItemSet& rSet = GetItemSet(); + for (sal_uInt16 i=0; pWhich[i]; i++) + rSet.ClearItem(pWhich[i]); + mxHashCode.reset(); +} + +static SfxStyleSheetBase* lcl_CopyStyleToPool + ( + SfxStyleSheetBase* pSrcStyle, + SfxStyleSheetBasePool* pSrcPool, + SfxStyleSheetBasePool* pDestPool, + const SvNumberFormatterIndexTable* pFormatExchangeList + ) +{ + if ( !pSrcStyle || !pDestPool || !pSrcPool ) + { + OSL_FAIL( "CopyStyleToPool: Invalid Arguments :-/" ); + return nullptr; + } + + const OUString aStrSrcStyle = pSrcStyle->GetName(); + const SfxStyleFamily eFamily = pSrcStyle->GetFamily(); + SfxStyleSheetBase* pDestStyle = pDestPool->Find( aStrSrcStyle, eFamily ); + + if ( !pDestStyle ) + { + const OUString aStrParent = pSrcStyle->GetParent(); + const SfxItemSet& rSrcSet = pSrcStyle->GetItemSet(); + + pDestStyle = &pDestPool->Make( aStrSrcStyle, eFamily, SfxStyleSearchBits::UserDefined ); + SfxItemSet& rDestSet = pDestStyle->GetItemSet(); + rDestSet.Put( rSrcSet ); + + // number format exchange list has to be handled here, too + // (only called for cell styles) + + const SfxUInt32Item* pSrcItem; + if ( pFormatExchangeList && + (pSrcItem = rSrcSet.GetItemIfSet( ATTR_VALUE_FORMAT, false )) ) + { + sal_uLong nOldFormat = pSrcItem->GetValue(); + SvNumberFormatterIndexTable::const_iterator it = pFormatExchangeList->find(nOldFormat); + if (it != pFormatExchangeList->end()) + { + sal_uInt32 nNewFormat = it->second; + rDestSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + } + } + + // if necessary create derivative Styles, if not available: + + if ( ScResId(STR_STYLENAME_STANDARD) != aStrParent && + aStrSrcStyle != aStrParent && + !pDestPool->Find( aStrParent, eFamily ) ) + { + lcl_CopyStyleToPool( pSrcPool->Find( aStrParent, eFamily ), + pSrcPool, pDestPool, pFormatExchangeList ); + } + + pDestStyle->SetParent( aStrParent ); + } + + return pDestStyle; +} + +ScPatternAttr* ScPatternAttr::PutInPool( ScDocument* pDestDoc, ScDocument* pSrcDoc ) const +{ + const SfxItemSet* pSrcSet = &GetItemSet(); + + ScPatternAttr aDestPattern( pDestDoc->GetPool() ); + SfxItemSet* pDestSet = &aDestPattern.GetItemSet(); + + // Copy cell pattern style to other document: + + if ( pDestDoc != pSrcDoc ) + { + OSL_ENSURE( pStyle, "Missing Pattern-Style! :-/" ); + + // if pattern in DestDoc is available, use this, otherwise copy + // parent style to style or create if necessary and attach DestDoc + + SfxStyleSheetBase* pStyleCpy = lcl_CopyStyleToPool( pStyle, + pSrcDoc->GetStyleSheetPool(), + pDestDoc->GetStyleSheetPool(), + pDestDoc->GetFormatExchangeList() ); + + aDestPattern.SetStyleSheet( static_cast<ScStyleSheet*>(pStyleCpy) ); + } + + for ( sal_uInt16 nAttrId = ATTR_PATTERN_START; nAttrId <= ATTR_PATTERN_END; nAttrId++ ) + { + const SfxPoolItem* pSrcItem; + SfxItemState eItemState = pSrcSet->GetItemState( nAttrId, false, &pSrcItem ); + if (eItemState==SfxItemState::SET) + { + std::unique_ptr<SfxPoolItem> pNewItem; + + if ( nAttrId == ATTR_VALIDDATA ) + { + // Copy validity to the new document + + sal_uLong nNewIndex = 0; + ScValidationDataList* pSrcList = pSrcDoc->GetValidationList(); + if ( pSrcList ) + { + sal_uLong nOldIndex = static_cast<const SfxUInt32Item*>(pSrcItem)->GetValue(); + const ScValidationData* pOldData = pSrcList->GetData( nOldIndex ); + if ( pOldData ) + nNewIndex = pDestDoc->AddValidationEntry( *pOldData ); + } + pNewItem.reset(new SfxUInt32Item( ATTR_VALIDDATA, nNewIndex )); + } + else if ( nAttrId == ATTR_VALUE_FORMAT && pDestDoc->GetFormatExchangeList() ) + { + // Number format to Exchange List + + sal_uLong nOldFormat = static_cast<const SfxUInt32Item*>(pSrcItem)->GetValue(); + SvNumberFormatterIndexTable::const_iterator it = pDestDoc->GetFormatExchangeList()->find(nOldFormat); + if (it != pDestDoc->GetFormatExchangeList()->end()) + { + sal_uInt32 nNewFormat = it->second; + pNewItem.reset(new SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat )); + } + } + + if ( pNewItem ) + { + pDestSet->Put(std::move(pNewItem)); + } + else + pDestSet->Put(*pSrcItem); + } + } + + ScPatternAttr* pPatternAttr = const_cast<ScPatternAttr*>( &pDestDoc->GetPool()->Put(aDestPattern) ); + return pPatternAttr; +} + +bool ScPatternAttr::IsVisible() const +{ + const SfxItemSet& rSet = GetItemSet(); + + if ( const SvxBrushItem* pItem = rSet.GetItemIfSet( ATTR_BACKGROUND ) ) + if ( pItem->GetColor() != COL_TRANSPARENT ) + return true; + + if ( const SvxBoxItem* pBoxItem = rSet.GetItemIfSet( ATTR_BORDER ) ) + { + if ( pBoxItem->GetTop() || pBoxItem->GetBottom() || + pBoxItem->GetLeft() || pBoxItem->GetRight() ) + return true; + } + + if ( const SvxLineItem* pItem = rSet.GetItemIfSet( ATTR_BORDER_TLBR ) ) + if( pItem->GetLine() ) + return true; + + if ( const SvxLineItem* pItem = rSet.GetItemIfSet( ATTR_BORDER_BLTR ) ) + if( pItem->GetLine() ) + return true; + + if ( const SvxShadowItem* pItem = rSet.GetItemIfSet( ATTR_SHADOW ) ) + if ( pItem->GetLocation() != SvxShadowLocation::NONE ) + return true; + + return false; +} + +static bool OneEqual( const SfxItemSet& rSet1, const SfxItemSet& rSet2, sal_uInt16 nId ) +{ + const SfxPoolItem* pItem1 = &rSet1.Get(nId); + const SfxPoolItem* pItem2 = &rSet2.Get(nId); + return ( pItem1 == pItem2 || *pItem1 == *pItem2 ); +} + +bool ScPatternAttr::IsVisibleEqual( const ScPatternAttr& rOther ) const +{ + const SfxItemSet& rThisSet = GetItemSet(); + const SfxItemSet& rOtherSet = rOther.GetItemSet(); + + return OneEqual( rThisSet, rOtherSet, ATTR_BACKGROUND ) && + OneEqual( rThisSet, rOtherSet, ATTR_BORDER ) && + OneEqual( rThisSet, rOtherSet, ATTR_BORDER_TLBR ) && + OneEqual( rThisSet, rOtherSet, ATTR_BORDER_BLTR ) && + OneEqual( rThisSet, rOtherSet, ATTR_SHADOW ); + + //TODO: also here only check really visible values !!! +} + +const OUString* ScPatternAttr::GetStyleName() const +{ + return pName ? &*pName : ( pStyle ? &pStyle->GetName() : nullptr ); +} + +void ScPatternAttr::SetStyleSheet( ScStyleSheet* pNewStyle, bool bClearDirectFormat ) +{ + if (pNewStyle) + { + SfxItemSet& rPatternSet = GetItemSet(); + const SfxItemSet& rStyleSet = pNewStyle->GetItemSet(); + + if (bClearDirectFormat) + { + for (sal_uInt16 i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END; i++) + { + if (rStyleSet.GetItemState(i) == SfxItemState::SET) + rPatternSet.ClearItem(i); + } + } + rPatternSet.SetParent(&pNewStyle->GetItemSet()); + pStyle = pNewStyle; + pName.reset(); + } + else + { + OSL_FAIL( "ScPatternAttr::SetStyleSheet( NULL ) :-|" ); + GetItemSet().SetParent(nullptr); + pStyle = nullptr; + } + mxHashCode.reset(); +} + +void ScPatternAttr::UpdateStyleSheet(const ScDocument& rDoc) +{ + if (pName) + { + pStyle = static_cast<ScStyleSheet*>(rDoc.GetStyleSheetPool()->Find(*pName, SfxStyleFamily::Para)); + + // use Standard if Style is not found, + // to avoid empty display in Toolbox-Controller + // Assumes that "Standard" is always the 1st entry! + if (!pStyle) + { + std::unique_ptr<SfxStyleSheetIterator> pIter = rDoc.GetStyleSheetPool()->CreateIterator(SfxStyleFamily::Para); + pStyle = dynamic_cast< ScStyleSheet* >(pIter->First()); + } + + if (pStyle) + { + GetItemSet().SetParent(&pStyle->GetItemSet()); + pName.reset(); + } + } + else + pStyle = nullptr; + mxHashCode.reset(); +} + +void ScPatternAttr::StyleToName() +{ + // Style was deleted, remember name: + + if ( pStyle ) + { + pName = pStyle->GetName(); + pStyle = nullptr; + GetItemSet().SetParent( nullptr ); + mxHashCode.reset(); + } +} + +bool ScPatternAttr::IsSymbolFont() const +{ + if( const SvxFontItem* pItem = GetItemSet().GetItemIfSet( ATTR_FONT ) ) + return pItem->GetCharSet() == RTL_TEXTENCODING_SYMBOL; + else + return false; +} + +namespace { + +sal_uInt32 getNumberFormatKey(const SfxItemSet& rSet) +{ + return rSet.Get(ATTR_VALUE_FORMAT).GetValue(); +} + +LanguageType getLanguageType(const SfxItemSet& rSet) +{ + return rSet.Get(ATTR_LANGUAGE_FORMAT).GetLanguage(); +} + +} + +sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter ) const +{ + sal_uInt32 nFormat = getNumberFormatKey(GetItemSet()); + LanguageType eLang = getLanguageType(GetItemSet()); + if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM ) + ; // it remains as it is + else if ( pFormatter ) + nFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nFormat, eLang ); + return nFormat; +} + +// the same if conditional formatting is in play: + +sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter, + const SfxItemSet* pCondSet ) const +{ + assert(pFormatter); + if (!pCondSet) + return GetNumberFormat(pFormatter); + + // Conditional format takes precedence over style and even hard format. + + sal_uInt32 nFormat; + LanguageType eLang; + if (pCondSet->GetItemState(ATTR_VALUE_FORMAT) == SfxItemState::SET ) + { + nFormat = getNumberFormatKey(*pCondSet); + if (pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT) == SfxItemState::SET) + eLang = getLanguageType(*pCondSet); + else + eLang = getLanguageType(GetItemSet()); + } + else + { + nFormat = getNumberFormatKey(GetItemSet()); + eLang = getLanguageType(GetItemSet()); + } + + return pFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLang); +} + +const SfxPoolItem& ScPatternAttr::GetItem( sal_uInt16 nWhich, const SfxItemSet& rItemSet, const SfxItemSet* pCondSet ) +{ + const SfxPoolItem* pCondItem; + if ( pCondSet && pCondSet->GetItemState( nWhich, true, &pCondItem ) == SfxItemState::SET ) + return *pCondItem; + return rItemSet.Get(nWhich); +} + +const SfxPoolItem& ScPatternAttr::GetItem( sal_uInt16 nSubWhich, const SfxItemSet* pCondSet ) const +{ + return GetItem( nSubWhich, GetItemSet(), pCondSet ); +} + +// GetRotateVal is tested before ATTR_ORIENTATION + +Degree100 ScPatternAttr::GetRotateVal( const SfxItemSet* pCondSet ) const +{ + Degree100 nAttrRotate(0); + if ( GetCellOrientation() == SvxCellOrientation::Standard ) + { + bool bRepeat = ( GetItem(ATTR_HOR_JUSTIFY, pCondSet). + GetValue() == SvxCellHorJustify::Repeat ); + // ignore orientation/rotation if "repeat" is active + if ( !bRepeat ) + nAttrRotate = GetItem( ATTR_ROTATE_VALUE, pCondSet ).GetValue(); + } + return nAttrRotate; +} + +ScRotateDir ScPatternAttr::GetRotateDir( const SfxItemSet* pCondSet ) const +{ + ScRotateDir nRet = ScRotateDir::NONE; + + Degree100 nAttrRotate = GetRotateVal( pCondSet ); + if ( nAttrRotate ) + { + SvxRotateMode eRotMode = GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue(); + + if ( eRotMode == SVX_ROTATE_MODE_STANDARD || nAttrRotate == 18000_deg100 ) + nRet = ScRotateDir::Standard; + else if ( eRotMode == SVX_ROTATE_MODE_CENTER ) + nRet = ScRotateDir::Center; + else if ( eRotMode == SVX_ROTATE_MODE_TOP || eRotMode == SVX_ROTATE_MODE_BOTTOM ) + { + Degree100 nRot180 = nAttrRotate % 18000_deg100; // 1/100 degrees + if ( nRot180 == 9000_deg100 ) + nRet = ScRotateDir::Center; + else if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nRot180 < 9000_deg100 ) || + ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nRot180 > 9000_deg100 ) ) + nRet = ScRotateDir::Left; + else + nRet = ScRotateDir::Right; + } + } + + return nRet; +} + +void ScPatternAttr::SetKey(sal_uInt64 nKey) +{ + mnKey = nKey; +} + +sal_uInt64 ScPatternAttr::GetKey() const +{ + return mnKey; +} + +void ScPatternAttr::CalcHashCode() const +{ + auto const & rSet = GetItemSet(); + if( rSet.TotalCount() != compareSize ) // see EqualPatternSets() + { + mxHashCode = 0; // invalid + return; + } + mxHashCode = 1; // Set up seed so that an empty pattern does not have an (invalid) hash of 0. + boost::hash_range(*mxHashCode, rSet.GetItems_Impl(), rSet.GetItems_Impl() + compareSize); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |