| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| #include "xestyle.hxx" |
| |
| #include <algorithm> |
| #include <iterator> |
| #include <set> |
| #include <com/sun/star/i18n/ScriptType.hpp> |
| #include <vcl/font.hxx> |
| #include <svl/zformat.hxx> |
| #include <svl/languageoptions.hxx> |
| #include <sfx2/printer.hxx> |
| #include "scitems.hxx" |
| #include <svx/algitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/bolnitem.hxx> |
| #include <svx/rotmodit.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <editeng/frmdiritem.hxx> |
| #include <editeng/eeitem.hxx> |
| #include <editeng/escpitem.hxx> |
| #include "document.hxx" |
| #include "stlpool.hxx" |
| #include "stlsheet.hxx" |
| #include "patattr.hxx" |
| #include "attrib.hxx" |
| #include "globstr.hrc" |
| #include "xestring.hxx" |
| |
| using namespace ::oox; |
| |
| using ::rtl::OString; |
| using ::rtl::OUString; |
| |
| // PALETTE record - color information ========================================= |
| |
| namespace { |
| |
| sal_uInt32 lclGetWeighting( XclExpColorType eType ) |
| { |
| switch( eType ) |
| { |
| case EXC_COLOR_CHARTLINE: return 1; |
| case EXC_COLOR_CELLBORDER: |
| case EXC_COLOR_CHARTAREA: return 2; |
| case EXC_COLOR_CELLTEXT: |
| case EXC_COLOR_CHARTTEXT: |
| case EXC_COLOR_CTRLTEXT: return 10; |
| case EXC_COLOR_TABBG: |
| case EXC_COLOR_CELLAREA: return 20; |
| case EXC_COLOR_GRID: return 50; |
| default: DBG_ERRORFILE( "lclGetWeighting - unknown color type" ); |
| } |
| return 1; |
| } |
| |
| sal_Int32 lclGetColorDistance( const Color& rColor1, const Color& rColor2 ) |
| { |
| sal_Int32 nDist = rColor1.GetRed() - rColor2.GetRed(); |
| nDist *= nDist * 77; |
| sal_Int32 nDummy = rColor1.GetGreen() - rColor2.GetGreen(); |
| nDist += nDummy * nDummy * 151; |
| nDummy = rColor1.GetBlue() - rColor2.GetBlue(); |
| nDist += nDummy * nDummy * 28; |
| return nDist; |
| } |
| |
| sal_uInt8 lclGetMergedColorComp( sal_uInt8 nComp1, sal_uInt32 nWeight1, sal_uInt8 nComp2, sal_uInt32 nWeight2 ) |
| { |
| sal_uInt8 nComp1Dist = ::std::min< sal_uInt8 >( nComp1, 0xFF - nComp1 ); |
| sal_uInt8 nComp2Dist = ::std::min< sal_uInt8 >( nComp2, 0xFF - nComp2 ); |
| if( nComp1Dist != nComp2Dist ) |
| { |
| /* #i36945# One of the passed RGB components is nearer at the limits (0x00 or 0xFF). |
| Increase its weighting to prevent fading of the colors during reduction. */ |
| const sal_uInt8& rnCompNearer = (nComp1Dist < nComp2Dist) ? nComp1 : nComp2; |
| sal_uInt32& rnWeight = (nComp1Dist < nComp2Dist) ? nWeight1 : nWeight2; |
| rnWeight *= ((rnCompNearer - 0x80L) * (rnCompNearer - 0x7FL) / 0x1000L + 1); |
| } |
| sal_uInt32 nWSum = nWeight1 + nWeight2; |
| return static_cast< sal_uInt8 >( (nComp1 * nWeight1 + nComp2 * nWeight2 + nWSum / 2) / nWSum ); |
| } |
| |
| void lclSetMixedColor( Color& rDest, const Color& rSrc1, const Color& rSrc2 ) |
| { |
| rDest.SetRed( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetRed() ) + rSrc2.GetRed()) / 2 ) ); |
| rDest.SetGreen( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetGreen() ) + rSrc2.GetGreen()) / 2 ) ); |
| rDest.SetBlue( static_cast< sal_uInt8 >( (static_cast< sal_uInt16 >( rSrc1.GetBlue() ) + rSrc2.GetBlue()) / 2 ) ); |
| } |
| |
| } // namespace |
| |
| // additional classes for color reduction ------------------------------------- |
| |
| namespace { |
| |
| /** Represents an entry in a color list. |
| |
| The color stores a weighting value, which increases the more the color is |
| used in the document. Heavy-weighted colors will change less than others on |
| color reduction. |
| */ |
| class XclListColor |
| { |
| DECL_FIXEDMEMPOOL_NEWDEL( XclListColor ) |
| |
| private: |
| Color maColor; /// The color value of this palette entry. |
| sal_uInt32 mnColorId; /// Unique color ID for color reduction. |
| sal_uInt32 mnWeight; /// Weighting for color reduction. |
| bool mbBaseColor; /// true = Handle as base color, (don't remove/merge). |
| |
| public: |
| explicit XclListColor( const Color& rColor, sal_uInt32 nColorId ); |
| |
| /** Returns the RGB color value of the color. */ |
| inline const Color& GetColor() const { return maColor; } |
| /** Returns the unique ID of the color. */ |
| inline sal_uInt32 GetColorId() const { return mnColorId; } |
| /** Returns the current weighting of the color. */ |
| inline sal_uInt32 GetWeighting() const { return mnWeight; } |
| /** Returns true, if this color is a base color, i.e. it will not be removed or merged. */ |
| inline bool IsBaseColor() const { return mbBaseColor; } |
| |
| /** Adds the passed weighting to this color. */ |
| inline void AddWeighting( sal_uInt32 nWeight ) { mnWeight += nWeight; } |
| /** Merges this color with rColor, regarding weighting settings. */ |
| void Merge( const XclListColor& rColor ); |
| }; |
| |
| IMPL_FIXEDMEMPOOL_NEWDEL( XclListColor, 100, 100 ) |
| |
| XclListColor::XclListColor( const Color& rColor, sal_uInt32 nColorId ) : |
| maColor( rColor ), |
| mnColorId( nColorId ), |
| mnWeight( 0 ) |
| { |
| mbBaseColor = |
| ((rColor.GetRed() == 0x00) || (rColor.GetRed() == 0xFF)) && |
| ((rColor.GetGreen() == 0x00) || (rColor.GetGreen() == 0xFF)) && |
| ((rColor.GetBlue() == 0x00) || (rColor.GetBlue() == 0xFF)); |
| } |
| |
| void XclListColor::Merge( const XclListColor& rColor ) |
| { |
| sal_uInt32 nWeight2 = rColor.GetWeighting(); |
| // do not change RGB value of base colors |
| if( !mbBaseColor ) |
| { |
| maColor.SetRed( lclGetMergedColorComp( maColor.GetRed(), mnWeight, rColor.maColor.GetRed(), nWeight2 ) ); |
| maColor.SetGreen( lclGetMergedColorComp( maColor.GetGreen(), mnWeight, rColor.maColor.GetGreen(), nWeight2 ) ); |
| maColor.SetBlue( lclGetMergedColorComp( maColor.GetBlue(), mnWeight, rColor.maColor.GetBlue(), nWeight2 ) ); |
| } |
| AddWeighting( nWeight2 ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| /** Data for each inserted original color, represented by a color ID. */ |
| struct XclColorIdData |
| { |
| Color maColor; /// The original inserted color. |
| sal_uInt32 mnIndex; /// Maps current color ID to color list or export color vector. |
| /** Sets the contents of this struct. */ |
| inline void Set( const Color& rColor, sal_uInt32 nIndex ) { maColor = rColor; mnIndex = nIndex; } |
| }; |
| |
| /** A color that will be written to the Excel file. */ |
| struct XclPaletteColor |
| { |
| Color maColor; /// Resulting color to export. |
| bool mbUsed; /// true = Entry is used in the document. |
| |
| inline explicit XclPaletteColor( const Color& rColor ) : maColor( rColor ), mbUsed( false ) {} |
| inline void SetColor( const Color& rColor ) { maColor = rColor; mbUsed = true; } |
| }; |
| |
| /** Maps a color list index to a palette index. |
| @descr Used to remap the color ID data vector from list indexes to palette indexes. */ |
| struct XclRemap |
| { |
| sal_uInt32 mnPalIndex; /// Index to palette. |
| bool mbProcessed; /// true = List color already processed. |
| |
| inline explicit XclRemap() : mnPalIndex( 0 ), mbProcessed( false ) {} |
| inline void SetIndex( sal_uInt32 nPalIndex ) |
| { mnPalIndex = nPalIndex; mbProcessed = true; } |
| }; |
| |
| /** Stores the nearest palette color index of a list color. */ |
| struct XclNearest |
| { |
| sal_uInt32 mnPalIndex; /// Index to nearest palette color. |
| sal_Int32 mnDist; /// Distance to palette color. |
| |
| inline explicit XclNearest() : mnPalIndex( 0 ), mnDist( 0 ) {} |
| }; |
| |
| typedef ::std::vector< XclRemap > XclRemapVec; |
| typedef ::std::vector< XclNearest > XclNearestVec; |
| |
| } // namespace |
| |
| // ---------------------------------------------------------------------------- |
| |
| class XclExpPaletteImpl |
| { |
| public: |
| explicit XclExpPaletteImpl( const XclDefaultPalette& rDefPal ); |
| |
| /** Inserts the color into the list and updates weighting. |
| @param nAutoDefault The Excel palette index for automatic color. |
| @return A unique ID for this color. */ |
| sal_uInt32 InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault = 0 ); |
| /** Returns the color ID representing a fixed Excel palette index (i.e. for auto colors). */ |
| static sal_uInt32 GetColorIdFromIndex( sal_uInt16 nIndex ); |
| |
| /** Reduces the color list to the maximum count of the current BIFF version. */ |
| void Finalize(); |
| |
| /** Returns the Excel palette index of the color with passed color ID. */ |
| sal_uInt16 GetColorIndex( sal_uInt32 nColorId ) const; |
| |
| /** Returns a foreground and background color for the two passed color IDs. |
| @descr If rnXclPattern contains a solid pattern, this function tries to find |
| the two best fitting colors and a mix pattern (25%, 50% or 75%) for nForeColorId. |
| This will result in a better approximation to the passed foreground color. */ |
| void GetMixedColors( |
| sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern, |
| sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const; |
| |
| /** Returns the RGB color data for a (non-zero-based) Excel palette entry. |
| @return The color from current or default palette or COL_AUTO, if nothing else found. */ |
| ColorData GetColorData( sal_uInt16 nXclIndex ) const; |
| /** Returns the color for a (non-zero-based) Excel palette entry. |
| @return The color from current or default palette or COL_AUTO, if nothing else found. */ |
| inline Color GetColor( sal_uInt16 nXclIndex ) const |
| { return Color( GetColorData( nXclIndex ) ); } |
| |
| /** Returns true, if all colors of the palette are equal to default palette colors. */ |
| bool IsDefaultPalette() const; |
| /** Writes the color list (contents of the palette record) to the passed stream. */ |
| void WriteBody( XclExpStream& rStrm ); |
| void SaveXml( XclExpXmlStream& rStrm ); |
| |
| private: |
| /** Returns the Excel index of a 0-based color index. */ |
| inline sal_uInt16 GetXclIndex( sal_uInt32 nIndex ) const |
| { return static_cast< sal_uInt16 >( nIndex + EXC_COLOR_USEROFFSET ); } |
| |
| /** Returns the original inserted color represented by the color ID nColorId. */ |
| const Color& GetOriginalColor( sal_uInt32 nColorId ) const; |
| |
| /** Searches for rColor, returns the ordered insertion index for rColor in rnIndex. */ |
| XclListColor* SearchListEntry( const Color& rColor, sal_uInt32& rnIndex ); |
| /** Creates and inserts a new color list entry at the specified list position. */ |
| XclListColor* CreateListEntry( const Color& rColor, sal_uInt32 nIndex ); |
| |
| /** Raw and fast reduction of the palette. */ |
| void RawReducePalette( sal_uInt32 nPass ); |
| /** Reduction of one color using advanced color merging based on color weighting. */ |
| void ReduceLeastUsedColor(); |
| |
| /** Finds the least used color and returns its current list index. */ |
| sal_uInt32 GetLeastUsedListColor() const; |
| /** Returns the list index of the color nearest to rColor. |
| @param nIgnore List index of a color which will be ignored. |
| @return The list index of the found color. */ |
| sal_uInt32 GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const; |
| /** Returns the list index of the color nearest to the color with list index nIndex. */ |
| sal_uInt32 GetNearestListColor( sal_uInt32 nIndex ) const; |
| |
| /** Returns in rnIndex the palette index of the color nearest to rColor. |
| @param bDefaultOnly true = Searches for default colors only (colors never replaced). |
| @return The distance from passed color to found color. */ |
| sal_Int32 GetNearestPaletteColor( |
| sal_uInt32& rnIndex, |
| const Color& rColor, bool bDefaultOnly ) const; |
| /** Returns in rnFirst and rnSecond the palette indexes of the two colors nearest to rColor. |
| @return The minimum distance from passed color to found colors. */ |
| sal_Int32 GetNearPaletteColors( |
| sal_uInt32& rnFirst, sal_uInt32& rnSecond, |
| const Color& rColor ) const; |
| |
| private: |
| typedef ScfDelList< XclListColor > XclListColorList; |
| typedef ScfRef< XclListColorList > XclListColorListRef; |
| typedef ::std::vector< XclColorIdData > XclColorIdDataVec; |
| typedef ::std::vector< XclPaletteColor > XclPaletteColorVec; |
| |
| const XclDefaultPalette& mrDefPal; /// The default palette for the current BIFF version. |
| XclListColorListRef mxColorList; /// Working color list. |
| XclColorIdDataVec maColorIdDataVec; /// Data of all CIDs. |
| XclPaletteColorVec maPalette; /// Contains resulting colors to export. |
| sal_uInt32 mnLastIdx; /// Last insertion index for search opt. |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| const sal_uInt32 EXC_PAL_INDEXBASE = 0xFFFF0000; |
| const sal_uInt32 EXC_PAL_MAXRAWSIZE = 1024; |
| |
| XclExpPaletteImpl::XclExpPaletteImpl( const XclDefaultPalette& rDefPal ) : |
| mrDefPal( rDefPal ), |
| mxColorList( new XclListColorList ), |
| mnLastIdx( 0 ) |
| { |
| // initialize maPalette with default colors |
| sal_uInt16 nCount = static_cast< sal_uInt16 >( mrDefPal.GetColorCount() ); |
| maPalette.reserve( nCount ); |
| for( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) |
| maPalette.push_back( XclPaletteColor( mrDefPal.GetDefColor( GetXclIndex( nIdx ) ) ) ); |
| |
| InsertColor( Color( COL_BLACK ), EXC_COLOR_CELLTEXT ); |
| } |
| |
| sal_uInt32 XclExpPaletteImpl::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault ) |
| { |
| if( rColor.GetColor() == COL_AUTO ) |
| return GetColorIdFromIndex( nAutoDefault ); |
| |
| sal_uInt32 nFoundIdx = 0; |
| XclListColor* pEntry = SearchListEntry( rColor, nFoundIdx ); |
| if( !pEntry || (pEntry->GetColor() != rColor) ) |
| pEntry = CreateListEntry( rColor, nFoundIdx ); |
| pEntry->AddWeighting( lclGetWeighting( eType ) ); |
| |
| return pEntry->GetColorId(); |
| } |
| |
| sal_uInt32 XclExpPaletteImpl::GetColorIdFromIndex( sal_uInt16 nIndex ) |
| { |
| return EXC_PAL_INDEXBASE | nIndex; |
| } |
| |
| void XclExpPaletteImpl::Finalize() |
| { |
| // --- build initial color ID data vector (maColorIdDataVec) --- |
| |
| sal_uInt32 nCount = mxColorList->Count(); |
| maColorIdDataVec.resize( nCount ); |
| for( sal_uInt32 nIdx = 0; nIdx < nCount; ++nIdx ) |
| { |
| XclListColor* pListColor = mxColorList->GetObject( nIdx ); |
| maColorIdDataVec[ pListColor->GetColorId() ].Set( pListColor->GetColor(), nIdx ); |
| } |
| |
| // --- loop as long as current color count does not fit into palette of current BIFF --- |
| |
| // phase 1: raw reduction (performance reasons, #i36945#) |
| sal_uInt32 nPass = 0; |
| while( mxColorList->Count() > EXC_PAL_MAXRAWSIZE ) |
| RawReducePalette( nPass++ ); |
| |
| // phase 2: precise reduction using advanced color merging based on color weighting |
| while( mxColorList->Count() > mrDefPal.GetColorCount() ) |
| ReduceLeastUsedColor(); |
| |
| // --- #104865# use default palette and replace colors with nearest used colors --- |
| |
| nCount = mxColorList->Count(); |
| XclRemapVec aRemapVec( nCount ); |
| XclNearestVec aNearestVec( nCount ); |
| |
| // in each run: search the best fitting color and replace a default color with it |
| for( sal_uInt32 nRun = 0; nRun < nCount; ++nRun ) |
| { |
| sal_uInt32 nIndex; |
| // find nearest unused default color for each unprocessed list color |
| for( nIndex = 0; nIndex < nCount; ++nIndex ) |
| aNearestVec[ nIndex ].mnDist = aRemapVec[ nIndex ].mbProcessed ? SAL_MAX_INT32 : |
| GetNearestPaletteColor( aNearestVec[ nIndex ].mnPalIndex, mxColorList->GetObject( nIndex )->GetColor(), true ); |
| // find the list color which is nearest to a default color |
| sal_uInt32 nFound = 0; |
| for( nIndex = 1; nIndex < nCount; ++nIndex ) |
| if( aNearestVec[ nIndex ].mnDist < aNearestVec[ nFound ].mnDist ) |
| nFound = nIndex; |
| // replace default color with list color |
| sal_uInt32 nNearest = aNearestVec[ nFound ].mnPalIndex; |
| DBG_ASSERT( mxColorList->GetObject( nFound ), "XclExpPaletteImpl::Finalize - missing a color" ); |
| DBG_ASSERT( nNearest < maPalette.size(), "XclExpPaletteImpl::Finalize - algorithm error" ); |
| maPalette[ nNearest ].SetColor( mxColorList->GetObject( nFound )->GetColor() ); |
| aRemapVec[ nFound ].SetIndex( nNearest ); |
| } |
| |
| // remap color ID data map (maColorIdDataVec) from list indexes to palette indexes |
| for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt ) |
| aIt->mnIndex = aRemapVec[ aIt->mnIndex ].mnPalIndex; |
| } |
| |
| sal_uInt16 XclExpPaletteImpl::GetColorIndex( sal_uInt32 nColorId ) const |
| { |
| sal_uInt16 nRet = 0; |
| if( nColorId >= EXC_PAL_INDEXBASE ) |
| nRet = static_cast< sal_uInt16 >( nColorId & ~EXC_PAL_INDEXBASE ); |
| else if( nColorId < maColorIdDataVec.size() ) |
| nRet = GetXclIndex( maColorIdDataVec[ nColorId ].mnIndex ); |
| return nRet; |
| } |
| |
| void XclExpPaletteImpl::GetMixedColors( |
| sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern, |
| sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const |
| { |
| rnXclForeIx = GetColorIndex( nForeColorId ); |
| rnXclBackIx = GetColorIndex( nBackColorId ); |
| if( (rnXclPattern != EXC_PATT_SOLID) || (nForeColorId >= maColorIdDataVec.size()) ) |
| return; |
| |
| // now we have solid pattern, and a defined foreground (background doesn't care for solid pattern) |
| |
| sal_uInt32 nIndex1, nIndex2; |
| Color aForeColor( GetOriginalColor( nForeColorId ) ); |
| sal_Int32 nFirstDist = GetNearPaletteColors( nIndex1, nIndex2, aForeColor ); |
| if( (nIndex1 >= maPalette.size()) || (nIndex2 >= maPalette.size()) ) |
| return; |
| |
| Color aColorArr[ 5 ]; |
| aColorArr[ 0 ] = maPalette[ nIndex1 ].maColor; |
| aColorArr[ 4 ] = maPalette[ nIndex2 ].maColor; |
| lclSetMixedColor( aColorArr[ 2 ], aColorArr[ 0 ], aColorArr[ 4 ] ); |
| lclSetMixedColor( aColorArr[ 1 ], aColorArr[ 0 ], aColorArr[ 2 ] ); |
| lclSetMixedColor( aColorArr[ 3 ], aColorArr[ 2 ], aColorArr[ 4 ] ); |
| |
| sal_Int32 nMinDist = nFirstDist; |
| sal_uInt32 nMinIndex = 0; |
| for( sal_uInt32 nCnt = 1; nCnt < 4; ++nCnt ) |
| { |
| sal_Int32 nDist = lclGetColorDistance( aForeColor, aColorArr[ nCnt ] ); |
| if( nDist < nMinDist ) |
| { |
| nMinDist = nDist; |
| nMinIndex = nCnt; |
| } |
| } |
| rnXclForeIx = GetXclIndex( nIndex1 ); |
| rnXclBackIx = GetXclIndex( nIndex2 ); |
| if( nMinDist < nFirstDist ) |
| { |
| switch( nMinIndex ) |
| { |
| case 1: rnXclPattern = EXC_PATT_75_PERC; break; |
| case 2: rnXclPattern = EXC_PATT_50_PERC; break; |
| case 3: rnXclPattern = EXC_PATT_25_PERC; break; |
| } |
| } |
| } |
| |
| ColorData XclExpPaletteImpl::GetColorData( sal_uInt16 nXclIndex ) const |
| { |
| if( nXclIndex >= EXC_COLOR_USEROFFSET ) |
| { |
| sal_uInt32 nIdx = nXclIndex - EXC_COLOR_USEROFFSET; |
| if( nIdx < maPalette.size() ) |
| return maPalette[ nIdx ].maColor.GetColor(); |
| } |
| return mrDefPal.GetDefColorData( nXclIndex ); |
| } |
| |
| bool XclExpPaletteImpl::IsDefaultPalette() const |
| { |
| bool bDefault = true; |
| for( sal_uInt32 nIdx = 0, nSize = static_cast< sal_uInt32 >( maPalette.size() ); bDefault && (nIdx < nSize); ++nIdx ) |
| bDefault = maPalette[ nIdx ].maColor == mrDefPal.GetDefColor( GetXclIndex( nIdx ) ); |
| return bDefault; |
| } |
| |
| void XclExpPaletteImpl::WriteBody( XclExpStream& rStrm ) |
| { |
| rStrm << static_cast< sal_uInt16 >( maPalette.size() ); |
| for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt ) |
| rStrm << aIt->maColor; |
| } |
| |
| void XclExpPaletteImpl::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| if( !maPalette.size() ) |
| return; |
| |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| rStyleSheet->startElement( XML_colors, FSEND ); |
| rStyleSheet->startElement( XML_indexedColors, FSEND ); |
| for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); aIt != aEnd; ++aIt ) |
| rStyleSheet->singleElement( XML_rgbColor, |
| XML_rgb, XclXmlUtils::ToOString( aIt->maColor ).getStr(), |
| FSEND ); |
| rStyleSheet->endElement( XML_indexedColors ); |
| rStyleSheet->endElement( XML_colors ); |
| } |
| |
| const Color& XclExpPaletteImpl::GetOriginalColor( sal_uInt32 nColorId ) const |
| { |
| if( nColorId < maColorIdDataVec.size() ) |
| return maColorIdDataVec[ nColorId ].maColor; |
| return maPalette[ 0 ].maColor; |
| } |
| |
| XclListColor* XclExpPaletteImpl::SearchListEntry( const Color& rColor, sal_uInt32& rnIndex ) |
| { |
| rnIndex = mnLastIdx; |
| XclListColor* pEntry = mxColorList->GetObject( rnIndex ); |
| |
| // search optimization for equal-colored objects occuring repeatedly |
| if( pEntry && (pEntry->GetColor() == rColor) ) |
| return pEntry; |
| |
| // binary search for color |
| sal_uInt32 nBegIdx = 0; |
| sal_uInt32 nEndIdx = mxColorList->Count(); |
| bool bFound = false; |
| while( !bFound && (nBegIdx < nEndIdx) ) |
| { |
| rnIndex = (nBegIdx + nEndIdx) / 2; |
| pEntry = mxColorList->GetObject( rnIndex ); |
| bFound = pEntry->GetColor() == rColor; |
| if( !bFound ) |
| { |
| if( pEntry->GetColor().GetColor() < rColor.GetColor() ) |
| nBegIdx = rnIndex + 1; |
| else |
| nEndIdx = rnIndex; |
| } |
| } |
| // not found - use end of range as new insertion position |
| if( !bFound ) |
| pEntry = mxColorList->GetObject( rnIndex = nEndIdx ); |
| |
| mnLastIdx = rnIndex; |
| return pEntry; |
| } |
| |
| XclListColor* XclExpPaletteImpl::CreateListEntry( const Color& rColor, sal_uInt32 nIndex ) |
| { |
| XclListColor* pEntry = new XclListColor( rColor, mxColorList->Count() ); |
| mxColorList->Insert( pEntry, nIndex ); |
| return pEntry; |
| } |
| |
| void XclExpPaletteImpl::RawReducePalette( sal_uInt32 nPass ) |
| { |
| /* Fast palette reduction - in each call of this function one RGB component |
| of each color is reduced to a lower number of distinct values. |
| Pass 0: Blue is reduced to 128 distinct values. |
| Pass 1: Red is reduced to 128 distinct values. |
| Pass 2: Green is reduced to 128 distinct values. |
| Pass 3: Blue is reduced to 64 distinct values. |
| Pass 4: Red is reduced to 64 distinct values. |
| Pass 5: Green is reduced to 64 distinct values. |
| And so on... |
| */ |
| |
| XclListColorListRef xOldList = mxColorList; |
| mxColorList.reset( new XclListColorList ); |
| |
| // maps old list indexes to new list indexes, used to update maColorIdDataVec |
| ScfUInt32Vec aListIndexMap; |
| aListIndexMap.reserve( xOldList->Count() ); |
| |
| // preparations |
| sal_uInt8 nR, nG, nB; |
| sal_uInt8& rnComp = ((nPass % 3 == 0) ? nB : ((nPass % 3 == 1) ? nR : nG)); |
| nPass /= 3; |
| DBG_ASSERT( nPass < 7, "XclExpPaletteImpl::RawReducePalette - reduction not terminated" ); |
| |
| static const sal_uInt8 spnFactor2[] = { 0x81, 0x82, 0x84, 0x88, 0x92, 0xAA, 0xFF }; |
| sal_uInt8 nFactor1 = static_cast< sal_uInt8 >( 0x02 << nPass ); |
| sal_uInt8 nFactor2 = spnFactor2[ nPass ]; |
| sal_uInt8 nFactor3 = static_cast< sal_uInt8 >( 0x40 >> nPass ); |
| |
| // process each color in the old color list |
| for( sal_uInt32 nIdx = 0, nCount = xOldList->Count(); nIdx < nCount; ++nIdx ) |
| { |
| // get the old list entry |
| const XclListColor* pOldEntry = xOldList->GetObject( nIdx ); |
| nR = pOldEntry->GetColor().GetRed(); |
| nG = pOldEntry->GetColor().GetGreen(); |
| nB = pOldEntry->GetColor().GetBlue(); |
| |
| /* Calculate the new RGB component (rnComp points to one of nR, nG, nB). |
| Using integer arithmetic with its rounding errors, the results of |
| this calculation are always exactly in the range 0x00 to 0xFF |
| (simply cutting the lower bits would darken the colors slightly). */ |
| sal_uInt32 nNewComp = rnComp; |
| nNewComp /= nFactor1; |
| nNewComp *= nFactor2; |
| nNewComp /= nFactor3; |
| rnComp = static_cast< sal_uInt8 >( nNewComp ); |
| Color aNewColor( nR, nG, nB ); |
| |
| // find or insert the new color |
| sal_uInt32 nFoundIdx = 0; |
| XclListColor* pNewEntry = SearchListEntry( aNewColor, nFoundIdx ); |
| if( !pNewEntry || (pNewEntry->GetColor() != aNewColor) ) |
| pNewEntry = CreateListEntry( aNewColor, nFoundIdx ); |
| pNewEntry->AddWeighting( pOldEntry->GetWeighting() ); |
| aListIndexMap.push_back( nFoundIdx ); |
| } |
| |
| // update color ID data map (maps color IDs to color list indexes), replace old by new list indexes |
| for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt ) |
| aIt->mnIndex = aListIndexMap[ aIt->mnIndex ]; |
| } |
| |
| void XclExpPaletteImpl::ReduceLeastUsedColor() |
| { |
| // find a list color to remove |
| sal_uInt32 nRemove = GetLeastUsedListColor(); |
| // find its nearest neighbor |
| sal_uInt32 nKeep = GetNearestListColor( nRemove ); |
| |
| // merge both colors to one color, remove one color from list |
| XclListColor* pKeepEntry = mxColorList->GetObject( nKeep ); |
| XclListColor* pRemoveEntry = mxColorList->GetObject( nRemove ); |
| if( pKeepEntry && pRemoveEntry ) |
| { |
| // merge both colors (if pKeepEntry is a base color, it will not change) |
| pKeepEntry->Merge( *pRemoveEntry ); |
| // remove the less used color, adjust nKeep index if kept color follows removed color |
| mxColorList->Delete( nRemove ); |
| if( nKeep > nRemove ) --nKeep; |
| |
| // recalculate color ID data map (maps color IDs to color list indexes) |
| for( XclColorIdDataVec::iterator aIt = maColorIdDataVec.begin(), aEnd = maColorIdDataVec.end(); aIt != aEnd; ++aIt ) |
| { |
| if( aIt->mnIndex > nRemove ) |
| --aIt->mnIndex; |
| else if( aIt->mnIndex == nRemove ) |
| aIt->mnIndex = nKeep; |
| } |
| } |
| } |
| |
| sal_uInt32 XclExpPaletteImpl::GetLeastUsedListColor() const |
| { |
| sal_uInt32 nFound = 0; |
| sal_uInt32 nMinW = SAL_MAX_UINT32; |
| |
| for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx ) |
| { |
| XclListColor* pEntry = mxColorList->GetObject( nIdx ); |
| // ignore the base colors |
| if( !pEntry->IsBaseColor() && (pEntry->GetWeighting() < nMinW) ) |
| { |
| nFound = nIdx; |
| nMinW = pEntry->GetWeighting(); |
| } |
| } |
| return nFound; |
| } |
| |
| sal_uInt32 XclExpPaletteImpl::GetNearestListColor( const Color& rColor, sal_uInt32 nIgnore ) const |
| { |
| sal_uInt32 nFound = 0; |
| sal_Int32 nMinD = SAL_MAX_INT32; |
| |
| for( sal_uInt32 nIdx = 0, nCount = mxColorList->Count(); nIdx < nCount; ++nIdx ) |
| { |
| if( nIdx != nIgnore ) |
| { |
| if( XclListColor* pEntry = mxColorList->GetObject( nIdx ) ) |
| { |
| sal_Int32 nDist = lclGetColorDistance( rColor, pEntry->GetColor() ); |
| if( nDist < nMinD ) |
| { |
| nFound = nIdx; |
| nMinD = nDist; |
| } |
| } |
| } |
| } |
| return nFound; |
| } |
| |
| sal_uInt32 XclExpPaletteImpl::GetNearestListColor( sal_uInt32 nIndex ) const |
| { |
| XclListColor* pEntry = mxColorList->GetObject( nIndex ); |
| return pEntry ? GetNearestListColor( pEntry->GetColor(), nIndex ) : 0; |
| } |
| |
| sal_Int32 XclExpPaletteImpl::GetNearestPaletteColor( |
| sal_uInt32& rnIndex, const Color& rColor, bool bDefaultOnly ) const |
| { |
| rnIndex = 0; |
| sal_Int32 nDist = SAL_MAX_INT32; |
| |
| for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); |
| aIt != aEnd; ++aIt ) |
| { |
| if( !bDefaultOnly || !aIt->mbUsed ) |
| { |
| sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor ); |
| if( nCurrDist < nDist ) |
| { |
| rnIndex = aIt - maPalette.begin(); |
| nDist = nCurrDist; |
| } |
| } |
| } |
| return nDist; |
| } |
| |
| sal_Int32 XclExpPaletteImpl::GetNearPaletteColors( |
| sal_uInt32& rnFirst, sal_uInt32& rnSecond, const Color& rColor ) const |
| { |
| rnFirst = rnSecond = 0; |
| sal_Int32 nDist1 = SAL_MAX_INT32; |
| sal_Int32 nDist2 = SAL_MAX_INT32; |
| |
| for( XclPaletteColorVec::const_iterator aIt = maPalette.begin(), aEnd = maPalette.end(); |
| aIt != aEnd; ++aIt ) |
| { |
| sal_Int32 nCurrDist = lclGetColorDistance( rColor, aIt->maColor ); |
| if( nCurrDist < nDist1 ) |
| { |
| rnSecond = rnFirst; |
| nDist2 = nDist1; |
| rnFirst = aIt - maPalette.begin(); |
| nDist1 = nCurrDist; |
| } |
| else if( nCurrDist < nDist2 ) |
| { |
| rnSecond = aIt - maPalette.begin(); |
| nDist2 = nCurrDist; |
| } |
| } |
| return nDist1; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpPalette::XclExpPalette( const XclExpRoot& rRoot ) : |
| XclDefaultPalette( rRoot ), |
| XclExpRecord( EXC_ID_PALETTE ) |
| { |
| mxImpl.reset( new XclExpPaletteImpl( *this ) ); |
| SetRecSize( GetColorCount() * 4 + 2 ); |
| } |
| |
| XclExpPalette::~XclExpPalette() |
| { |
| } |
| |
| sal_uInt32 XclExpPalette::InsertColor( const Color& rColor, XclExpColorType eType, sal_uInt16 nAutoDefault ) |
| { |
| return mxImpl->InsertColor( rColor, eType, nAutoDefault ); |
| } |
| |
| sal_uInt32 XclExpPalette::GetColorIdFromIndex( sal_uInt16 nIndex ) |
| { |
| return XclExpPaletteImpl::GetColorIdFromIndex( nIndex ); |
| } |
| |
| void XclExpPalette::Finalize() |
| { |
| mxImpl->Finalize(); |
| } |
| |
| sal_uInt16 XclExpPalette::GetColorIndex( sal_uInt32 nColorId ) const |
| { |
| return mxImpl->GetColorIndex( nColorId ); |
| } |
| |
| void XclExpPalette::GetMixedColors( |
| sal_uInt16& rnXclForeIx, sal_uInt16& rnXclBackIx, sal_uInt8& rnXclPattern, |
| sal_uInt32 nForeColorId, sal_uInt32 nBackColorId ) const |
| { |
| return mxImpl->GetMixedColors( rnXclForeIx, rnXclBackIx, rnXclPattern, nForeColorId, nBackColorId ); |
| } |
| |
| ColorData XclExpPalette::GetColorData( sal_uInt16 nXclIndex ) const |
| { |
| return mxImpl->GetColorData( nXclIndex ); |
| } |
| |
| void XclExpPalette::Save( XclExpStream& rStrm ) |
| { |
| if( !mxImpl->IsDefaultPalette() ) |
| XclExpRecord::Save( rStrm ); |
| } |
| |
| void XclExpPalette::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| if( !mxImpl->IsDefaultPalette() ) |
| mxImpl->SaveXml( rStrm ); |
| } |
| |
| void XclExpPalette::WriteBody( XclExpStream& rStrm ) |
| { |
| mxImpl->WriteBody( rStrm ); |
| } |
| |
| // FONT record - font information ============================================= |
| |
| namespace { |
| |
| typedef ::std::pair< sal_uInt16, sal_Int16 > WhichAndScript; |
| |
| sal_Int16 lclCheckFontItems( const SfxItemSet& rItemSet, |
| const WhichAndScript& rWAS1, const WhichAndScript& rWAS2, const WhichAndScript& rWAS3 ) |
| { |
| if( ScfTools::CheckItem( rItemSet, rWAS1.first, false ) ) return rWAS1.second; |
| if( ScfTools::CheckItem( rItemSet, rWAS2.first, false ) ) return rWAS2.second; |
| if( ScfTools::CheckItem( rItemSet, rWAS3.first, false ) ) return rWAS3.second; |
| return 0; |
| }; |
| |
| } // namespace |
| |
| /*static*/ sal_Int16 XclExpFontHelper::GetFirstUsedScript( const XclExpRoot& rRoot, const SfxItemSet& rItemSet ) |
| { |
| namespace ApiScriptType = ::com::sun::star::i18n::ScriptType; |
| |
| /* #i17050# #i107170# We need to determine which font items are set in the |
| item set, and which script type we should prefer according to the |
| current language settings. */ |
| |
| static const WhichAndScript WAS_LATIN( ATTR_FONT, ::com::sun::star::i18n::ScriptType::LATIN ); |
| static const WhichAndScript WAS_ASIAN( ATTR_CJK_FONT, ::com::sun::star::i18n::ScriptType::ASIAN ); |
| static const WhichAndScript WAS_CMPLX( ATTR_CTL_FONT, ::com::sun::star::i18n::ScriptType::COMPLEX ); |
| |
| /* #114008# do not let a font from a parent style override an explicit |
| cell font. */ |
| |
| sal_Int16 nDefScript = rRoot.GetDefApiScript(); |
| sal_Int16 nScript = 0; |
| const SfxItemSet* pCurrSet = &rItemSet; |
| |
| while( (nScript == 0) && pCurrSet ) |
| { |
| switch( nDefScript ) |
| { |
| case ApiScriptType::LATIN: |
| nScript = lclCheckFontItems( *pCurrSet, WAS_LATIN, WAS_CMPLX, WAS_ASIAN ); |
| break; |
| case ApiScriptType::ASIAN: |
| nScript = lclCheckFontItems( *pCurrSet, WAS_ASIAN, WAS_CMPLX, WAS_LATIN ); |
| break; |
| case ApiScriptType::COMPLEX: |
| nScript = lclCheckFontItems( *pCurrSet, WAS_CMPLX, WAS_ASIAN, WAS_LATIN ); |
| break; |
| default: |
| DBG_ERRORFILE( "XclExpFontHelper::GetFirstUsedScript - unknown script type" ); |
| nScript = ApiScriptType::LATIN; |
| }; |
| pCurrSet = pCurrSet->GetParent(); |
| } |
| |
| return nScript; |
| } |
| |
| /*static*/ Font XclExpFontHelper::GetFontFromItemSet( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript ) |
| { |
| namespace ApiScriptType = ::com::sun::star::i18n::ScriptType; |
| |
| // if WEAK is passed, guess script type from existing items in the item set |
| if( nScript == ApiScriptType::WEAK ) |
| nScript = GetFirstUsedScript( rRoot, rItemSet ); |
| |
| // convert to core script type constants |
| sal_uInt8 nScScript = SCRIPTTYPE_LATIN; |
| switch( nScript ) |
| { |
| case ApiScriptType::LATIN: nScScript = SCRIPTTYPE_LATIN; break; |
| case ApiScriptType::ASIAN: nScScript = SCRIPTTYPE_ASIAN; break; |
| case ApiScriptType::COMPLEX: nScScript = SCRIPTTYPE_COMPLEX; break; |
| default: DBG_ERRORFILE( "XclExpFontHelper::GetFontFromItemSet - unknown script type" ); |
| } |
| |
| // fill the font object |
| Font aFont; |
| ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW, 0, 0, 0, nScScript ); |
| return aFont; |
| } |
| |
| /*static*/ bool XclExpFontHelper::CheckItems( const XclExpRoot& rRoot, const SfxItemSet& rItemSet, sal_Int16 nScript, bool bDeep ) |
| { |
| static const sal_uInt16 pnCommonIds[] = { |
| ATTR_FONT_UNDERLINE, ATTR_FONT_CROSSEDOUT, ATTR_FONT_CONTOUR, |
| ATTR_FONT_SHADOWED, ATTR_FONT_COLOR, ATTR_FONT_LANGUAGE, 0 }; |
| static const sal_uInt16 pnLatinIds[] = { |
| ATTR_FONT, ATTR_FONT_HEIGHT, ATTR_FONT_WEIGHT, ATTR_FONT_POSTURE, 0 }; |
| static const sal_uInt16 pnAsianIds[] = { |
| ATTR_CJK_FONT, ATTR_CJK_FONT_HEIGHT, ATTR_CJK_FONT_WEIGHT, ATTR_CJK_FONT_POSTURE, 0 }; |
| static const sal_uInt16 pnComplexIds[] = { |
| ATTR_CTL_FONT, ATTR_CTL_FONT_HEIGHT, ATTR_CTL_FONT_WEIGHT, ATTR_CTL_FONT_POSTURE, 0 }; |
| |
| bool bUsed = ScfTools::CheckItems( rItemSet, pnCommonIds, bDeep ); |
| if( !bUsed ) |
| { |
| namespace ApiScriptType = ::com::sun::star::i18n::ScriptType; |
| // if WEAK is passed, guess script type from existing items in the item set |
| if( nScript == ApiScriptType::WEAK ) |
| nScript = GetFirstUsedScript( rRoot, rItemSet ); |
| // check the correct items |
| switch( nScript ) |
| { |
| case ApiScriptType::LATIN: bUsed = ScfTools::CheckItems( rItemSet, pnLatinIds, bDeep ); break; |
| case ApiScriptType::ASIAN: bUsed = ScfTools::CheckItems( rItemSet, pnAsianIds, bDeep ); break; |
| case ApiScriptType::COMPLEX: bUsed = ScfTools::CheckItems( rItemSet, pnComplexIds, bDeep ); break; |
| default: DBG_ERRORFILE( "XclExpFontHelper::CheckItems - unknown script type" ); |
| } |
| } |
| return bUsed; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| namespace { |
| |
| sal_uInt32 lclCalcHash( const XclFontData& rFontData ) |
| { |
| sal_uInt32 nHash = rFontData.maName.Len(); |
| nHash += rFontData.maColor.GetColor() * 2; |
| nHash += rFontData.mnWeight * 3; |
| nHash += rFontData.mnCharSet * 5; |
| nHash += rFontData.mnFamily * 7; |
| nHash += rFontData.mnHeight * 11; |
| nHash += rFontData.mnUnderline * 13; |
| nHash += rFontData.mnEscapem * 17; |
| if( rFontData.mbItalic ) nHash += 19; |
| if( rFontData.mbStrikeout ) nHash += 23; |
| if( rFontData.mbOutline ) nHash += 29; |
| if( rFontData.mbShadow ) nHash += 31; |
| return nHash; |
| } |
| |
| } // namespace |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpFont::XclExpFont( const XclExpRoot& rRoot, |
| const XclFontData& rFontData, XclExpColorType eColorType ) : |
| XclExpRecord( EXC_ID2_FONT, 14 ), |
| XclExpRoot( rRoot ), |
| maData( rFontData ) |
| { |
| // insert font color into palette |
| mnColorId = rRoot.GetPalette().InsertColor( rFontData.maColor, eColorType, EXC_COLOR_FONTAUTO ); |
| // hash value for faster comparison |
| mnHash = lclCalcHash( maData ); |
| // record size |
| sal_Size nStrLen = maData.maName.Len(); |
| SetRecSize( ((GetBiff() == EXC_BIFF8) ? (nStrLen * 2 + 1) : nStrLen) + 15 ); |
| } |
| |
| bool XclExpFont::Equals( const XclFontData& rFontData, sal_uInt32 nHash ) const |
| { |
| return (mnHash == nHash) && (maData == rFontData); |
| } |
| |
| void XclExpFont::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| rStyleSheet->startElement( XML_font, FSEND ); |
| rStrm.WriteFontData( maData, XML_name ); |
| // OOXTODO: XML_scheme; //scheme/@val values: "major", "minor", "none" |
| rStyleSheet->endElement( XML_font ); |
| } |
| |
| // private -------------------------------------------------------------------- |
| |
| void XclExpFont::WriteBody( XclExpStream& rStrm ) |
| { |
| sal_uInt16 nAttr = EXC_FONTATTR_NONE; |
| ::set_flag( nAttr, EXC_FONTATTR_ITALIC, maData.mbItalic ); |
| ::set_flag( nAttr, EXC_FONTATTR_STRIKEOUT, maData.mbStrikeout ); |
| ::set_flag( nAttr, EXC_FONTATTR_OUTLINE, maData.mbOutline ); |
| ::set_flag( nAttr, EXC_FONTATTR_SHADOW, maData.mbShadow ); |
| |
| DBG_ASSERT( maData.maName.Len() < 256, "XclExpFont::WriteBody - font name too long" ); |
| XclExpString aFontName; |
| if( GetBiff() <= EXC_BIFF5 ) |
| aFontName.AssignByte( maData.maName, GetTextEncoding(), EXC_STR_8BITLENGTH ); |
| else |
| aFontName.Assign( maData.maName, EXC_STR_FORCEUNICODE | EXC_STR_8BITLENGTH ); |
| |
| rStrm << maData.mnHeight |
| << nAttr |
| << GetPalette().GetColorIndex( mnColorId ) |
| << maData.mnWeight |
| << maData.mnEscapem |
| << maData.mnUnderline |
| << maData.mnFamily |
| << maData.mnCharSet |
| << sal_uInt8( 0 ) |
| << aFontName; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpBlindFont::XclExpBlindFont( const XclExpRoot& rRoot ) : |
| XclExpFont( rRoot, XclFontData(), EXC_COLOR_CELLTEXT ) |
| { |
| } |
| |
| bool XclExpBlindFont::Equals( const XclFontData& /*rFontData*/, sal_uInt32 /*nHash*/ ) const |
| { |
| return false; |
| } |
| |
| void XclExpBlindFont::Save( XclExpStream& /*rStrm*/ ) |
| { |
| // do nothing |
| } |
| |
| // ============================================================================ |
| |
| XclExpFontBuffer::XclExpFontBuffer( const XclExpRoot& rRoot ) : |
| XclExpRoot( rRoot ), |
| mnXclMaxSize( 0 ) |
| { |
| switch( GetBiff() ) |
| { |
| case EXC_BIFF4: mnXclMaxSize = EXC_FONT_MAXCOUNT4; break; |
| case EXC_BIFF5: mnXclMaxSize = EXC_FONT_MAXCOUNT5; break; |
| case EXC_BIFF8: mnXclMaxSize = EXC_FONT_MAXCOUNT8; break; |
| default: DBG_ERROR_BIFF(); |
| } |
| InitDefaultFonts(); |
| } |
| |
| const XclExpFont* XclExpFontBuffer::GetFont( sal_uInt16 nXclFont ) const |
| { |
| return maFontList.GetRecord( nXclFont ).get(); |
| } |
| |
| const XclFontData& XclExpFontBuffer::GetAppFontData() const |
| { |
| return maFontList.GetRecord( EXC_FONT_APP )->GetFontData(); // exists always |
| } |
| |
| sal_uInt16 XclExpFontBuffer::Insert( |
| const XclFontData& rFontData, XclExpColorType eColorType, bool bAppFont ) |
| { |
| if( bAppFont ) |
| { |
| XclExpFontRef xFont( new XclExpFont( GetRoot(), rFontData, eColorType ) ); |
| maFontList.ReplaceRecord( xFont, EXC_FONT_APP ); |
| // #108487# set width of '0' character for column width export |
| SetCharWidth( xFont->GetFontData() ); |
| return EXC_FONT_APP; |
| } |
| |
| size_t nPos = Find( rFontData ); |
| if( nPos == EXC_FONTLIST_NOTFOUND ) |
| { |
| // not found in buffer - create new font |
| size_t nSize = maFontList.GetSize(); |
| if( nSize < mnXclMaxSize ) |
| { |
| // possible to insert |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), rFontData, eColorType ) ); |
| nPos = nSize; // old size is last position now |
| } |
| else |
| { |
| // buffer is full - ignore new font, use default font |
| nPos = EXC_FONT_APP; |
| } |
| } |
| return static_cast< sal_uInt16 >( nPos ); |
| } |
| |
| sal_uInt16 XclExpFontBuffer::Insert( |
| const Font& rFont, XclExpColorType eColorType, bool bAppFont ) |
| { |
| return Insert( XclFontData( rFont ), eColorType, bAppFont ); |
| } |
| |
| sal_uInt16 XclExpFontBuffer::Insert( |
| const SvxFont& rFont, XclExpColorType eColorType, bool bAppFont ) |
| { |
| return Insert( XclFontData( rFont ), eColorType, bAppFont ); |
| } |
| |
| sal_uInt16 XclExpFontBuffer::Insert( const SfxItemSet& rItemSet, |
| sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont ) |
| { |
| // #i17050# #114008# #115495# script type now provided by caller |
| Font aFont = XclExpFontHelper::GetFontFromItemSet( GetRoot(), rItemSet, nScript ); |
| return Insert( aFont, eColorType, bAppFont ); |
| } |
| |
| sal_uInt16 XclExpFontBuffer::Insert( const ScPatternAttr& rPattern, |
| sal_Int16 nScript, XclExpColorType eColorType, bool bAppFont ) |
| { |
| return Insert( rPattern.GetItemSet(), nScript, eColorType, bAppFont ); |
| } |
| |
| void XclExpFontBuffer::Save( XclExpStream& rStrm ) |
| { |
| maFontList.Save( rStrm ); |
| } |
| |
| void XclExpFontBuffer::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| if( maFontList.IsEmpty() ) |
| return; |
| |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| rStyleSheet->startElement( XML_fonts, |
| XML_count, OString::valueOf( (sal_Int32) maFontList.GetSize() ).getStr(), |
| FSEND ); |
| |
| maFontList.SaveXml( rStrm ); |
| |
| rStyleSheet->endElement( XML_fonts ); |
| } |
| |
| // private -------------------------------------------------------------------- |
| |
| void XclExpFontBuffer::InitDefaultFonts() |
| { |
| XclFontData aFontData; |
| aFontData.maName.AssignAscii( "Arial" ); |
| aFontData.SetScFamily( FAMILY_DONTKNOW ); |
| aFontData.SetFontEncoding( ScfTools::GetSystemTextEncoding() ); |
| aFontData.SetScHeight( 200 ); // 200 twips = 10 pt |
| aFontData.SetScWeight( WEIGHT_NORMAL ); |
| |
| switch( GetBiff() ) |
| { |
| case EXC_BIFF5: |
| { |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| aFontData.SetScWeight( WEIGHT_BOLD ); |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| aFontData.SetScWeight( WEIGHT_NORMAL ); |
| aFontData.SetScPosture( ITALIC_NORMAL ); |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| aFontData.SetScWeight( WEIGHT_BOLD ); |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| // the blind font with index 4 |
| maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) ); |
| // already add the first user defined font (Excel does it too) |
| aFontData.SetScWeight( WEIGHT_NORMAL ); |
| aFontData.SetScPosture( ITALIC_NONE ); |
| maFontList.AppendNewRecord( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| } |
| break; |
| case EXC_BIFF8: |
| { |
| XclExpFontRef xFont( new XclExpFont( GetRoot(), aFontData, EXC_COLOR_CELLTEXT ) ); |
| maFontList.AppendRecord( xFont ); |
| maFontList.AppendRecord( xFont ); |
| maFontList.AppendRecord( xFont ); |
| maFontList.AppendRecord( xFont ); |
| if( GetOutput() == EXC_OUTPUT_BINARY ) |
| // the blind font with index 4 |
| maFontList.AppendNewRecord( new XclExpBlindFont( GetRoot() ) ); |
| } |
| break; |
| default: |
| DBG_ERROR_BIFF(); |
| } |
| } |
| |
| size_t XclExpFontBuffer::Find( const XclFontData& rFontData ) |
| { |
| sal_uInt32 nHash = lclCalcHash( rFontData ); |
| for( size_t nPos = 0, nSize = maFontList.GetSize(); nPos < nSize; ++nPos ) |
| if( maFontList.GetRecord( nPos )->Equals( rFontData, nHash ) ) |
| return nPos; |
| return EXC_FONTLIST_NOTFOUND; |
| } |
| |
| // FORMAT record - number formats ============================================= |
| |
| /** Predicate for search algorithm. */ |
| struct XclExpNumFmtPred |
| { |
| sal_uLong mnScNumFmt; |
| inline explicit XclExpNumFmtPred( sal_uLong nScNumFmt ) : mnScNumFmt( nScNumFmt ) {} |
| inline bool operator()( const XclExpNumFmt& rFormat ) const |
| { return rFormat.mnScNumFmt == mnScNumFmt; } |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpNumFmtBuffer::XclExpNumFmtBuffer( const XclExpRoot& rRoot ) : |
| XclExpRoot( rRoot ), |
| /* Compiler needs a hint, this doesn't work: new NfKeywordTable; |
| cannot convert from 'class String *' to 'class String (*)[54]' |
| The effective result here is class String (*)[54*1] */ |
| mxFormatter( new SvNumberFormatter( rRoot.GetDoc().GetServiceManager(), LANGUAGE_ENGLISH_US ) ), |
| mpKeywordTable( new NfKeywordTable[ 1 ] ), |
| mnStdFmt( GetFormatter().GetStandardFormat( ScGlobal::eLnge ) ) |
| { |
| switch( GetBiff() ) |
| { |
| case EXC_BIFF5: mnXclOffset = EXC_FORMAT_OFFSET5; break; |
| case EXC_BIFF8: mnXclOffset = EXC_FORMAT_OFFSET8; break; |
| default: DBG_ERROR_BIFF(); |
| } |
| |
| mxFormatter->FillKeywordTable( *mpKeywordTable, LANGUAGE_ENGLISH_US ); |
| // remap codes unknown to Excel |
| (*mpKeywordTable)[ NF_KEY_NN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDD" ) ); |
| (*mpKeywordTable)[ NF_KEY_NNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) ); |
| // NNNN gets a separator appended in SvNumberformat::GetMappedFormatString() |
| (*mpKeywordTable)[ NF_KEY_NNNN ] = String( RTL_CONSTASCII_USTRINGPARAM( "DDDD" ) ); |
| // Export the Thai T NatNum modifier. |
| (*mpKeywordTable)[ NF_KEY_THAI_T ] = String( RTL_CONSTASCII_USTRINGPARAM( "T" ) ); |
| } |
| |
| XclExpNumFmtBuffer::~XclExpNumFmtBuffer() |
| { |
| delete[] mpKeywordTable; |
| } |
| |
| sal_uInt16 XclExpNumFmtBuffer::Insert( sal_uLong nScNumFmt ) |
| { |
| XclExpNumFmtVec::const_iterator aIt = |
| ::std::find_if( maFormatMap.begin(), maFormatMap.end(), XclExpNumFmtPred( nScNumFmt ) ); |
| if( aIt != maFormatMap.end() ) |
| return aIt->mnXclNumFmt; |
| |
| size_t nSize = maFormatMap.size(); |
| if( nSize < static_cast< size_t >( 0xFFFF - mnXclOffset ) ) |
| { |
| sal_uInt16 nXclNumFmt = static_cast< sal_uInt16 >( nSize + mnXclOffset ); |
| maFormatMap.push_back( XclExpNumFmt( nScNumFmt, nXclNumFmt ) ); |
| return nXclNumFmt; |
| } |
| |
| return 0; |
| } |
| |
| void XclExpNumFmtBuffer::Save( XclExpStream& rStrm ) |
| { |
| for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt ) |
| WriteFormatRecord( rStrm, *aIt ); |
| } |
| |
| void XclExpNumFmtBuffer::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| if( !maFormatMap.size() ) |
| return; |
| |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| rStyleSheet->startElement( XML_numFmts, |
| XML_count, OString::valueOf( (sal_Int32) maFormatMap.size() ).getStr(), |
| FSEND ); |
| for( XclExpNumFmtVec::const_iterator aIt = maFormatMap.begin(), aEnd = maFormatMap.end(); aIt != aEnd; ++aIt ) |
| { |
| rStyleSheet->singleElement( XML_numFmt, |
| XML_numFmtId, OString::valueOf( sal_Int32(aIt->mnXclNumFmt) ).getStr(), |
| XML_formatCode, XclXmlUtils::ToOString( GetFormatCode( *aIt ) ).getStr(), |
| FSEND ); |
| } |
| rStyleSheet->endElement( XML_numFmts ); |
| } |
| |
| void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const String& rFormatStr ) |
| { |
| XclExpString aExpStr; |
| if( GetBiff() <= EXC_BIFF5 ) |
| aExpStr.AssignByte( rFormatStr, GetTextEncoding(), EXC_STR_8BITLENGTH ); |
| else |
| aExpStr.Assign( rFormatStr ); |
| |
| rStrm.StartRecord( EXC_ID4_FORMAT, 2 + aExpStr.GetSize() ); |
| rStrm << nXclNumFmt << aExpStr; |
| rStrm.EndRecord(); |
| } |
| |
| void XclExpNumFmtBuffer::WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat ) |
| { |
| WriteFormatRecord( rStrm, rFormat.mnXclNumFmt, GetFormatCode( rFormat ) ); |
| } |
| |
| String XclExpNumFmtBuffer::GetFormatCode( const XclExpNumFmt& rFormat ) |
| { |
| String aFormatStr; |
| |
| if( const SvNumberformat* pEntry = GetFormatter().GetEntry( rFormat.mnScNumFmt ) ) |
| { |
| if( pEntry->GetType() == NUMBERFORMAT_LOGICAL ) |
| { |
| // build Boolean number format |
| Color* pColor = 0; |
| String aTemp; |
| const_cast< SvNumberformat* >( pEntry )->GetOutputString( 1.0, aTemp, &pColor ); |
| aFormatStr.Append( '"' ).Append( aTemp ).AppendAscii( "\";\"" ).Append( aTemp ).AppendAscii( "\";\"" ); |
| const_cast< SvNumberformat* >( pEntry )->GetOutputString( 0.0, aTemp, &pColor ); |
| aFormatStr.Append( aTemp ).Append( '"' ); |
| } |
| else |
| { |
| LanguageType eLang = pEntry->GetLanguage(); |
| if( eLang != LANGUAGE_ENGLISH_US ) |
| { |
| xub_StrLen nCheckPos; |
| short nType = NUMBERFORMAT_DEFINED; |
| sal_uInt32 nKey; |
| String aTemp( pEntry->GetFormatstring() ); |
| mxFormatter->PutandConvertEntry( aTemp, nCheckPos, nType, nKey, eLang, LANGUAGE_ENGLISH_US ); |
| DBG_ASSERT( nCheckPos == 0, "XclExpNumFmtBuffer::WriteFormatRecord - format code not convertible" ); |
| pEntry = mxFormatter->GetEntry( nKey ); |
| } |
| |
| aFormatStr = pEntry->GetMappedFormatstring( *mpKeywordTable, *mxFormatter->GetLocaleData() ); |
| if( aFormatStr.EqualsAscii( "Standard" ) ) |
| aFormatStr.AssignAscii( "General" ); |
| } |
| } |
| else |
| { |
| DBG_ERRORFILE( "XclExpNumFmtBuffer::WriteFormatRecord - format not found" ); |
| aFormatStr.AssignAscii( "General" ); |
| } |
| |
| return aFormatStr; |
| } |
| |
| // XF, STYLE record - Cell formatting ========================================= |
| |
| bool XclExpCellProt::FillFromItemSet( const SfxItemSet& rItemSet, bool bStyle ) |
| { |
| const ScProtectionAttr& rProtItem = GETITEM( rItemSet, ScProtectionAttr, ATTR_PROTECTION ); |
| mbLocked = rProtItem.GetProtection(); |
| mbHidden = rProtItem.GetHideFormula() || rProtItem.GetHideCell(); |
| return ScfTools::CheckItem( rItemSet, ATTR_PROTECTION, bStyle ); |
| } |
| |
| #if 0 |
| void XclExpCellProt::FillToXF2( sal_uInt8& rnNumFmt ) const |
| { |
| ::set_flag( rnNumFmt, EXC_XF2_LOCKED, mbLocked ); |
| ::set_flag( rnNumFmt, EXC_XF2_HIDDEN, mbHidden ); |
| } |
| #endif |
| |
| void XclExpCellProt::FillToXF3( sal_uInt16& rnProt ) const |
| { |
| ::set_flag( rnProt, EXC_XF_LOCKED, mbLocked ); |
| ::set_flag( rnProt, EXC_XF_HIDDEN, mbHidden ); |
| } |
| |
| void XclExpCellProt::SaveXml( XclExpXmlStream& rStrm ) const |
| { |
| rStrm.GetCurrentStream()->singleElement( XML_protection, |
| XML_locked, XclXmlUtils::ToPsz( mbLocked ), |
| XML_hidden, XclXmlUtils::ToPsz( mbHidden ), |
| FSEND ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| bool XclExpCellAlign::FillFromItemSet( |
| const SfxItemSet& rItemSet, bool bForceLineBreak, XclBiff eBiff, bool bStyle ) |
| { |
| bool bUsed = false; |
| |
| switch( eBiff ) |
| { |
| // ALL 'case's - run through! |
| |
| case EXC_BIFF8: // attributes new in BIFF8 |
| { |
| // text indent |
| long nTmpIndent = GETITEMVALUE( rItemSet, SfxUInt16Item, ATTR_INDENT, sal_Int32 ); |
| (nTmpIndent += 100) /= 200; // 1 Excel unit == 10 pt == 200 twips |
| mnIndent = limit_cast< sal_uInt8 >( nTmpIndent, 0, 15 ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_INDENT, bStyle ); |
| |
| // shrink to fit |
| mbShrink = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_SHRINKTOFIT, sal_Bool ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_SHRINKTOFIT, bStyle ); |
| |
| // CTL text direction |
| SetScFrameDir( GETITEMVALUE( rItemSet, SvxFrameDirectionItem, ATTR_WRITINGDIR, SvxFrameDirection ) ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_WRITINGDIR, bStyle ); |
| } |
| |
| case EXC_BIFF5: // attributes new in BIFF5 |
| case EXC_BIFF4: // attributes new in BIFF4 |
| { |
| // vertical alignment |
| SetScVerAlign( GETITEMVALUE( rItemSet, SvxVerJustifyItem, ATTR_VER_JUSTIFY, SvxCellVerJustify ) ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_VER_JUSTIFY, bStyle ); |
| |
| // stacked/rotation |
| bool bStacked = GETITEMVALUE( rItemSet, SfxBoolItem, ATTR_STACKED, sal_Bool ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_STACKED, bStyle ); |
| if( bStacked ) |
| { |
| mnRotation = EXC_ROT_STACKED; |
| } |
| else |
| { |
| // rotation |
| sal_Int32 nScRot = GETITEMVALUE( rItemSet, SfxInt32Item, ATTR_ROTATE_VALUE, sal_Int32 ); |
| mnRotation = XclTools::GetXclRotation( nScRot ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_ROTATE_VALUE, bStyle ); |
| } |
| mnOrient = XclTools::GetXclOrientFromRot( mnRotation ); |
| } |
| |
| case EXC_BIFF3: // attributes new in BIFF3 |
| { |
| // text wrap |
| mbLineBreak = bForceLineBreak || GETITEMBOOL( rItemSet, ATTR_LINEBREAK ); |
| bUsed |= bForceLineBreak || ScfTools::CheckItem( rItemSet, ATTR_LINEBREAK, bStyle ); |
| } |
| |
| case EXC_BIFF2: // attributes new in BIFF2 |
| { |
| // horizontal alignment |
| SetScHorAlign( GETITEMVALUE( rItemSet, SvxHorJustifyItem, ATTR_HOR_JUSTIFY, SvxCellHorJustify ) ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_HOR_JUSTIFY, bStyle ); |
| } |
| |
| break; |
| default: DBG_ERROR_BIFF(); |
| } |
| |
| return bUsed; |
| } |
| |
| #if 0 |
| void XclExpCellAlign::FillToXF2( sal_uInt8& rnFlags ) const |
| { |
| ::insert_value( rnFlags, mnHorAlign, 0, 3 ); |
| } |
| |
| void XclExpCellAlign::FillToXF3( sal_uInt16& rnAlign ) const |
| { |
| ::insert_value( rnAlign, mnHorAlign, 0, 3 ); |
| ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak ); |
| } |
| |
| void XclExpCellAlign::FillToXF4( sal_uInt16& rnAlign ) const |
| { |
| FillToXF3( rnAlign ); |
| ::insert_value( rnAlign, mnVerAlign, 4, 2 ); |
| ::insert_value( rnAlign, mnOrient, 6, 2 ); |
| } |
| #endif |
| |
| void XclExpCellAlign::FillToXF5( sal_uInt16& rnAlign ) const |
| { |
| ::insert_value( rnAlign, mnHorAlign, 0, 3 ); |
| ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak ); |
| ::insert_value( rnAlign, mnVerAlign, 4, 3 ); |
| ::insert_value( rnAlign, mnOrient, 8, 2 ); |
| } |
| |
| void XclExpCellAlign::FillToXF8( sal_uInt16& rnAlign, sal_uInt16& rnMiscAttrib ) const |
| { |
| ::insert_value( rnAlign, mnHorAlign, 0, 3 ); |
| ::set_flag( rnAlign, EXC_XF_LINEBREAK, mbLineBreak ); |
| ::insert_value( rnAlign, mnVerAlign, 4, 3 ); |
| ::insert_value( rnAlign, mnRotation, 8, 8 ); |
| ::insert_value( rnMiscAttrib, mnIndent, 0, 4 ); |
| ::set_flag( rnMiscAttrib, EXC_XF8_SHRINK, mbShrink ); |
| ::insert_value( rnMiscAttrib, mnTextDir, 6, 2 ); |
| } |
| |
| static const char* ToHorizontalAlignment( sal_uInt8 nHorAlign ) |
| { |
| switch( nHorAlign ) |
| { |
| case EXC_XF_HOR_GENERAL: return "general"; |
| case EXC_XF_HOR_LEFT: return "left"; |
| case EXC_XF_HOR_CENTER: return "center"; |
| case EXC_XF_HOR_RIGHT: return "right"; |
| case EXC_XF_HOR_FILL: return "fill"; |
| case EXC_XF_HOR_JUSTIFY: return "justify"; |
| case EXC_XF_HOR_CENTER_AS: return "centerContinuous"; |
| case EXC_XF_HOR_DISTRIB: return "distributed"; |
| } |
| return "*unknown*"; |
| } |
| |
| static const char* ToVerticalAlignment( sal_uInt8 nVerAlign ) |
| { |
| switch( nVerAlign ) |
| { |
| case EXC_XF_VER_TOP: return "top"; |
| case EXC_XF_VER_CENTER: return "center"; |
| case EXC_XF_VER_BOTTOM: return "bottom"; |
| case EXC_XF_VER_JUSTIFY: return "justify"; |
| case EXC_XF_VER_DISTRIB: return "distributed"; |
| } |
| return "*unknown*"; |
| } |
| |
| void XclExpCellAlign::SaveXml( XclExpXmlStream& rStrm ) const |
| { |
| rStrm.GetCurrentStream()->singleElement( XML_alignment, |
| XML_horizontal, ToHorizontalAlignment( mnHorAlign ), |
| XML_vertical, ToVerticalAlignment( mnVerAlign ), |
| XML_textRotation, OString::valueOf( (sal_Int32) mnRotation ).getStr(), |
| XML_wrapText, XclXmlUtils::ToPsz( mbLineBreak ), |
| XML_indent, OString::valueOf( (sal_Int32) mnIndent ).getStr(), |
| // OOXTODO: XML_relativeIndent, mnIndent? |
| // OOXTODO: XML_justifyLastLine, |
| XML_shrinkToFit, XclXmlUtils::ToPsz( mbShrink ), |
| // OOXTODO: XML_readingOrder, |
| FSEND ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| namespace { |
| |
| void lclGetBorderLine( |
| sal_uInt8& rnXclLine, sal_uInt32& rnColorId, |
| const SvxBorderLine* pLine, XclExpPalette& rPalette, XclBiff eBiff ) |
| { |
| rnXclLine = EXC_LINE_NONE; |
| if( pLine ) |
| { |
| sal_uInt16 nOuterWidth = pLine->GetOutWidth(); |
| sal_uInt16 nDistance = pLine->GetDistance(); |
| if( nDistance > 0 ) |
| rnXclLine = EXC_LINE_DOUBLE; |
| else if( nOuterWidth > DEF_LINE_WIDTH_2 ) |
| rnXclLine = EXC_LINE_THICK; |
| else if( nOuterWidth > DEF_LINE_WIDTH_1 ) |
| rnXclLine = EXC_LINE_MEDIUM; |
| else if( nOuterWidth > DEF_LINE_WIDTH_0 ) |
| rnXclLine = EXC_LINE_THIN; |
| else if( nOuterWidth > 0 ) |
| rnXclLine = EXC_LINE_HAIR; |
| else |
| rnXclLine = EXC_LINE_NONE; |
| } |
| if( (eBiff == EXC_BIFF2) && (rnXclLine != EXC_LINE_NONE) ) |
| rnXclLine = EXC_LINE_THIN; |
| |
| rnColorId = (pLine && (rnXclLine != EXC_LINE_NONE)) ? |
| rPalette.InsertColor( pLine->GetColor(), EXC_COLOR_CELLBORDER ) : |
| XclExpPalette::GetColorIdFromIndex( 0 ); |
| } |
| |
| } // namespace |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpCellBorder::XclExpCellBorder() : |
| mnLeftColorId( XclExpPalette::GetColorIdFromIndex( mnLeftColor ) ), |
| mnRightColorId( XclExpPalette::GetColorIdFromIndex( mnRightColor ) ), |
| mnTopColorId( XclExpPalette::GetColorIdFromIndex( mnTopColor ) ), |
| mnBottomColorId( XclExpPalette::GetColorIdFromIndex( mnBottomColor ) ), |
| mnDiagColorId( XclExpPalette::GetColorIdFromIndex( mnDiagColor ) ) |
| { |
| } |
| |
| bool XclExpCellBorder::FillFromItemSet( |
| const SfxItemSet& rItemSet, XclExpPalette& rPalette, XclBiff eBiff, bool bStyle ) |
| { |
| bool bUsed = false; |
| |
| switch( eBiff ) |
| { |
| // ALL 'case's - run through! |
| |
| case EXC_BIFF8: // attributes new in BIFF8 |
| { |
| const SvxLineItem& rTLBRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_TLBR ); |
| sal_uInt8 nTLBRLine; |
| sal_uInt32 nTLBRColorId; |
| lclGetBorderLine( nTLBRLine, nTLBRColorId, rTLBRItem.GetLine(), rPalette, eBiff ); |
| mbDiagTLtoBR = (nTLBRLine != EXC_LINE_NONE); |
| |
| const SvxLineItem& rBLTRItem = GETITEM( rItemSet, SvxLineItem, ATTR_BORDER_BLTR ); |
| sal_uInt8 nBLTRLine; |
| sal_uInt32 nBLTRColorId; |
| lclGetBorderLine( nBLTRLine, nBLTRColorId, rBLTRItem.GetLine(), rPalette, eBiff ); |
| mbDiagBLtoTR = (nBLTRLine != EXC_LINE_NONE); |
| |
| if( ::ScHasPriority( rTLBRItem.GetLine(), rBLTRItem.GetLine() ) ) |
| { |
| mnDiagLine = nTLBRLine; |
| mnDiagColorId = nTLBRColorId; |
| } |
| else |
| { |
| mnDiagLine = nBLTRLine; |
| mnDiagColorId = nBLTRColorId; |
| } |
| |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER_TLBR, bStyle ) || |
| ScfTools::CheckItem( rItemSet, ATTR_BORDER_BLTR, bStyle ); |
| } |
| |
| case EXC_BIFF5: |
| case EXC_BIFF4: |
| case EXC_BIFF3: |
| case EXC_BIFF2: |
| { |
| const SvxBoxItem& rBoxItem = GETITEM( rItemSet, SvxBoxItem, ATTR_BORDER ); |
| lclGetBorderLine( mnLeftLine, mnLeftColorId, rBoxItem.GetLeft(), rPalette, eBiff ); |
| lclGetBorderLine( mnRightLine, mnRightColorId, rBoxItem.GetRight(), rPalette, eBiff ); |
| lclGetBorderLine( mnTopLine, mnTopColorId, rBoxItem.GetTop(), rPalette, eBiff ); |
| lclGetBorderLine( mnBottomLine, mnBottomColorId, rBoxItem.GetBottom(), rPalette, eBiff ); |
| bUsed |= ScfTools::CheckItem( rItemSet, ATTR_BORDER, bStyle ); |
| } |
| |
| break; |
| default: DBG_ERROR_BIFF(); |
| } |
| |
| return bUsed; |
| } |
| |
| void XclExpCellBorder::SetFinalColors( const XclExpPalette& rPalette ) |
| { |
| mnLeftColor = rPalette.GetColorIndex( mnLeftColorId ); |
| mnRightColor = rPalette.GetColorIndex( mnRightColorId ); |
| mnTopColor = rPalette.GetColorIndex( mnTopColorId ); |
| mnBottomColor = rPalette.GetColorIndex( mnBottomColorId ); |
| mnDiagColor = rPalette.GetColorIndex( mnDiagColorId ); |
| } |
| |
| #if 0 |
| void XclExpCellBorder::FillToXF2( sal_uInt8& rnFlags ) const |
| { |
| ::set_flag( rnFlags, EXC_XF2_LEFTLINE, mnLeftLine != EXC_LINE_NONE ); |
| ::set_flag( rnFlags, EXC_XF2_RIGHTLINE, mnRightLine != EXC_LINE_NONE ); |
| ::set_flag( rnFlags, EXC_XF2_TOPLINE, mnTopLine != EXC_LINE_NONE ); |
| ::set_flag( rnFlags, EXC_XF2_BOTTOMLINE, mnBottomLine != EXC_LINE_NONE ); |
| } |
| |
| void XclExpCellBorder::FillToXF3( sal_uInt32& rnBorder ) const |
| { |
| ::insert_value( rnBorder, mnTopLine, 0, 3 ); |
| ::insert_value( rnBorder, mnLeftLine, 8, 3 ); |
| ::insert_value( rnBorder, mnBottomLine, 16, 3 ); |
| ::insert_value( rnBorder, mnRightLine, 24, 3 ); |
| ::insert_value( rnBorder, mnTopColor, 3, 5 ); |
| ::insert_value( rnBorder, mnLeftColor, 11, 5 ); |
| ::insert_value( rnBorder, mnBottomColor, 19, 5 ); |
| ::insert_value( rnBorder, mnRightColor, 27, 5 ); |
| } |
| #endif |
| |
| void XclExpCellBorder::FillToXF5( sal_uInt32& rnBorder, sal_uInt32& rnArea ) const |
| { |
| ::insert_value( rnBorder, mnTopLine, 0, 3 ); |
| ::insert_value( rnBorder, mnLeftLine, 3, 3 ); |
| ::insert_value( rnArea, mnBottomLine, 22, 3 ); |
| ::insert_value( rnBorder, mnRightLine, 6, 3 ); |
| ::insert_value( rnBorder, mnTopColor, 9, 7 ); |
| ::insert_value( rnBorder, mnLeftColor, 16, 7 ); |
| ::insert_value( rnArea, mnBottomColor, 25, 7 ); |
| ::insert_value( rnBorder, mnRightColor, 23, 7 ); |
| } |
| |
| void XclExpCellBorder::FillToXF8( sal_uInt32& rnBorder1, sal_uInt32& rnBorder2 ) const |
| { |
| ::insert_value( rnBorder1, mnLeftLine, 0, 4 ); |
| ::insert_value( rnBorder1, mnRightLine, 4, 4 ); |
| ::insert_value( rnBorder1, mnTopLine, 8, 4 ); |
| ::insert_value( rnBorder1, mnBottomLine, 12, 4 ); |
| ::insert_value( rnBorder1, mnLeftColor, 16, 7 ); |
| ::insert_value( rnBorder1, mnRightColor, 23, 7 ); |
| ::insert_value( rnBorder2, mnTopColor, 0, 7 ); |
| ::insert_value( rnBorder2, mnBottomColor, 7, 7 ); |
| ::insert_value( rnBorder2, mnDiagColor, 14, 7 ); |
| ::insert_value( rnBorder2, mnDiagLine, 21, 4 ); |
| ::set_flag( rnBorder1, EXC_XF_DIAGONAL_TL_TO_BR, mbDiagTLtoBR ); |
| ::set_flag( rnBorder1, EXC_XF_DIAGONAL_BL_TO_TR, mbDiagBLtoTR ); |
| } |
| |
| void XclExpCellBorder::FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const |
| { |
| ::insert_value( rnLine, mnLeftLine, 0, 4 ); |
| ::insert_value( rnLine, mnRightLine, 4, 4 ); |
| ::insert_value( rnLine, mnTopLine, 8, 4 ); |
| ::insert_value( rnLine, mnBottomLine, 12, 4 ); |
| ::insert_value( rnColor, mnLeftColor, 0, 7 ); |
| ::insert_value( rnColor, mnRightColor, 7, 7 ); |
| ::insert_value( rnColor, mnTopColor, 16, 7 ); |
| ::insert_value( rnColor, mnBottomColor, 23, 7 ); |
| } |
| |
| static const char* ToLineStyle( sal_uInt8 nLineStyle ) |
| { |
| switch( nLineStyle ) |
| { |
| case EXC_LINE_NONE: return "none"; |
| case EXC_LINE_THIN: return "thin"; |
| case EXC_LINE_MEDIUM: return "medium"; |
| case EXC_LINE_THICK: return "thick"; |
| case EXC_LINE_DOUBLE: return "double"; |
| case EXC_LINE_HAIR: return "hair"; |
| } |
| return "*unknown*"; |
| } |
| |
| static void lcl_WriteBorder( XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor ) |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| if( nLineStyle == EXC_LINE_NONE ) |
| rStyleSheet->singleElement( nElement, FSEND ); |
| else if( rColor == Color( 0, 0, 0, 0 ) ) |
| rStyleSheet->singleElement( nElement, |
| XML_style, ToLineStyle( nLineStyle ), |
| FSEND ); |
| else |
| { |
| rStyleSheet->startElement( nElement, |
| XML_style, ToLineStyle( nLineStyle ), |
| FSEND ); |
| rStyleSheet->singleElement( XML_color, |
| XML_rgb, XclXmlUtils::ToOString( rColor ).getStr(), |
| FSEND ); |
| rStyleSheet->endElement( nElement ); |
| } |
| } |
| |
| void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) const |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| |
| XclExpPalette& rPalette = rStrm.GetRoot().GetPalette(); |
| |
| rStyleSheet->startElement( XML_border, |
| XML_diagonalUp, XclXmlUtils::ToPsz( mbDiagBLtoTR ), |
| XML_diagonalDown, XclXmlUtils::ToPsz( mbDiagTLtoBR ), |
| // OOXTODO: XML_outline, |
| FSEND ); |
| lcl_WriteBorder( rStrm, XML_left, mnLeftLine, rPalette.GetColor( mnLeftColor ) ); |
| lcl_WriteBorder( rStrm, XML_right, mnRightLine, rPalette.GetColor( mnRightColor ) ); |
| lcl_WriteBorder( rStrm, XML_top, mnTopLine, rPalette.GetColor( mnTopColor ) ); |
| lcl_WriteBorder( rStrm, XML_bottom, mnBottomLine, rPalette.GetColor( mnBottomColor ) ); |
| lcl_WriteBorder( rStrm, XML_diagonal, mnDiagLine, rPalette.GetColor( mnDiagColor ) ); |
| // OOXTODO: XML_vertical, XML_horizontal |
| rStyleSheet->endElement( XML_border ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpCellArea::XclExpCellArea() : |
| mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ), |
| mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) ) |
| { |
| } |
| |
| bool XclExpCellArea::FillFromItemSet( const SfxItemSet& rItemSet, XclExpPalette& rPalette, bool bStyle ) |
| { |
| const SvxBrushItem& rBrushItem = GETITEM( rItemSet, SvxBrushItem, ATTR_BACKGROUND ); |
| if( rBrushItem.GetColor().GetTransparency() ) |
| { |
| mnPattern = EXC_PATT_NONE; |
| mnForeColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT ); |
| mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWBACK ); |
| } |
| else |
| { |
| mnPattern = EXC_PATT_SOLID; |
| mnForeColorId = rPalette.InsertColor( rBrushItem.GetColor(), EXC_COLOR_CELLAREA ); |
| mnBackColorId = XclExpPalette::GetColorIdFromIndex( EXC_COLOR_WINDOWTEXT ); |
| } |
| return ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, bStyle ); |
| } |
| |
| void XclExpCellArea::SetFinalColors( const XclExpPalette& rPalette ) |
| { |
| rPalette.GetMixedColors( mnForeColor, mnBackColor, mnPattern, mnForeColorId, mnBackColorId ); |
| } |
| |
| #if 0 |
| void XclExpCellArea::FillToXF2( sal_uInt8& rnFlags ) const |
| { |
| ::set_flag( rnFlags, EXC_XF2_BACKGROUND, mnPattern != EXC_PATT_NONE ); |
| } |
| |
| void XclExpCellArea::FillToXF3( sal_uInt16& rnArea ) const |
| { |
| ::insert_value( rnArea, mnPattern, 0, 6 ); |
| ::insert_value( rnArea, mnForeColor, 6, 5 ); |
| ::insert_value( rnArea, mnBackColor, 11, 5 ); |
| } |
| #endif |
| |
| void XclExpCellArea::FillToXF5( sal_uInt32& rnArea ) const |
| { |
| ::insert_value( rnArea, mnPattern, 16, 6 ); |
| ::insert_value( rnArea, mnForeColor, 0, 7 ); |
| ::insert_value( rnArea, mnBackColor, 7, 7 ); |
| } |
| |
| void XclExpCellArea::FillToXF8( sal_uInt32& rnBorder2, sal_uInt16& rnArea ) const |
| { |
| ::insert_value( rnBorder2, mnPattern, 26, 6 ); |
| ::insert_value( rnArea, mnForeColor, 0, 7 ); |
| ::insert_value( rnArea, mnBackColor, 7, 7 ); |
| } |
| |
| void XclExpCellArea::FillToCF8( sal_uInt16& rnPattern, sal_uInt16& rnColor ) const |
| { |
| XclCellArea aTmp( *this ); |
| if( !aTmp.IsTransparent() && (aTmp.mnBackColor == EXC_COLOR_WINDOWTEXT) ) |
| aTmp.mnBackColor = 0; |
| if( aTmp.mnPattern == EXC_PATT_SOLID ) |
| ::std::swap( aTmp.mnForeColor, aTmp.mnBackColor ); |
| ::insert_value( rnColor, aTmp.mnForeColor, 0, 7 ); |
| ::insert_value( rnColor, aTmp.mnBackColor, 7, 7 ); |
| ::insert_value( rnPattern, aTmp.mnPattern, 10, 6 ); |
| } |
| |
| static const char* ToPatternType( sal_uInt8 nPattern ) |
| { |
| switch( nPattern ) |
| { |
| case EXC_PATT_NONE: return "none"; |
| case EXC_PATT_SOLID: return "solid"; |
| case EXC_PATT_50_PERC: return "mediumGray"; |
| case EXC_PATT_75_PERC: return "darkGray"; |
| case EXC_PATT_25_PERC: return "lightGray"; |
| case EXC_PATT_12_5_PERC: return "gray125"; |
| case EXC_PATT_6_25_PERC: return "gray0625"; |
| } |
| return "*unknown*"; |
| } |
| |
| void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) const |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| rStyleSheet->startElement( XML_fill, |
| FSEND ); |
| |
| // OOXTODO: XML_gradientFill |
| |
| XclExpPalette& rPalette = rStrm.GetRoot().GetPalette(); |
| |
| if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) ) |
| rStyleSheet->singleElement( XML_patternFill, |
| XML_patternType, ToPatternType( mnPattern ), |
| FSEND ); |
| else |
| { |
| rStyleSheet->startElement( XML_patternFill, |
| XML_patternType, ToPatternType( mnPattern ), |
| FSEND ); |
| rStyleSheet->singleElement( XML_fgColor, |
| XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnForeColor ) ).getStr(), |
| FSEND ); |
| rStyleSheet->singleElement( XML_bgColor, |
| XML_rgb, XclXmlUtils::ToOString( rPalette.GetColor( mnBackColor ) ).getStr(), |
| FSEND ); |
| rStyleSheet->endElement( XML_patternFill ); |
| } |
| |
| rStyleSheet->endElement( XML_fill ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpXFId::XclExpXFId() : |
| mnXFId( XclExpXFBuffer::GetDefCellXFId() ), |
| mnXFIndex( EXC_XF_DEFAULTCELL ) |
| { |
| } |
| |
| XclExpXFId::XclExpXFId( sal_uInt32 nXFId ) : |
| mnXFId( nXFId ), |
| mnXFIndex( EXC_XF_DEFAULTCELL ) |
| { |
| } |
| |
| void XclExpXFId::ConvertXFIndex( const XclExpRoot& rRoot ) |
| { |
| mnXFIndex = rRoot.GetXFBuffer().GetXFIndex( mnXFId ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpXF::XclExpXF( |
| const XclExpRoot& rRoot, const ScPatternAttr& rPattern, sal_Int16 nScript, |
| sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) |
| : XclXFBase(true), |
| XclExpRecord(), |
| XclExpRoot(rRoot), |
| mpItemSet(0), |
| maProtection(), |
| maAlignment(), |
| maBorder(), |
| maArea(), |
| mnParentXFId(), |
| mnScNumFmt(), |
| mnXclFont(), |
| mnXclNumFmt(), |
| mnBorderId(), |
| mnFillId(), |
| mnIndexInXFList(0) |
| { |
| mnParentXFId = GetXFBuffer().InsertStyle( rPattern.GetStyleSheet() ); |
| Init( rPattern.GetItemSet(), nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak, false ); |
| } |
| |
| XclExpXF::XclExpXF( const XclExpRoot& rRoot, const SfxStyleSheetBase& rStyleSheet ) |
| : XclXFBase(false), |
| XclExpRecord(), |
| XclExpRoot(rRoot), |
| mpItemSet(0), |
| maProtection(), |
| maAlignment(), |
| maBorder(), |
| maArea(), |
| mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)), |
| mnScNumFmt(), |
| mnXclFont(), |
| mnXclNumFmt(), |
| mnBorderId(), |
| mnFillId(), |
| mnIndexInXFList(0) |
| { |
| bool bDefStyle = (rStyleSheet.GetName() == ScGlobal::GetRscString( STR_STYLENAME_STANDARD )); |
| sal_Int16 nScript = bDefStyle ? GetDefApiScript() : ::com::sun::star::i18n::ScriptType::WEAK; |
| Init( const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet(), nScript, |
| NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false, bDefStyle ); |
| } |
| |
| XclExpXF::XclExpXF( const XclExpRoot& rRoot, bool bCellXF ) |
| : XclXFBase(bCellXF), |
| XclExpRecord(), |
| XclExpRoot(rRoot), |
| mpItemSet(0), |
| maProtection(), |
| maAlignment(), |
| maBorder(), |
| maArea(), |
| mnParentXFId(XclExpXFBuffer::GetXFIdFromIndex(EXC_XF_STYLEPARENT)), |
| mnScNumFmt(), |
| mnXclFont(), |
| mnXclNumFmt(), |
| mnBorderId(), |
| mnFillId(), |
| mnIndexInXFList(0) |
| { |
| InitDefault(); |
| } |
| |
| bool XclExpXF::Equals( const ScPatternAttr& rPattern, |
| sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) const |
| { |
| return IsCellXF() && (mpItemSet == &rPattern.GetItemSet()) && |
| (!bForceLineBreak || maAlignment.mbLineBreak) && |
| ((nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) || (mnScNumFmt == nForceScNumFmt)) && |
| ((nForceXclFont == EXC_FONT_NOTFOUND) || (mnXclFont == nForceXclFont)); |
| } |
| |
| bool XclExpXF::Equals( const SfxStyleSheetBase& rStyleSheet ) const |
| { |
| return IsStyleXF() && (mpItemSet == &const_cast< SfxStyleSheetBase& >( rStyleSheet ).GetItemSet()); |
| } |
| |
| void XclExpXF::SetFinalColors() |
| { |
| maBorder.SetFinalColors( GetPalette() ); |
| maArea.SetFinalColors( GetPalette() ); |
| } |
| |
| bool XclExpXF::Equals( const XclExpXF& rCmpXF ) const |
| { |
| return XclXFBase::Equals( rCmpXF ) && |
| (maProtection == rCmpXF.maProtection) && (maAlignment == rCmpXF.maAlignment) && |
| (maBorder == rCmpXF.maBorder) && (maArea == rCmpXF.maArea) && |
| (mnXclFont == rCmpXF.mnXclFont) && (mnXclNumFmt == rCmpXF.mnXclNumFmt) && |
| (mnParentXFId == rCmpXF.mnParentXFId); |
| } |
| |
| void XclExpXF::InitDefault() |
| { |
| SetRecHeader( EXC_ID5_XF, (GetBiff() == EXC_BIFF8) ? 20 : 16 ); |
| mpItemSet = 0; |
| mnScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| mnXclFont = mnXclNumFmt = 0; |
| } |
| |
| void XclExpXF::Init( const SfxItemSet& rItemSet, sal_Int16 nScript, |
| sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak, bool bDefStyle ) |
| { |
| InitDefault(); |
| mpItemSet = &rItemSet; |
| |
| // cell protection |
| mbProtUsed = maProtection.FillFromItemSet( rItemSet, IsStyleXF() ); |
| |
| // font |
| if( nForceXclFont == EXC_FONT_NOTFOUND ) |
| { |
| mnXclFont = GetFontBuffer().Insert( rItemSet, nScript, EXC_COLOR_CELLTEXT, bDefStyle ); |
| mbFontUsed = XclExpFontHelper::CheckItems( GetRoot(), rItemSet, nScript, IsStyleXF() ); |
| } |
| else |
| { |
| mnXclFont = nForceXclFont; |
| mbFontUsed = true; |
| } |
| |
| // number format |
| mnScNumFmt = (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) ? |
| GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) : nForceScNumFmt; |
| mnXclNumFmt = GetNumFmtBuffer().Insert( mnScNumFmt ); |
| mbFmtUsed = ScfTools::CheckItem( rItemSet, ATTR_VALUE_FORMAT, IsStyleXF() ); |
| |
| // alignment |
| mbAlignUsed = maAlignment.FillFromItemSet( rItemSet, bForceLineBreak, GetBiff(), IsStyleXF() ); |
| |
| // cell border |
| mbBorderUsed = maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff(), IsStyleXF() ); |
| |
| // background area |
| mbAreaUsed = maArea.FillFromItemSet( rItemSet, GetPalette(), IsStyleXF() ); |
| |
| // set all b***Used flags to true in "Default"/"Normal" style |
| if( bDefStyle ) |
| SetAllUsedFlags( true ); |
| } |
| |
| sal_uInt8 XclExpXF::GetUsedFlags() const |
| { |
| sal_uInt8 nUsedFlags = 0; |
| /* In cell XFs a set bit means a used attribute, in style XFs a cleared bit. |
| "mbCellXF == mb***Used" evaluates to correct value in cell and style XFs. */ |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_PROT, mbCellXF == mbProtUsed ); |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_FONT, mbCellXF == mbFontUsed ); |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_VALFMT, mbCellXF == mbFmtUsed ); |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_ALIGN, mbCellXF == mbAlignUsed ); |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_BORDER, mbCellXF == mbBorderUsed ); |
| ::set_flag( nUsedFlags, EXC_XF_DIFF_AREA, mbCellXF == mbAreaUsed ); |
| return nUsedFlags; |
| } |
| |
| void XclExpXF::WriteBody5( XclExpStream& rStrm ) |
| { |
| sal_uInt16 nTypeProt = 0, nAlign = 0; |
| sal_uInt32 nArea = 0, nBorder = 0; |
| |
| ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() ); |
| ::insert_value( nTypeProt, mnParent, 4, 12 ); |
| ::insert_value( nAlign, GetUsedFlags(), 10, 6 ); |
| |
| maProtection.FillToXF3( nTypeProt ); |
| maAlignment.FillToXF5( nAlign ); |
| maBorder.FillToXF5( nBorder, nArea ); |
| maArea.FillToXF5( nArea ); |
| |
| rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nArea << nBorder; |
| } |
| |
| void XclExpXF::WriteBody8( XclExpStream& rStrm ) |
| { |
| sal_uInt16 nTypeProt = 0, nAlign = 0, nMiscAttrib = 0, nArea = 0; |
| sal_uInt32 nBorder1 = 0, nBorder2 = 0; |
| |
| ::set_flag( nTypeProt, EXC_XF_STYLE, IsStyleXF() ); |
| ::insert_value( nTypeProt, mnParent, 4, 12 ); |
| ::insert_value( nMiscAttrib, GetUsedFlags(), 10, 6 ); |
| |
| maProtection.FillToXF3( nTypeProt ); |
| maAlignment.FillToXF8( nAlign, nMiscAttrib ); |
| maBorder.FillToXF8( nBorder1, nBorder2 ); |
| maArea.FillToXF8( nBorder2, nArea ); |
| |
| rStrm << mnXclFont << mnXclNumFmt << nTypeProt << nAlign << nMiscAttrib << nBorder1 << nBorder2 << nArea; |
| } |
| |
| void XclExpXF::WriteBody( XclExpStream& rStrm ) |
| { |
| XclExpXFId aParentId( mnParentXFId ); |
| aParentId.ConvertXFIndex( GetRoot() ); |
| mnParent = aParentId.mnXFIndex; |
| switch( GetBiff() ) |
| { |
| case EXC_BIFF5: WriteBody5( rStrm ); break; |
| case EXC_BIFF8: WriteBody8( rStrm ); break; |
| default: DBG_ERROR_BIFF(); |
| } |
| } |
| |
| void XclExpXF::SetXmlIds( sal_uInt32 nBorderId, sal_uInt32 nFillId ) |
| { |
| mnBorderId = nBorderId; |
| mnFillId = nFillId; |
| } |
| |
| void XclExpXF::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| |
| sal_Int32 nXfId = 0; |
| if( IsCellXF() ) |
| { |
| sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( mnParentXFId ); |
| nXfId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( nXFIndex ); |
| } |
| |
| rStyleSheet->startElement( XML_xf, |
| XML_numFmtId, OString::valueOf( (sal_Int32) mnXclNumFmt ).getStr(), |
| XML_fontId, OString::valueOf( (sal_Int32) mnXclFont ).getStr(), |
| XML_fillId, OString::valueOf( (sal_Int32) mnFillId ).getStr(), |
| XML_borderId, OString::valueOf( (sal_Int32) mnBorderId ).getStr(), |
| XML_xfId, IsStyleXF() ? NULL : OString::valueOf( nXfId ).getStr(), |
| // OOXTODO: XML_quotePrefix, |
| // OOXTODO: XML_pivotButton, |
| // OOXTODO: XML_applyNumberFormat, ; |
| XML_applyFont, XclXmlUtils::ToPsz( mbFontUsed ), |
| // OOXTODO: XML_applyFill, |
| XML_applyBorder, XclXmlUtils::ToPsz( mbBorderUsed ), |
| XML_applyAlignment, XclXmlUtils::ToPsz( mbAlignUsed ), |
| XML_applyProtection, XclXmlUtils::ToPsz( mbProtUsed ), |
| FSEND ); |
| if( mbAlignUsed ) |
| maAlignment.SaveXml( rStrm ); |
| if( mbProtUsed ) |
| maProtection.SaveXml( rStrm ); |
| // OOXTODO: XML_extLst |
| rStyleSheet->endElement( XML_xf ); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpDefaultXF::XclExpDefaultXF( const XclExpRoot& rRoot, bool bCellXF ) : |
| XclExpXF( rRoot, bCellXF ) |
| { |
| } |
| |
| //UNUSED2008-05 void XclExpDefaultXF::SetParent( sal_uInt32 nParentXFId ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 DBG_ASSERT( IsCellXF(), "XclExpDefaultXF::SetParent - not allowed in style XFs" ); |
| //UNUSED2008-05 if( IsCellXF() ) |
| //UNUSED2008-05 mnParentXFId = nParentXFId; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void XclExpDefaultXF::SetUsedFlags( |
| //UNUSED2008-05 bool bProtUsed, bool bFontUsed, bool bFmtUsed, |
| //UNUSED2008-05 bool bAlignUsed, bool bBorderUsed, bool bAreaUsed ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 mbProtUsed = bProtUsed; |
| //UNUSED2008-05 mbFontUsed = bFontUsed; |
| //UNUSED2008-05 mbFmtUsed = bFmtUsed; |
| //UNUSED2008-05 mbAlignUsed = bAlignUsed; |
| //UNUSED2008-05 mbBorderUsed = bBorderUsed; |
| //UNUSED2008-05 mbAreaUsed = bAreaUsed; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void XclExpDefaultXF::SetProtection( const XclExpCellProt& rProtection ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 maProtection = rProtection; |
| //UNUSED2008-05 mbProtUsed = true; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void XclExpDefaultXF::SetAlignment( const XclExpCellAlign& rAlignment ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 maAlignment = rAlignment; |
| //UNUSED2008-05 mbAlignUsed = true; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void XclExpDefaultXF::SetBorder( const XclExpCellBorder& rBorder ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 maBorder = rBorder; |
| //UNUSED2008-05 mbBorderUsed = true; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void XclExpDefaultXF::SetArea( const XclExpCellArea& rArea ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 maArea = rArea; |
| //UNUSED2008-05 mbAreaUsed = true; |
| //UNUSED2008-05 } |
| |
| void XclExpDefaultXF::SetFont( sal_uInt16 nXclFont ) |
| { |
| mnXclFont = nXclFont; |
| mbFontUsed = true; |
| } |
| |
| void XclExpDefaultXF::SetNumFmt( sal_uInt16 nXclNumFmt ) |
| { |
| mnXclNumFmt = nXclNumFmt; |
| mbFmtUsed = true; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpStyle::XclExpStyle( sal_uInt32 nXFId, const String& rStyleName ) : |
| XclExpRecord( EXC_ID_STYLE, 4 ), |
| maName( rStyleName ), |
| maXFId( nXFId ), |
| mnStyleId( EXC_STYLE_USERDEF ), |
| mnLevel( EXC_STYLE_NOLEVEL ) |
| { |
| DBG_ASSERT( maName.Len(), "XclExpStyle::XclExpStyle - empty style name" ); |
| #ifdef DBG_UTIL |
| sal_uInt8 nStyleId, nLevel; // do not use members for debug tests |
| DBG_ASSERT( !XclTools::GetBuiltInStyleId( nStyleId, nLevel, maName ), |
| "XclExpStyle::XclExpStyle - this is a built-in style" ); |
| #endif |
| } |
| |
| XclExpStyle::XclExpStyle( sal_uInt32 nXFId, sal_uInt8 nStyleId, sal_uInt8 nLevel ) : |
| XclExpRecord( EXC_ID_STYLE, 4 ), |
| maXFId( nXFId ), |
| mnStyleId( nStyleId ), |
| mnLevel( nLevel ) |
| { |
| } |
| |
| void XclExpStyle::WriteBody( XclExpStream& rStrm ) |
| { |
| maXFId.ConvertXFIndex( rStrm.GetRoot() ); |
| ::set_flag( maXFId.mnXFIndex, EXC_STYLE_BUILTIN, IsBuiltIn() ); |
| rStrm << maXFId.mnXFIndex; |
| |
| if( IsBuiltIn() ) |
| { |
| rStrm << mnStyleId << mnLevel; |
| } |
| else |
| { |
| XclExpString aNameEx; |
| if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ) |
| aNameEx.Assign( maName ); |
| else |
| aNameEx.AssignByte( maName, rStrm.GetRoot().GetTextEncoding(), EXC_STR_8BITLENGTH ); |
| rStrm << aNameEx; |
| } |
| } |
| |
| static const char* lcl_StyleNameFromId( sal_Int32 nStyleId ) |
| { |
| switch( nStyleId ) |
| { |
| case 0: return "Normal"; |
| case 3: return "Comma"; |
| case 4: return "Currency"; |
| case 5: return "Percent"; |
| case 6: return "Comma [0]"; |
| case 7: return "Currency [0]"; |
| } |
| return "*unknown*"; |
| } |
| |
| void XclExpStyle::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| OString sName; |
| if( IsBuiltIn() ) |
| { |
| sName = OString( lcl_StyleNameFromId( mnStyleId ) ); |
| } |
| else |
| sName = XclXmlUtils::ToOString( maName ); |
| sal_Int32 nXFId = rStrm.GetRoot().GetXFBuffer().GetXmlStyleIndex( maXFId.mnXFId ); |
| rStrm.GetCurrentStream()->singleElement( XML_cellStyle, |
| XML_name, sName.getStr(), |
| XML_xfId, OString::valueOf( nXFId ).getStr(), |
| XML_builtinId, OString::valueOf( (sal_Int32) mnStyleId ).getStr(), |
| // OOXTODO: XML_iLevel, |
| // OOXTODO: XML_hidden, |
| XML_customBuiltin, XclXmlUtils::ToPsz( ! IsBuiltIn() ), |
| FSEND ); |
| // OOXTODO: XML_extLst |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| namespace { |
| |
| const sal_uInt32 EXC_XFLIST_INDEXBASE = 0xFFFE0000; |
| /** Maximum count of XF records to store in the XF list (performance). */ |
| const sal_uInt32 EXC_XFLIST_HARDLIMIT = 256 * 1024; |
| |
| bool lclIsBuiltInStyle( const String& rStyleName ) |
| { |
| return |
| XclTools::IsBuiltInStyleName( rStyleName ) || |
| XclTools::IsCondFormatStyleName( rStyleName ); |
| } |
| |
| } // namespace |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclExpXFBuffer::XclExpBuiltInInfo::XclExpBuiltInInfo() : |
| mnStyleId( EXC_STYLE_USERDEF ), |
| mnLevel( EXC_STYLE_NOLEVEL ), |
| mbPredefined( true ), |
| mbHasStyleRec( false ) |
| { |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| /** Predicate for search algorithm. */ |
| struct XclExpBorderPred |
| { |
| const XclExpCellBorder& |
| mrBorder; |
| inline explicit XclExpBorderPred( const XclExpCellBorder& rBorder ) : mrBorder( rBorder ) {} |
| bool operator()( const XclExpCellBorder& rBorder ) const; |
| }; |
| |
| bool XclExpBorderPred::operator()( const XclExpCellBorder& rBorder ) const |
| { |
| return |
| mrBorder.mnLeftColor == rBorder.mnLeftColor && |
| mrBorder.mnRightColor == rBorder.mnRightColor && |
| mrBorder.mnTopColor == rBorder.mnTopColor && |
| mrBorder.mnBottomColor == rBorder.mnBottomColor && |
| mrBorder.mnDiagColor == rBorder.mnDiagColor && |
| mrBorder.mnLeftLine == rBorder.mnLeftLine && |
| mrBorder.mnRightLine == rBorder.mnRightLine && |
| mrBorder.mnTopLine == rBorder.mnTopLine && |
| mrBorder.mnBottomLine == rBorder.mnBottomLine && |
| mrBorder.mnDiagLine == rBorder.mnDiagLine && |
| mrBorder.mbDiagTLtoBR == rBorder.mbDiagTLtoBR && |
| mrBorder.mbDiagBLtoTR == rBorder.mbDiagBLtoTR && |
| mrBorder.mnLeftColorId == rBorder.mnLeftColorId && |
| mrBorder.mnRightColorId == rBorder.mnRightColorId && |
| mrBorder.mnTopColorId == rBorder.mnTopColorId && |
| mrBorder.mnBottomColorId == rBorder.mnBottomColorId && |
| mrBorder.mnDiagColorId == rBorder.mnDiagColorId; |
| } |
| |
| struct XclExpFillPred |
| { |
| const XclExpCellArea& |
| mrFill; |
| inline explicit XclExpFillPred( const XclExpCellArea& rFill ) : mrFill( rFill ) {} |
| bool operator()( const XclExpCellArea& rFill ) const; |
| }; |
| |
| bool XclExpFillPred::operator()( const XclExpCellArea& rFill ) const |
| { |
| return |
| mrFill.mnForeColor == rFill.mnForeColor && |
| mrFill.mnBackColor == rFill.mnBackColor && |
| mrFill.mnPattern == rFill.mnPattern && |
| mrFill.mnForeColorId == rFill.mnForeColorId && |
| mrFill.mnBackColorId == rFill.mnBackColorId; |
| } |
| |
| static bool XclExpXFBuffer_mbUseMultimapBuffer = true; |
| |
| XclExpXFBuffer::XclExpXFBuffer( const XclExpRoot& rRoot ) |
| : XclExpRecordBase(), |
| XclExpRoot(rRoot), |
| maXFList(), |
| maStyleList(), |
| maBuiltInMap(), |
| maXFIndexVec(), |
| maStyleIndexes(), |
| maCellIndexes(), |
| maSortedXFList(), |
| maBorders(), |
| maFills(), |
| maXclExpXFMap() |
| { |
| } |
| |
| void XclExpXFBuffer::Initialize() |
| { |
| InsertDefaultRecords(); |
| InsertUserStyles(); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::Insert( const ScPatternAttr* pPattern, sal_Int16 nScript ) |
| { |
| return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND, false ); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::InsertWithFont( const ScPatternAttr* pPattern, sal_Int16 nScript, |
| sal_uInt16 nForceXclFont, bool bForceLineBreak ) |
| { |
| return InsertCellXF( pPattern, nScript, NUMBERFORMAT_ENTRY_NOT_FOUND, nForceXclFont, bForceLineBreak ); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::InsertWithNumFmt( const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uLong nForceScNumFmt, bool bForceLineBreak ) |
| { |
| return InsertCellXF( pPattern, nScript, nForceScNumFmt, EXC_FONT_NOTFOUND, bForceLineBreak ); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::InsertStyle( const SfxStyleSheetBase* pStyleSheet ) |
| { |
| return pStyleSheet ? InsertStyleXF( *pStyleSheet ) : GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE ); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::GetXFIdFromIndex( sal_uInt16 nXFIndex ) |
| { |
| return EXC_XFLIST_INDEXBASE | nXFIndex; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::GetDefCellXFId() |
| { |
| return GetXFIdFromIndex( EXC_XF_DEFAULTCELL ); |
| } |
| |
| const XclExpXF* XclExpXFBuffer::GetXFById( sal_uInt32 nXFId ) const |
| { |
| return maXFList.GetRecord( nXFId ).get(); |
| } |
| |
| void XclExpXFBuffer::Finalize() |
| { |
| for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos ) |
| maXFList.GetRecord( nPos )->SetFinalColors(); |
| |
| sal_uInt32 nTotalCount = static_cast< sal_uInt32 >( maXFList.GetSize() ); |
| sal_uInt32 nId; |
| maXFIndexVec.resize( nTotalCount, EXC_XF_DEFAULTCELL ); |
| maStyleIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL ); |
| maCellIndexes.resize( nTotalCount, EXC_XF_DEFAULTCELL ); |
| |
| XclExpBuiltInMap::const_iterator aBuiltInEnd = maBuiltInMap.end(); |
| /* nMaxBuiltInXFId used to decide faster whether an XF record is |
| user-defined. If the current XF ID is greater than this value, |
| maBuiltInMap doesn't need to be searched. */ |
| sal_uInt32 nMaxBuiltInXFId = maBuiltInMap.empty() ? 0 : maBuiltInMap.rbegin()->first; |
| |
| // *** map all built-in XF records (cell and style) *** ------------------- |
| |
| // do not change XF order -> std::map<> iterates elements in ascending order |
| for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(); aIt != aBuiltInEnd; ++aIt ) |
| AppendXFIndex( aIt->first ); |
| |
| // *** insert all user-defined style XF records, without reduce *** ------- |
| |
| sal_uInt32 nStyleXFCount = 0; // counts up to EXC_XF_MAXSTYLECOUNT limit |
| |
| for( nId = 0; nId < nTotalCount; ++nId ) |
| { |
| XclExpXFRef xXF = maXFList.GetRecord( nId ); |
| if( xXF->IsStyleXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) ) |
| { |
| if( nStyleXFCount < EXC_XF_MAXSTYLECOUNT ) |
| { |
| // maximum count of styles not reached |
| AppendXFIndex( nId ); |
| ++nStyleXFCount; |
| } |
| else |
| { |
| /* Maximum count of styles reached - do not append more |
| pointers to XFs; use default style XF instead; do not break |
| the loop to initialize all maXFIndexVec elements. */ |
| maXFIndexVec[ nId ] = EXC_XF_DEFAULTSTYLE; |
| } |
| } |
| } |
| |
| // *** insert all cell XF records *** ------------------------------------- |
| |
| // start position to search for equal inserted XF records |
| size_t nSearchStart = maSortedXFList.GetSize(); |
| |
| // break the loop if XF limit reached - maXFIndexVec is already initialized with default index |
| XclExpXFRef xDefCellXF = maXFList.GetRecord( EXC_XF_DEFAULTCELL ); |
| for( nId = 0; (nId < nTotalCount) && (maSortedXFList.GetSize() < EXC_XF_MAXCOUNT); ++nId ) |
| { |
| XclExpXFRef xXF = maXFList.GetRecord( nId ); |
| if( xXF->IsCellXF() && ((nId > nMaxBuiltInXFId) || (maBuiltInMap.find( nId ) == aBuiltInEnd)) ) |
| { |
| // try to find an XF record equal to *xXF, which is already inserted |
| sal_uInt16 nFoundIndex = EXC_XF_NOTFOUND; |
| |
| // first try if it is equal to the default cell XF |
| if( xDefCellXF->Equals( *xXF ) ) |
| { |
| nFoundIndex = EXC_XF_DEFAULTCELL; |
| } |
| else for( size_t nSearchPos = nSearchStart, nSearchEnd = maSortedXFList.GetSize(); |
| (nSearchPos < nSearchEnd) && (nFoundIndex == EXC_XF_NOTFOUND); ++nSearchPos ) |
| { |
| if( maSortedXFList.GetRecord( nSearchPos )->Equals( *xXF ) ) |
| nFoundIndex = static_cast< sal_uInt16 >( nSearchPos ); |
| } |
| |
| if( nFoundIndex != EXC_XF_NOTFOUND ) |
| // equal XF already in the list, use its resulting XF index |
| maXFIndexVec[ nId ] = nFoundIndex; |
| else |
| AppendXFIndex( nId ); |
| } |
| } |
| |
| sal_uInt16 nXmlStyleIndex = 0; |
| sal_uInt16 nXmlCellIndex = 0; |
| |
| size_t nXFCount = maSortedXFList.GetSize(); |
| for( size_t i = 0; i < nXFCount; ++i ) |
| { |
| XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i ); |
| if( xXF->IsStyleXF() ) |
| maStyleIndexes[ i ] = nXmlStyleIndex++; |
| else |
| maCellIndexes[ i ] = nXmlCellIndex++; |
| } |
| } |
| |
| sal_uInt16 XclExpXFBuffer::GetXFIndex( sal_uInt32 nXFId ) const |
| { |
| sal_uInt16 nXFIndex = EXC_XF_DEFAULTSTYLE; |
| if( nXFId >= EXC_XFLIST_INDEXBASE ) |
| nXFIndex = static_cast< sal_uInt16 >( nXFId & ~EXC_XFLIST_INDEXBASE ); |
| else if( nXFId < maXFIndexVec.size() ) |
| nXFIndex = maXFIndexVec[ nXFId ]; |
| return nXFIndex; |
| } |
| |
| sal_Int32 XclExpXFBuffer::GetXmlStyleIndex( sal_uInt32 nXFIndex ) const |
| { |
| DBG_ASSERT( nXFIndex < maStyleIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" ); |
| if( nXFIndex > maStyleIndexes.size() ) |
| return 0; // should be caught/debugged via above assert; return "valid" index. |
| return maStyleIndexes[ nXFIndex ]; |
| } |
| |
| sal_Int32 XclExpXFBuffer::GetXmlCellIndex( sal_uInt32 nXFIndex ) const |
| { |
| DBG_ASSERT( nXFIndex < maCellIndexes.size(), "XclExpXFBuffer::GetXmlStyleIndex - invalid index!" ); |
| if( nXFIndex > maCellIndexes.size() ) |
| return 0; // should be caught/debugged via above assert; return "valid" index. |
| return maCellIndexes[ nXFIndex ]; |
| } |
| |
| void XclExpXFBuffer::Save( XclExpStream& rStrm ) |
| { |
| // save all XF records contained in the maSortedXFList vector (sorted by XF index) |
| maSortedXFList.Save( rStrm ); |
| // save all STYLE records |
| maStyleList.Save( rStrm ); |
| } |
| |
| static void lcl_GetCellCounts( const XclExpRecordList< XclExpXF >& rXFList, sal_Int32& rCells, sal_Int32& rStyles ) |
| { |
| rCells = 0; |
| rStyles = 0; |
| size_t nXFCount = rXFList.GetSize(); |
| for( size_t i = 0; i < nXFCount; ++i ) |
| { |
| XclExpRecordList< XclExpXF >::RecordRefType xXF = rXFList.GetRecord( i ); |
| if( xXF->IsCellXF() ) |
| ++rCells; |
| else if( xXF->IsStyleXF() ) |
| ++rStyles; |
| } |
| } |
| |
| void XclExpXFBuffer::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); |
| |
| rStyleSheet->startElement( XML_fills, |
| XML_count, OString::valueOf( (sal_Int32) maFills.size() ).getStr(), |
| FSEND ); |
| for( XclExpFillList::iterator aIt = maFills.begin(), aEnd = maFills.end(); |
| aIt != aEnd; ++aIt ) |
| { |
| aIt->SaveXml( rStrm ); |
| } |
| rStyleSheet->endElement( XML_fills ); |
| |
| rStyleSheet->startElement( XML_borders, |
| XML_count, OString::valueOf( (sal_Int32) maBorders.size() ).getStr(), |
| FSEND ); |
| for( XclExpBorderList::iterator aIt = maBorders.begin(), aEnd = maBorders.end(); |
| aIt != aEnd; ++aIt ) |
| { |
| aIt->SaveXml( rStrm ); |
| } |
| rStyleSheet->endElement( XML_borders ); |
| |
| // save all XF records contained in the maSortedXFList vector (sorted by XF index) |
| sal_Int32 nCells, nStyles; |
| lcl_GetCellCounts( maSortedXFList, nCells, nStyles ); |
| |
| if( nStyles > 0 ) |
| { |
| rStyleSheet->startElement( XML_cellStyleXfs, |
| XML_count, OString::valueOf( nStyles ).getStr(), |
| FSEND ); |
| size_t nXFCount = maSortedXFList.GetSize(); |
| for( size_t i = 0; i < nXFCount; ++i ) |
| { |
| XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i ); |
| if( ! xXF->IsStyleXF() ) |
| continue; |
| SaveXFXml( rStrm, *xXF ); |
| } |
| rStyleSheet->endElement( XML_cellStyleXfs ); |
| } |
| |
| if( nCells > 0 ) |
| { |
| rStyleSheet->startElement( XML_cellXfs, |
| XML_count, OString::valueOf( nCells ).getStr(), |
| FSEND ); |
| size_t nXFCount = maSortedXFList.GetSize(); |
| for( size_t i = 0; i < nXFCount; ++i ) |
| { |
| XclExpXFList::RecordRefType xXF = maSortedXFList.GetRecord( i ); |
| if( ! xXF->IsCellXF() ) |
| continue; |
| SaveXFXml( rStrm, *xXF ); |
| } |
| rStyleSheet->endElement( XML_cellXfs ); |
| } |
| |
| // save all STYLE records |
| rStyleSheet->startElement( XML_cellStyles, |
| XML_count, OString::valueOf( (sal_Int32) maStyleList.GetSize() ).getStr(), |
| FSEND ); |
| maStyleList.SaveXml( rStrm ); |
| rStyleSheet->endElement( XML_cellStyles ); |
| } |
| |
| void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, XclExpXF& rXF ) |
| { |
| XclExpBorderList::iterator aBorderPos = |
| std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ); |
| DBG_ASSERT( aBorderPos != maBorders.end(), "XclExpXFBuffer::SaveXml - Invalid @borderId!" ); |
| XclExpFillList::iterator aFillPos = |
| std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ); |
| DBG_ASSERT( aFillPos != maFills.end(), "XclExpXFBuffer::SaveXml - Invalid @fillId!" ); |
| |
| sal_Int32 nBorderId = 0, nFillId = 0; |
| if( aBorderPos != maBorders.end() ) |
| nBorderId = std::distance( maBorders.begin(), aBorderPos ); |
| if( aFillPos != maFills.end() ) |
| nFillId = std::distance( maFills.begin(), aFillPos ); |
| |
| rXF.SetXmlIds( nBorderId, nFillId ); |
| rXF.SaveXml( rStrm ); |
| } |
| |
| void XclExpXFBuffer::impAddMissingValuesFromXFListToXclExpXFMap() |
| { |
| for(size_t nPos(maXclExpXFMap.size()); nPos < maXFList.GetSize(); ++nPos) |
| { |
| XclExpXF* pValue = maXFList.GetRecord(nPos).get(); |
| |
| if(pValue) |
| { |
| const SfxItemSet* pKey = maXFList.GetRecord(nPos)->getItemSet(); |
| |
| maXclExpXFMap.insert(std::pair< const SfxItemSet*, XclExpXF* >(pKey, pValue)); |
| pValue->setIndexInXFList(nPos); |
| } |
| else |
| { |
| OSL_ENSURE(false, "maXFList has empty entries (!)"); |
| } |
| } |
| } |
| |
| sal_uInt32 XclExpXFBuffer::FindXF(const ScPatternAttr& rPattern, sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak) const |
| { |
| // define return value |
| sal_uInt32 nXFId(EXC_XFID_NOTFOUND); |
| |
| if(XclExpXFBuffer_mbUseMultimapBuffer) |
| { |
| // add values from maXFList which are not yet in maXclExpXFMap |
| const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap(); |
| |
| // get the full range for the pattern set |
| typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT; |
| typedef std::pair< CIT, CIT > Range; |
| const SfxItemSet* pPatternSet = &(rPattern.GetItemSet()); |
| const Range range(maXclExpXFMap.equal_range(pPatternSet)); |
| |
| // iterate over evtl. multiple candidates using the pattern set |
| for(CIT ite(range.first); ite != range.second; ++ite) |
| { |
| XclExpXF* pIte = ite->second; |
| |
| if(pIte->Equals(rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak)) |
| { |
| nXFId = pIte->getIndexInXFList(); |
| break; |
| } |
| } |
| } |
| else |
| { |
| // old, unbuffered implementation |
| for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos ) |
| if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ) |
| return static_cast< sal_uInt32 >( nPos ); |
| } |
| |
| return nXFId; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const |
| { |
| if(XclExpXFBuffer_mbUseMultimapBuffer) |
| { |
| // add values from maXFList which are not yet in maXclExpXFMap |
| const_cast< XclExpXFBuffer* >(this)->impAddMissingValuesFromXFListToXclExpXFMap(); |
| |
| // find entry with given ItemSet (by StyleSheet) |
| const SfxItemSet& rItemSet = const_cast< SfxStyleSheetBase& >(rStyleSheet).GetItemSet(); |
| typedef std::multimap< const SfxItemSet*, XclExpXF* >::const_iterator CIT; |
| const CIT aFound(maXclExpXFMap.find(&rItemSet)); |
| |
| if(aFound != maXclExpXFMap.end()) |
| { |
| return aFound->second->getIndexInXFList(); |
| } |
| } |
| else |
| { |
| // old, unbuffered implementation |
| for( size_t nPos = 0, nSize = maXFList.GetSize(); nPos < nSize; ++nPos ) |
| if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) ) |
| return static_cast< sal_uInt32 >( nPos ); |
| } |
| |
| return EXC_XFID_NOTFOUND; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 nStyleId, sal_uInt8 nLevel ) const |
| { |
| for( XclExpBuiltInMap::const_iterator aIt = maBuiltInMap.begin(), aEnd = maBuiltInMap.end(); aIt != aEnd; ++aIt ) |
| if( (aIt->second.mnStyleId == nStyleId) && (aIt->second.mnLevel == nLevel) ) |
| return aIt->first; |
| return EXC_XFID_NOTFOUND; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, sal_Int16 nScript, |
| sal_uLong nForceScNumFmt, sal_uInt16 nForceXclFont, bool bForceLineBreak ) |
| { |
| const ScPatternAttr* pDefPattern = GetDoc().GetDefPattern(); |
| if( !pPattern ) |
| pPattern = pDefPattern; |
| |
| // special handling for default cell formatting |
| if( (pPattern == pDefPattern) && !bForceLineBreak && |
| (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND) && |
| (nForceXclFont == EXC_FONT_NOTFOUND) ) |
| { |
| // Is it the first try to insert the default cell format? |
| bool& rbPredefined = maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined; |
| if( rbPredefined ) |
| { |
| // replace default cell pattern |
| XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) ); |
| maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL ); |
| |
| // need to clear the multimap buffer to force reinsertin of the new element |
| if(XclExpXFBuffer_mbUseMultimapBuffer) |
| { |
| maXclExpXFMap.clear(); |
| } |
| |
| rbPredefined = false; |
| } |
| return GetDefCellXFId(); |
| } |
| |
| sal_uInt32 nXFId = FindXF( *pPattern, nForceScNumFmt, nForceXclFont, bForceLineBreak ); |
| if( nXFId == EXC_XFID_NOTFOUND ) |
| { |
| // not found - insert new cell XF |
| if( maXFList.GetSize() < EXC_XFLIST_HARDLIMIT ) |
| { |
| maXFList.AppendNewRecord( new XclExpXF( |
| GetRoot(), *pPattern, nScript, nForceScNumFmt, nForceXclFont, bForceLineBreak ) ); |
| // do not set nXFId before the AppendNewRecord() call - it may insert 2 XFs (style+cell) |
| nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 ); |
| } |
| else |
| { |
| // list full - fall back to default cell XF |
| nXFId = GetDefCellXFId(); |
| } |
| } |
| return nXFId; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::InsertStyleXF( const SfxStyleSheetBase& rStyleSheet ) |
| { |
| // *** try, if it is a built-in style - create new XF or replace existing predefined XF *** |
| |
| sal_uInt8 nStyleId, nLevel; |
| if( XclTools::GetBuiltInStyleId( nStyleId, nLevel, rStyleSheet.GetName() ) ) |
| { |
| // try to find the built-in XF record (if already created in InsertDefaultRecords()) |
| sal_uInt32 nXFId = FindBuiltInXF( nStyleId, nLevel ); |
| if( nXFId == EXC_XFID_NOTFOUND ) |
| { |
| // built-in style XF not yet created - do it now |
| XclExpXFRef xXF( new XclExpXF( GetRoot(), rStyleSheet ) ); |
| nXFId = AppendBuiltInXFWithStyle( xXF, nStyleId, nLevel ); |
| // this new XF record is not predefined |
| maBuiltInMap[ nXFId ].mbPredefined = false; |
| } |
| else |
| { |
| DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::InsertStyleXF - built-in XF not found" ); |
| // XF record still predefined? -> Replace with real XF |
| bool& rbPredefined = maBuiltInMap[ nXFId ].mbPredefined; |
| if( rbPredefined ) |
| { |
| // replace predefined built-in style (ReplaceRecord() deletes old record) |
| maXFList.ReplaceRecord( XclExpXFRef( new XclExpXF( GetRoot(), rStyleSheet ) ), nXFId ); |
| |
| // need to clear the multimap buffer to force reinsertin of the new element |
| if(XclExpXFBuffer_mbUseMultimapBuffer) |
| { |
| maXclExpXFMap.clear(); |
| } |
| |
| rbPredefined = false; |
| } |
| } |
| |
| // STYLE already inserted? (may be not, i.e. for RowLevel/ColLevel or Hyperlink styles) |
| bool& rbHasStyleRec = maBuiltInMap[ nXFId ].mbHasStyleRec; |
| if( !rbHasStyleRec ) |
| { |
| maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) ); |
| rbHasStyleRec = true; |
| } |
| |
| return nXFId; |
| } |
| |
| // *** try to find the XF record of a user-defined style *** |
| |
| sal_uInt32 nXFId = FindXF( rStyleSheet ); |
| if( nXFId == EXC_XFID_NOTFOUND ) |
| { |
| // not found - insert new style XF and STYLE |
| nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() ); |
| if( nXFId < EXC_XFLIST_HARDLIMIT ) |
| { |
| maXFList.AppendNewRecord( new XclExpXF( GetRoot(), rStyleSheet ) ); |
| // create the STYLE record |
| if( rStyleSheet.GetName().Len() ) |
| maStyleList.AppendNewRecord( new XclExpStyle( nXFId, rStyleSheet.GetName() ) ); |
| } |
| else |
| // list full - fall back to default style XF |
| nXFId = GetXFIdFromIndex( EXC_XF_DEFAULTSTYLE ); |
| } |
| return nXFId; |
| } |
| |
| void XclExpXFBuffer::InsertUserStyles() |
| { |
| SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA ); |
| for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() ) |
| if( pStyleSheet->IsUserDefined() && !lclIsBuiltInStyle( pStyleSheet->GetName() ) ) |
| InsertStyleXF( *pStyleSheet ); |
| } |
| |
| sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel ) |
| { |
| sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() ); |
| maXFList.AppendRecord( xXF ); |
| XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ]; |
| rInfo.mnStyleId = nStyleId; |
| rInfo.mnLevel = nLevel; |
| rInfo.mbPredefined = true; |
| return nXFId; |
| } |
| |
| sal_uInt32 XclExpXFBuffer::AppendBuiltInXFWithStyle( XclExpXFRef xXF, sal_uInt8 nStyleId, sal_uInt8 nLevel ) |
| { |
| sal_uInt32 nXFId = AppendBuiltInXF( xXF, nStyleId, nLevel ); |
| maStyleList.AppendNewRecord( new XclExpStyle( nXFId, nStyleId, nLevel ) ); |
| maBuiltInMap[ nXFId ].mbHasStyleRec = true; // mark existing STYLE record |
| return nXFId; |
| } |
| |
| static XclExpCellArea lcl_GetPatternFill_None() |
| { |
| XclExpCellArea aFill; |
| aFill.mnPattern = EXC_PATT_NONE; |
| return aFill; |
| } |
| |
| static XclExpCellArea lcl_GetPatternFill_Gray125() |
| { |
| XclExpCellArea aFill; |
| aFill.mnPattern = EXC_PATT_12_5_PERC; |
| aFill.mnForeColor = 0; |
| aFill.mnBackColor = 0; |
| return aFill; |
| } |
| |
| void XclExpXFBuffer::InsertDefaultRecords() |
| { |
| maFills.push_back( lcl_GetPatternFill_None() ); |
| maFills.push_back( lcl_GetPatternFill_Gray125() ); |
| |
| // index 0: default style |
| if( SfxStyleSheetBase* pDefStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) ) |
| { |
| XclExpXFRef xDefStyle( new XclExpXF( GetRoot(), *pDefStyleSheet ) ); |
| sal_uInt32 nXFId = AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL ); |
| // mark this XF as not predefined, prevents overwriting |
| maBuiltInMap[ nXFId ].mbPredefined = false; |
| } |
| else |
| { |
| DBG_ERRORFILE( "XclExpXFBuffer::InsertDefaultRecords - default style not found" ); |
| XclExpXFRef xDefStyle( new XclExpDefaultXF( GetRoot(), false ) ); |
| xDefStyle->SetAllUsedFlags( true ); |
| AppendBuiltInXFWithStyle( xDefStyle, EXC_STYLE_NORMAL ); |
| } |
| |
| // index 1-14: RowLevel and ColLevel styles (without STYLE records) |
| XclExpDefaultXF aLevelStyle( GetRoot(), false ); |
| // RowLevel_1, ColLevel_1 |
| aLevelStyle.SetFont( 1 ); |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 0 ); |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 0 ); |
| // RowLevel_2, ColLevel_2 |
| aLevelStyle.SetFont( 2 ); |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, 1 ); |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, 1 ); |
| // RowLevel_3, ColLevel_3 ... RowLevel_7, ColLevel_7 |
| aLevelStyle.SetFont( 0 ); |
| for( sal_uInt8 nLevel = 2; nLevel < EXC_STYLE_LEVELCOUNT; ++nLevel ) |
| { |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_ROWLEVEL, nLevel ); |
| AppendBuiltInXF( XclExpXFRef( new XclExpDefaultXF( aLevelStyle ) ), EXC_STYLE_COLLEVEL, nLevel ); |
| } |
| |
| // index 15: default hard cell format, placeholder to be able to add more built-in styles |
| maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) ); |
| maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true; |
| |
| // index 16-20: other built-in styles |
| XclExpDefaultXF aFormatStyle( GetRoot(), false ); |
| aFormatStyle.SetFont( 1 ); |
| aFormatStyle.SetNumFmt( 43 ); |
| AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA ); |
| aFormatStyle.SetNumFmt( 41 ); |
| AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_COMMA_0 ); |
| aFormatStyle.SetNumFmt( 44 ); |
| AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY ); |
| aFormatStyle.SetNumFmt( 42 ); |
| AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_CURRENCY_0 ); |
| aFormatStyle.SetNumFmt( 9 ); |
| AppendBuiltInXFWithStyle( XclExpXFRef( new XclExpDefaultXF( aFormatStyle ) ), EXC_STYLE_PERCENT ); |
| |
| // other built-in style XF records (i.e. Hyperlink styles) are created on demand |
| |
| /* Insert the real default hard cell format -> 0 is document default pattern. |
| Do it here (and not already above) to really have all built-in styles. */ |
| Insert( 0, GetDefApiScript() ); |
| } |
| |
| void XclExpXFBuffer::AppendXFIndex( sal_uInt32 nXFId ) |
| { |
| DBG_ASSERT( nXFId < maXFIndexVec.size(), "XclExpXFBuffer::AppendXFIndex - XF ID out of range" ); |
| maXFIndexVec[ nXFId ] = static_cast< sal_uInt16 >( maSortedXFList.GetSize() ); |
| XclExpXFRef xXF = maXFList.GetRecord( nXFId ); |
| AddBorderAndFill( *xXF ); |
| maSortedXFList.AppendRecord( xXF ); |
| DBG_ASSERT( maXFList.HasRecord( nXFId ), "XclExpXFBuffer::AppendXFIndex - XF not found" ); |
| } |
| |
| void XclExpXFBuffer::AddBorderAndFill( const XclExpXF& rXF ) |
| { |
| if( std::find_if( maBorders.begin(), maBorders.end(), XclExpBorderPred( rXF.GetBorderData() ) ) == maBorders.end() ) |
| { |
| maBorders.push_back( rXF.GetBorderData() ); |
| } |
| |
| if( std::find_if( maFills.begin(), maFills.end(), XclExpFillPred( rXF.GetAreaData() ) ) == maFills.end() ) |
| { |
| maFills.push_back( rXF.GetAreaData() ); |
| } |
| } |
| |
| // ============================================================================ |
| |
| XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot ) |
| : XclExpRoot( rRoot ) |
| { |
| } |
| |
| void XclExpXmlStyleSheet::SaveXml( XclExpXmlStream& rStrm ) |
| { |
| sax_fastparser::FSHelperPtr aStyleSheet = rStrm.CreateOutputStream( |
| OUString::createFromAscii( "xl/styles.xml" ), |
| OUString::createFromAscii( "styles.xml" ), |
| rStrm.GetCurrentStream()->getOutputStream(), |
| "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", |
| "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" ); |
| rStrm.PushStream( aStyleSheet ); |
| |
| aStyleSheet->startElement( XML_styleSheet, |
| XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main", |
| FSEND ); |
| |
| CreateRecord( EXC_ID_FORMATLIST )->SaveXml( rStrm ); |
| CreateRecord( EXC_ID_FONTLIST )->SaveXml( rStrm ); |
| CreateRecord( EXC_ID_XFLIST )->SaveXml( rStrm ); |
| CreateRecord( EXC_ID_PALETTE )->SaveXml( rStrm ); |
| |
| aStyleSheet->endElement( XML_styleSheet ); |
| |
| rStrm.PopStream(); |
| } |
| |
| // ============================================================================ |
| |